diff --git a/local/recipes/libs/libdrm/recipe.toml b/local/recipes/libs/libdrm/recipe.toml index c12b35926b..2100d359bf 100644 --- a/local/recipes/libs/libdrm/recipe.toml +++ b/local/recipes/libs/libdrm/recipe.toml @@ -1,7 +1,7 @@ [source] tar = "https://gitlab.freedesktop.org/mesa/libdrm/-/archive/libdrm-2.4.125/libdrm-libdrm-2.4.125.tar.gz" blake3 = "33e6448252639f4ff8a8cd30129b335c5d85356c1c93f8d77a79221003b14f66" -patches = ["redox.patch"] +patches = ["redox.patch", "../../../patches/libdrm/P1-drm-ioctl-bridge.patch", "../../../patches/libdrm/P2-drm-get-pci-info.patch"] [build] template = "meson" @@ -11,4 +11,6 @@ mesonflags = [ "-Dnouveau=disabled", "-Dradeon=disabled", "-Dvmwgfx=disabled", + "-Dtests=false", + "-Dc_args=-Wno-unused-function", ] diff --git a/local/recipes/libs/libdrm/source/xf86drm.c b/local/recipes/libs/libdrm/source/xf86drm.c index 0379aafd7e..1b206ccd4a 100644 --- a/local/recipes/libs/libdrm/source/xf86drm.c +++ b/local/recipes/libs/libdrm/source/xf86drm.c @@ -91,6 +91,7 @@ #include "xf86drm_redox.h" #include "libdrm_macros.h" #include "drm_fourcc.h" +#include "virtgpu_drm.h" #include "util_math.h" @@ -114,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; @@ -805,14 +806,6 @@ unsigned long redox_translate_request(unsigned long linux_nr) return REDOX_DRM_IOCTL_SET_CLIENT_CAP; case 0x09: return REDOX_DRM_IOCTL_GEM_CLOSE; - case 0x0B: - return REDOX_DRM_IOCTL_GEM_OPEN; - case 0x0A: - return REDOX_DRM_IOCTL_GEM_FLINK; - case 0x2D: - return REDOX_DRM_IOCTL_PRIME_HANDLE_TO_FD; - case 0x2E: - return REDOX_DRM_IOCTL_PRIME_FD_TO_HANDLE; case 0xA6: return REDOX_DRM_IOCTL_MODE_GETENCODER; case 0xB3: @@ -821,50 +814,53 @@ unsigned long redox_translate_request(unsigned long linux_nr) return REDOX_DRM_IOCTL_MODE_DESTROY_DUMB; case 0xAF: return REDOX_DRM_IOCTL_MODE_RMFB; - case 0x02: - return REDOX_DRM_IOCTL_GET_MAGIC; - case 0x11: - return REDOX_DRM_IOCTL_AUTH_MAGIC; - case 0x1e: - return REDOX_DRM_IOCTL_SET_MASTER; - case 0x1f: - return REDOX_DRM_IOCTL_DROP_MASTER; - case 0xB9: - return REDOX_DRM_IOCTL_MODE_OBJ_GETPROPERTIES; - case 0xAA: - return REDOX_DRM_IOCTL_MODE_GETPROPERTY; - case 0xAC: - return REDOX_DRM_IOCTL_MODE_GETPROPBLOB; - case 0xC6: - return REDOX_DRM_IOCTL_MODE_CREATE_LEASE; - case 0xC7: - return REDOX_DRM_IOCTL_MODE_LIST_LESSEES; - case 0xBA: - return REDOX_DRM_IOCTL_MODE_OBJ_SETPROPERTY; - case 0xB5: - return REDOX_DRM_IOCTL_MODE_GETPLANERESOURCES; - case 0xB6: - return REDOX_DRM_IOCTL_MODE_GETPLANE; - case 0xB7: - return REDOX_DRM_IOCTL_MODE_SETPLANE; - case 0xB8: - return REDOX_DRM_IOCTL_MODE_ADDFB2; + /* 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 0xA7: + case 0xA3: return REDOX_DRM_IOCTL_MODE_GETCONNECTOR; - case 0xAE: - return REDOX_DRM_IOCTL_MODE_ADDFB; - case 0xB0: + case 0xA4: return REDOX_DRM_IOCTL_MODE_PAGE_FLIP; - case 0xB2: + case 0xA8: return REDOX_DRM_IOCTL_MODE_CREATE_DUMB; - case 0x00: - return REDOX_DRM_IOCTL_VERSION; + 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; default: return 0; } @@ -957,777 +953,87 @@ int redox_drm_exchange_alloc(int fd, unsigned long request_code, return 0; } -static void redox_drm_modeinfo_from_wire(struct drm_mode_modeinfo *mode, - const struct redox_drm_mode_wire *wire, - const char *name) -{ - size_t name_len = 0; - - memclear(*mode); - mode->clock = wire->clock; - mode->hdisplay = wire->hdisplay; - mode->hsync_start = wire->hsync_start; - mode->hsync_end = wire->hsync_end; - mode->htotal = wire->htotal; - mode->hskew = wire->hskew; - mode->vdisplay = wire->vdisplay; - mode->vsync_start = wire->vsync_start; - mode->vsync_end = wire->vsync_end; - mode->vtotal = wire->vtotal; - mode->vscan = wire->vscan; - mode->vrefresh = wire->vrefresh; - mode->flags = wire->flags; - mode->type = wire->type; - - if (!name) - return; - - name_len = strlen(name); - if (name_len >= DRM_DISPLAY_MODE_LEN) - name_len = DRM_DISPLAY_MODE_LEN - 1; - memcpy(mode->name, name, name_len); -} - -static int redox_drm_fetch_resources_wire(int fd, - struct redox_drm_resources_wire *header, - uint32_t **connector_ids) -{ - void *response = NULL; - size_t response_size = 0; - size_t expected_size; - - if (redox_drm_exchange_alloc(fd, REDOX_DRM_IOCTL_MODE_GETRESOURCES, - NULL, 0, - &response, &response_size) != 0) { - return -1; - } - - if (response_size < sizeof(*header)) { - drmFree(response); - errno = EPROTO; - return -1; - } - - memcpy(header, response, sizeof(*header)); - expected_size = sizeof(*header) + - ((size_t)header->connector_count * sizeof(uint32_t)); - if (response_size < expected_size) { - drmFree(response); - errno = EPROTO; - return -1; - } - - *connector_ids = NULL; - if (header->connector_count != 0) { - *connector_ids = drmMalloc(header->connector_count * sizeof(uint32_t)); - if (!*connector_ids) { - drmFree(response); - errno = ENOMEM; - return -1; - } - memcpy(*connector_ids, (const uint8_t *)response + sizeof(*header), - header->connector_count * sizeof(uint32_t)); - } - - drmFree(response); - return 0; -} - -static int redox_drm_fetch_connector_blob(int fd, uint32_t connector_id, - void **response, - size_t *response_size) -{ - return redox_drm_exchange_alloc(fd, REDOX_DRM_IOCTL_MODE_GETCONNECTOR, - &connector_id, sizeof(connector_id), - response, response_size); -} - -static int redox_drm_parse_connector_blob(const void *blob, size_t blob_size, - struct redox_drm_connector_wire *header, - struct drm_mode_modeinfo *modes, - uint32_t modes_capacity, - uint32_t *min_width, - uint32_t *max_width, - uint32_t *min_height, - uint32_t *max_height) -{ - const uint8_t *bytes = blob; - size_t offset = sizeof(*header); - uint32_t i; - - if (blob_size < sizeof(*header)) { - errno = EPROTO; - return -1; - } - - memcpy(header, bytes, sizeof(*header)); - for (i = 0; i < header->mode_count; ++i) { - struct redox_drm_mode_wire mode_wire; - const char *name; - size_t name_len; - uint32_t width; - uint32_t height; - - if (blob_size - offset < sizeof(mode_wire)) { - errno = EPROTO; - return -1; - } - - memcpy(&mode_wire, bytes + offset, sizeof(mode_wire)); - offset += sizeof(mode_wire); - name = (const char *)bytes + offset; - name_len = strnlen(name, blob_size - offset); - if (offset + name_len >= blob_size) { - errno = EPROTO; - return -1; - } - - if (modes && i < modes_capacity) - redox_drm_modeinfo_from_wire(&modes[i], &mode_wire, name); - - width = mode_wire.hdisplay; - height = mode_wire.vdisplay; - if (min_width && (*min_width == 0 || width < *min_width)) - *min_width = width; - if (max_width && width > *max_width) - *max_width = width; - if (min_height && (*min_height == 0 || height < *min_height)) - *min_height = height; - if (max_height && height > *max_height) - *max_height = height; - - offset += name_len + 1; - } - - return 0; -} - -struct redox_drm_get_plane_resources_wire { - uint64_t plane_id_ptr; - uint32_t count_planes; -}; - -struct redox_drm_get_plane_wire { - uint32_t plane_id; - uint32_t crtc_id; - uint32_t fb_id; - uint32_t possible_crtcs; - uint32_t gamma_size; - uint32_t count_format_types; - uint64_t format_type_ptr; -}; - -struct redox_drm_mode_obj_get_properties_wire { - uint64_t props_ptr; - uint64_t prop_values_ptr; - uint32_t count_props; - uint32_t obj_id; - uint32_t obj_type; -}; - -static uint32_t redox_drm_connector_type_id(int fd, uint32_t connector_id, - uint32_t connector_type) -{ - struct redox_drm_resources_wire resources; - uint32_t *connector_ids = NULL; - uint32_t ordinal = 0; - uint32_t i; - - if (redox_drm_fetch_resources_wire(fd, &resources, &connector_ids) != 0) - return 0; - - for (i = 0; i < resources.connector_count; ++i) { - struct redox_drm_connector_wire header; - void *response = NULL; - size_t response_size = 0; - int ret; - - ret = redox_drm_fetch_connector_blob(fd, connector_ids[i], - &response, &response_size); - if (ret != 0) - break; - - ret = redox_drm_parse_connector_blob(response, response_size, - &header, NULL, 0, - NULL, NULL, NULL, NULL); - drmFree(response); - if (ret != 0) - break; - - if (header.connector_type == connector_type) - ++ordinal; - if (header.connector_id == connector_id) - break; - } - - drmFree(connector_ids); - return ordinal; -} - -static int redox_drm_ioctl_getplaneresources(int fd, - struct drm_mode_get_plane_res *resources) -{ - struct redox_drm_get_plane_resources_wire response; - void *response_blob = NULL; - size_t response_size = 0; - size_t expected_size; - uint32_t input_plane_count; - uint32_t copy_count; - - if (!resources) { - errno = EINVAL; - return -1; - } - - input_plane_count = resources->count_planes; - if (redox_drm_exchange_alloc(fd, REDOX_DRM_IOCTL_MODE_GETPLANERESOURCES, - resources, sizeof(*resources), - &response_blob, &response_size) != 0) { - return -1; - } - - if (response_size < sizeof(response)) { - drmFree(response_blob); - errno = EPROTO; - return -1; - } - - memcpy(&response, response_blob, sizeof(response)); - resources->count_planes = response.count_planes; - copy_count = input_plane_count < response.count_planes ? - input_plane_count : response.count_planes; - if (copy_count != 0) { - expected_size = sizeof(response) + - ((size_t)copy_count * sizeof(uint32_t)); - if (response_size < expected_size) { - drmFree(response_blob); - errno = EPROTO; - return -1; - } - - if (resources->plane_id_ptr) { - memcpy((void *)(uintptr_t)resources->plane_id_ptr, - (const uint8_t *)response_blob + sizeof(response), - copy_count * sizeof(uint32_t)); - } - } - - drmFree(response_blob); - return 0; -} - -static int redox_drm_ioctl_getplane(int fd, struct drm_mode_get_plane *plane) -{ - struct redox_drm_get_plane_wire response; - void *response_blob = NULL; - size_t response_size = 0; - size_t expected_size; - uint32_t input_format_count; - uint32_t copy_count; - - if (!plane) { - errno = EINVAL; - return -1; - } - - input_format_count = plane->count_format_types; - if (redox_drm_exchange_alloc(fd, REDOX_DRM_IOCTL_MODE_GETPLANE, - plane, sizeof(*plane), - &response_blob, &response_size) != 0) { - return -1; - } - - if (response_size < sizeof(response)) { - drmFree(response_blob); - errno = EPROTO; - return -1; - } - - memcpy(&response, response_blob, sizeof(response)); - plane->plane_id = response.plane_id; - plane->crtc_id = response.crtc_id; - plane->fb_id = response.fb_id; - plane->possible_crtcs = response.possible_crtcs; - plane->gamma_size = response.gamma_size; - plane->count_format_types = response.count_format_types; - - copy_count = input_format_count < response.count_format_types ? - input_format_count : response.count_format_types; - if (copy_count != 0) { - expected_size = sizeof(response) + - ((size_t)copy_count * sizeof(uint32_t)); - if (response_size < expected_size) { - drmFree(response_blob); - errno = EPROTO; - return -1; - } - - if (plane->format_type_ptr) { - memcpy((void *)(uintptr_t)plane->format_type_ptr, - (const uint8_t *)response_blob + sizeof(response), - copy_count * sizeof(uint32_t)); - } - } - - drmFree(response_blob); - return 0; -} - -static int redox_drm_ioctl_obj_getproperties( - int fd, - struct drm_mode_obj_get_properties *properties) -{ - struct redox_drm_mode_obj_get_properties_wire response; - void *response_blob = NULL; - size_t response_size = 0; - size_t expected_size; - uint32_t input_count; - uint32_t copy_count; - - if (!properties) { - errno = EINVAL; - return -1; - } - - input_count = properties->count_props; - if (redox_drm_exchange_alloc(fd, REDOX_DRM_IOCTL_MODE_OBJ_GETPROPERTIES, - properties, sizeof(*properties), - &response_blob, &response_size) != 0) { - return -1; - } - - if (response_size < sizeof(response)) { - drmFree(response_blob); - errno = EPROTO; - return -1; - } - - memcpy(&response, response_blob, sizeof(response)); - properties->count_props = response.count_props; - properties->obj_id = response.obj_id; - properties->obj_type = response.obj_type; - - copy_count = input_count < response.count_props ? - input_count : response.count_props; - if (copy_count != 0) { - expected_size = sizeof(response) + - ((size_t)copy_count * sizeof(uint32_t)) + - ((size_t)copy_count * sizeof(uint64_t)); - if (response_size < expected_size) { - drmFree(response_blob); - errno = EPROTO; - return -1; - } - - if (properties->props_ptr) { - memcpy((void *)(uintptr_t)properties->props_ptr, - (const uint8_t *)response_blob + sizeof(response), - copy_count * sizeof(uint32_t)); - } - - if (properties->prop_values_ptr) { - memcpy((void *)(uintptr_t)properties->prop_values_ptr, - (const uint8_t *)response_blob + sizeof(response) + - ((size_t)copy_count * sizeof(uint32_t)), - copy_count * sizeof(uint64_t)); - } - } - - drmFree(response_blob); - return 0; -} - -static int redox_drm_ioctl_getproperty( - int fd, - struct drm_mode_get_property *prop) -{ - struct drm_mode_get_property response_wire; - void *response_blob = NULL; - size_t response_size = 0; - size_t expected_size; - uint32_t input_count_values; - uint32_t input_count_enums; - uint32_t copy_values; - uint32_t copy_enums; - size_t values_data; - - if (!prop) { - errno = EINVAL; - return -1; - } - - input_count_values = prop->count_values; - input_count_enums = prop->count_enum_blobs; - - if (redox_drm_exchange_alloc(fd, REDOX_DRM_IOCTL_MODE_GETPROPERTY, - prop, sizeof(*prop), - &response_blob, &response_size) != 0) { - return -1; - } - - if (response_size < sizeof(response_wire)) { - drmFree(response_blob); - errno = EPROTO; - return -1; - } - - memcpy(&response_wire, response_blob, sizeof(response_wire)); - prop->prop_id = response_wire.prop_id; - prop->flags = response_wire.flags; - memcpy(prop->name, response_wire.name, DRM_PROP_NAME_LEN); - prop->count_values = response_wire.count_values; - prop->count_enum_blobs = response_wire.count_enum_blobs; - - copy_values = input_count_values < response_wire.count_values ? - input_count_values : response_wire.count_values; - if (copy_values != 0 && prop->values_ptr) { - expected_size = sizeof(response_wire) + - ((size_t)copy_values * sizeof(uint64_t)); - if (response_size < expected_size) { - drmFree(response_blob); - errno = EPROTO; - return -1; - } - - memcpy((void *)(uintptr_t)prop->values_ptr, - (const uint8_t *)response_blob + sizeof(response_wire), - copy_values * sizeof(uint64_t)); - } - - copy_enums = input_count_enums < response_wire.count_enum_blobs ? - input_count_enums : response_wire.count_enum_blobs; - if (copy_enums != 0 && prop->enum_blob_ptr) { - values_data = (size_t)response_wire.count_values * sizeof(uint64_t); - expected_size = sizeof(response_wire) + values_data + - ((size_t)copy_enums * sizeof(struct drm_mode_property_enum)); - if (response_size < expected_size) { - drmFree(response_blob); - errno = EPROTO; - return -1; - } - - memcpy((void *)(uintptr_t)prop->enum_blob_ptr, - (const uint8_t *)response_blob + sizeof(response_wire) + values_data, - copy_enums * sizeof(struct drm_mode_property_enum)); - } - - drmFree(response_blob); - return 0; -} - -static int redox_drm_ioctl_version(int fd, struct drm_version *version) -{ - struct redox_drm_version_wire response; - size_t driver_name_len; - size_t name_capacity; - - if (!version) { - errno = EINVAL; - return -1; - } - - name_capacity = version->name_len; - if (redox_drm_exchange(fd, REDOX_DRM_IOCTL_VERSION, - NULL, 0, - &response, sizeof(response), - NULL) != 0) { - return -1; - } - - driver_name_len = strnlen(response.name, sizeof(response.name)); - version->version_major = response.major; - version->version_minor = response.minor; - version->version_patchlevel = response.patch; - version->name_len = driver_name_len; - version->date_len = 0; - version->desc_len = 0; - - if (version->name && name_capacity != 0) { - size_t copy_len = driver_name_len < name_capacity ? - driver_name_len : name_capacity; - memcpy(version->name, response.name, copy_len); - } - - return 0; -} - -static int redox_drm_ioctl_getresources(int fd, struct drm_mode_card_res *resources) -{ - struct redox_drm_resources_wire response; - uint32_t *connector_ids = NULL; - uint32_t input_crtc_count; - uint32_t input_connector_count; - uint32_t input_encoder_count; - uint32_t i; - int ret = -1; - - if (!resources) { - errno = EINVAL; - return -1; - } - - input_crtc_count = resources->count_crtcs; - input_connector_count = resources->count_connectors; - input_encoder_count = resources->count_encoders; - - if (redox_drm_fetch_resources_wire(fd, &response, &connector_ids) != 0) - return -1; - - resources->count_fbs = 0; - resources->count_crtcs = response.crtc_count; - resources->count_connectors = response.connector_count; - resources->count_encoders = response.encoder_count; - resources->min_width = 0; - resources->max_width = 0; - resources->min_height = 0; - resources->max_height = 0; - - if (resources->connector_id_ptr && - input_connector_count >= response.connector_count) { - memcpy((void *)(uintptr_t)resources->connector_id_ptr, connector_ids, - response.connector_count * sizeof(uint32_t)); - } - - if (resources->crtc_id_ptr && input_crtc_count >= response.crtc_count) { - uint32_t *crtcs = (uint32_t *)(uintptr_t)resources->crtc_id_ptr; - for (i = 0; i < response.crtc_count; ++i) - crtcs[i] = i + 1; - } - - for (i = 0; i < response.connector_count; ++i) { - struct redox_drm_connector_wire header; - void *connector_blob = NULL; - size_t connector_blob_size = 0; - - if (redox_drm_fetch_connector_blob(fd, connector_ids[i], - &connector_blob, - &connector_blob_size) != 0) { - goto out; - } - - if (redox_drm_parse_connector_blob(connector_blob, connector_blob_size, - &header, NULL, 0, - &resources->min_width, - &resources->max_width, - &resources->min_height, - &resources->max_height) != 0) { - drmFree(connector_blob); - goto out; - } - - if (resources->encoder_id_ptr && - input_encoder_count >= response.encoder_count && - i < response.encoder_count) { - ((uint32_t *)(uintptr_t)resources->encoder_id_ptr)[i] = - header.encoder_id; - } - - drmFree(connector_blob); - } - - if (resources->encoder_id_ptr && input_encoder_count >= response.encoder_count) { - uint32_t *encoders = (uint32_t *)(uintptr_t)resources->encoder_id_ptr; - for (i = response.connector_count; i < response.encoder_count; ++i) - encoders[i] = 0; - } - - ret = 0; - -out: - drmFree(connector_ids); - return ret; -} - -static int redox_drm_ioctl_getcrtc(int fd, struct drm_mode_crtc *crtc) -{ - struct redox_drm_get_crtc_wire request; - struct redox_drm_get_crtc_wire response; - - if (!crtc) { - errno = EINVAL; - return -1; - } - - memclear(request); - request.crtc_id = crtc->crtc_id; - if (redox_drm_exchange(fd, REDOX_DRM_IOCTL_MODE_GETCRTC, - &request, sizeof(request), - &response, sizeof(response), - NULL) != 0) { - return -1; - } - - crtc->count_connectors = 0; - crtc->crtc_id = response.crtc_id; - crtc->fb_id = response.fb_id; - crtc->x = response.x; - crtc->y = response.y; - crtc->gamma_size = 0; - crtc->mode_valid = response.mode_valid; - if (crtc->mode_valid) { - char mode_name[DRM_DISPLAY_MODE_LEN]; - - snprintf(mode_name, sizeof(mode_name), "%ux%u@%u", - response.mode.hdisplay, - response.mode.vdisplay, - response.mode.vrefresh); - redox_drm_modeinfo_from_wire(&crtc->mode, &response.mode, mode_name); - } else { - memclear(crtc->mode); - } - - return 0; -} - -static int redox_drm_ioctl_getconnector(int fd, - struct drm_mode_get_connector *connector) -{ - struct redox_drm_connector_wire header; - void *response = NULL; - size_t response_size = 0; - uint32_t input_mode_count; - uint32_t input_encoder_count; - - if (!connector) { - errno = EINVAL; - return -1; - } - - input_mode_count = connector->count_modes; - input_encoder_count = connector->count_encoders; - if (redox_drm_fetch_connector_blob(fd, connector->connector_id, - &response, &response_size) != 0) { - return -1; - } - - if (redox_drm_parse_connector_blob(response, response_size, - &header, - NULL, 0, - NULL, NULL, NULL, NULL) != 0) { - drmFree(response); - return -1; - } - - if (connector->modes_ptr && input_mode_count >= header.mode_count && - redox_drm_parse_connector_blob(response, response_size, - &header, - (struct drm_mode_modeinfo *)(uintptr_t)connector->modes_ptr, - header.mode_count, - NULL, NULL, NULL, NULL) != 0) { - drmFree(response); - return -1; - } - - connector->count_modes = header.mode_count; - connector->count_props = 0; - connector->count_encoders = header.encoder_id ? 1U : 0U; - connector->encoder_id = header.encoder_id; - connector->connector_id = header.connector_id; - connector->connector_type = header.connector_type; - connector->connector_type_id = redox_drm_connector_type_id(fd, - header.connector_id, - header.connector_type); - connector->connection = header.connection; - connector->mm_width = header.mm_width; - connector->mm_height = header.mm_height; - connector->subpixel = 0; - - if (connector->count_encoders != 0 && connector->encoders_ptr && - input_encoder_count >= connector->count_encoders) { - ((uint32_t *)(uintptr_t)connector->encoders_ptr)[0] = header.encoder_id; - } - - drmFree(response); - return 0; -} - static size_t redox_drm_expected_response_size(unsigned long linux_nr, size_t arg_size) { switch (linux_nr) { - case 0x00: - return sizeof(struct redox_drm_version_wire); - case 0x02: + case 0x00: /* VERSION */ case 0x0C: - case 0x11: + 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 0xA9: - case 0xAA: - case 0xAC: - case 0xB8: - case 0xB9: case 0xB3: - case 0xC6: - case 0xC7: - case 0xBA: return arg_size; - case 0x1e: - case 0x1f: - return 0; - case 0xA0: - return sizeof(struct redox_drm_resources_wire); - case 0xA1: - return sizeof(struct redox_drm_get_crtc_wire); - case 0xA7: - return sizeof(struct redox_drm_connector_wire); - case 0x60: - return sizeof(struct redox_drm_pci_info_wire); 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 capped_arg_size = arg_size > 256 ? 256 : arg_size; - const size_t expected_response_size = redox_drm_expected_response_size(linux_nr, arg_size); - - fprintf(stderr, "[LIBDRM] ioctl nr=0x%02lX request_code=0x%04lX arg_size=%zu\n", - linux_nr, request_code, arg_size); - fflush(stderr); +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) { - fprintf(stderr, "[LIBDRM] UNHANDLED ioctl nr=0x%02lX → ENOTTY\n", linux_nr); - fflush(stderr); - errno = ENOTTY; - return -1; - } - - if (arg) { - switch (linux_nr) { - case 0x00: - return redox_drm_ioctl_version(fd, arg); - case 0xA0: - return redox_drm_ioctl_getresources(fd, arg); - case 0xA1: - return redox_drm_ioctl_getcrtc(fd, arg); - case 0xA7: - return redox_drm_ioctl_getconnector(fd, arg); - case 0xB5: - return redox_drm_ioctl_getplaneresources(fd, arg); - case 0xB6: - return redox_drm_ioctl_getplane(fd, arg); - case 0xB9: - return redox_drm_ioctl_obj_getproperties(fd, arg); - case 0xAA: - return redox_drm_ioctl_getproperty(fd, arg); - default: - break; - } + if (request_code == 0) { + errno = ENOTTY; + return -1; } - - if (redox_drm_exchange(fd, request_code, - arg, arg ? capped_arg_size : 0, - expected_response_size ? arg : NULL, - expected_response_size, - NULL) != 0) { - return -1; - } - - return 0; - } + + 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 /** @@ -2466,11 +1772,6 @@ drm_public drmVersionPtr drmGetVersion(int fd) retval->version_major = version.major; retval->version_minor = version.minor; retval->version_patchlevel = version.patch; - if (version.name[0] != '\0') { - size_t name_len = strnlen(version.name, sizeof(version.name)); - retval->name_len = name_len; - retval->name = strndup(version.name, name_len); - } return retval; #else drmVersionPtr retval; @@ -4903,6 +4204,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; @@ -5112,6 +4428,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; @@ -5865,55 +5198,63 @@ drm_public int drmGetNodeTypeFromDevId(dev_t devid) drm_public int drmGetDevice2(int fd, uint32_t flags, drmDevicePtr *device) { #if defined(__redox__) - struct stat sbuf; - drmDevicePtr dev; - char *addr; + 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; - if (fd == -1 || device == NULL) - return -EINVAL; + pret = redox_drm_exchange(fd, REDOX_DRM_IOCTL_GET_PCI_INFO, NULL, 0, + pbuf, sizeof(pbuf), &prsize); + if (pret != 0 || prsize < 17) + return -EIO; - if (fstat(fd, &sbuf)) - return -errno; + 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]; - if (!S_ISCHR(sbuf.st_mode)) - return -EINVAL; - - const char *node = "/scheme/drm/card0"; - - dev = drmDeviceAlloc(DRM_NODE_PRIMARY, node, - sizeof(drmPciBusInfo), - sizeof(drmPciDeviceInfo), &addr); - if (!dev) + 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; - dev->bustype = DRM_BUS_PCI; + 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); - struct redox_drm_pci_info_wire pci_info; - size_t resp_size = 0; - int ret = redox_drm_exchange(fd, REDOX_DRM_IOCTL_GET_PCI_INFO, - NULL, 0, - &pci_info, sizeof(pci_info), &resp_size); + 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; - if (ret == 0 && resp_size >= 20) { - dev->businfo.pci = (drmPciBusInfoPtr)addr; - dev->businfo.pci->domain = pci_info.domain; - dev->businfo.pci->bus = pci_info.bus; - dev->businfo.pci->dev = pci_info.dev; - dev->businfo.pci->func = pci_info.func; + 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; - addr += sizeof(drmPciBusInfo); - dev->deviceinfo.pci = (drmPciDeviceInfoPtr)addr; - dev->deviceinfo.pci->vendor_id = pci_info.vendor_id; - dev->deviceinfo.pci->device_id = pci_info.device_id; - dev->deviceinfo.pci->subvendor_id = pci_info.subvendor_id; - dev->deviceinfo.pci->subdevice_id = pci_info.subdevice_id; - dev->deviceinfo.pci->revision_id = pci_info.revision_id; - } else { - free(dev); - return -ENODEV; - } - - *device = dev; + *device = devp; return 0; #else struct stat sbuf; diff --git a/local/recipes/libs/libdrm/source/xf86drm_redox.h b/local/recipes/libs/libdrm/source/xf86drm_redox.h index 3b6c2a6a25..c1abe82565 100644 --- a/local/recipes/libs/libdrm/source/xf86drm_redox.h +++ b/local/recipes/libs/libdrm/source/xf86drm_redox.h @@ -26,39 +26,21 @@ #define REDOX_DRM_IOCTL_SET_CLIENT_CAP (REDOX_DRM_IOCTL_BASE + 24) #define REDOX_DRM_IOCTL_VERSION (REDOX_DRM_IOCTL_BASE + 25) #define REDOX_DRM_IOCTL_GEM_CLOSE (REDOX_DRM_IOCTL_BASE + 27) -#define REDOX_DRM_IOCTL_GEM_FLINK (REDOX_DRM_IOCTL_BASE + 10) -#define REDOX_DRM_IOCTL_GEM_OPEN (REDOX_DRM_IOCTL_BASE + 11) #define REDOX_DRM_IOCTL_PRIME_HANDLE_TO_FD (REDOX_DRM_IOCTL_BASE + 29) #define REDOX_DRM_IOCTL_PRIME_FD_TO_HANDLE (REDOX_DRM_IOCTL_BASE + 30) -#define REDOX_DRM_IOCTL_GET_MAGIC (REDOX_DRM_IOCTL_BASE + 33) -#define REDOX_DRM_IOCTL_AUTH_MAGIC (REDOX_DRM_IOCTL_BASE + 34) -#define REDOX_DRM_IOCTL_SET_MASTER (REDOX_DRM_IOCTL_BASE + 35) -#define REDOX_DRM_IOCTL_DROP_MASTER (REDOX_DRM_IOCTL_BASE + 36) -#define REDOX_DRM_IOCTL_MODE_OBJ_GETPROPERTIES (REDOX_DRM_IOCTL_BASE + 0x50) -#define REDOX_DRM_IOCTL_MODE_GETPROPERTY (REDOX_DRM_IOCTL_BASE + 0x51) -#define REDOX_DRM_IOCTL_MODE_GETPROPBLOB (REDOX_DRM_IOCTL_BASE + 0x52) -#define REDOX_DRM_IOCTL_MODE_CREATE_LEASE (REDOX_DRM_IOCTL_BASE + 0x53) -#define REDOX_DRM_IOCTL_MODE_LIST_LESSEES (REDOX_DRM_IOCTL_BASE + 0x54) -#define REDOX_DRM_IOCTL_MODE_OBJ_SETPROPERTY (REDOX_DRM_IOCTL_BASE + 0x55) -#define REDOX_DRM_IOCTL_MODE_GETPLANERESOURCES (REDOX_DRM_IOCTL_BASE + 0x56) -#define REDOX_DRM_IOCTL_MODE_GETPLANE (REDOX_DRM_IOCTL_BASE + 0x57) -#define REDOX_DRM_IOCTL_MODE_SETPLANE (REDOX_DRM_IOCTL_BASE + 0x58) -#define REDOX_DRM_IOCTL_MODE_ADDFB2 (REDOX_DRM_IOCTL_BASE + 0x59) -#define REDOX_DRM_IOCTL_GET_PCI_INFO (REDOX_DRM_IOCTL_BASE + 0x60) +#define REDOX_DRM_IOCTL_VIRTGPU_MAP (REDOX_DRM_IOCTL_BASE + 31) +#define REDOX_DRM_IOCTL_VIRTGPU_EXECBUFFER (REDOX_DRM_IOCTL_BASE + 32) +#define REDOX_DRM_IOCTL_VIRTGPU_GETPARAM (REDOX_DRM_IOCTL_BASE + 33) +#define REDOX_DRM_IOCTL_VIRTGPU_RESOURCE_CREATE (REDOX_DRM_IOCTL_BASE + 34) +#define REDOX_DRM_IOCTL_VIRTGPU_RESOURCE_INFO (REDOX_DRM_IOCTL_BASE + 35) +#define REDOX_DRM_IOCTL_VIRTGPU_TRANSFER_FROM_HOST (REDOX_DRM_IOCTL_BASE + 36) +#define REDOX_DRM_IOCTL_VIRTGPU_TRANSFER_TO_HOST (REDOX_DRM_IOCTL_BASE + 37) +#define REDOX_DRM_IOCTL_VIRTGPU_WAIT (REDOX_DRM_IOCTL_BASE + 38) +#define REDOX_DRM_IOCTL_VIRTGPU_GET_CAPS (REDOX_DRM_IOCTL_BASE + 39) +#define REDOX_DRM_IOCTL_VIRTGPU_RESOURCE_CREATE_BLOB (REDOX_DRM_IOCTL_BASE + 40) +#define REDOX_DRM_IOCTL_VIRTGPU_CONTEXT_INIT (REDOX_DRM_IOCTL_BASE + 41) -struct redox_drm_pci_info_wire { - uint16_t vendor_id; - uint16_t device_id; - uint16_t subvendor_id; - uint16_t subdevice_id; - uint8_t revision_id; - uint8_t pad[3]; - uint16_t domain; - uint8_t bus; - uint8_t dev; - uint8_t func; - uint8_t pad2[3]; -}; +#define REDOX_DRM_IOCTL_GET_PCI_INFO (REDOX_DRM_IOCTL_BASE + 0x60) struct redox_drm_resources_wire { uint32_t connector_count; @@ -156,7 +138,6 @@ struct redox_drm_version_wire { int32_t major; int32_t minor; int32_t patch; - char name[64]; }; struct redox_drm_prime_handle_to_fd_wire {