1d722e3fbSopenharmony_ci/** 2d722e3fbSopenharmony_ci * \file xf86drm.c 3d722e3fbSopenharmony_ci * User-level interface to DRM device 4d722e3fbSopenharmony_ci * 5d722e3fbSopenharmony_ci * \author Rickard E. (Rik) Faith <faith@valinux.com> 6d722e3fbSopenharmony_ci * \author Kevin E. Martin <martin@valinux.com> 7d722e3fbSopenharmony_ci */ 8d722e3fbSopenharmony_ci 9d722e3fbSopenharmony_ci/* 10d722e3fbSopenharmony_ci * Copyright 1999 Precision Insight, Inc., Cedar Park, Texas. 11d722e3fbSopenharmony_ci * Copyright 2000 VA Linux Systems, Inc., Sunnyvale, California. 12d722e3fbSopenharmony_ci * All Rights Reserved. 13d722e3fbSopenharmony_ci * 14d722e3fbSopenharmony_ci * Permission is hereby granted, free of charge, to any person obtaining a 15d722e3fbSopenharmony_ci * copy of this software and associated documentation files (the "Software"), 16d722e3fbSopenharmony_ci * to deal in the Software without restriction, including without limitation 17d722e3fbSopenharmony_ci * the rights to use, copy, modify, merge, publish, distribute, sublicense, 18d722e3fbSopenharmony_ci * and/or sell copies of the Software, and to permit persons to whom the 19d722e3fbSopenharmony_ci * Software is furnished to do so, subject to the following conditions: 20d722e3fbSopenharmony_ci * 21d722e3fbSopenharmony_ci * The above copyright notice and this permission notice (including the next 22d722e3fbSopenharmony_ci * paragraph) shall be included in all copies or substantial portions of the 23d722e3fbSopenharmony_ci * Software. 24d722e3fbSopenharmony_ci * 25d722e3fbSopenharmony_ci * THE SOFTWARE IS PROVIDED "AS IS", WITHOUT WARRANTY OF ANY KIND, EXPRESS OR 26d722e3fbSopenharmony_ci * IMPLIED, INCLUDING BUT NOT LIMITED TO THE WARRANTIES OF MERCHANTABILITY, 27d722e3fbSopenharmony_ci * FITNESS FOR A PARTICULAR PURPOSE AND NONINFRINGEMENT. IN NO EVENT SHALL 28d722e3fbSopenharmony_ci * PRECISION INSIGHT AND/OR ITS SUPPLIERS BE LIABLE FOR ANY CLAIM, DAMAGES OR 29d722e3fbSopenharmony_ci * OTHER LIABILITY, WHETHER IN AN ACTION OF CONTRACT, TORT OR OTHERWISE, 30d722e3fbSopenharmony_ci * ARISING FROM, OUT OF OR IN CONNECTION WITH THE SOFTWARE OR THE USE OR OTHER 31d722e3fbSopenharmony_ci * DEALINGS IN THE SOFTWARE. 32d722e3fbSopenharmony_ci */ 33d722e3fbSopenharmony_ci 34d722e3fbSopenharmony_ci#include <stdio.h> 35d722e3fbSopenharmony_ci#include <stdlib.h> 36d722e3fbSopenharmony_ci#include <stdbool.h> 37d722e3fbSopenharmony_ci#include <unistd.h> 38d722e3fbSopenharmony_ci#include <string.h> 39d722e3fbSopenharmony_ci#include <strings.h> 40d722e3fbSopenharmony_ci#include <ctype.h> 41d722e3fbSopenharmony_ci#include <dirent.h> 42d722e3fbSopenharmony_ci#include <stddef.h> 43d722e3fbSopenharmony_ci#include <fcntl.h> 44d722e3fbSopenharmony_ci#include <errno.h> 45d722e3fbSopenharmony_ci#include <limits.h> 46d722e3fbSopenharmony_ci#include <signal.h> 47d722e3fbSopenharmony_ci#include <time.h> 48d722e3fbSopenharmony_ci#include <sys/types.h> 49d722e3fbSopenharmony_ci#include <sys/stat.h> 50d722e3fbSopenharmony_ci#define stat_t struct stat 51d722e3fbSopenharmony_ci#include <sys/ioctl.h> 52d722e3fbSopenharmony_ci#include <sys/time.h> 53d722e3fbSopenharmony_ci#include <stdarg.h> 54d722e3fbSopenharmony_ci#ifdef MAJOR_IN_MKDEV 55d722e3fbSopenharmony_ci#include <sys/mkdev.h> 56d722e3fbSopenharmony_ci#endif 57d722e3fbSopenharmony_ci#ifdef MAJOR_IN_SYSMACROS 58d722e3fbSopenharmony_ci#include <sys/sysmacros.h> 59d722e3fbSopenharmony_ci#endif 60d722e3fbSopenharmony_ci#if HAVE_SYS_SYSCTL_H 61d722e3fbSopenharmony_ci#include <sys/sysctl.h> 62d722e3fbSopenharmony_ci#endif 63d722e3fbSopenharmony_ci#include <math.h> 64d722e3fbSopenharmony_ci#include <inttypes.h> 65d722e3fbSopenharmony_ci 66d722e3fbSopenharmony_ci#if defined(__FreeBSD__) 67d722e3fbSopenharmony_ci#include <sys/param.h> 68d722e3fbSopenharmony_ci#include <sys/pciio.h> 69d722e3fbSopenharmony_ci#endif 70d722e3fbSopenharmony_ci 71d722e3fbSopenharmony_ci#define ARRAY_SIZE(a) (sizeof(a) / sizeof((a)[0])) 72d722e3fbSopenharmony_ci 73d722e3fbSopenharmony_ci/* Not all systems have MAP_FAILED defined */ 74d722e3fbSopenharmony_ci#ifndef MAP_FAILED 75d722e3fbSopenharmony_ci#define MAP_FAILED ((void *)-1) 76d722e3fbSopenharmony_ci#endif 77d722e3fbSopenharmony_ci 78d722e3fbSopenharmony_ci#include "xf86drm.h" 79d722e3fbSopenharmony_ci#include "libdrm_macros.h" 80d722e3fbSopenharmony_ci#include "drm_fourcc.h" 81d722e3fbSopenharmony_ci 82d722e3fbSopenharmony_ci#include "util_math.h" 83d722e3fbSopenharmony_ci 84d722e3fbSopenharmony_ci#ifdef __DragonFly__ 85d722e3fbSopenharmony_ci#define DRM_MAJOR 145 86d722e3fbSopenharmony_ci#endif 87d722e3fbSopenharmony_ci 88d722e3fbSopenharmony_ci#ifdef __NetBSD__ 89d722e3fbSopenharmony_ci#define DRM_MAJOR 34 90d722e3fbSopenharmony_ci#endif 91d722e3fbSopenharmony_ci 92d722e3fbSopenharmony_ci#ifdef __OpenBSD__ 93d722e3fbSopenharmony_ci#ifdef __i386__ 94d722e3fbSopenharmony_ci#define DRM_MAJOR 88 95d722e3fbSopenharmony_ci#else 96d722e3fbSopenharmony_ci#define DRM_MAJOR 87 97d722e3fbSopenharmony_ci#endif 98d722e3fbSopenharmony_ci#endif /* __OpenBSD__ */ 99d722e3fbSopenharmony_ci 100d722e3fbSopenharmony_ci#ifndef DRM_MAJOR 101d722e3fbSopenharmony_ci#define DRM_MAJOR 226 /* Linux */ 102d722e3fbSopenharmony_ci#endif 103d722e3fbSopenharmony_ci 104d722e3fbSopenharmony_ci#if defined(__OpenBSD__) || defined(__DragonFly__) 105d722e3fbSopenharmony_cistruct drm_pciinfo { 106d722e3fbSopenharmony_ci uint16_t domain; 107d722e3fbSopenharmony_ci uint8_t bus; 108d722e3fbSopenharmony_ci uint8_t dev; 109d722e3fbSopenharmony_ci uint8_t func; 110d722e3fbSopenharmony_ci uint16_t vendor_id; 111d722e3fbSopenharmony_ci uint16_t device_id; 112d722e3fbSopenharmony_ci uint16_t subvendor_id; 113d722e3fbSopenharmony_ci uint16_t subdevice_id; 114d722e3fbSopenharmony_ci uint8_t revision_id; 115d722e3fbSopenharmony_ci}; 116d722e3fbSopenharmony_ci 117d722e3fbSopenharmony_ci#define DRM_IOCTL_GET_PCIINFO DRM_IOR(0x15, struct drm_pciinfo) 118d722e3fbSopenharmony_ci#endif 119d722e3fbSopenharmony_ci 120d722e3fbSopenharmony_ci#define DRM_MSG_VERBOSITY 3 121d722e3fbSopenharmony_ci 122d722e3fbSopenharmony_ci#define memclear(s) memset(&s, 0, sizeof(s)) 123d722e3fbSopenharmony_ci 124d722e3fbSopenharmony_cistatic drmServerInfoPtr drm_server_info; 125d722e3fbSopenharmony_ci 126d722e3fbSopenharmony_cistatic bool drmNodeIsDRM(int maj, int min); 127d722e3fbSopenharmony_cistatic char *drmGetMinorNameForFD(int fd, int type); 128d722e3fbSopenharmony_ci 129d722e3fbSopenharmony_ci#define DRM_MODIFIER(v, f, f_name) \ 130d722e3fbSopenharmony_ci .modifier = DRM_FORMAT_MOD_##v ## _ ##f, \ 131d722e3fbSopenharmony_ci .modifier_name = #f_name 132d722e3fbSopenharmony_ci 133d722e3fbSopenharmony_ci#define DRM_MODIFIER_INVALID(v, f_name) \ 134d722e3fbSopenharmony_ci .modifier = DRM_FORMAT_MOD_INVALID, .modifier_name = #f_name 135d722e3fbSopenharmony_ci 136d722e3fbSopenharmony_ci#define DRM_MODIFIER_LINEAR(v, f_name) \ 137d722e3fbSopenharmony_ci .modifier = DRM_FORMAT_MOD_LINEAR, .modifier_name = #f_name 138d722e3fbSopenharmony_ci 139d722e3fbSopenharmony_ci/* Intel is abit special as the format doesn't follow other vendors naming 140d722e3fbSopenharmony_ci * scheme */ 141d722e3fbSopenharmony_ci#define DRM_MODIFIER_INTEL(f, f_name) \ 142d722e3fbSopenharmony_ci .modifier = I915_FORMAT_MOD_##f, .modifier_name = #f_name 143d722e3fbSopenharmony_ci 144d722e3fbSopenharmony_cistruct drmFormatModifierInfo { 145d722e3fbSopenharmony_ci uint64_t modifier; 146d722e3fbSopenharmony_ci const char *modifier_name; 147d722e3fbSopenharmony_ci}; 148d722e3fbSopenharmony_ci 149d722e3fbSopenharmony_cistruct drmFormatModifierVendorInfo { 150d722e3fbSopenharmony_ci uint8_t vendor; 151d722e3fbSopenharmony_ci const char *vendor_name; 152d722e3fbSopenharmony_ci}; 153d722e3fbSopenharmony_ci 154d722e3fbSopenharmony_ci#include "generated_static_table_fourcc.h" 155d722e3fbSopenharmony_ci 156d722e3fbSopenharmony_cistruct drmVendorInfo { 157d722e3fbSopenharmony_ci uint8_t vendor; 158d722e3fbSopenharmony_ci char *(*vendor_cb)(uint64_t modifier); 159d722e3fbSopenharmony_ci}; 160d722e3fbSopenharmony_ci 161d722e3fbSopenharmony_cistruct drmFormatVendorModifierInfo { 162d722e3fbSopenharmony_ci uint64_t modifier; 163d722e3fbSopenharmony_ci const char *modifier_name; 164d722e3fbSopenharmony_ci}; 165d722e3fbSopenharmony_ci 166d722e3fbSopenharmony_cistatic char * 167d722e3fbSopenharmony_cidrmGetFormatModifierNameFromArm(uint64_t modifier); 168d722e3fbSopenharmony_ci 169d722e3fbSopenharmony_cistatic char * 170d722e3fbSopenharmony_cidrmGetFormatModifierNameFromNvidia(uint64_t modifier); 171d722e3fbSopenharmony_ci 172d722e3fbSopenharmony_cistatic char * 173d722e3fbSopenharmony_cidrmGetFormatModifierNameFromAmd(uint64_t modifier); 174d722e3fbSopenharmony_ci 175d722e3fbSopenharmony_cistatic char * 176d722e3fbSopenharmony_cidrmGetFormatModifierNameFromAmlogic(uint64_t modifier); 177d722e3fbSopenharmony_ci 178d722e3fbSopenharmony_cistatic const struct drmVendorInfo modifier_format_vendor_table[] = { 179d722e3fbSopenharmony_ci { DRM_FORMAT_MOD_VENDOR_ARM, drmGetFormatModifierNameFromArm }, 180d722e3fbSopenharmony_ci { DRM_FORMAT_MOD_VENDOR_NVIDIA, drmGetFormatModifierNameFromNvidia }, 181d722e3fbSopenharmony_ci { DRM_FORMAT_MOD_VENDOR_AMD, drmGetFormatModifierNameFromAmd }, 182d722e3fbSopenharmony_ci { DRM_FORMAT_MOD_VENDOR_AMLOGIC, drmGetFormatModifierNameFromAmlogic }, 183d722e3fbSopenharmony_ci}; 184d722e3fbSopenharmony_ci 185d722e3fbSopenharmony_ci#ifndef AFBC_FORMAT_MOD_MODE_VALUE_MASK 186d722e3fbSopenharmony_ci#define AFBC_FORMAT_MOD_MODE_VALUE_MASK 0x000fffffffffffffULL 187d722e3fbSopenharmony_ci#endif 188d722e3fbSopenharmony_ci 189d722e3fbSopenharmony_cistatic const struct drmFormatVendorModifierInfo arm_mode_value_table[] = { 190d722e3fbSopenharmony_ci { AFBC_FORMAT_MOD_YTR, "YTR" }, 191d722e3fbSopenharmony_ci { AFBC_FORMAT_MOD_SPLIT, "SPLIT" }, 192d722e3fbSopenharmony_ci { AFBC_FORMAT_MOD_SPARSE, "SPARSE" }, 193d722e3fbSopenharmony_ci { AFBC_FORMAT_MOD_CBR, "CBR" }, 194d722e3fbSopenharmony_ci { AFBC_FORMAT_MOD_TILED, "TILED" }, 195d722e3fbSopenharmony_ci { AFBC_FORMAT_MOD_SC, "SC" }, 196d722e3fbSopenharmony_ci { AFBC_FORMAT_MOD_DB, "DB" }, 197d722e3fbSopenharmony_ci { AFBC_FORMAT_MOD_BCH, "BCH" }, 198d722e3fbSopenharmony_ci { AFBC_FORMAT_MOD_USM, "USM" }, 199d722e3fbSopenharmony_ci}; 200d722e3fbSopenharmony_ci 201d722e3fbSopenharmony_cistatic bool is_x_t_amd_gfx9_tile(uint64_t tile) 202d722e3fbSopenharmony_ci{ 203d722e3fbSopenharmony_ci switch (tile) { 204d722e3fbSopenharmony_ci case AMD_FMT_MOD_TILE_GFX9_64K_S_X: 205d722e3fbSopenharmony_ci case AMD_FMT_MOD_TILE_GFX9_64K_D_X: 206d722e3fbSopenharmony_ci case AMD_FMT_MOD_TILE_GFX9_64K_R_X: 207d722e3fbSopenharmony_ci return true; 208d722e3fbSopenharmony_ci } 209d722e3fbSopenharmony_ci 210d722e3fbSopenharmony_ci return false; 211d722e3fbSopenharmony_ci} 212d722e3fbSopenharmony_ci 213d722e3fbSopenharmony_cistatic bool 214d722e3fbSopenharmony_cidrmGetAfbcFormatModifierNameFromArm(uint64_t modifier, FILE *fp) 215d722e3fbSopenharmony_ci{ 216d722e3fbSopenharmony_ci uint64_t mode_value = modifier & AFBC_FORMAT_MOD_MODE_VALUE_MASK; 217d722e3fbSopenharmony_ci uint64_t block_size = mode_value & AFBC_FORMAT_MOD_BLOCK_SIZE_MASK; 218d722e3fbSopenharmony_ci 219d722e3fbSopenharmony_ci const char *block = NULL; 220d722e3fbSopenharmony_ci const char *mode = NULL; 221d722e3fbSopenharmony_ci bool did_print_mode = false; 222d722e3fbSopenharmony_ci 223d722e3fbSopenharmony_ci /* add block, can only have a (single) block */ 224d722e3fbSopenharmony_ci switch (block_size) { 225d722e3fbSopenharmony_ci case AFBC_FORMAT_MOD_BLOCK_SIZE_16x16: 226d722e3fbSopenharmony_ci block = "16x16"; 227d722e3fbSopenharmony_ci break; 228d722e3fbSopenharmony_ci case AFBC_FORMAT_MOD_BLOCK_SIZE_32x8: 229d722e3fbSopenharmony_ci block = "32x8"; 230d722e3fbSopenharmony_ci break; 231d722e3fbSopenharmony_ci case AFBC_FORMAT_MOD_BLOCK_SIZE_64x4: 232d722e3fbSopenharmony_ci block = "64x4"; 233d722e3fbSopenharmony_ci break; 234d722e3fbSopenharmony_ci case AFBC_FORMAT_MOD_BLOCK_SIZE_32x8_64x4: 235d722e3fbSopenharmony_ci block = "32x8_64x4"; 236d722e3fbSopenharmony_ci break; 237d722e3fbSopenharmony_ci } 238d722e3fbSopenharmony_ci 239d722e3fbSopenharmony_ci if (!block) { 240d722e3fbSopenharmony_ci return false; 241d722e3fbSopenharmony_ci } 242d722e3fbSopenharmony_ci 243d722e3fbSopenharmony_ci fprintf(fp, "BLOCK_SIZE=%s,", block); 244d722e3fbSopenharmony_ci 245d722e3fbSopenharmony_ci /* add mode */ 246d722e3fbSopenharmony_ci for (unsigned int i = 0; i < ARRAY_SIZE(arm_mode_value_table); i++) { 247d722e3fbSopenharmony_ci if (arm_mode_value_table[i].modifier & mode_value) { 248d722e3fbSopenharmony_ci mode = arm_mode_value_table[i].modifier_name; 249d722e3fbSopenharmony_ci if (!did_print_mode) { 250d722e3fbSopenharmony_ci fprintf(fp, "MODE=%s", mode); 251d722e3fbSopenharmony_ci did_print_mode = true; 252d722e3fbSopenharmony_ci } else { 253d722e3fbSopenharmony_ci fprintf(fp, "|%s", mode); 254d722e3fbSopenharmony_ci } 255d722e3fbSopenharmony_ci } 256d722e3fbSopenharmony_ci } 257d722e3fbSopenharmony_ci 258d722e3fbSopenharmony_ci return true; 259d722e3fbSopenharmony_ci} 260d722e3fbSopenharmony_ci 261d722e3fbSopenharmony_cistatic bool 262d722e3fbSopenharmony_cidrmGetAfrcFormatModifierNameFromArm(uint64_t modifier, FILE *fp) 263d722e3fbSopenharmony_ci{ 264d722e3fbSopenharmony_ci bool scan_layout; 265d722e3fbSopenharmony_ci for (unsigned int i = 0; i < 2; ++i) { 266d722e3fbSopenharmony_ci uint64_t coding_unit_block = 267d722e3fbSopenharmony_ci (modifier >> (i * 4)) & AFRC_FORMAT_MOD_CU_SIZE_MASK; 268d722e3fbSopenharmony_ci const char *coding_unit_size = NULL; 269d722e3fbSopenharmony_ci 270d722e3fbSopenharmony_ci switch (coding_unit_block) { 271d722e3fbSopenharmony_ci case AFRC_FORMAT_MOD_CU_SIZE_16: 272d722e3fbSopenharmony_ci coding_unit_size = "CU_16"; 273d722e3fbSopenharmony_ci break; 274d722e3fbSopenharmony_ci case AFRC_FORMAT_MOD_CU_SIZE_24: 275d722e3fbSopenharmony_ci coding_unit_size = "CU_24"; 276d722e3fbSopenharmony_ci break; 277d722e3fbSopenharmony_ci case AFRC_FORMAT_MOD_CU_SIZE_32: 278d722e3fbSopenharmony_ci coding_unit_size = "CU_32"; 279d722e3fbSopenharmony_ci break; 280d722e3fbSopenharmony_ci } 281d722e3fbSopenharmony_ci 282d722e3fbSopenharmony_ci if (!coding_unit_size) { 283d722e3fbSopenharmony_ci if (i == 0) { 284d722e3fbSopenharmony_ci return false; 285d722e3fbSopenharmony_ci } 286d722e3fbSopenharmony_ci break; 287d722e3fbSopenharmony_ci } 288d722e3fbSopenharmony_ci 289d722e3fbSopenharmony_ci if (i == 0) { 290d722e3fbSopenharmony_ci fprintf(fp, "P0=%s,", coding_unit_size); 291d722e3fbSopenharmony_ci } else { 292d722e3fbSopenharmony_ci fprintf(fp, "P12=%s,", coding_unit_size); 293d722e3fbSopenharmony_ci } 294d722e3fbSopenharmony_ci } 295d722e3fbSopenharmony_ci 296d722e3fbSopenharmony_ci scan_layout = 297d722e3fbSopenharmony_ci (modifier & AFRC_FORMAT_MOD_LAYOUT_SCAN) == AFRC_FORMAT_MOD_LAYOUT_SCAN; 298d722e3fbSopenharmony_ci if (scan_layout) { 299d722e3fbSopenharmony_ci fprintf(fp, "SCAN"); 300d722e3fbSopenharmony_ci } else { 301d722e3fbSopenharmony_ci fprintf(fp, "ROT"); 302d722e3fbSopenharmony_ci } 303d722e3fbSopenharmony_ci return true; 304d722e3fbSopenharmony_ci} 305d722e3fbSopenharmony_ci 306d722e3fbSopenharmony_cistatic char * 307d722e3fbSopenharmony_cidrmGetFormatModifierNameFromArm(uint64_t modifier) 308d722e3fbSopenharmony_ci{ 309d722e3fbSopenharmony_ci uint64_t type = (modifier >> 52) & 0xf; 310d722e3fbSopenharmony_ci 311d722e3fbSopenharmony_ci FILE *fp; 312d722e3fbSopenharmony_ci size_t size = 0; 313d722e3fbSopenharmony_ci char *modifier_name = NULL; 314d722e3fbSopenharmony_ci bool result = false; 315d722e3fbSopenharmony_ci 316d722e3fbSopenharmony_ci fp = open_memstream(&modifier_name, &size); 317d722e3fbSopenharmony_ci if (!fp) 318d722e3fbSopenharmony_ci return NULL; 319d722e3fbSopenharmony_ci 320d722e3fbSopenharmony_ci switch (type) { 321d722e3fbSopenharmony_ci case DRM_FORMAT_MOD_ARM_TYPE_AFBC: 322d722e3fbSopenharmony_ci result = drmGetAfbcFormatModifierNameFromArm(modifier, fp); 323d722e3fbSopenharmony_ci break; 324d722e3fbSopenharmony_ci case DRM_FORMAT_MOD_ARM_TYPE_AFRC: 325d722e3fbSopenharmony_ci result = drmGetAfrcFormatModifierNameFromArm(modifier, fp); 326d722e3fbSopenharmony_ci break; 327d722e3fbSopenharmony_ci /* misc type is already handled by the static table */ 328d722e3fbSopenharmony_ci case DRM_FORMAT_MOD_ARM_TYPE_MISC: 329d722e3fbSopenharmony_ci default: 330d722e3fbSopenharmony_ci result = false; 331d722e3fbSopenharmony_ci break; 332d722e3fbSopenharmony_ci } 333d722e3fbSopenharmony_ci 334d722e3fbSopenharmony_ci fclose(fp); 335d722e3fbSopenharmony_ci if (!result) { 336d722e3fbSopenharmony_ci free(modifier_name); 337d722e3fbSopenharmony_ci return NULL; 338d722e3fbSopenharmony_ci } 339d722e3fbSopenharmony_ci 340d722e3fbSopenharmony_ci return modifier_name; 341d722e3fbSopenharmony_ci} 342d722e3fbSopenharmony_ci 343d722e3fbSopenharmony_cistatic char * 344d722e3fbSopenharmony_cidrmGetFormatModifierNameFromNvidia(uint64_t modifier) 345d722e3fbSopenharmony_ci{ 346d722e3fbSopenharmony_ci uint64_t height, kind, gen, sector, compression; 347d722e3fbSopenharmony_ci 348d722e3fbSopenharmony_ci height = modifier & 0xf; 349d722e3fbSopenharmony_ci kind = (modifier >> 12) & 0xff; 350d722e3fbSopenharmony_ci 351d722e3fbSopenharmony_ci gen = (modifier >> 20) & 0x3; 352d722e3fbSopenharmony_ci sector = (modifier >> 22) & 0x1; 353d722e3fbSopenharmony_ci compression = (modifier >> 23) & 0x7; 354d722e3fbSopenharmony_ci 355d722e3fbSopenharmony_ci /* just in case there could other simpler modifiers, not yet added, avoid 356d722e3fbSopenharmony_ci * testing against TEGRA_TILE */ 357d722e3fbSopenharmony_ci if ((modifier & 0x10) == 0x10) { 358d722e3fbSopenharmony_ci char *mod_nvidia; 359d722e3fbSopenharmony_ci asprintf(&mod_nvidia, "BLOCK_LINEAR_2D,HEIGHT=%"PRIu64",KIND=%"PRIu64"," 360d722e3fbSopenharmony_ci "GEN=%"PRIu64",SECTOR=%"PRIu64",COMPRESSION=%"PRIu64"", height, 361d722e3fbSopenharmony_ci kind, gen, sector, compression); 362d722e3fbSopenharmony_ci return mod_nvidia; 363d722e3fbSopenharmony_ci } 364d722e3fbSopenharmony_ci 365d722e3fbSopenharmony_ci return NULL; 366d722e3fbSopenharmony_ci} 367d722e3fbSopenharmony_ci 368d722e3fbSopenharmony_cistatic void 369d722e3fbSopenharmony_cidrmGetFormatModifierNameFromAmdDcc(uint64_t modifier, FILE *fp) 370d722e3fbSopenharmony_ci{ 371d722e3fbSopenharmony_ci uint64_t dcc_max_compressed_block = 372d722e3fbSopenharmony_ci AMD_FMT_MOD_GET(DCC_MAX_COMPRESSED_BLOCK, modifier); 373d722e3fbSopenharmony_ci uint64_t dcc_retile = AMD_FMT_MOD_GET(DCC_RETILE, modifier); 374d722e3fbSopenharmony_ci 375d722e3fbSopenharmony_ci const char *dcc_max_compressed_block_str = NULL; 376d722e3fbSopenharmony_ci 377d722e3fbSopenharmony_ci fprintf(fp, ",DCC"); 378d722e3fbSopenharmony_ci 379d722e3fbSopenharmony_ci if (dcc_retile) 380d722e3fbSopenharmony_ci fprintf(fp, ",DCC_RETILE"); 381d722e3fbSopenharmony_ci 382d722e3fbSopenharmony_ci if (!dcc_retile && AMD_FMT_MOD_GET(DCC_PIPE_ALIGN, modifier)) 383d722e3fbSopenharmony_ci fprintf(fp, ",DCC_PIPE_ALIGN"); 384d722e3fbSopenharmony_ci 385d722e3fbSopenharmony_ci if (AMD_FMT_MOD_GET(DCC_INDEPENDENT_64B, modifier)) 386d722e3fbSopenharmony_ci fprintf(fp, ",DCC_INDEPENDENT_64B"); 387d722e3fbSopenharmony_ci 388d722e3fbSopenharmony_ci if (AMD_FMT_MOD_GET(DCC_INDEPENDENT_128B, modifier)) 389d722e3fbSopenharmony_ci fprintf(fp, ",DCC_INDEPENDENT_128B"); 390d722e3fbSopenharmony_ci 391d722e3fbSopenharmony_ci switch (dcc_max_compressed_block) { 392d722e3fbSopenharmony_ci case AMD_FMT_MOD_DCC_BLOCK_64B: 393d722e3fbSopenharmony_ci dcc_max_compressed_block_str = "64B"; 394d722e3fbSopenharmony_ci break; 395d722e3fbSopenharmony_ci case AMD_FMT_MOD_DCC_BLOCK_128B: 396d722e3fbSopenharmony_ci dcc_max_compressed_block_str = "128B"; 397d722e3fbSopenharmony_ci break; 398d722e3fbSopenharmony_ci case AMD_FMT_MOD_DCC_BLOCK_256B: 399d722e3fbSopenharmony_ci dcc_max_compressed_block_str = "256B"; 400d722e3fbSopenharmony_ci break; 401d722e3fbSopenharmony_ci } 402d722e3fbSopenharmony_ci 403d722e3fbSopenharmony_ci if (dcc_max_compressed_block_str) 404d722e3fbSopenharmony_ci fprintf(fp, ",DCC_MAX_COMPRESSED_BLOCK=%s", 405d722e3fbSopenharmony_ci dcc_max_compressed_block_str); 406d722e3fbSopenharmony_ci 407d722e3fbSopenharmony_ci if (AMD_FMT_MOD_GET(DCC_CONSTANT_ENCODE, modifier)) 408d722e3fbSopenharmony_ci fprintf(fp, ",DCC_CONSTANT_ENCODE"); 409d722e3fbSopenharmony_ci} 410d722e3fbSopenharmony_ci 411d722e3fbSopenharmony_cistatic void 412d722e3fbSopenharmony_cidrmGetFormatModifierNameFromAmdTile(uint64_t modifier, FILE *fp) 413d722e3fbSopenharmony_ci{ 414d722e3fbSopenharmony_ci uint64_t pipe_xor_bits, bank_xor_bits, packers, rb; 415d722e3fbSopenharmony_ci uint64_t pipe, pipe_align, dcc, dcc_retile, tile_version; 416d722e3fbSopenharmony_ci 417d722e3fbSopenharmony_ci pipe_align = AMD_FMT_MOD_GET(DCC_PIPE_ALIGN, modifier); 418d722e3fbSopenharmony_ci pipe_xor_bits = AMD_FMT_MOD_GET(PIPE_XOR_BITS, modifier); 419d722e3fbSopenharmony_ci dcc = AMD_FMT_MOD_GET(DCC, modifier); 420d722e3fbSopenharmony_ci dcc_retile = AMD_FMT_MOD_GET(DCC_RETILE, modifier); 421d722e3fbSopenharmony_ci tile_version = AMD_FMT_MOD_GET(TILE_VERSION, modifier); 422d722e3fbSopenharmony_ci 423d722e3fbSopenharmony_ci fprintf(fp, ",PIPE_XOR_BITS=%"PRIu64, pipe_xor_bits); 424d722e3fbSopenharmony_ci 425d722e3fbSopenharmony_ci if (tile_version == AMD_FMT_MOD_TILE_VER_GFX9) { 426d722e3fbSopenharmony_ci bank_xor_bits = AMD_FMT_MOD_GET(BANK_XOR_BITS, modifier); 427d722e3fbSopenharmony_ci fprintf(fp, ",BANK_XOR_BITS=%"PRIu64, bank_xor_bits); 428d722e3fbSopenharmony_ci } 429d722e3fbSopenharmony_ci 430d722e3fbSopenharmony_ci if (tile_version == AMD_FMT_MOD_TILE_VER_GFX10_RBPLUS) { 431d722e3fbSopenharmony_ci packers = AMD_FMT_MOD_GET(PACKERS, modifier); 432d722e3fbSopenharmony_ci fprintf(fp, ",PACKERS=%"PRIu64, packers); 433d722e3fbSopenharmony_ci } 434d722e3fbSopenharmony_ci 435d722e3fbSopenharmony_ci if (dcc && tile_version == AMD_FMT_MOD_TILE_VER_GFX9) { 436d722e3fbSopenharmony_ci rb = AMD_FMT_MOD_GET(RB, modifier); 437d722e3fbSopenharmony_ci fprintf(fp, ",RB=%"PRIu64, rb); 438d722e3fbSopenharmony_ci } 439d722e3fbSopenharmony_ci 440d722e3fbSopenharmony_ci if (dcc && tile_version == AMD_FMT_MOD_TILE_VER_GFX9 && 441d722e3fbSopenharmony_ci (dcc_retile || pipe_align)) { 442d722e3fbSopenharmony_ci pipe = AMD_FMT_MOD_GET(PIPE, modifier); 443d722e3fbSopenharmony_ci fprintf(fp, ",PIPE_%"PRIu64, pipe); 444d722e3fbSopenharmony_ci } 445d722e3fbSopenharmony_ci} 446d722e3fbSopenharmony_ci 447d722e3fbSopenharmony_cistatic char * 448d722e3fbSopenharmony_cidrmGetFormatModifierNameFromAmd(uint64_t modifier) 449d722e3fbSopenharmony_ci{ 450d722e3fbSopenharmony_ci uint64_t tile, tile_version, dcc; 451d722e3fbSopenharmony_ci FILE *fp; 452d722e3fbSopenharmony_ci char *mod_amd = NULL; 453d722e3fbSopenharmony_ci size_t size = 0; 454d722e3fbSopenharmony_ci 455d722e3fbSopenharmony_ci const char *str_tile = NULL; 456d722e3fbSopenharmony_ci const char *str_tile_version = NULL; 457d722e3fbSopenharmony_ci 458d722e3fbSopenharmony_ci tile = AMD_FMT_MOD_GET(TILE, modifier); 459d722e3fbSopenharmony_ci tile_version = AMD_FMT_MOD_GET(TILE_VERSION, modifier); 460d722e3fbSopenharmony_ci dcc = AMD_FMT_MOD_GET(DCC, modifier); 461d722e3fbSopenharmony_ci 462d722e3fbSopenharmony_ci fp = open_memstream(&mod_amd, &size); 463d722e3fbSopenharmony_ci if (!fp) 464d722e3fbSopenharmony_ci return NULL; 465d722e3fbSopenharmony_ci 466d722e3fbSopenharmony_ci /* add tile */ 467d722e3fbSopenharmony_ci switch (tile_version) { 468d722e3fbSopenharmony_ci case AMD_FMT_MOD_TILE_VER_GFX9: 469d722e3fbSopenharmony_ci str_tile_version = "GFX9"; 470d722e3fbSopenharmony_ci break; 471d722e3fbSopenharmony_ci case AMD_FMT_MOD_TILE_VER_GFX10: 472d722e3fbSopenharmony_ci str_tile_version = "GFX10"; 473d722e3fbSopenharmony_ci break; 474d722e3fbSopenharmony_ci case AMD_FMT_MOD_TILE_VER_GFX10_RBPLUS: 475d722e3fbSopenharmony_ci str_tile_version = "GFX10_RBPLUS"; 476d722e3fbSopenharmony_ci break; 477d722e3fbSopenharmony_ci } 478d722e3fbSopenharmony_ci 479d722e3fbSopenharmony_ci if (str_tile_version) { 480d722e3fbSopenharmony_ci fprintf(fp, "%s", str_tile_version); 481d722e3fbSopenharmony_ci } else { 482d722e3fbSopenharmony_ci fclose(fp); 483d722e3fbSopenharmony_ci free(mod_amd); 484d722e3fbSopenharmony_ci return NULL; 485d722e3fbSopenharmony_ci } 486d722e3fbSopenharmony_ci 487d722e3fbSopenharmony_ci /* add tile str */ 488d722e3fbSopenharmony_ci switch (tile) { 489d722e3fbSopenharmony_ci case AMD_FMT_MOD_TILE_GFX9_64K_S: 490d722e3fbSopenharmony_ci str_tile = "GFX9_64K_S"; 491d722e3fbSopenharmony_ci break; 492d722e3fbSopenharmony_ci case AMD_FMT_MOD_TILE_GFX9_64K_D: 493d722e3fbSopenharmony_ci str_tile = "GFX9_64K_D"; 494d722e3fbSopenharmony_ci break; 495d722e3fbSopenharmony_ci case AMD_FMT_MOD_TILE_GFX9_64K_S_X: 496d722e3fbSopenharmony_ci str_tile = "GFX9_64K_S_X"; 497d722e3fbSopenharmony_ci break; 498d722e3fbSopenharmony_ci case AMD_FMT_MOD_TILE_GFX9_64K_D_X: 499d722e3fbSopenharmony_ci str_tile = "GFX9_64K_D_X"; 500d722e3fbSopenharmony_ci break; 501d722e3fbSopenharmony_ci case AMD_FMT_MOD_TILE_GFX9_64K_R_X: 502d722e3fbSopenharmony_ci str_tile = "GFX9_64K_R_X"; 503d722e3fbSopenharmony_ci break; 504d722e3fbSopenharmony_ci } 505d722e3fbSopenharmony_ci 506d722e3fbSopenharmony_ci if (str_tile) 507d722e3fbSopenharmony_ci fprintf(fp, ",%s", str_tile); 508d722e3fbSopenharmony_ci 509d722e3fbSopenharmony_ci if (dcc) 510d722e3fbSopenharmony_ci drmGetFormatModifierNameFromAmdDcc(modifier, fp); 511d722e3fbSopenharmony_ci 512d722e3fbSopenharmony_ci if (tile_version >= AMD_FMT_MOD_TILE_VER_GFX9 && is_x_t_amd_gfx9_tile(tile)) 513d722e3fbSopenharmony_ci drmGetFormatModifierNameFromAmdTile(modifier, fp); 514d722e3fbSopenharmony_ci 515d722e3fbSopenharmony_ci fclose(fp); 516d722e3fbSopenharmony_ci return mod_amd; 517d722e3fbSopenharmony_ci} 518d722e3fbSopenharmony_ci 519d722e3fbSopenharmony_cistatic char * 520d722e3fbSopenharmony_cidrmGetFormatModifierNameFromAmlogic(uint64_t modifier) 521d722e3fbSopenharmony_ci{ 522d722e3fbSopenharmony_ci uint64_t layout = modifier & 0xff; 523d722e3fbSopenharmony_ci uint64_t options = (modifier >> 8) & 0xff; 524d722e3fbSopenharmony_ci char *mod_amlogic = NULL; 525d722e3fbSopenharmony_ci 526d722e3fbSopenharmony_ci const char *layout_str; 527d722e3fbSopenharmony_ci const char *opts_str; 528d722e3fbSopenharmony_ci 529d722e3fbSopenharmony_ci switch (layout) { 530d722e3fbSopenharmony_ci case AMLOGIC_FBC_LAYOUT_BASIC: 531d722e3fbSopenharmony_ci layout_str = "BASIC"; 532d722e3fbSopenharmony_ci break; 533d722e3fbSopenharmony_ci case AMLOGIC_FBC_LAYOUT_SCATTER: 534d722e3fbSopenharmony_ci layout_str = "SCATTER"; 535d722e3fbSopenharmony_ci break; 536d722e3fbSopenharmony_ci default: 537d722e3fbSopenharmony_ci layout_str = "INVALID_LAYOUT"; 538d722e3fbSopenharmony_ci break; 539d722e3fbSopenharmony_ci } 540d722e3fbSopenharmony_ci 541d722e3fbSopenharmony_ci if (options & AMLOGIC_FBC_OPTION_MEM_SAVING) 542d722e3fbSopenharmony_ci opts_str = "MEM_SAVING"; 543d722e3fbSopenharmony_ci else 544d722e3fbSopenharmony_ci opts_str = "0"; 545d722e3fbSopenharmony_ci 546d722e3fbSopenharmony_ci asprintf(&mod_amlogic, "FBC,LAYOUT=%s,OPTIONS=%s", layout_str, opts_str); 547d722e3fbSopenharmony_ci return mod_amlogic; 548d722e3fbSopenharmony_ci} 549d722e3fbSopenharmony_ci 550d722e3fbSopenharmony_cistatic unsigned log2_int(unsigned x) 551d722e3fbSopenharmony_ci{ 552d722e3fbSopenharmony_ci unsigned l; 553d722e3fbSopenharmony_ci 554d722e3fbSopenharmony_ci if (x < 2) { 555d722e3fbSopenharmony_ci return 0; 556d722e3fbSopenharmony_ci } 557d722e3fbSopenharmony_ci for (l = 2; ; l++) { 558d722e3fbSopenharmony_ci if ((unsigned)(1 << l) > x) { 559d722e3fbSopenharmony_ci return l - 1; 560d722e3fbSopenharmony_ci } 561d722e3fbSopenharmony_ci } 562d722e3fbSopenharmony_ci return 0; 563d722e3fbSopenharmony_ci} 564d722e3fbSopenharmony_ci 565d722e3fbSopenharmony_ci 566d722e3fbSopenharmony_cidrm_public void drmSetServerInfo(drmServerInfoPtr info) 567d722e3fbSopenharmony_ci{ 568d722e3fbSopenharmony_ci drm_server_info = info; 569d722e3fbSopenharmony_ci} 570d722e3fbSopenharmony_ci 571d722e3fbSopenharmony_ci/** 572d722e3fbSopenharmony_ci * Output a message to stderr. 573d722e3fbSopenharmony_ci * 574d722e3fbSopenharmony_ci * \param format printf() like format string. 575d722e3fbSopenharmony_ci * 576d722e3fbSopenharmony_ci * \internal 577d722e3fbSopenharmony_ci * This function is a wrapper around vfprintf(). 578d722e3fbSopenharmony_ci */ 579d722e3fbSopenharmony_ci 580d722e3fbSopenharmony_cistatic int DRM_PRINTFLIKE(1, 0) 581d722e3fbSopenharmony_cidrmDebugPrint(const char *format, va_list ap) 582d722e3fbSopenharmony_ci{ 583d722e3fbSopenharmony_ci return vfprintf(stderr, format, ap); 584d722e3fbSopenharmony_ci} 585d722e3fbSopenharmony_ci 586d722e3fbSopenharmony_cidrm_public void 587d722e3fbSopenharmony_cidrmMsg(const char *format, ...) 588d722e3fbSopenharmony_ci{ 589d722e3fbSopenharmony_ci va_list ap; 590d722e3fbSopenharmony_ci const char *env; 591d722e3fbSopenharmony_ci if (((env = getenv("LIBGL_DEBUG")) && strstr(env, "verbose")) || 592d722e3fbSopenharmony_ci (drm_server_info && drm_server_info->debug_print)) 593d722e3fbSopenharmony_ci { 594d722e3fbSopenharmony_ci va_start(ap, format); 595d722e3fbSopenharmony_ci if (drm_server_info) { 596d722e3fbSopenharmony_ci drm_server_info->debug_print(format,ap); 597d722e3fbSopenharmony_ci } else { 598d722e3fbSopenharmony_ci drmDebugPrint(format, ap); 599d722e3fbSopenharmony_ci } 600d722e3fbSopenharmony_ci va_end(ap); 601d722e3fbSopenharmony_ci } 602d722e3fbSopenharmony_ci} 603d722e3fbSopenharmony_ci 604d722e3fbSopenharmony_cistatic void *drmHashTable = NULL; /* Context switch callbacks */ 605d722e3fbSopenharmony_ci 606d722e3fbSopenharmony_cidrm_public void *drmGetHashTable(void) 607d722e3fbSopenharmony_ci{ 608d722e3fbSopenharmony_ci return drmHashTable; 609d722e3fbSopenharmony_ci} 610d722e3fbSopenharmony_ci 611d722e3fbSopenharmony_cidrm_public void *drmMalloc(int size) 612d722e3fbSopenharmony_ci{ 613d722e3fbSopenharmony_ci return calloc(1, size); 614d722e3fbSopenharmony_ci} 615d722e3fbSopenharmony_ci 616d722e3fbSopenharmony_cidrm_public void drmFree(void *pt) 617d722e3fbSopenharmony_ci{ 618d722e3fbSopenharmony_ci free(pt); 619d722e3fbSopenharmony_ci} 620d722e3fbSopenharmony_ci 621d722e3fbSopenharmony_ci/** 622d722e3fbSopenharmony_ci * Call ioctl, restarting if it is interrupted 623d722e3fbSopenharmony_ci */ 624d722e3fbSopenharmony_cidrm_public int 625d722e3fbSopenharmony_cidrmIoctl(int fd, unsigned long request, void *arg) 626d722e3fbSopenharmony_ci{ 627d722e3fbSopenharmony_ci int ret; 628d722e3fbSopenharmony_ci 629d722e3fbSopenharmony_ci do { 630d722e3fbSopenharmony_ci ret = ioctl(fd, request, arg); 631d722e3fbSopenharmony_ci } while (ret == -1 && (errno == EINTR || errno == EAGAIN)); 632d722e3fbSopenharmony_ci return ret; 633d722e3fbSopenharmony_ci} 634d722e3fbSopenharmony_ci 635d722e3fbSopenharmony_cistatic unsigned long drmGetKeyFromFd(int fd) 636d722e3fbSopenharmony_ci{ 637d722e3fbSopenharmony_ci stat_t st; 638d722e3fbSopenharmony_ci 639d722e3fbSopenharmony_ci st.st_rdev = 0; 640d722e3fbSopenharmony_ci fstat(fd, &st); 641d722e3fbSopenharmony_ci return st.st_rdev; 642d722e3fbSopenharmony_ci} 643d722e3fbSopenharmony_ci 644d722e3fbSopenharmony_cidrm_public drmHashEntry *drmGetEntry(int fd) 645d722e3fbSopenharmony_ci{ 646d722e3fbSopenharmony_ci unsigned long key = drmGetKeyFromFd(fd); 647d722e3fbSopenharmony_ci void *value; 648d722e3fbSopenharmony_ci drmHashEntry *entry; 649d722e3fbSopenharmony_ci 650d722e3fbSopenharmony_ci if (!drmHashTable) 651d722e3fbSopenharmony_ci drmHashTable = drmHashCreate(); 652d722e3fbSopenharmony_ci 653d722e3fbSopenharmony_ci if (drmHashLookup(drmHashTable, key, &value)) { 654d722e3fbSopenharmony_ci entry = drmMalloc(sizeof(*entry)); 655d722e3fbSopenharmony_ci entry->fd = fd; 656d722e3fbSopenharmony_ci entry->f = NULL; 657d722e3fbSopenharmony_ci entry->tagTable = drmHashCreate(); 658d722e3fbSopenharmony_ci drmHashInsert(drmHashTable, key, entry); 659d722e3fbSopenharmony_ci } else { 660d722e3fbSopenharmony_ci entry = value; 661d722e3fbSopenharmony_ci } 662d722e3fbSopenharmony_ci return entry; 663d722e3fbSopenharmony_ci} 664d722e3fbSopenharmony_ci 665d722e3fbSopenharmony_ci/** 666d722e3fbSopenharmony_ci * Compare two busid strings 667d722e3fbSopenharmony_ci * 668d722e3fbSopenharmony_ci * \param first 669d722e3fbSopenharmony_ci * \param second 670d722e3fbSopenharmony_ci * 671d722e3fbSopenharmony_ci * \return 1 if matched. 672d722e3fbSopenharmony_ci * 673d722e3fbSopenharmony_ci * \internal 674d722e3fbSopenharmony_ci * This function compares two bus ID strings. It understands the older 675d722e3fbSopenharmony_ci * PCI:b:d:f format and the newer pci:oooo:bb:dd.f format. In the format, o is 676d722e3fbSopenharmony_ci * domain, b is bus, d is device, f is function. 677d722e3fbSopenharmony_ci */ 678d722e3fbSopenharmony_cistatic int drmMatchBusID(const char *id1, const char *id2, int pci_domain_ok) 679d722e3fbSopenharmony_ci{ 680d722e3fbSopenharmony_ci /* First, check if the IDs are exactly the same */ 681d722e3fbSopenharmony_ci if (strcasecmp(id1, id2) == 0) 682d722e3fbSopenharmony_ci return 1; 683d722e3fbSopenharmony_ci 684d722e3fbSopenharmony_ci /* Try to match old/new-style PCI bus IDs. */ 685d722e3fbSopenharmony_ci if (strncasecmp(id1, "pci", 3) == 0) { 686d722e3fbSopenharmony_ci unsigned int o1, b1, d1, f1; 687d722e3fbSopenharmony_ci unsigned int o2, b2, d2, f2; 688d722e3fbSopenharmony_ci int ret; 689d722e3fbSopenharmony_ci 690d722e3fbSopenharmony_ci ret = sscanf(id1, "pci:%04x:%02x:%02x.%u", &o1, &b1, &d1, &f1); 691d722e3fbSopenharmony_ci if (ret != 4) { 692d722e3fbSopenharmony_ci o1 = 0; 693d722e3fbSopenharmony_ci ret = sscanf(id1, "PCI:%u:%u:%u", &b1, &d1, &f1); 694d722e3fbSopenharmony_ci if (ret != 3) 695d722e3fbSopenharmony_ci return 0; 696d722e3fbSopenharmony_ci } 697d722e3fbSopenharmony_ci 698d722e3fbSopenharmony_ci ret = sscanf(id2, "pci:%04x:%02x:%02x.%u", &o2, &b2, &d2, &f2); 699d722e3fbSopenharmony_ci if (ret != 4) { 700d722e3fbSopenharmony_ci o2 = 0; 701d722e3fbSopenharmony_ci ret = sscanf(id2, "PCI:%u:%u:%u", &b2, &d2, &f2); 702d722e3fbSopenharmony_ci if (ret != 3) 703d722e3fbSopenharmony_ci return 0; 704d722e3fbSopenharmony_ci } 705d722e3fbSopenharmony_ci 706d722e3fbSopenharmony_ci /* If domains aren't properly supported by the kernel interface, 707d722e3fbSopenharmony_ci * just ignore them, which sucks less than picking a totally random 708d722e3fbSopenharmony_ci * card with "open by name" 709d722e3fbSopenharmony_ci */ 710d722e3fbSopenharmony_ci if (!pci_domain_ok) 711d722e3fbSopenharmony_ci o1 = o2 = 0; 712d722e3fbSopenharmony_ci 713d722e3fbSopenharmony_ci if ((o1 != o2) || (b1 != b2) || (d1 != d2) || (f1 != f2)) 714d722e3fbSopenharmony_ci return 0; 715d722e3fbSopenharmony_ci else 716d722e3fbSopenharmony_ci return 1; 717d722e3fbSopenharmony_ci } 718d722e3fbSopenharmony_ci return 0; 719d722e3fbSopenharmony_ci} 720d722e3fbSopenharmony_ci 721d722e3fbSopenharmony_ci/** 722d722e3fbSopenharmony_ci * Handles error checking for chown call. 723d722e3fbSopenharmony_ci * 724d722e3fbSopenharmony_ci * \param path to file. 725d722e3fbSopenharmony_ci * \param id of the new owner. 726d722e3fbSopenharmony_ci * \param id of the new group. 727d722e3fbSopenharmony_ci * 728d722e3fbSopenharmony_ci * \return zero if success or -1 if failure. 729d722e3fbSopenharmony_ci * 730d722e3fbSopenharmony_ci * \internal 731d722e3fbSopenharmony_ci * Checks for failure. If failure was caused by signal call chown again. 732d722e3fbSopenharmony_ci * If any other failure happened then it will output error message using 733d722e3fbSopenharmony_ci * drmMsg() call. 734d722e3fbSopenharmony_ci */ 735d722e3fbSopenharmony_ci#if !UDEV 736d722e3fbSopenharmony_cistatic int chown_check_return(const char *path, uid_t owner, gid_t group) 737d722e3fbSopenharmony_ci{ 738d722e3fbSopenharmony_ci int rv; 739d722e3fbSopenharmony_ci 740d722e3fbSopenharmony_ci do { 741d722e3fbSopenharmony_ci rv = chown(path, owner, group); 742d722e3fbSopenharmony_ci } while (rv != 0 && errno == EINTR); 743d722e3fbSopenharmony_ci 744d722e3fbSopenharmony_ci if (rv == 0) 745d722e3fbSopenharmony_ci return 0; 746d722e3fbSopenharmony_ci 747d722e3fbSopenharmony_ci drmMsg("Failed to change owner or group for file %s! %d: %s\n", 748d722e3fbSopenharmony_ci path, errno, strerror(errno)); 749d722e3fbSopenharmony_ci return -1; 750d722e3fbSopenharmony_ci} 751d722e3fbSopenharmony_ci#endif 752d722e3fbSopenharmony_ci 753d722e3fbSopenharmony_cistatic const char *drmGetDeviceName(int type) 754d722e3fbSopenharmony_ci{ 755d722e3fbSopenharmony_ci switch (type) { 756d722e3fbSopenharmony_ci case DRM_NODE_PRIMARY: 757d722e3fbSopenharmony_ci return DRM_DEV_NAME; 758d722e3fbSopenharmony_ci case DRM_NODE_CONTROL: 759d722e3fbSopenharmony_ci return DRM_CONTROL_DEV_NAME; 760d722e3fbSopenharmony_ci case DRM_NODE_RENDER: 761d722e3fbSopenharmony_ci return DRM_RENDER_DEV_NAME; 762d722e3fbSopenharmony_ci } 763d722e3fbSopenharmony_ci return NULL; 764d722e3fbSopenharmony_ci} 765d722e3fbSopenharmony_ci 766d722e3fbSopenharmony_ci/** 767d722e3fbSopenharmony_ci * Open the DRM device, creating it if necessary. 768d722e3fbSopenharmony_ci * 769d722e3fbSopenharmony_ci * \param dev major and minor numbers of the device. 770d722e3fbSopenharmony_ci * \param minor minor number of the device. 771d722e3fbSopenharmony_ci * 772d722e3fbSopenharmony_ci * \return a file descriptor on success, or a negative value on error. 773d722e3fbSopenharmony_ci * 774d722e3fbSopenharmony_ci * \internal 775d722e3fbSopenharmony_ci * Assembles the device name from \p minor and opens it, creating the device 776d722e3fbSopenharmony_ci * special file node with the major and minor numbers specified by \p dev and 777d722e3fbSopenharmony_ci * parent directory if necessary and was called by root. 778d722e3fbSopenharmony_ci */ 779d722e3fbSopenharmony_cistatic int drmOpenDevice(dev_t dev, int minor, int type) 780d722e3fbSopenharmony_ci{ 781d722e3fbSopenharmony_ci stat_t st; 782d722e3fbSopenharmony_ci const char *dev_name = drmGetDeviceName(type); 783d722e3fbSopenharmony_ci char buf[DRM_NODE_NAME_MAX]; 784d722e3fbSopenharmony_ci int fd; 785d722e3fbSopenharmony_ci mode_t devmode = DRM_DEV_MODE, serv_mode; 786d722e3fbSopenharmony_ci gid_t serv_group; 787d722e3fbSopenharmony_ci#if !UDEV 788d722e3fbSopenharmony_ci int isroot = !geteuid(); 789d722e3fbSopenharmony_ci uid_t user = DRM_DEV_UID; 790d722e3fbSopenharmony_ci gid_t group = DRM_DEV_GID; 791d722e3fbSopenharmony_ci#endif 792d722e3fbSopenharmony_ci 793d722e3fbSopenharmony_ci if (!dev_name) 794d722e3fbSopenharmony_ci return -EINVAL; 795d722e3fbSopenharmony_ci 796d722e3fbSopenharmony_ci sprintf(buf, dev_name, DRM_DIR_NAME, minor); 797d722e3fbSopenharmony_ci drmMsg("drmOpenDevice: node name is %s\n", buf); 798d722e3fbSopenharmony_ci 799d722e3fbSopenharmony_ci if (drm_server_info && drm_server_info->get_perms) { 800d722e3fbSopenharmony_ci drm_server_info->get_perms(&serv_group, &serv_mode); 801d722e3fbSopenharmony_ci devmode = serv_mode ? serv_mode : DRM_DEV_MODE; 802d722e3fbSopenharmony_ci devmode &= ~(S_IXUSR|S_IXGRP|S_IXOTH); 803d722e3fbSopenharmony_ci } 804d722e3fbSopenharmony_ci 805d722e3fbSopenharmony_ci#if !UDEV 806d722e3fbSopenharmony_ci if (stat(DRM_DIR_NAME, &st)) { 807d722e3fbSopenharmony_ci if (!isroot) 808d722e3fbSopenharmony_ci return DRM_ERR_NOT_ROOT; 809d722e3fbSopenharmony_ci mkdir(DRM_DIR_NAME, DRM_DEV_DIRMODE); 810d722e3fbSopenharmony_ci chown_check_return(DRM_DIR_NAME, 0, 0); /* root:root */ 811d722e3fbSopenharmony_ci chmod(DRM_DIR_NAME, DRM_DEV_DIRMODE); 812d722e3fbSopenharmony_ci } 813d722e3fbSopenharmony_ci 814d722e3fbSopenharmony_ci /* Check if the device node exists and create it if necessary. */ 815d722e3fbSopenharmony_ci if (stat(buf, &st)) { 816d722e3fbSopenharmony_ci if (!isroot) 817d722e3fbSopenharmony_ci return DRM_ERR_NOT_ROOT; 818d722e3fbSopenharmony_ci remove(buf); 819d722e3fbSopenharmony_ci mknod(buf, S_IFCHR | devmode, dev); 820d722e3fbSopenharmony_ci } 821d722e3fbSopenharmony_ci 822d722e3fbSopenharmony_ci if (drm_server_info && drm_server_info->get_perms) { 823d722e3fbSopenharmony_ci group = ((int)serv_group >= 0) ? serv_group : DRM_DEV_GID; 824d722e3fbSopenharmony_ci chown_check_return(buf, user, group); 825d722e3fbSopenharmony_ci chmod(buf, devmode); 826d722e3fbSopenharmony_ci } 827d722e3fbSopenharmony_ci#else 828d722e3fbSopenharmony_ci /* if we modprobed then wait for udev */ 829d722e3fbSopenharmony_ci { 830d722e3fbSopenharmony_ci int udev_count = 0; 831d722e3fbSopenharmony_ciwait_for_udev: 832d722e3fbSopenharmony_ci if (stat(DRM_DIR_NAME, &st)) { 833d722e3fbSopenharmony_ci usleep(20); 834d722e3fbSopenharmony_ci udev_count++; 835d722e3fbSopenharmony_ci 836d722e3fbSopenharmony_ci if (udev_count == 50) 837d722e3fbSopenharmony_ci return -1; 838d722e3fbSopenharmony_ci goto wait_for_udev; 839d722e3fbSopenharmony_ci } 840d722e3fbSopenharmony_ci 841d722e3fbSopenharmony_ci if (stat(buf, &st)) { 842d722e3fbSopenharmony_ci usleep(20); 843d722e3fbSopenharmony_ci udev_count++; 844d722e3fbSopenharmony_ci 845d722e3fbSopenharmony_ci if (udev_count == 50) 846d722e3fbSopenharmony_ci return -1; 847d722e3fbSopenharmony_ci goto wait_for_udev; 848d722e3fbSopenharmony_ci } 849d722e3fbSopenharmony_ci } 850d722e3fbSopenharmony_ci#endif 851d722e3fbSopenharmony_ci 852d722e3fbSopenharmony_ci fd = open(buf, O_RDWR | O_CLOEXEC, 0); 853d722e3fbSopenharmony_ci drmMsg("drmOpenDevice: open result is %d, (%s)\n", 854d722e3fbSopenharmony_ci fd, fd < 0 ? strerror(errno) : "OK"); 855d722e3fbSopenharmony_ci if (fd >= 0) 856d722e3fbSopenharmony_ci return fd; 857d722e3fbSopenharmony_ci 858d722e3fbSopenharmony_ci#if !UDEV 859d722e3fbSopenharmony_ci /* Check if the device node is not what we expect it to be, and recreate it 860d722e3fbSopenharmony_ci * and try again if so. 861d722e3fbSopenharmony_ci */ 862d722e3fbSopenharmony_ci if (st.st_rdev != dev) { 863d722e3fbSopenharmony_ci if (!isroot) 864d722e3fbSopenharmony_ci return DRM_ERR_NOT_ROOT; 865d722e3fbSopenharmony_ci remove(buf); 866d722e3fbSopenharmony_ci mknod(buf, S_IFCHR | devmode, dev); 867d722e3fbSopenharmony_ci if (drm_server_info && drm_server_info->get_perms) { 868d722e3fbSopenharmony_ci chown_check_return(buf, user, group); 869d722e3fbSopenharmony_ci chmod(buf, devmode); 870d722e3fbSopenharmony_ci } 871d722e3fbSopenharmony_ci } 872d722e3fbSopenharmony_ci fd = open(buf, O_RDWR | O_CLOEXEC, 0); 873d722e3fbSopenharmony_ci drmMsg("drmOpenDevice: open result is %d, (%s)\n", 874d722e3fbSopenharmony_ci fd, fd < 0 ? strerror(errno) : "OK"); 875d722e3fbSopenharmony_ci if (fd >= 0) 876d722e3fbSopenharmony_ci return fd; 877d722e3fbSopenharmony_ci 878d722e3fbSopenharmony_ci drmMsg("drmOpenDevice: Open failed\n"); 879d722e3fbSopenharmony_ci remove(buf); 880d722e3fbSopenharmony_ci#endif 881d722e3fbSopenharmony_ci return -errno; 882d722e3fbSopenharmony_ci} 883d722e3fbSopenharmony_ci 884d722e3fbSopenharmony_ci 885d722e3fbSopenharmony_ci/** 886d722e3fbSopenharmony_ci * Open the DRM device 887d722e3fbSopenharmony_ci * 888d722e3fbSopenharmony_ci * \param minor device minor number. 889d722e3fbSopenharmony_ci * \param create allow to create the device if set. 890d722e3fbSopenharmony_ci * 891d722e3fbSopenharmony_ci * \return a file descriptor on success, or a negative value on error. 892d722e3fbSopenharmony_ci * 893d722e3fbSopenharmony_ci * \internal 894d722e3fbSopenharmony_ci * Calls drmOpenDevice() if \p create is set, otherwise assembles the device 895d722e3fbSopenharmony_ci * name from \p minor and opens it. 896d722e3fbSopenharmony_ci */ 897d722e3fbSopenharmony_cistatic int drmOpenMinor(int minor, int create, int type) 898d722e3fbSopenharmony_ci{ 899d722e3fbSopenharmony_ci int fd; 900d722e3fbSopenharmony_ci char buf[DRM_NODE_NAME_MAX]; 901d722e3fbSopenharmony_ci const char *dev_name = drmGetDeviceName(type); 902d722e3fbSopenharmony_ci 903d722e3fbSopenharmony_ci if (create) 904d722e3fbSopenharmony_ci return drmOpenDevice(makedev(DRM_MAJOR, minor), minor, type); 905d722e3fbSopenharmony_ci 906d722e3fbSopenharmony_ci if (!dev_name) 907d722e3fbSopenharmony_ci return -EINVAL; 908d722e3fbSopenharmony_ci 909d722e3fbSopenharmony_ci sprintf(buf, dev_name, DRM_DIR_NAME, minor); 910d722e3fbSopenharmony_ci if ((fd = open(buf, O_RDWR | O_CLOEXEC, 0)) >= 0) 911d722e3fbSopenharmony_ci return fd; 912d722e3fbSopenharmony_ci return -errno; 913d722e3fbSopenharmony_ci} 914d722e3fbSopenharmony_ci 915d722e3fbSopenharmony_ci 916d722e3fbSopenharmony_ci/** 917d722e3fbSopenharmony_ci * Determine whether the DRM kernel driver has been loaded. 918d722e3fbSopenharmony_ci * 919d722e3fbSopenharmony_ci * \return 1 if the DRM driver is loaded, 0 otherwise. 920d722e3fbSopenharmony_ci * 921d722e3fbSopenharmony_ci * \internal 922d722e3fbSopenharmony_ci * Determine the presence of the kernel driver by attempting to open the 0 923d722e3fbSopenharmony_ci * minor and get version information. For backward compatibility with older 924d722e3fbSopenharmony_ci * Linux implementations, /proc/dri is also checked. 925d722e3fbSopenharmony_ci */ 926d722e3fbSopenharmony_cidrm_public int drmAvailable(void) 927d722e3fbSopenharmony_ci{ 928d722e3fbSopenharmony_ci drmVersionPtr version; 929d722e3fbSopenharmony_ci int retval = 0; 930d722e3fbSopenharmony_ci int fd; 931d722e3fbSopenharmony_ci 932d722e3fbSopenharmony_ci if ((fd = drmOpenMinor(0, 1, DRM_NODE_PRIMARY)) < 0) { 933d722e3fbSopenharmony_ci#ifdef __linux__ 934d722e3fbSopenharmony_ci /* Try proc for backward Linux compatibility */ 935d722e3fbSopenharmony_ci if (!access("/proc/dri/0", R_OK)) 936d722e3fbSopenharmony_ci return 1; 937d722e3fbSopenharmony_ci#endif 938d722e3fbSopenharmony_ci return 0; 939d722e3fbSopenharmony_ci } 940d722e3fbSopenharmony_ci 941d722e3fbSopenharmony_ci if ((version = drmGetVersion(fd))) { 942d722e3fbSopenharmony_ci retval = 1; 943d722e3fbSopenharmony_ci drmFreeVersion(version); 944d722e3fbSopenharmony_ci } 945d722e3fbSopenharmony_ci close(fd); 946d722e3fbSopenharmony_ci 947d722e3fbSopenharmony_ci return retval; 948d722e3fbSopenharmony_ci} 949d722e3fbSopenharmony_ci 950d722e3fbSopenharmony_cistatic int drmGetMinorBase(int type) 951d722e3fbSopenharmony_ci{ 952d722e3fbSopenharmony_ci switch (type) { 953d722e3fbSopenharmony_ci case DRM_NODE_PRIMARY: 954d722e3fbSopenharmony_ci return 0; 955d722e3fbSopenharmony_ci case DRM_NODE_CONTROL: 956d722e3fbSopenharmony_ci return 64; 957d722e3fbSopenharmony_ci case DRM_NODE_RENDER: 958d722e3fbSopenharmony_ci return 128; 959d722e3fbSopenharmony_ci default: 960d722e3fbSopenharmony_ci return -1; 961d722e3fbSopenharmony_ci }; 962d722e3fbSopenharmony_ci} 963d722e3fbSopenharmony_ci 964d722e3fbSopenharmony_cistatic int drmGetMinorType(int major, int minor) 965d722e3fbSopenharmony_ci{ 966d722e3fbSopenharmony_ci#ifdef __FreeBSD__ 967d722e3fbSopenharmony_ci char name[SPECNAMELEN]; 968d722e3fbSopenharmony_ci int id; 969d722e3fbSopenharmony_ci 970d722e3fbSopenharmony_ci if (!devname_r(makedev(major, minor), S_IFCHR, name, sizeof(name))) 971d722e3fbSopenharmony_ci return -1; 972d722e3fbSopenharmony_ci 973d722e3fbSopenharmony_ci if (sscanf(name, "drm/%d", &id) != 1) { 974d722e3fbSopenharmony_ci // If not in /dev/drm/ we have the type in the name 975d722e3fbSopenharmony_ci if (sscanf(name, "dri/card%d\n", &id) >= 1) 976d722e3fbSopenharmony_ci return DRM_NODE_PRIMARY; 977d722e3fbSopenharmony_ci else if (sscanf(name, "dri/control%d\n", &id) >= 1) 978d722e3fbSopenharmony_ci return DRM_NODE_CONTROL; 979d722e3fbSopenharmony_ci else if (sscanf(name, "dri/renderD%d\n", &id) >= 1) 980d722e3fbSopenharmony_ci return DRM_NODE_RENDER; 981d722e3fbSopenharmony_ci return -1; 982d722e3fbSopenharmony_ci } 983d722e3fbSopenharmony_ci 984d722e3fbSopenharmony_ci minor = id; 985d722e3fbSopenharmony_ci#endif 986d722e3fbSopenharmony_ci int type = minor >> 6; 987d722e3fbSopenharmony_ci 988d722e3fbSopenharmony_ci if (minor < 0) 989d722e3fbSopenharmony_ci return -1; 990d722e3fbSopenharmony_ci 991d722e3fbSopenharmony_ci switch (type) { 992d722e3fbSopenharmony_ci case DRM_NODE_PRIMARY: 993d722e3fbSopenharmony_ci case DRM_NODE_CONTROL: 994d722e3fbSopenharmony_ci case DRM_NODE_RENDER: 995d722e3fbSopenharmony_ci return type; 996d722e3fbSopenharmony_ci default: 997d722e3fbSopenharmony_ci return -1; 998d722e3fbSopenharmony_ci } 999d722e3fbSopenharmony_ci} 1000d722e3fbSopenharmony_ci 1001d722e3fbSopenharmony_cistatic const char *drmGetMinorName(int type) 1002d722e3fbSopenharmony_ci{ 1003d722e3fbSopenharmony_ci switch (type) { 1004d722e3fbSopenharmony_ci case DRM_NODE_PRIMARY: 1005d722e3fbSopenharmony_ci return DRM_PRIMARY_MINOR_NAME; 1006d722e3fbSopenharmony_ci case DRM_NODE_CONTROL: 1007d722e3fbSopenharmony_ci return DRM_CONTROL_MINOR_NAME; 1008d722e3fbSopenharmony_ci case DRM_NODE_RENDER: 1009d722e3fbSopenharmony_ci return DRM_RENDER_MINOR_NAME; 1010d722e3fbSopenharmony_ci default: 1011d722e3fbSopenharmony_ci return NULL; 1012d722e3fbSopenharmony_ci } 1013d722e3fbSopenharmony_ci} 1014d722e3fbSopenharmony_ci 1015d722e3fbSopenharmony_ci/** 1016d722e3fbSopenharmony_ci * Open the device by bus ID. 1017d722e3fbSopenharmony_ci * 1018d722e3fbSopenharmony_ci * \param busid bus ID. 1019d722e3fbSopenharmony_ci * \param type device node type. 1020d722e3fbSopenharmony_ci * 1021d722e3fbSopenharmony_ci * \return a file descriptor on success, or a negative value on error. 1022d722e3fbSopenharmony_ci * 1023d722e3fbSopenharmony_ci * \internal 1024d722e3fbSopenharmony_ci * This function attempts to open every possible minor (up to DRM_MAX_MINOR), 1025d722e3fbSopenharmony_ci * comparing the device bus ID with the one supplied. 1026d722e3fbSopenharmony_ci * 1027d722e3fbSopenharmony_ci * \sa drmOpenMinor() and drmGetBusid(). 1028d722e3fbSopenharmony_ci */ 1029d722e3fbSopenharmony_cistatic int drmOpenByBusid(const char *busid, int type) 1030d722e3fbSopenharmony_ci{ 1031d722e3fbSopenharmony_ci int i, pci_domain_ok = 1; 1032d722e3fbSopenharmony_ci int fd; 1033d722e3fbSopenharmony_ci const char *buf; 1034d722e3fbSopenharmony_ci drmSetVersion sv; 1035d722e3fbSopenharmony_ci int base = drmGetMinorBase(type); 1036d722e3fbSopenharmony_ci 1037d722e3fbSopenharmony_ci if (base < 0) 1038d722e3fbSopenharmony_ci return -1; 1039d722e3fbSopenharmony_ci 1040d722e3fbSopenharmony_ci drmMsg("drmOpenByBusid: Searching for BusID %s\n", busid); 1041d722e3fbSopenharmony_ci for (i = base; i < base + DRM_MAX_MINOR; i++) { 1042d722e3fbSopenharmony_ci fd = drmOpenMinor(i, 1, type); 1043d722e3fbSopenharmony_ci drmMsg("drmOpenByBusid: drmOpenMinor returns %d\n", fd); 1044d722e3fbSopenharmony_ci if (fd >= 0) { 1045d722e3fbSopenharmony_ci /* We need to try for 1.4 first for proper PCI domain support 1046d722e3fbSopenharmony_ci * and if that fails, we know the kernel is busted 1047d722e3fbSopenharmony_ci */ 1048d722e3fbSopenharmony_ci sv.drm_di_major = 1; 1049d722e3fbSopenharmony_ci sv.drm_di_minor = 4; 1050d722e3fbSopenharmony_ci sv.drm_dd_major = -1; /* Don't care */ 1051d722e3fbSopenharmony_ci sv.drm_dd_minor = -1; /* Don't care */ 1052d722e3fbSopenharmony_ci if (drmSetInterfaceVersion(fd, &sv)) { 1053d722e3fbSopenharmony_ci#ifndef __alpha__ 1054d722e3fbSopenharmony_ci pci_domain_ok = 0; 1055d722e3fbSopenharmony_ci#endif 1056d722e3fbSopenharmony_ci sv.drm_di_major = 1; 1057d722e3fbSopenharmony_ci sv.drm_di_minor = 1; 1058d722e3fbSopenharmony_ci sv.drm_dd_major = -1; /* Don't care */ 1059d722e3fbSopenharmony_ci sv.drm_dd_minor = -1; /* Don't care */ 1060d722e3fbSopenharmony_ci drmMsg("drmOpenByBusid: Interface 1.4 failed, trying 1.1\n"); 1061d722e3fbSopenharmony_ci drmSetInterfaceVersion(fd, &sv); 1062d722e3fbSopenharmony_ci } 1063d722e3fbSopenharmony_ci buf = drmGetBusid(fd); 1064d722e3fbSopenharmony_ci drmMsg("drmOpenByBusid: drmGetBusid reports %s\n", buf); 1065d722e3fbSopenharmony_ci if (buf && drmMatchBusID(buf, busid, pci_domain_ok)) { 1066d722e3fbSopenharmony_ci drmFreeBusid(buf); 1067d722e3fbSopenharmony_ci return fd; 1068d722e3fbSopenharmony_ci } 1069d722e3fbSopenharmony_ci if (buf) 1070d722e3fbSopenharmony_ci drmFreeBusid(buf); 1071d722e3fbSopenharmony_ci close(fd); 1072d722e3fbSopenharmony_ci } 1073d722e3fbSopenharmony_ci } 1074d722e3fbSopenharmony_ci return -1; 1075d722e3fbSopenharmony_ci} 1076d722e3fbSopenharmony_ci 1077d722e3fbSopenharmony_ci 1078d722e3fbSopenharmony_ci/** 1079d722e3fbSopenharmony_ci * Open the device by name. 1080d722e3fbSopenharmony_ci * 1081d722e3fbSopenharmony_ci * \param name driver name. 1082d722e3fbSopenharmony_ci * \param type the device node type. 1083d722e3fbSopenharmony_ci * 1084d722e3fbSopenharmony_ci * \return a file descriptor on success, or a negative value on error. 1085d722e3fbSopenharmony_ci * 1086d722e3fbSopenharmony_ci * \internal 1087d722e3fbSopenharmony_ci * This function opens the first minor number that matches the driver name and 1088d722e3fbSopenharmony_ci * isn't already in use. If it's in use it then it will already have a bus ID 1089d722e3fbSopenharmony_ci * assigned. 1090d722e3fbSopenharmony_ci * 1091d722e3fbSopenharmony_ci * \sa drmOpenMinor(), drmGetVersion() and drmGetBusid(). 1092d722e3fbSopenharmony_ci */ 1093d722e3fbSopenharmony_cistatic int drmOpenByName(const char *name, int type) 1094d722e3fbSopenharmony_ci{ 1095d722e3fbSopenharmony_ci int i; 1096d722e3fbSopenharmony_ci int fd; 1097d722e3fbSopenharmony_ci drmVersionPtr version; 1098d722e3fbSopenharmony_ci char * id; 1099d722e3fbSopenharmony_ci int base = drmGetMinorBase(type); 1100d722e3fbSopenharmony_ci 1101d722e3fbSopenharmony_ci if (base < 0) 1102d722e3fbSopenharmony_ci return -1; 1103d722e3fbSopenharmony_ci 1104d722e3fbSopenharmony_ci /* 1105d722e3fbSopenharmony_ci * Open the first minor number that matches the driver name and isn't 1106d722e3fbSopenharmony_ci * already in use. If it's in use it will have a busid assigned already. 1107d722e3fbSopenharmony_ci */ 1108d722e3fbSopenharmony_ci for (i = base; i < base + DRM_MAX_MINOR; i++) { 1109d722e3fbSopenharmony_ci if ((fd = drmOpenMinor(i, 1, type)) >= 0) { 1110d722e3fbSopenharmony_ci if ((version = drmGetVersion(fd))) { 1111d722e3fbSopenharmony_ci if (!strcmp(version->name, name)) { 1112d722e3fbSopenharmony_ci drmFreeVersion(version); 1113d722e3fbSopenharmony_ci id = drmGetBusid(fd); 1114d722e3fbSopenharmony_ci drmMsg("drmGetBusid returned '%s'\n", id ? id : "NULL"); 1115d722e3fbSopenharmony_ci if (!id || !*id) { 1116d722e3fbSopenharmony_ci if (id) 1117d722e3fbSopenharmony_ci drmFreeBusid(id); 1118d722e3fbSopenharmony_ci return fd; 1119d722e3fbSopenharmony_ci } else { 1120d722e3fbSopenharmony_ci drmFreeBusid(id); 1121d722e3fbSopenharmony_ci } 1122d722e3fbSopenharmony_ci } else { 1123d722e3fbSopenharmony_ci drmFreeVersion(version); 1124d722e3fbSopenharmony_ci } 1125d722e3fbSopenharmony_ci } 1126d722e3fbSopenharmony_ci close(fd); 1127d722e3fbSopenharmony_ci } 1128d722e3fbSopenharmony_ci } 1129d722e3fbSopenharmony_ci 1130d722e3fbSopenharmony_ci#ifdef __linux__ 1131d722e3fbSopenharmony_ci /* Backward-compatibility /proc support */ 1132d722e3fbSopenharmony_ci for (i = 0; i < 8; i++) { 1133d722e3fbSopenharmony_ci char proc_name[64], buf[512]; 1134d722e3fbSopenharmony_ci char *driver, *pt, *devstring; 1135d722e3fbSopenharmony_ci int retcode; 1136d722e3fbSopenharmony_ci 1137d722e3fbSopenharmony_ci sprintf(proc_name, "/proc/dri/%d/name", i); 1138d722e3fbSopenharmony_ci if ((fd = open(proc_name, O_RDONLY, 0)) >= 0) { 1139d722e3fbSopenharmony_ci retcode = read(fd, buf, sizeof(buf)-1); 1140d722e3fbSopenharmony_ci close(fd); 1141d722e3fbSopenharmony_ci if (retcode) { 1142d722e3fbSopenharmony_ci buf[retcode-1] = '\0'; 1143d722e3fbSopenharmony_ci for (driver = pt = buf; *pt && *pt != ' '; ++pt) 1144d722e3fbSopenharmony_ci ; 1145d722e3fbSopenharmony_ci if (*pt) { /* Device is next */ 1146d722e3fbSopenharmony_ci *pt = '\0'; 1147d722e3fbSopenharmony_ci if (!strcmp(driver, name)) { /* Match */ 1148d722e3fbSopenharmony_ci for (devstring = ++pt; *pt && *pt != ' '; ++pt) 1149d722e3fbSopenharmony_ci ; 1150d722e3fbSopenharmony_ci if (*pt) { /* Found busid */ 1151d722e3fbSopenharmony_ci return drmOpenByBusid(++pt, type); 1152d722e3fbSopenharmony_ci } else { /* No busid */ 1153d722e3fbSopenharmony_ci return drmOpenDevice(strtol(devstring, NULL, 0),i, type); 1154d722e3fbSopenharmony_ci } 1155d722e3fbSopenharmony_ci } 1156d722e3fbSopenharmony_ci } 1157d722e3fbSopenharmony_ci } 1158d722e3fbSopenharmony_ci } 1159d722e3fbSopenharmony_ci } 1160d722e3fbSopenharmony_ci#endif 1161d722e3fbSopenharmony_ci 1162d722e3fbSopenharmony_ci return -1; 1163d722e3fbSopenharmony_ci} 1164d722e3fbSopenharmony_ci 1165d722e3fbSopenharmony_ci 1166d722e3fbSopenharmony_ci/** 1167d722e3fbSopenharmony_ci * Open the DRM device. 1168d722e3fbSopenharmony_ci * 1169d722e3fbSopenharmony_ci * Looks up the specified name and bus ID, and opens the device found. The 1170d722e3fbSopenharmony_ci * entry in /dev/dri is created if necessary and if called by root. 1171d722e3fbSopenharmony_ci * 1172d722e3fbSopenharmony_ci * \param name driver name. Not referenced if bus ID is supplied. 1173d722e3fbSopenharmony_ci * \param busid bus ID. Zero if not known. 1174d722e3fbSopenharmony_ci * 1175d722e3fbSopenharmony_ci * \return a file descriptor on success, or a negative value on error. 1176d722e3fbSopenharmony_ci * 1177d722e3fbSopenharmony_ci * \internal 1178d722e3fbSopenharmony_ci * It calls drmOpenByBusid() if \p busid is specified or drmOpenByName() 1179d722e3fbSopenharmony_ci * otherwise. 1180d722e3fbSopenharmony_ci */ 1181d722e3fbSopenharmony_cidrm_public int drmOpen(const char *name, const char *busid) 1182d722e3fbSopenharmony_ci{ 1183d722e3fbSopenharmony_ci return drmOpenWithType(name, busid, DRM_NODE_PRIMARY); 1184d722e3fbSopenharmony_ci} 1185d722e3fbSopenharmony_ci 1186d722e3fbSopenharmony_ci/** 1187d722e3fbSopenharmony_ci * Open the DRM device with specified type. 1188d722e3fbSopenharmony_ci * 1189d722e3fbSopenharmony_ci * Looks up the specified name and bus ID, and opens the device found. The 1190d722e3fbSopenharmony_ci * entry in /dev/dri is created if necessary and if called by root. 1191d722e3fbSopenharmony_ci * 1192d722e3fbSopenharmony_ci * \param name driver name. Not referenced if bus ID is supplied. 1193d722e3fbSopenharmony_ci * \param busid bus ID. Zero if not known. 1194d722e3fbSopenharmony_ci * \param type the device node type to open, PRIMARY, CONTROL or RENDER 1195d722e3fbSopenharmony_ci * 1196d722e3fbSopenharmony_ci * \return a file descriptor on success, or a negative value on error. 1197d722e3fbSopenharmony_ci * 1198d722e3fbSopenharmony_ci * \internal 1199d722e3fbSopenharmony_ci * It calls drmOpenByBusid() if \p busid is specified or drmOpenByName() 1200d722e3fbSopenharmony_ci * otherwise. 1201d722e3fbSopenharmony_ci */ 1202d722e3fbSopenharmony_cidrm_public int drmOpenWithType(const char *name, const char *busid, int type) 1203d722e3fbSopenharmony_ci{ 1204d722e3fbSopenharmony_ci if (name != NULL && drm_server_info && 1205d722e3fbSopenharmony_ci drm_server_info->load_module && !drmAvailable()) { 1206d722e3fbSopenharmony_ci /* try to load the kernel module */ 1207d722e3fbSopenharmony_ci if (!drm_server_info->load_module(name)) { 1208d722e3fbSopenharmony_ci drmMsg("[drm] failed to load kernel module \"%s\"\n", name); 1209d722e3fbSopenharmony_ci return -1; 1210d722e3fbSopenharmony_ci } 1211d722e3fbSopenharmony_ci } 1212d722e3fbSopenharmony_ci 1213d722e3fbSopenharmony_ci if (busid) { 1214d722e3fbSopenharmony_ci int fd = drmOpenByBusid(busid, type); 1215d722e3fbSopenharmony_ci if (fd >= 0) 1216d722e3fbSopenharmony_ci return fd; 1217d722e3fbSopenharmony_ci } 1218d722e3fbSopenharmony_ci 1219d722e3fbSopenharmony_ci if (name) 1220d722e3fbSopenharmony_ci return drmOpenByName(name, type); 1221d722e3fbSopenharmony_ci 1222d722e3fbSopenharmony_ci return -1; 1223d722e3fbSopenharmony_ci} 1224d722e3fbSopenharmony_ci 1225d722e3fbSopenharmony_cidrm_public int drmOpenControl(int minor) 1226d722e3fbSopenharmony_ci{ 1227d722e3fbSopenharmony_ci return drmOpenMinor(minor, 0, DRM_NODE_CONTROL); 1228d722e3fbSopenharmony_ci} 1229d722e3fbSopenharmony_ci 1230d722e3fbSopenharmony_cidrm_public int drmOpenRender(int minor) 1231d722e3fbSopenharmony_ci{ 1232d722e3fbSopenharmony_ci return drmOpenMinor(minor, 0, DRM_NODE_RENDER); 1233d722e3fbSopenharmony_ci} 1234d722e3fbSopenharmony_ci 1235d722e3fbSopenharmony_ci/** 1236d722e3fbSopenharmony_ci * Free the version information returned by drmGetVersion(). 1237d722e3fbSopenharmony_ci * 1238d722e3fbSopenharmony_ci * \param v pointer to the version information. 1239d722e3fbSopenharmony_ci * 1240d722e3fbSopenharmony_ci * \internal 1241d722e3fbSopenharmony_ci * It frees the memory pointed by \p %v as well as all the non-null strings 1242d722e3fbSopenharmony_ci * pointers in it. 1243d722e3fbSopenharmony_ci */ 1244d722e3fbSopenharmony_cidrm_public void drmFreeVersion(drmVersionPtr v) 1245d722e3fbSopenharmony_ci{ 1246d722e3fbSopenharmony_ci if (!v) 1247d722e3fbSopenharmony_ci return; 1248d722e3fbSopenharmony_ci drmFree(v->name); 1249d722e3fbSopenharmony_ci drmFree(v->date); 1250d722e3fbSopenharmony_ci drmFree(v->desc); 1251d722e3fbSopenharmony_ci drmFree(v); 1252d722e3fbSopenharmony_ci} 1253d722e3fbSopenharmony_ci 1254d722e3fbSopenharmony_ci 1255d722e3fbSopenharmony_ci/** 1256d722e3fbSopenharmony_ci * Free the non-public version information returned by the kernel. 1257d722e3fbSopenharmony_ci * 1258d722e3fbSopenharmony_ci * \param v pointer to the version information. 1259d722e3fbSopenharmony_ci * 1260d722e3fbSopenharmony_ci * \internal 1261d722e3fbSopenharmony_ci * Used by drmGetVersion() to free the memory pointed by \p %v as well as all 1262d722e3fbSopenharmony_ci * the non-null strings pointers in it. 1263d722e3fbSopenharmony_ci */ 1264d722e3fbSopenharmony_cistatic void drmFreeKernelVersion(drm_version_t *v) 1265d722e3fbSopenharmony_ci{ 1266d722e3fbSopenharmony_ci if (!v) 1267d722e3fbSopenharmony_ci return; 1268d722e3fbSopenharmony_ci drmFree(v->name); 1269d722e3fbSopenharmony_ci drmFree(v->date); 1270d722e3fbSopenharmony_ci drmFree(v->desc); 1271d722e3fbSopenharmony_ci drmFree(v); 1272d722e3fbSopenharmony_ci} 1273d722e3fbSopenharmony_ci 1274d722e3fbSopenharmony_ci 1275d722e3fbSopenharmony_ci/** 1276d722e3fbSopenharmony_ci * Copy version information. 1277d722e3fbSopenharmony_ci * 1278d722e3fbSopenharmony_ci * \param d destination pointer. 1279d722e3fbSopenharmony_ci * \param s source pointer. 1280d722e3fbSopenharmony_ci * 1281d722e3fbSopenharmony_ci * \internal 1282d722e3fbSopenharmony_ci * Used by drmGetVersion() to translate the information returned by the ioctl 1283d722e3fbSopenharmony_ci * interface in a private structure into the public structure counterpart. 1284d722e3fbSopenharmony_ci */ 1285d722e3fbSopenharmony_cistatic void drmCopyVersion(drmVersionPtr d, const drm_version_t *s) 1286d722e3fbSopenharmony_ci{ 1287d722e3fbSopenharmony_ci d->version_major = s->version_major; 1288d722e3fbSopenharmony_ci d->version_minor = s->version_minor; 1289d722e3fbSopenharmony_ci d->version_patchlevel = s->version_patchlevel; 1290d722e3fbSopenharmony_ci d->name_len = s->name_len; 1291d722e3fbSopenharmony_ci d->name = strdup(s->name); 1292d722e3fbSopenharmony_ci d->date_len = s->date_len; 1293d722e3fbSopenharmony_ci d->date = strdup(s->date); 1294d722e3fbSopenharmony_ci d->desc_len = s->desc_len; 1295d722e3fbSopenharmony_ci d->desc = strdup(s->desc); 1296d722e3fbSopenharmony_ci} 1297d722e3fbSopenharmony_ci 1298d722e3fbSopenharmony_ci 1299d722e3fbSopenharmony_ci/** 1300d722e3fbSopenharmony_ci * Query the driver version information. 1301d722e3fbSopenharmony_ci * 1302d722e3fbSopenharmony_ci * \param fd file descriptor. 1303d722e3fbSopenharmony_ci * 1304d722e3fbSopenharmony_ci * \return pointer to a drmVersion structure which should be freed with 1305d722e3fbSopenharmony_ci * drmFreeVersion(). 1306d722e3fbSopenharmony_ci * 1307d722e3fbSopenharmony_ci * \note Similar information is available via /proc/dri. 1308d722e3fbSopenharmony_ci * 1309d722e3fbSopenharmony_ci * \internal 1310d722e3fbSopenharmony_ci * It gets the version information via successive DRM_IOCTL_VERSION ioctls, 1311d722e3fbSopenharmony_ci * first with zeros to get the string lengths, and then the actually strings. 1312d722e3fbSopenharmony_ci * It also null-terminates them since they might not be already. 1313d722e3fbSopenharmony_ci */ 1314d722e3fbSopenharmony_cidrm_public drmVersionPtr drmGetVersion(int fd) 1315d722e3fbSopenharmony_ci{ 1316d722e3fbSopenharmony_ci drmVersionPtr retval; 1317d722e3fbSopenharmony_ci drm_version_t *version = drmMalloc(sizeof(*version)); 1318d722e3fbSopenharmony_ci 1319d722e3fbSopenharmony_ci if (drmIoctl(fd, DRM_IOCTL_VERSION, version)) { 1320d722e3fbSopenharmony_ci drmFreeKernelVersion(version); 1321d722e3fbSopenharmony_ci return NULL; 1322d722e3fbSopenharmony_ci } 1323d722e3fbSopenharmony_ci 1324d722e3fbSopenharmony_ci if (version->name_len) 1325d722e3fbSopenharmony_ci version->name = drmMalloc(version->name_len + 1); 1326d722e3fbSopenharmony_ci if (version->date_len) 1327d722e3fbSopenharmony_ci version->date = drmMalloc(version->date_len + 1); 1328d722e3fbSopenharmony_ci if (version->desc_len) 1329d722e3fbSopenharmony_ci version->desc = drmMalloc(version->desc_len + 1); 1330d722e3fbSopenharmony_ci 1331d722e3fbSopenharmony_ci if (drmIoctl(fd, DRM_IOCTL_VERSION, version)) { 1332d722e3fbSopenharmony_ci drmMsg("DRM_IOCTL_VERSION: %s\n", strerror(errno)); 1333d722e3fbSopenharmony_ci drmFreeKernelVersion(version); 1334d722e3fbSopenharmony_ci return NULL; 1335d722e3fbSopenharmony_ci } 1336d722e3fbSopenharmony_ci 1337d722e3fbSopenharmony_ci /* The results might not be null-terminated strings, so terminate them. */ 1338d722e3fbSopenharmony_ci if (version->name_len) version->name[version->name_len] = '\0'; 1339d722e3fbSopenharmony_ci if (version->date_len) version->date[version->date_len] = '\0'; 1340d722e3fbSopenharmony_ci if (version->desc_len) version->desc[version->desc_len] = '\0'; 1341d722e3fbSopenharmony_ci 1342d722e3fbSopenharmony_ci retval = drmMalloc(sizeof(*retval)); 1343d722e3fbSopenharmony_ci drmCopyVersion(retval, version); 1344d722e3fbSopenharmony_ci drmFreeKernelVersion(version); 1345d722e3fbSopenharmony_ci return retval; 1346d722e3fbSopenharmony_ci} 1347d722e3fbSopenharmony_ci 1348d722e3fbSopenharmony_ci 1349d722e3fbSopenharmony_ci/** 1350d722e3fbSopenharmony_ci * Get version information for the DRM user space library. 1351d722e3fbSopenharmony_ci * 1352d722e3fbSopenharmony_ci * This version number is driver independent. 1353d722e3fbSopenharmony_ci * 1354d722e3fbSopenharmony_ci * \param fd file descriptor. 1355d722e3fbSopenharmony_ci * 1356d722e3fbSopenharmony_ci * \return version information. 1357d722e3fbSopenharmony_ci * 1358d722e3fbSopenharmony_ci * \internal 1359d722e3fbSopenharmony_ci * This function allocates and fills a drm_version structure with a hard coded 1360d722e3fbSopenharmony_ci * version number. 1361d722e3fbSopenharmony_ci */ 1362d722e3fbSopenharmony_cidrm_public drmVersionPtr drmGetLibVersion(int fd) 1363d722e3fbSopenharmony_ci{ 1364d722e3fbSopenharmony_ci drm_version_t *version = drmMalloc(sizeof(*version)); 1365d722e3fbSopenharmony_ci 1366d722e3fbSopenharmony_ci /* Version history: 1367d722e3fbSopenharmony_ci * NOTE THIS MUST NOT GO ABOVE VERSION 1.X due to drivers needing it 1368d722e3fbSopenharmony_ci * revision 1.0.x = original DRM interface with no drmGetLibVersion 1369d722e3fbSopenharmony_ci * entry point and many drm<Device> extensions 1370d722e3fbSopenharmony_ci * revision 1.1.x = added drmCommand entry points for device extensions 1371d722e3fbSopenharmony_ci * added drmGetLibVersion to identify libdrm.a version 1372d722e3fbSopenharmony_ci * revision 1.2.x = added drmSetInterfaceVersion 1373d722e3fbSopenharmony_ci * modified drmOpen to handle both busid and name 1374d722e3fbSopenharmony_ci * revision 1.3.x = added server + memory manager 1375d722e3fbSopenharmony_ci */ 1376d722e3fbSopenharmony_ci version->version_major = 1; 1377d722e3fbSopenharmony_ci version->version_minor = 3; 1378d722e3fbSopenharmony_ci version->version_patchlevel = 0; 1379d722e3fbSopenharmony_ci 1380d722e3fbSopenharmony_ci return (drmVersionPtr)version; 1381d722e3fbSopenharmony_ci} 1382d722e3fbSopenharmony_ci 1383d722e3fbSopenharmony_cidrm_public int drmGetCap(int fd, uint64_t capability, uint64_t *value) 1384d722e3fbSopenharmony_ci{ 1385d722e3fbSopenharmony_ci struct drm_get_cap cap; 1386d722e3fbSopenharmony_ci int ret; 1387d722e3fbSopenharmony_ci 1388d722e3fbSopenharmony_ci memclear(cap); 1389d722e3fbSopenharmony_ci cap.capability = capability; 1390d722e3fbSopenharmony_ci 1391d722e3fbSopenharmony_ci ret = drmIoctl(fd, DRM_IOCTL_GET_CAP, &cap); 1392d722e3fbSopenharmony_ci if (ret) 1393d722e3fbSopenharmony_ci return ret; 1394d722e3fbSopenharmony_ci 1395d722e3fbSopenharmony_ci *value = cap.value; 1396d722e3fbSopenharmony_ci return 0; 1397d722e3fbSopenharmony_ci} 1398d722e3fbSopenharmony_ci 1399d722e3fbSopenharmony_cidrm_public int drmSetClientCap(int fd, uint64_t capability, uint64_t value) 1400d722e3fbSopenharmony_ci{ 1401d722e3fbSopenharmony_ci struct drm_set_client_cap cap; 1402d722e3fbSopenharmony_ci 1403d722e3fbSopenharmony_ci memclear(cap); 1404d722e3fbSopenharmony_ci cap.capability = capability; 1405d722e3fbSopenharmony_ci cap.value = value; 1406d722e3fbSopenharmony_ci 1407d722e3fbSopenharmony_ci return drmIoctl(fd, DRM_IOCTL_SET_CLIENT_CAP, &cap); 1408d722e3fbSopenharmony_ci} 1409d722e3fbSopenharmony_ci 1410d722e3fbSopenharmony_ci/** 1411d722e3fbSopenharmony_ci * Free the bus ID information. 1412d722e3fbSopenharmony_ci * 1413d722e3fbSopenharmony_ci * \param busid bus ID information string as given by drmGetBusid(). 1414d722e3fbSopenharmony_ci * 1415d722e3fbSopenharmony_ci * \internal 1416d722e3fbSopenharmony_ci * This function is just frees the memory pointed by \p busid. 1417d722e3fbSopenharmony_ci */ 1418d722e3fbSopenharmony_cidrm_public void drmFreeBusid(const char *busid) 1419d722e3fbSopenharmony_ci{ 1420d722e3fbSopenharmony_ci drmFree((void *)busid); 1421d722e3fbSopenharmony_ci} 1422d722e3fbSopenharmony_ci 1423d722e3fbSopenharmony_ci 1424d722e3fbSopenharmony_ci/** 1425d722e3fbSopenharmony_ci * Get the bus ID of the device. 1426d722e3fbSopenharmony_ci * 1427d722e3fbSopenharmony_ci * \param fd file descriptor. 1428d722e3fbSopenharmony_ci * 1429d722e3fbSopenharmony_ci * \return bus ID string. 1430d722e3fbSopenharmony_ci * 1431d722e3fbSopenharmony_ci * \internal 1432d722e3fbSopenharmony_ci * This function gets the bus ID via successive DRM_IOCTL_GET_UNIQUE ioctls to 1433d722e3fbSopenharmony_ci * get the string length and data, passing the arguments in a drm_unique 1434d722e3fbSopenharmony_ci * structure. 1435d722e3fbSopenharmony_ci */ 1436d722e3fbSopenharmony_cidrm_public char *drmGetBusid(int fd) 1437d722e3fbSopenharmony_ci{ 1438d722e3fbSopenharmony_ci drm_unique_t u; 1439d722e3fbSopenharmony_ci 1440d722e3fbSopenharmony_ci memclear(u); 1441d722e3fbSopenharmony_ci 1442d722e3fbSopenharmony_ci if (drmIoctl(fd, DRM_IOCTL_GET_UNIQUE, &u)) 1443d722e3fbSopenharmony_ci return NULL; 1444d722e3fbSopenharmony_ci u.unique = drmMalloc(u.unique_len + 1); 1445d722e3fbSopenharmony_ci if (drmIoctl(fd, DRM_IOCTL_GET_UNIQUE, &u)) { 1446d722e3fbSopenharmony_ci drmFree(u.unique); 1447d722e3fbSopenharmony_ci return NULL; 1448d722e3fbSopenharmony_ci } 1449d722e3fbSopenharmony_ci u.unique[u.unique_len] = '\0'; 1450d722e3fbSopenharmony_ci 1451d722e3fbSopenharmony_ci return u.unique; 1452d722e3fbSopenharmony_ci} 1453d722e3fbSopenharmony_ci 1454d722e3fbSopenharmony_ci 1455d722e3fbSopenharmony_ci/** 1456d722e3fbSopenharmony_ci * Set the bus ID of the device. 1457d722e3fbSopenharmony_ci * 1458d722e3fbSopenharmony_ci * \param fd file descriptor. 1459d722e3fbSopenharmony_ci * \param busid bus ID string. 1460d722e3fbSopenharmony_ci * 1461d722e3fbSopenharmony_ci * \return zero on success, negative on failure. 1462d722e3fbSopenharmony_ci * 1463d722e3fbSopenharmony_ci * \internal 1464d722e3fbSopenharmony_ci * This function is a wrapper around the DRM_IOCTL_SET_UNIQUE ioctl, passing 1465d722e3fbSopenharmony_ci * the arguments in a drm_unique structure. 1466d722e3fbSopenharmony_ci */ 1467d722e3fbSopenharmony_cidrm_public int drmSetBusid(int fd, const char *busid) 1468d722e3fbSopenharmony_ci{ 1469d722e3fbSopenharmony_ci drm_unique_t u; 1470d722e3fbSopenharmony_ci 1471d722e3fbSopenharmony_ci memclear(u); 1472d722e3fbSopenharmony_ci u.unique = (char *)busid; 1473d722e3fbSopenharmony_ci u.unique_len = strlen(busid); 1474d722e3fbSopenharmony_ci 1475d722e3fbSopenharmony_ci if (drmIoctl(fd, DRM_IOCTL_SET_UNIQUE, &u)) { 1476d722e3fbSopenharmony_ci return -errno; 1477d722e3fbSopenharmony_ci } 1478d722e3fbSopenharmony_ci return 0; 1479d722e3fbSopenharmony_ci} 1480d722e3fbSopenharmony_ci 1481d722e3fbSopenharmony_cidrm_public int drmGetMagic(int fd, drm_magic_t * magic) 1482d722e3fbSopenharmony_ci{ 1483d722e3fbSopenharmony_ci drm_auth_t auth; 1484d722e3fbSopenharmony_ci 1485d722e3fbSopenharmony_ci memclear(auth); 1486d722e3fbSopenharmony_ci 1487d722e3fbSopenharmony_ci *magic = 0; 1488d722e3fbSopenharmony_ci if (drmIoctl(fd, DRM_IOCTL_GET_MAGIC, &auth)) 1489d722e3fbSopenharmony_ci return -errno; 1490d722e3fbSopenharmony_ci *magic = auth.magic; 1491d722e3fbSopenharmony_ci return 0; 1492d722e3fbSopenharmony_ci} 1493d722e3fbSopenharmony_ci 1494d722e3fbSopenharmony_cidrm_public int drmAuthMagic(int fd, drm_magic_t magic) 1495d722e3fbSopenharmony_ci{ 1496d722e3fbSopenharmony_ci drm_auth_t auth; 1497d722e3fbSopenharmony_ci 1498d722e3fbSopenharmony_ci memclear(auth); 1499d722e3fbSopenharmony_ci auth.magic = magic; 1500d722e3fbSopenharmony_ci if (drmIoctl(fd, DRM_IOCTL_AUTH_MAGIC, &auth)) 1501d722e3fbSopenharmony_ci return -errno; 1502d722e3fbSopenharmony_ci return 0; 1503d722e3fbSopenharmony_ci} 1504d722e3fbSopenharmony_ci 1505d722e3fbSopenharmony_ci/** 1506d722e3fbSopenharmony_ci * Specifies a range of memory that is available for mapping by a 1507d722e3fbSopenharmony_ci * non-root process. 1508d722e3fbSopenharmony_ci * 1509d722e3fbSopenharmony_ci * \param fd file descriptor. 1510d722e3fbSopenharmony_ci * \param offset usually the physical address. The actual meaning depends of 1511d722e3fbSopenharmony_ci * the \p type parameter. See below. 1512d722e3fbSopenharmony_ci * \param size of the memory in bytes. 1513d722e3fbSopenharmony_ci * \param type type of the memory to be mapped. 1514d722e3fbSopenharmony_ci * \param flags combination of several flags to modify the function actions. 1515d722e3fbSopenharmony_ci * \param handle will be set to a value that may be used as the offset 1516d722e3fbSopenharmony_ci * parameter for mmap(). 1517d722e3fbSopenharmony_ci * 1518d722e3fbSopenharmony_ci * \return zero on success or a negative value on error. 1519d722e3fbSopenharmony_ci * 1520d722e3fbSopenharmony_ci * \par Mapping the frame buffer 1521d722e3fbSopenharmony_ci * For the frame buffer 1522d722e3fbSopenharmony_ci * - \p offset will be the physical address of the start of the frame buffer, 1523d722e3fbSopenharmony_ci * - \p size will be the size of the frame buffer in bytes, and 1524d722e3fbSopenharmony_ci * - \p type will be DRM_FRAME_BUFFER. 1525d722e3fbSopenharmony_ci * 1526d722e3fbSopenharmony_ci * \par 1527d722e3fbSopenharmony_ci * The area mapped will be uncached. If MTRR support is available in the 1528d722e3fbSopenharmony_ci * kernel, the frame buffer area will be set to write combining. 1529d722e3fbSopenharmony_ci * 1530d722e3fbSopenharmony_ci * \par Mapping the MMIO register area 1531d722e3fbSopenharmony_ci * For the MMIO register area, 1532d722e3fbSopenharmony_ci * - \p offset will be the physical address of the start of the register area, 1533d722e3fbSopenharmony_ci * - \p size will be the size of the register area bytes, and 1534d722e3fbSopenharmony_ci * - \p type will be DRM_REGISTERS. 1535d722e3fbSopenharmony_ci * \par 1536d722e3fbSopenharmony_ci * The area mapped will be uncached. 1537d722e3fbSopenharmony_ci * 1538d722e3fbSopenharmony_ci * \par Mapping the SAREA 1539d722e3fbSopenharmony_ci * For the SAREA, 1540d722e3fbSopenharmony_ci * - \p offset will be ignored and should be set to zero, 1541d722e3fbSopenharmony_ci * - \p size will be the desired size of the SAREA in bytes, 1542d722e3fbSopenharmony_ci * - \p type will be DRM_SHM. 1543d722e3fbSopenharmony_ci * 1544d722e3fbSopenharmony_ci * \par 1545d722e3fbSopenharmony_ci * A shared memory area of the requested size will be created and locked in 1546d722e3fbSopenharmony_ci * kernel memory. This area may be mapped into client-space by using the handle 1547d722e3fbSopenharmony_ci * returned. 1548d722e3fbSopenharmony_ci * 1549d722e3fbSopenharmony_ci * \note May only be called by root. 1550d722e3fbSopenharmony_ci * 1551d722e3fbSopenharmony_ci * \internal 1552d722e3fbSopenharmony_ci * This function is a wrapper around the DRM_IOCTL_ADD_MAP ioctl, passing 1553d722e3fbSopenharmony_ci * the arguments in a drm_map structure. 1554d722e3fbSopenharmony_ci */ 1555d722e3fbSopenharmony_cidrm_public int drmAddMap(int fd, drm_handle_t offset, drmSize size, drmMapType type, 1556d722e3fbSopenharmony_ci drmMapFlags flags, drm_handle_t *handle) 1557d722e3fbSopenharmony_ci{ 1558d722e3fbSopenharmony_ci drm_map_t map; 1559d722e3fbSopenharmony_ci 1560d722e3fbSopenharmony_ci memclear(map); 1561d722e3fbSopenharmony_ci map.offset = offset; 1562d722e3fbSopenharmony_ci map.size = size; 1563d722e3fbSopenharmony_ci map.type = (enum drm_map_type)type; 1564d722e3fbSopenharmony_ci map.flags = (enum drm_map_flags)flags; 1565d722e3fbSopenharmony_ci if (drmIoctl(fd, DRM_IOCTL_ADD_MAP, &map)) 1566d722e3fbSopenharmony_ci return -errno; 1567d722e3fbSopenharmony_ci if (handle) 1568d722e3fbSopenharmony_ci *handle = (drm_handle_t)(uintptr_t)map.handle; 1569d722e3fbSopenharmony_ci return 0; 1570d722e3fbSopenharmony_ci} 1571d722e3fbSopenharmony_ci 1572d722e3fbSopenharmony_cidrm_public int drmRmMap(int fd, drm_handle_t handle) 1573d722e3fbSopenharmony_ci{ 1574d722e3fbSopenharmony_ci drm_map_t map; 1575d722e3fbSopenharmony_ci 1576d722e3fbSopenharmony_ci memclear(map); 1577d722e3fbSopenharmony_ci map.handle = (void *)(uintptr_t)handle; 1578d722e3fbSopenharmony_ci 1579d722e3fbSopenharmony_ci if(drmIoctl(fd, DRM_IOCTL_RM_MAP, &map)) 1580d722e3fbSopenharmony_ci return -errno; 1581d722e3fbSopenharmony_ci return 0; 1582d722e3fbSopenharmony_ci} 1583d722e3fbSopenharmony_ci 1584d722e3fbSopenharmony_ci/** 1585d722e3fbSopenharmony_ci * Make buffers available for DMA transfers. 1586d722e3fbSopenharmony_ci * 1587d722e3fbSopenharmony_ci * \param fd file descriptor. 1588d722e3fbSopenharmony_ci * \param count number of buffers. 1589d722e3fbSopenharmony_ci * \param size size of each buffer. 1590d722e3fbSopenharmony_ci * \param flags buffer allocation flags. 1591d722e3fbSopenharmony_ci * \param agp_offset offset in the AGP aperture 1592d722e3fbSopenharmony_ci * 1593d722e3fbSopenharmony_ci * \return number of buffers allocated, negative on error. 1594d722e3fbSopenharmony_ci * 1595d722e3fbSopenharmony_ci * \internal 1596d722e3fbSopenharmony_ci * This function is a wrapper around DRM_IOCTL_ADD_BUFS ioctl. 1597d722e3fbSopenharmony_ci * 1598d722e3fbSopenharmony_ci * \sa drm_buf_desc. 1599d722e3fbSopenharmony_ci */ 1600d722e3fbSopenharmony_cidrm_public int drmAddBufs(int fd, int count, int size, drmBufDescFlags flags, 1601d722e3fbSopenharmony_ci int agp_offset) 1602d722e3fbSopenharmony_ci{ 1603d722e3fbSopenharmony_ci drm_buf_desc_t request; 1604d722e3fbSopenharmony_ci 1605d722e3fbSopenharmony_ci memclear(request); 1606d722e3fbSopenharmony_ci request.count = count; 1607d722e3fbSopenharmony_ci request.size = size; 1608d722e3fbSopenharmony_ci request.flags = (int)flags; 1609d722e3fbSopenharmony_ci request.agp_start = agp_offset; 1610d722e3fbSopenharmony_ci 1611d722e3fbSopenharmony_ci if (drmIoctl(fd, DRM_IOCTL_ADD_BUFS, &request)) 1612d722e3fbSopenharmony_ci return -errno; 1613d722e3fbSopenharmony_ci return request.count; 1614d722e3fbSopenharmony_ci} 1615d722e3fbSopenharmony_ci 1616d722e3fbSopenharmony_cidrm_public int drmMarkBufs(int fd, double low, double high) 1617d722e3fbSopenharmony_ci{ 1618d722e3fbSopenharmony_ci drm_buf_info_t info; 1619d722e3fbSopenharmony_ci int i; 1620d722e3fbSopenharmony_ci 1621d722e3fbSopenharmony_ci memclear(info); 1622d722e3fbSopenharmony_ci 1623d722e3fbSopenharmony_ci if (drmIoctl(fd, DRM_IOCTL_INFO_BUFS, &info)) 1624d722e3fbSopenharmony_ci return -EINVAL; 1625d722e3fbSopenharmony_ci 1626d722e3fbSopenharmony_ci if (!info.count) 1627d722e3fbSopenharmony_ci return -EINVAL; 1628d722e3fbSopenharmony_ci 1629d722e3fbSopenharmony_ci if (!(info.list = drmMalloc(info.count * sizeof(*info.list)))) 1630d722e3fbSopenharmony_ci return -ENOMEM; 1631d722e3fbSopenharmony_ci 1632d722e3fbSopenharmony_ci if (drmIoctl(fd, DRM_IOCTL_INFO_BUFS, &info)) { 1633d722e3fbSopenharmony_ci int retval = -errno; 1634d722e3fbSopenharmony_ci drmFree(info.list); 1635d722e3fbSopenharmony_ci return retval; 1636d722e3fbSopenharmony_ci } 1637d722e3fbSopenharmony_ci 1638d722e3fbSopenharmony_ci for (i = 0; i < info.count; i++) { 1639d722e3fbSopenharmony_ci info.list[i].low_mark = low * info.list[i].count; 1640d722e3fbSopenharmony_ci info.list[i].high_mark = high * info.list[i].count; 1641d722e3fbSopenharmony_ci if (drmIoctl(fd, DRM_IOCTL_MARK_BUFS, &info.list[i])) { 1642d722e3fbSopenharmony_ci int retval = -errno; 1643d722e3fbSopenharmony_ci drmFree(info.list); 1644d722e3fbSopenharmony_ci return retval; 1645d722e3fbSopenharmony_ci } 1646d722e3fbSopenharmony_ci } 1647d722e3fbSopenharmony_ci drmFree(info.list); 1648d722e3fbSopenharmony_ci 1649d722e3fbSopenharmony_ci return 0; 1650d722e3fbSopenharmony_ci} 1651d722e3fbSopenharmony_ci 1652d722e3fbSopenharmony_ci/** 1653d722e3fbSopenharmony_ci * Free buffers. 1654d722e3fbSopenharmony_ci * 1655d722e3fbSopenharmony_ci * \param fd file descriptor. 1656d722e3fbSopenharmony_ci * \param count number of buffers to free. 1657d722e3fbSopenharmony_ci * \param list list of buffers to be freed. 1658d722e3fbSopenharmony_ci * 1659d722e3fbSopenharmony_ci * \return zero on success, or a negative value on failure. 1660d722e3fbSopenharmony_ci * 1661d722e3fbSopenharmony_ci * \note This function is primarily used for debugging. 1662d722e3fbSopenharmony_ci * 1663d722e3fbSopenharmony_ci * \internal 1664d722e3fbSopenharmony_ci * This function is a wrapper around the DRM_IOCTL_FREE_BUFS ioctl, passing 1665d722e3fbSopenharmony_ci * the arguments in a drm_buf_free structure. 1666d722e3fbSopenharmony_ci */ 1667d722e3fbSopenharmony_cidrm_public int drmFreeBufs(int fd, int count, int *list) 1668d722e3fbSopenharmony_ci{ 1669d722e3fbSopenharmony_ci drm_buf_free_t request; 1670d722e3fbSopenharmony_ci 1671d722e3fbSopenharmony_ci memclear(request); 1672d722e3fbSopenharmony_ci request.count = count; 1673d722e3fbSopenharmony_ci request.list = list; 1674d722e3fbSopenharmony_ci if (drmIoctl(fd, DRM_IOCTL_FREE_BUFS, &request)) 1675d722e3fbSopenharmony_ci return -errno; 1676d722e3fbSopenharmony_ci return 0; 1677d722e3fbSopenharmony_ci} 1678d722e3fbSopenharmony_ci 1679d722e3fbSopenharmony_ci 1680d722e3fbSopenharmony_ci/** 1681d722e3fbSopenharmony_ci * Close the device. 1682d722e3fbSopenharmony_ci * 1683d722e3fbSopenharmony_ci * \param fd file descriptor. 1684d722e3fbSopenharmony_ci * 1685d722e3fbSopenharmony_ci * \internal 1686d722e3fbSopenharmony_ci * This function closes the file descriptor. 1687d722e3fbSopenharmony_ci */ 1688d722e3fbSopenharmony_cidrm_public int drmClose(int fd) 1689d722e3fbSopenharmony_ci{ 1690d722e3fbSopenharmony_ci unsigned long key = drmGetKeyFromFd(fd); 1691d722e3fbSopenharmony_ci drmHashEntry *entry = drmGetEntry(fd); 1692d722e3fbSopenharmony_ci 1693d722e3fbSopenharmony_ci drmHashDestroy(entry->tagTable); 1694d722e3fbSopenharmony_ci entry->fd = 0; 1695d722e3fbSopenharmony_ci entry->f = NULL; 1696d722e3fbSopenharmony_ci entry->tagTable = NULL; 1697d722e3fbSopenharmony_ci 1698d722e3fbSopenharmony_ci drmHashDelete(drmHashTable, key); 1699d722e3fbSopenharmony_ci drmFree(entry); 1700d722e3fbSopenharmony_ci 1701d722e3fbSopenharmony_ci return close(fd); 1702d722e3fbSopenharmony_ci} 1703d722e3fbSopenharmony_ci 1704d722e3fbSopenharmony_ci 1705d722e3fbSopenharmony_ci/** 1706d722e3fbSopenharmony_ci * Map a region of memory. 1707d722e3fbSopenharmony_ci * 1708d722e3fbSopenharmony_ci * \param fd file descriptor. 1709d722e3fbSopenharmony_ci * \param handle handle returned by drmAddMap(). 1710d722e3fbSopenharmony_ci * \param size size in bytes. Must match the size used by drmAddMap(). 1711d722e3fbSopenharmony_ci * \param address will contain the user-space virtual address where the mapping 1712d722e3fbSopenharmony_ci * begins. 1713d722e3fbSopenharmony_ci * 1714d722e3fbSopenharmony_ci * \return zero on success, or a negative value on failure. 1715d722e3fbSopenharmony_ci * 1716d722e3fbSopenharmony_ci * \internal 1717d722e3fbSopenharmony_ci * This function is a wrapper for mmap(). 1718d722e3fbSopenharmony_ci */ 1719d722e3fbSopenharmony_cidrm_public int drmMap(int fd, drm_handle_t handle, drmSize size, 1720d722e3fbSopenharmony_ci drmAddressPtr address) 1721d722e3fbSopenharmony_ci{ 1722d722e3fbSopenharmony_ci static unsigned long pagesize_mask = 0; 1723d722e3fbSopenharmony_ci 1724d722e3fbSopenharmony_ci if (fd < 0) 1725d722e3fbSopenharmony_ci return -EINVAL; 1726d722e3fbSopenharmony_ci 1727d722e3fbSopenharmony_ci if (!pagesize_mask) 1728d722e3fbSopenharmony_ci pagesize_mask = getpagesize() - 1; 1729d722e3fbSopenharmony_ci 1730d722e3fbSopenharmony_ci size = (size + pagesize_mask) & ~pagesize_mask; 1731d722e3fbSopenharmony_ci 1732d722e3fbSopenharmony_ci *address = drm_mmap(0, size, PROT_READ|PROT_WRITE, MAP_SHARED, fd, handle); 1733d722e3fbSopenharmony_ci if (*address == MAP_FAILED) 1734d722e3fbSopenharmony_ci return -errno; 1735d722e3fbSopenharmony_ci return 0; 1736d722e3fbSopenharmony_ci} 1737d722e3fbSopenharmony_ci 1738d722e3fbSopenharmony_ci 1739d722e3fbSopenharmony_ci/** 1740d722e3fbSopenharmony_ci * Unmap mappings obtained with drmMap(). 1741d722e3fbSopenharmony_ci * 1742d722e3fbSopenharmony_ci * \param address address as given by drmMap(). 1743d722e3fbSopenharmony_ci * \param size size in bytes. Must match the size used by drmMap(). 1744d722e3fbSopenharmony_ci * 1745d722e3fbSopenharmony_ci * \return zero on success, or a negative value on failure. 1746d722e3fbSopenharmony_ci * 1747d722e3fbSopenharmony_ci * \internal 1748d722e3fbSopenharmony_ci * This function is a wrapper for munmap(). 1749d722e3fbSopenharmony_ci */ 1750d722e3fbSopenharmony_cidrm_public int drmUnmap(drmAddress address, drmSize size) 1751d722e3fbSopenharmony_ci{ 1752d722e3fbSopenharmony_ci return drm_munmap(address, size); 1753d722e3fbSopenharmony_ci} 1754d722e3fbSopenharmony_ci 1755d722e3fbSopenharmony_cidrm_public drmBufInfoPtr drmGetBufInfo(int fd) 1756d722e3fbSopenharmony_ci{ 1757d722e3fbSopenharmony_ci drm_buf_info_t info; 1758d722e3fbSopenharmony_ci drmBufInfoPtr retval; 1759d722e3fbSopenharmony_ci int i; 1760d722e3fbSopenharmony_ci 1761d722e3fbSopenharmony_ci memclear(info); 1762d722e3fbSopenharmony_ci 1763d722e3fbSopenharmony_ci if (drmIoctl(fd, DRM_IOCTL_INFO_BUFS, &info)) 1764d722e3fbSopenharmony_ci return NULL; 1765d722e3fbSopenharmony_ci 1766d722e3fbSopenharmony_ci if (info.count) { 1767d722e3fbSopenharmony_ci if (!(info.list = drmMalloc(info.count * sizeof(*info.list)))) 1768d722e3fbSopenharmony_ci return NULL; 1769d722e3fbSopenharmony_ci 1770d722e3fbSopenharmony_ci if (drmIoctl(fd, DRM_IOCTL_INFO_BUFS, &info)) { 1771d722e3fbSopenharmony_ci drmFree(info.list); 1772d722e3fbSopenharmony_ci return NULL; 1773d722e3fbSopenharmony_ci } 1774d722e3fbSopenharmony_ci 1775d722e3fbSopenharmony_ci retval = drmMalloc(sizeof(*retval)); 1776d722e3fbSopenharmony_ci retval->count = info.count; 1777d722e3fbSopenharmony_ci if (!(retval->list = drmMalloc(info.count * sizeof(*retval->list)))) { 1778d722e3fbSopenharmony_ci drmFree(retval); 1779d722e3fbSopenharmony_ci drmFree(info.list); 1780d722e3fbSopenharmony_ci return NULL; 1781d722e3fbSopenharmony_ci } 1782d722e3fbSopenharmony_ci 1783d722e3fbSopenharmony_ci for (i = 0; i < info.count; i++) { 1784d722e3fbSopenharmony_ci retval->list[i].count = info.list[i].count; 1785d722e3fbSopenharmony_ci retval->list[i].size = info.list[i].size; 1786d722e3fbSopenharmony_ci retval->list[i].low_mark = info.list[i].low_mark; 1787d722e3fbSopenharmony_ci retval->list[i].high_mark = info.list[i].high_mark; 1788d722e3fbSopenharmony_ci } 1789d722e3fbSopenharmony_ci drmFree(info.list); 1790d722e3fbSopenharmony_ci return retval; 1791d722e3fbSopenharmony_ci } 1792d722e3fbSopenharmony_ci return NULL; 1793d722e3fbSopenharmony_ci} 1794d722e3fbSopenharmony_ci 1795d722e3fbSopenharmony_ci/** 1796d722e3fbSopenharmony_ci * Map all DMA buffers into client-virtual space. 1797d722e3fbSopenharmony_ci * 1798d722e3fbSopenharmony_ci * \param fd file descriptor. 1799d722e3fbSopenharmony_ci * 1800d722e3fbSopenharmony_ci * \return a pointer to a ::drmBufMap structure. 1801d722e3fbSopenharmony_ci * 1802d722e3fbSopenharmony_ci * \note The client may not use these buffers until obtaining buffer indices 1803d722e3fbSopenharmony_ci * with drmDMA(). 1804d722e3fbSopenharmony_ci * 1805d722e3fbSopenharmony_ci * \internal 1806d722e3fbSopenharmony_ci * This function calls the DRM_IOCTL_MAP_BUFS ioctl and copies the returned 1807d722e3fbSopenharmony_ci * information about the buffers in a drm_buf_map structure into the 1808d722e3fbSopenharmony_ci * client-visible data structures. 1809d722e3fbSopenharmony_ci */ 1810d722e3fbSopenharmony_cidrm_public drmBufMapPtr drmMapBufs(int fd) 1811d722e3fbSopenharmony_ci{ 1812d722e3fbSopenharmony_ci drm_buf_map_t bufs; 1813d722e3fbSopenharmony_ci drmBufMapPtr retval; 1814d722e3fbSopenharmony_ci int i; 1815d722e3fbSopenharmony_ci 1816d722e3fbSopenharmony_ci memclear(bufs); 1817d722e3fbSopenharmony_ci if (drmIoctl(fd, DRM_IOCTL_MAP_BUFS, &bufs)) 1818d722e3fbSopenharmony_ci return NULL; 1819d722e3fbSopenharmony_ci 1820d722e3fbSopenharmony_ci if (!bufs.count) 1821d722e3fbSopenharmony_ci return NULL; 1822d722e3fbSopenharmony_ci 1823d722e3fbSopenharmony_ci if (!(bufs.list = drmMalloc(bufs.count * sizeof(*bufs.list)))) 1824d722e3fbSopenharmony_ci return NULL; 1825d722e3fbSopenharmony_ci 1826d722e3fbSopenharmony_ci if (drmIoctl(fd, DRM_IOCTL_MAP_BUFS, &bufs)) { 1827d722e3fbSopenharmony_ci drmFree(bufs.list); 1828d722e3fbSopenharmony_ci return NULL; 1829d722e3fbSopenharmony_ci } 1830d722e3fbSopenharmony_ci 1831d722e3fbSopenharmony_ci retval = drmMalloc(sizeof(*retval)); 1832d722e3fbSopenharmony_ci retval->count = bufs.count; 1833d722e3fbSopenharmony_ci retval->list = drmMalloc(bufs.count * sizeof(*retval->list)); 1834d722e3fbSopenharmony_ci for (i = 0; i < bufs.count; i++) { 1835d722e3fbSopenharmony_ci retval->list[i].idx = bufs.list[i].idx; 1836d722e3fbSopenharmony_ci retval->list[i].total = bufs.list[i].total; 1837d722e3fbSopenharmony_ci retval->list[i].used = 0; 1838d722e3fbSopenharmony_ci retval->list[i].address = bufs.list[i].address; 1839d722e3fbSopenharmony_ci } 1840d722e3fbSopenharmony_ci 1841d722e3fbSopenharmony_ci drmFree(bufs.list); 1842d722e3fbSopenharmony_ci return retval; 1843d722e3fbSopenharmony_ci} 1844d722e3fbSopenharmony_ci 1845d722e3fbSopenharmony_ci 1846d722e3fbSopenharmony_ci/** 1847d722e3fbSopenharmony_ci * Unmap buffers allocated with drmMapBufs(). 1848d722e3fbSopenharmony_ci * 1849d722e3fbSopenharmony_ci * \return zero on success, or negative value on failure. 1850d722e3fbSopenharmony_ci * 1851d722e3fbSopenharmony_ci * \internal 1852d722e3fbSopenharmony_ci * Calls munmap() for every buffer stored in \p bufs and frees the 1853d722e3fbSopenharmony_ci * memory allocated by drmMapBufs(). 1854d722e3fbSopenharmony_ci */ 1855d722e3fbSopenharmony_cidrm_public int drmUnmapBufs(drmBufMapPtr bufs) 1856d722e3fbSopenharmony_ci{ 1857d722e3fbSopenharmony_ci int i; 1858d722e3fbSopenharmony_ci 1859d722e3fbSopenharmony_ci for (i = 0; i < bufs->count; i++) { 1860d722e3fbSopenharmony_ci drm_munmap(bufs->list[i].address, bufs->list[i].total); 1861d722e3fbSopenharmony_ci } 1862d722e3fbSopenharmony_ci 1863d722e3fbSopenharmony_ci drmFree(bufs->list); 1864d722e3fbSopenharmony_ci drmFree(bufs); 1865d722e3fbSopenharmony_ci return 0; 1866d722e3fbSopenharmony_ci} 1867d722e3fbSopenharmony_ci 1868d722e3fbSopenharmony_ci 1869d722e3fbSopenharmony_ci#define DRM_DMA_RETRY 16 1870d722e3fbSopenharmony_ci 1871d722e3fbSopenharmony_ci/** 1872d722e3fbSopenharmony_ci * Reserve DMA buffers. 1873d722e3fbSopenharmony_ci * 1874d722e3fbSopenharmony_ci * \param fd file descriptor. 1875d722e3fbSopenharmony_ci * \param request 1876d722e3fbSopenharmony_ci * 1877d722e3fbSopenharmony_ci * \return zero on success, or a negative value on failure. 1878d722e3fbSopenharmony_ci * 1879d722e3fbSopenharmony_ci * \internal 1880d722e3fbSopenharmony_ci * Assemble the arguments into a drm_dma structure and keeps issuing the 1881d722e3fbSopenharmony_ci * DRM_IOCTL_DMA ioctl until success or until maximum number of retries. 1882d722e3fbSopenharmony_ci */ 1883d722e3fbSopenharmony_cidrm_public int drmDMA(int fd, drmDMAReqPtr request) 1884d722e3fbSopenharmony_ci{ 1885d722e3fbSopenharmony_ci drm_dma_t dma; 1886d722e3fbSopenharmony_ci int ret, i = 0; 1887d722e3fbSopenharmony_ci 1888d722e3fbSopenharmony_ci dma.context = request->context; 1889d722e3fbSopenharmony_ci dma.send_count = request->send_count; 1890d722e3fbSopenharmony_ci dma.send_indices = request->send_list; 1891d722e3fbSopenharmony_ci dma.send_sizes = request->send_sizes; 1892d722e3fbSopenharmony_ci dma.flags = (enum drm_dma_flags)request->flags; 1893d722e3fbSopenharmony_ci dma.request_count = request->request_count; 1894d722e3fbSopenharmony_ci dma.request_size = request->request_size; 1895d722e3fbSopenharmony_ci dma.request_indices = request->request_list; 1896d722e3fbSopenharmony_ci dma.request_sizes = request->request_sizes; 1897d722e3fbSopenharmony_ci dma.granted_count = 0; 1898d722e3fbSopenharmony_ci 1899d722e3fbSopenharmony_ci do { 1900d722e3fbSopenharmony_ci ret = ioctl( fd, DRM_IOCTL_DMA, &dma ); 1901d722e3fbSopenharmony_ci } while ( ret && errno == EAGAIN && i++ < DRM_DMA_RETRY ); 1902d722e3fbSopenharmony_ci 1903d722e3fbSopenharmony_ci if ( ret == 0 ) { 1904d722e3fbSopenharmony_ci request->granted_count = dma.granted_count; 1905d722e3fbSopenharmony_ci return 0; 1906d722e3fbSopenharmony_ci } else { 1907d722e3fbSopenharmony_ci return -errno; 1908d722e3fbSopenharmony_ci } 1909d722e3fbSopenharmony_ci} 1910d722e3fbSopenharmony_ci 1911d722e3fbSopenharmony_ci 1912d722e3fbSopenharmony_ci/** 1913d722e3fbSopenharmony_ci * Obtain heavyweight hardware lock. 1914d722e3fbSopenharmony_ci * 1915d722e3fbSopenharmony_ci * \param fd file descriptor. 1916d722e3fbSopenharmony_ci * \param context context. 1917d722e3fbSopenharmony_ci * \param flags flags that determine the state of the hardware when the function 1918d722e3fbSopenharmony_ci * returns. 1919d722e3fbSopenharmony_ci * 1920d722e3fbSopenharmony_ci * \return always zero. 1921d722e3fbSopenharmony_ci * 1922d722e3fbSopenharmony_ci * \internal 1923d722e3fbSopenharmony_ci * This function translates the arguments into a drm_lock structure and issue 1924d722e3fbSopenharmony_ci * the DRM_IOCTL_LOCK ioctl until the lock is successfully acquired. 1925d722e3fbSopenharmony_ci */ 1926d722e3fbSopenharmony_cidrm_public int drmGetLock(int fd, drm_context_t context, drmLockFlags flags) 1927d722e3fbSopenharmony_ci{ 1928d722e3fbSopenharmony_ci drm_lock_t lock; 1929d722e3fbSopenharmony_ci 1930d722e3fbSopenharmony_ci memclear(lock); 1931d722e3fbSopenharmony_ci lock.context = context; 1932d722e3fbSopenharmony_ci lock.flags = 0; 1933d722e3fbSopenharmony_ci if (flags & DRM_LOCK_READY) lock.flags |= _DRM_LOCK_READY; 1934d722e3fbSopenharmony_ci if (flags & DRM_LOCK_QUIESCENT) lock.flags |= _DRM_LOCK_QUIESCENT; 1935d722e3fbSopenharmony_ci if (flags & DRM_LOCK_FLUSH) lock.flags |= _DRM_LOCK_FLUSH; 1936d722e3fbSopenharmony_ci if (flags & DRM_LOCK_FLUSH_ALL) lock.flags |= _DRM_LOCK_FLUSH_ALL; 1937d722e3fbSopenharmony_ci if (flags & DRM_HALT_ALL_QUEUES) lock.flags |= _DRM_HALT_ALL_QUEUES; 1938d722e3fbSopenharmony_ci if (flags & DRM_HALT_CUR_QUEUES) lock.flags |= _DRM_HALT_CUR_QUEUES; 1939d722e3fbSopenharmony_ci 1940d722e3fbSopenharmony_ci while (drmIoctl(fd, DRM_IOCTL_LOCK, &lock)) 1941d722e3fbSopenharmony_ci ; 1942d722e3fbSopenharmony_ci return 0; 1943d722e3fbSopenharmony_ci} 1944d722e3fbSopenharmony_ci 1945d722e3fbSopenharmony_ci/** 1946d722e3fbSopenharmony_ci * Release the hardware lock. 1947d722e3fbSopenharmony_ci * 1948d722e3fbSopenharmony_ci * \param fd file descriptor. 1949d722e3fbSopenharmony_ci * \param context context. 1950d722e3fbSopenharmony_ci * 1951d722e3fbSopenharmony_ci * \return zero on success, or a negative value on failure. 1952d722e3fbSopenharmony_ci * 1953d722e3fbSopenharmony_ci * \internal 1954d722e3fbSopenharmony_ci * This function is a wrapper around the DRM_IOCTL_UNLOCK ioctl, passing the 1955d722e3fbSopenharmony_ci * argument in a drm_lock structure. 1956d722e3fbSopenharmony_ci */ 1957d722e3fbSopenharmony_cidrm_public int drmUnlock(int fd, drm_context_t context) 1958d722e3fbSopenharmony_ci{ 1959d722e3fbSopenharmony_ci drm_lock_t lock; 1960d722e3fbSopenharmony_ci 1961d722e3fbSopenharmony_ci memclear(lock); 1962d722e3fbSopenharmony_ci lock.context = context; 1963d722e3fbSopenharmony_ci return drmIoctl(fd, DRM_IOCTL_UNLOCK, &lock); 1964d722e3fbSopenharmony_ci} 1965d722e3fbSopenharmony_ci 1966d722e3fbSopenharmony_cidrm_public drm_context_t *drmGetReservedContextList(int fd, int *count) 1967d722e3fbSopenharmony_ci{ 1968d722e3fbSopenharmony_ci drm_ctx_res_t res; 1969d722e3fbSopenharmony_ci drm_ctx_t *list; 1970d722e3fbSopenharmony_ci drm_context_t * retval; 1971d722e3fbSopenharmony_ci int i; 1972d722e3fbSopenharmony_ci 1973d722e3fbSopenharmony_ci memclear(res); 1974d722e3fbSopenharmony_ci if (drmIoctl(fd, DRM_IOCTL_RES_CTX, &res)) 1975d722e3fbSopenharmony_ci return NULL; 1976d722e3fbSopenharmony_ci 1977d722e3fbSopenharmony_ci if (!res.count) 1978d722e3fbSopenharmony_ci return NULL; 1979d722e3fbSopenharmony_ci 1980d722e3fbSopenharmony_ci if (!(list = drmMalloc(res.count * sizeof(*list)))) 1981d722e3fbSopenharmony_ci return NULL; 1982d722e3fbSopenharmony_ci if (!(retval = drmMalloc(res.count * sizeof(*retval)))) 1983d722e3fbSopenharmony_ci goto err_free_list; 1984d722e3fbSopenharmony_ci 1985d722e3fbSopenharmony_ci res.contexts = list; 1986d722e3fbSopenharmony_ci if (drmIoctl(fd, DRM_IOCTL_RES_CTX, &res)) 1987d722e3fbSopenharmony_ci goto err_free_context; 1988d722e3fbSopenharmony_ci 1989d722e3fbSopenharmony_ci for (i = 0; i < res.count; i++) 1990d722e3fbSopenharmony_ci retval[i] = list[i].handle; 1991d722e3fbSopenharmony_ci drmFree(list); 1992d722e3fbSopenharmony_ci 1993d722e3fbSopenharmony_ci *count = res.count; 1994d722e3fbSopenharmony_ci return retval; 1995d722e3fbSopenharmony_ci 1996d722e3fbSopenharmony_cierr_free_list: 1997d722e3fbSopenharmony_ci drmFree(list); 1998d722e3fbSopenharmony_cierr_free_context: 1999d722e3fbSopenharmony_ci drmFree(retval); 2000d722e3fbSopenharmony_ci return NULL; 2001d722e3fbSopenharmony_ci} 2002d722e3fbSopenharmony_ci 2003d722e3fbSopenharmony_cidrm_public void drmFreeReservedContextList(drm_context_t *pt) 2004d722e3fbSopenharmony_ci{ 2005d722e3fbSopenharmony_ci drmFree(pt); 2006d722e3fbSopenharmony_ci} 2007d722e3fbSopenharmony_ci 2008d722e3fbSopenharmony_ci/** 2009d722e3fbSopenharmony_ci * Create context. 2010d722e3fbSopenharmony_ci * 2011d722e3fbSopenharmony_ci * Used by the X server during GLXContext initialization. This causes 2012d722e3fbSopenharmony_ci * per-context kernel-level resources to be allocated. 2013d722e3fbSopenharmony_ci * 2014d722e3fbSopenharmony_ci * \param fd file descriptor. 2015d722e3fbSopenharmony_ci * \param handle is set on success. To be used by the client when requesting DMA 2016d722e3fbSopenharmony_ci * dispatch with drmDMA(). 2017d722e3fbSopenharmony_ci * 2018d722e3fbSopenharmony_ci * \return zero on success, or a negative value on failure. 2019d722e3fbSopenharmony_ci * 2020d722e3fbSopenharmony_ci * \note May only be called by root. 2021d722e3fbSopenharmony_ci * 2022d722e3fbSopenharmony_ci * \internal 2023d722e3fbSopenharmony_ci * This function is a wrapper around the DRM_IOCTL_ADD_CTX ioctl, passing the 2024d722e3fbSopenharmony_ci * argument in a drm_ctx structure. 2025d722e3fbSopenharmony_ci */ 2026d722e3fbSopenharmony_cidrm_public int drmCreateContext(int fd, drm_context_t *handle) 2027d722e3fbSopenharmony_ci{ 2028d722e3fbSopenharmony_ci drm_ctx_t ctx; 2029d722e3fbSopenharmony_ci 2030d722e3fbSopenharmony_ci memclear(ctx); 2031d722e3fbSopenharmony_ci if (drmIoctl(fd, DRM_IOCTL_ADD_CTX, &ctx)) 2032d722e3fbSopenharmony_ci return -errno; 2033d722e3fbSopenharmony_ci *handle = ctx.handle; 2034d722e3fbSopenharmony_ci return 0; 2035d722e3fbSopenharmony_ci} 2036d722e3fbSopenharmony_ci 2037d722e3fbSopenharmony_cidrm_public int drmSwitchToContext(int fd, drm_context_t context) 2038d722e3fbSopenharmony_ci{ 2039d722e3fbSopenharmony_ci drm_ctx_t ctx; 2040d722e3fbSopenharmony_ci 2041d722e3fbSopenharmony_ci memclear(ctx); 2042d722e3fbSopenharmony_ci ctx.handle = context; 2043d722e3fbSopenharmony_ci if (drmIoctl(fd, DRM_IOCTL_SWITCH_CTX, &ctx)) 2044d722e3fbSopenharmony_ci return -errno; 2045d722e3fbSopenharmony_ci return 0; 2046d722e3fbSopenharmony_ci} 2047d722e3fbSopenharmony_ci 2048d722e3fbSopenharmony_cidrm_public int drmSetContextFlags(int fd, drm_context_t context, 2049d722e3fbSopenharmony_ci drm_context_tFlags flags) 2050d722e3fbSopenharmony_ci{ 2051d722e3fbSopenharmony_ci drm_ctx_t ctx; 2052d722e3fbSopenharmony_ci 2053d722e3fbSopenharmony_ci /* 2054d722e3fbSopenharmony_ci * Context preserving means that no context switches are done between DMA 2055d722e3fbSopenharmony_ci * buffers from one context and the next. This is suitable for use in the 2056d722e3fbSopenharmony_ci * X server (which promises to maintain hardware context), or in the 2057d722e3fbSopenharmony_ci * client-side library when buffers are swapped on behalf of two threads. 2058d722e3fbSopenharmony_ci */ 2059d722e3fbSopenharmony_ci memclear(ctx); 2060d722e3fbSopenharmony_ci ctx.handle = context; 2061d722e3fbSopenharmony_ci if (flags & DRM_CONTEXT_PRESERVED) 2062d722e3fbSopenharmony_ci ctx.flags |= _DRM_CONTEXT_PRESERVED; 2063d722e3fbSopenharmony_ci if (flags & DRM_CONTEXT_2DONLY) 2064d722e3fbSopenharmony_ci ctx.flags |= _DRM_CONTEXT_2DONLY; 2065d722e3fbSopenharmony_ci if (drmIoctl(fd, DRM_IOCTL_MOD_CTX, &ctx)) 2066d722e3fbSopenharmony_ci return -errno; 2067d722e3fbSopenharmony_ci return 0; 2068d722e3fbSopenharmony_ci} 2069d722e3fbSopenharmony_ci 2070d722e3fbSopenharmony_cidrm_public int drmGetContextFlags(int fd, drm_context_t context, 2071d722e3fbSopenharmony_ci drm_context_tFlagsPtr flags) 2072d722e3fbSopenharmony_ci{ 2073d722e3fbSopenharmony_ci drm_ctx_t ctx; 2074d722e3fbSopenharmony_ci 2075d722e3fbSopenharmony_ci memclear(ctx); 2076d722e3fbSopenharmony_ci ctx.handle = context; 2077d722e3fbSopenharmony_ci if (drmIoctl(fd, DRM_IOCTL_GET_CTX, &ctx)) 2078d722e3fbSopenharmony_ci return -errno; 2079d722e3fbSopenharmony_ci *flags = 0; 2080d722e3fbSopenharmony_ci if (ctx.flags & _DRM_CONTEXT_PRESERVED) 2081d722e3fbSopenharmony_ci *flags |= DRM_CONTEXT_PRESERVED; 2082d722e3fbSopenharmony_ci if (ctx.flags & _DRM_CONTEXT_2DONLY) 2083d722e3fbSopenharmony_ci *flags |= DRM_CONTEXT_2DONLY; 2084d722e3fbSopenharmony_ci return 0; 2085d722e3fbSopenharmony_ci} 2086d722e3fbSopenharmony_ci 2087d722e3fbSopenharmony_ci/** 2088d722e3fbSopenharmony_ci * Destroy context. 2089d722e3fbSopenharmony_ci * 2090d722e3fbSopenharmony_ci * Free any kernel-level resources allocated with drmCreateContext() associated 2091d722e3fbSopenharmony_ci * with the context. 2092d722e3fbSopenharmony_ci * 2093d722e3fbSopenharmony_ci * \param fd file descriptor. 2094d722e3fbSopenharmony_ci * \param handle handle given by drmCreateContext(). 2095d722e3fbSopenharmony_ci * 2096d722e3fbSopenharmony_ci * \return zero on success, or a negative value on failure. 2097d722e3fbSopenharmony_ci * 2098d722e3fbSopenharmony_ci * \note May only be called by root. 2099d722e3fbSopenharmony_ci * 2100d722e3fbSopenharmony_ci * \internal 2101d722e3fbSopenharmony_ci * This function is a wrapper around the DRM_IOCTL_RM_CTX ioctl, passing the 2102d722e3fbSopenharmony_ci * argument in a drm_ctx structure. 2103d722e3fbSopenharmony_ci */ 2104d722e3fbSopenharmony_cidrm_public int drmDestroyContext(int fd, drm_context_t handle) 2105d722e3fbSopenharmony_ci{ 2106d722e3fbSopenharmony_ci drm_ctx_t ctx; 2107d722e3fbSopenharmony_ci 2108d722e3fbSopenharmony_ci memclear(ctx); 2109d722e3fbSopenharmony_ci ctx.handle = handle; 2110d722e3fbSopenharmony_ci if (drmIoctl(fd, DRM_IOCTL_RM_CTX, &ctx)) 2111d722e3fbSopenharmony_ci return -errno; 2112d722e3fbSopenharmony_ci return 0; 2113d722e3fbSopenharmony_ci} 2114d722e3fbSopenharmony_ci 2115d722e3fbSopenharmony_cidrm_public int drmCreateDrawable(int fd, drm_drawable_t *handle) 2116d722e3fbSopenharmony_ci{ 2117d722e3fbSopenharmony_ci drm_draw_t draw; 2118d722e3fbSopenharmony_ci 2119d722e3fbSopenharmony_ci memclear(draw); 2120d722e3fbSopenharmony_ci if (drmIoctl(fd, DRM_IOCTL_ADD_DRAW, &draw)) 2121d722e3fbSopenharmony_ci return -errno; 2122d722e3fbSopenharmony_ci *handle = draw.handle; 2123d722e3fbSopenharmony_ci return 0; 2124d722e3fbSopenharmony_ci} 2125d722e3fbSopenharmony_ci 2126d722e3fbSopenharmony_cidrm_public int drmDestroyDrawable(int fd, drm_drawable_t handle) 2127d722e3fbSopenharmony_ci{ 2128d722e3fbSopenharmony_ci drm_draw_t draw; 2129d722e3fbSopenharmony_ci 2130d722e3fbSopenharmony_ci memclear(draw); 2131d722e3fbSopenharmony_ci draw.handle = handle; 2132d722e3fbSopenharmony_ci if (drmIoctl(fd, DRM_IOCTL_RM_DRAW, &draw)) 2133d722e3fbSopenharmony_ci return -errno; 2134d722e3fbSopenharmony_ci return 0; 2135d722e3fbSopenharmony_ci} 2136d722e3fbSopenharmony_ci 2137d722e3fbSopenharmony_cidrm_public int drmUpdateDrawableInfo(int fd, drm_drawable_t handle, 2138d722e3fbSopenharmony_ci drm_drawable_info_type_t type, 2139d722e3fbSopenharmony_ci unsigned int num, void *data) 2140d722e3fbSopenharmony_ci{ 2141d722e3fbSopenharmony_ci drm_update_draw_t update; 2142d722e3fbSopenharmony_ci 2143d722e3fbSopenharmony_ci memclear(update); 2144d722e3fbSopenharmony_ci update.handle = handle; 2145d722e3fbSopenharmony_ci update.type = type; 2146d722e3fbSopenharmony_ci update.num = num; 2147d722e3fbSopenharmony_ci update.data = (unsigned long long)(unsigned long)data; 2148d722e3fbSopenharmony_ci 2149d722e3fbSopenharmony_ci if (drmIoctl(fd, DRM_IOCTL_UPDATE_DRAW, &update)) 2150d722e3fbSopenharmony_ci return -errno; 2151d722e3fbSopenharmony_ci 2152d722e3fbSopenharmony_ci return 0; 2153d722e3fbSopenharmony_ci} 2154d722e3fbSopenharmony_ci 2155d722e3fbSopenharmony_cidrm_public int drmCrtcGetSequence(int fd, uint32_t crtcId, uint64_t *sequence, 2156d722e3fbSopenharmony_ci uint64_t *ns) 2157d722e3fbSopenharmony_ci{ 2158d722e3fbSopenharmony_ci struct drm_crtc_get_sequence get_seq; 2159d722e3fbSopenharmony_ci int ret; 2160d722e3fbSopenharmony_ci 2161d722e3fbSopenharmony_ci memclear(get_seq); 2162d722e3fbSopenharmony_ci get_seq.crtc_id = crtcId; 2163d722e3fbSopenharmony_ci ret = drmIoctl(fd, DRM_IOCTL_CRTC_GET_SEQUENCE, &get_seq); 2164d722e3fbSopenharmony_ci if (ret) 2165d722e3fbSopenharmony_ci return ret; 2166d722e3fbSopenharmony_ci 2167d722e3fbSopenharmony_ci if (sequence) 2168d722e3fbSopenharmony_ci *sequence = get_seq.sequence; 2169d722e3fbSopenharmony_ci if (ns) 2170d722e3fbSopenharmony_ci *ns = get_seq.sequence_ns; 2171d722e3fbSopenharmony_ci return 0; 2172d722e3fbSopenharmony_ci} 2173d722e3fbSopenharmony_ci 2174d722e3fbSopenharmony_cidrm_public int drmCrtcQueueSequence(int fd, uint32_t crtcId, uint32_t flags, 2175d722e3fbSopenharmony_ci uint64_t sequence, 2176d722e3fbSopenharmony_ci uint64_t *sequence_queued, 2177d722e3fbSopenharmony_ci uint64_t user_data) 2178d722e3fbSopenharmony_ci{ 2179d722e3fbSopenharmony_ci struct drm_crtc_queue_sequence queue_seq; 2180d722e3fbSopenharmony_ci int ret; 2181d722e3fbSopenharmony_ci 2182d722e3fbSopenharmony_ci memclear(queue_seq); 2183d722e3fbSopenharmony_ci queue_seq.crtc_id = crtcId; 2184d722e3fbSopenharmony_ci queue_seq.flags = flags; 2185d722e3fbSopenharmony_ci queue_seq.sequence = sequence; 2186d722e3fbSopenharmony_ci queue_seq.user_data = user_data; 2187d722e3fbSopenharmony_ci 2188d722e3fbSopenharmony_ci ret = drmIoctl(fd, DRM_IOCTL_CRTC_QUEUE_SEQUENCE, &queue_seq); 2189d722e3fbSopenharmony_ci if (ret == 0 && sequence_queued) 2190d722e3fbSopenharmony_ci *sequence_queued = queue_seq.sequence; 2191d722e3fbSopenharmony_ci 2192d722e3fbSopenharmony_ci return ret; 2193d722e3fbSopenharmony_ci} 2194d722e3fbSopenharmony_ci 2195d722e3fbSopenharmony_ci/** 2196d722e3fbSopenharmony_ci * Acquire the AGP device. 2197d722e3fbSopenharmony_ci * 2198d722e3fbSopenharmony_ci * Must be called before any of the other AGP related calls. 2199d722e3fbSopenharmony_ci * 2200d722e3fbSopenharmony_ci * \param fd file descriptor. 2201d722e3fbSopenharmony_ci * 2202d722e3fbSopenharmony_ci * \return zero on success, or a negative value on failure. 2203d722e3fbSopenharmony_ci * 2204d722e3fbSopenharmony_ci * \internal 2205d722e3fbSopenharmony_ci * This function is a wrapper around the DRM_IOCTL_AGP_ACQUIRE ioctl. 2206d722e3fbSopenharmony_ci */ 2207d722e3fbSopenharmony_cidrm_public int drmAgpAcquire(int fd) 2208d722e3fbSopenharmony_ci{ 2209d722e3fbSopenharmony_ci if (drmIoctl(fd, DRM_IOCTL_AGP_ACQUIRE, NULL)) 2210d722e3fbSopenharmony_ci return -errno; 2211d722e3fbSopenharmony_ci return 0; 2212d722e3fbSopenharmony_ci} 2213d722e3fbSopenharmony_ci 2214d722e3fbSopenharmony_ci 2215d722e3fbSopenharmony_ci/** 2216d722e3fbSopenharmony_ci * Release the AGP device. 2217d722e3fbSopenharmony_ci * 2218d722e3fbSopenharmony_ci * \param fd file descriptor. 2219d722e3fbSopenharmony_ci * 2220d722e3fbSopenharmony_ci * \return zero on success, or a negative value on failure. 2221d722e3fbSopenharmony_ci * 2222d722e3fbSopenharmony_ci * \internal 2223d722e3fbSopenharmony_ci * This function is a wrapper around the DRM_IOCTL_AGP_RELEASE ioctl. 2224d722e3fbSopenharmony_ci */ 2225d722e3fbSopenharmony_cidrm_public int drmAgpRelease(int fd) 2226d722e3fbSopenharmony_ci{ 2227d722e3fbSopenharmony_ci if (drmIoctl(fd, DRM_IOCTL_AGP_RELEASE, NULL)) 2228d722e3fbSopenharmony_ci return -errno; 2229d722e3fbSopenharmony_ci return 0; 2230d722e3fbSopenharmony_ci} 2231d722e3fbSopenharmony_ci 2232d722e3fbSopenharmony_ci 2233d722e3fbSopenharmony_ci/** 2234d722e3fbSopenharmony_ci * Set the AGP mode. 2235d722e3fbSopenharmony_ci * 2236d722e3fbSopenharmony_ci * \param fd file descriptor. 2237d722e3fbSopenharmony_ci * \param mode AGP mode. 2238d722e3fbSopenharmony_ci * 2239d722e3fbSopenharmony_ci * \return zero on success, or a negative value on failure. 2240d722e3fbSopenharmony_ci * 2241d722e3fbSopenharmony_ci * \internal 2242d722e3fbSopenharmony_ci * This function is a wrapper around the DRM_IOCTL_AGP_ENABLE ioctl, passing the 2243d722e3fbSopenharmony_ci * argument in a drm_agp_mode structure. 2244d722e3fbSopenharmony_ci */ 2245d722e3fbSopenharmony_cidrm_public int drmAgpEnable(int fd, unsigned long mode) 2246d722e3fbSopenharmony_ci{ 2247d722e3fbSopenharmony_ci drm_agp_mode_t m; 2248d722e3fbSopenharmony_ci 2249d722e3fbSopenharmony_ci memclear(m); 2250d722e3fbSopenharmony_ci m.mode = mode; 2251d722e3fbSopenharmony_ci if (drmIoctl(fd, DRM_IOCTL_AGP_ENABLE, &m)) 2252d722e3fbSopenharmony_ci return -errno; 2253d722e3fbSopenharmony_ci return 0; 2254d722e3fbSopenharmony_ci} 2255d722e3fbSopenharmony_ci 2256d722e3fbSopenharmony_ci 2257d722e3fbSopenharmony_ci/** 2258d722e3fbSopenharmony_ci * Allocate a chunk of AGP memory. 2259d722e3fbSopenharmony_ci * 2260d722e3fbSopenharmony_ci * \param fd file descriptor. 2261d722e3fbSopenharmony_ci * \param size requested memory size in bytes. Will be rounded to page boundary. 2262d722e3fbSopenharmony_ci * \param type type of memory to allocate. 2263d722e3fbSopenharmony_ci * \param address if not zero, will be set to the physical address of the 2264d722e3fbSopenharmony_ci * allocated memory. 2265d722e3fbSopenharmony_ci * \param handle on success will be set to a handle of the allocated memory. 2266d722e3fbSopenharmony_ci * 2267d722e3fbSopenharmony_ci * \return zero on success, or a negative value on failure. 2268d722e3fbSopenharmony_ci * 2269d722e3fbSopenharmony_ci * \internal 2270d722e3fbSopenharmony_ci * This function is a wrapper around the DRM_IOCTL_AGP_ALLOC ioctl, passing the 2271d722e3fbSopenharmony_ci * arguments in a drm_agp_buffer structure. 2272d722e3fbSopenharmony_ci */ 2273d722e3fbSopenharmony_cidrm_public int drmAgpAlloc(int fd, unsigned long size, unsigned long type, 2274d722e3fbSopenharmony_ci unsigned long *address, drm_handle_t *handle) 2275d722e3fbSopenharmony_ci{ 2276d722e3fbSopenharmony_ci drm_agp_buffer_t b; 2277d722e3fbSopenharmony_ci 2278d722e3fbSopenharmony_ci memclear(b); 2279d722e3fbSopenharmony_ci *handle = DRM_AGP_NO_HANDLE; 2280d722e3fbSopenharmony_ci b.size = size; 2281d722e3fbSopenharmony_ci b.type = type; 2282d722e3fbSopenharmony_ci if (drmIoctl(fd, DRM_IOCTL_AGP_ALLOC, &b)) 2283d722e3fbSopenharmony_ci return -errno; 2284d722e3fbSopenharmony_ci if (address != 0UL) 2285d722e3fbSopenharmony_ci *address = b.physical; 2286d722e3fbSopenharmony_ci *handle = b.handle; 2287d722e3fbSopenharmony_ci return 0; 2288d722e3fbSopenharmony_ci} 2289d722e3fbSopenharmony_ci 2290d722e3fbSopenharmony_ci 2291d722e3fbSopenharmony_ci/** 2292d722e3fbSopenharmony_ci * Free a chunk of AGP memory. 2293d722e3fbSopenharmony_ci * 2294d722e3fbSopenharmony_ci * \param fd file descriptor. 2295d722e3fbSopenharmony_ci * \param handle handle to the allocated memory, as given by drmAgpAllocate(). 2296d722e3fbSopenharmony_ci * 2297d722e3fbSopenharmony_ci * \return zero on success, or a negative value on failure. 2298d722e3fbSopenharmony_ci * 2299d722e3fbSopenharmony_ci * \internal 2300d722e3fbSopenharmony_ci * This function is a wrapper around the DRM_IOCTL_AGP_FREE ioctl, passing the 2301d722e3fbSopenharmony_ci * argument in a drm_agp_buffer structure. 2302d722e3fbSopenharmony_ci */ 2303d722e3fbSopenharmony_cidrm_public int drmAgpFree(int fd, drm_handle_t handle) 2304d722e3fbSopenharmony_ci{ 2305d722e3fbSopenharmony_ci drm_agp_buffer_t b; 2306d722e3fbSopenharmony_ci 2307d722e3fbSopenharmony_ci memclear(b); 2308d722e3fbSopenharmony_ci b.handle = handle; 2309d722e3fbSopenharmony_ci if (drmIoctl(fd, DRM_IOCTL_AGP_FREE, &b)) 2310d722e3fbSopenharmony_ci return -errno; 2311d722e3fbSopenharmony_ci return 0; 2312d722e3fbSopenharmony_ci} 2313d722e3fbSopenharmony_ci 2314d722e3fbSopenharmony_ci 2315d722e3fbSopenharmony_ci/** 2316d722e3fbSopenharmony_ci * Bind a chunk of AGP memory. 2317d722e3fbSopenharmony_ci * 2318d722e3fbSopenharmony_ci * \param fd file descriptor. 2319d722e3fbSopenharmony_ci * \param handle handle to the allocated memory, as given by drmAgpAllocate(). 2320d722e3fbSopenharmony_ci * \param offset offset in bytes. It will round to page boundary. 2321d722e3fbSopenharmony_ci * 2322d722e3fbSopenharmony_ci * \return zero on success, or a negative value on failure. 2323d722e3fbSopenharmony_ci * 2324d722e3fbSopenharmony_ci * \internal 2325d722e3fbSopenharmony_ci * This function is a wrapper around the DRM_IOCTL_AGP_BIND ioctl, passing the 2326d722e3fbSopenharmony_ci * argument in a drm_agp_binding structure. 2327d722e3fbSopenharmony_ci */ 2328d722e3fbSopenharmony_cidrm_public int drmAgpBind(int fd, drm_handle_t handle, unsigned long offset) 2329d722e3fbSopenharmony_ci{ 2330d722e3fbSopenharmony_ci drm_agp_binding_t b; 2331d722e3fbSopenharmony_ci 2332d722e3fbSopenharmony_ci memclear(b); 2333d722e3fbSopenharmony_ci b.handle = handle; 2334d722e3fbSopenharmony_ci b.offset = offset; 2335d722e3fbSopenharmony_ci if (drmIoctl(fd, DRM_IOCTL_AGP_BIND, &b)) 2336d722e3fbSopenharmony_ci return -errno; 2337d722e3fbSopenharmony_ci return 0; 2338d722e3fbSopenharmony_ci} 2339d722e3fbSopenharmony_ci 2340d722e3fbSopenharmony_ci 2341d722e3fbSopenharmony_ci/** 2342d722e3fbSopenharmony_ci * Unbind a chunk of AGP memory. 2343d722e3fbSopenharmony_ci * 2344d722e3fbSopenharmony_ci * \param fd file descriptor. 2345d722e3fbSopenharmony_ci * \param handle handle to the allocated memory, as given by drmAgpAllocate(). 2346d722e3fbSopenharmony_ci * 2347d722e3fbSopenharmony_ci * \return zero on success, or a negative value on failure. 2348d722e3fbSopenharmony_ci * 2349d722e3fbSopenharmony_ci * \internal 2350d722e3fbSopenharmony_ci * This function is a wrapper around the DRM_IOCTL_AGP_UNBIND ioctl, passing 2351d722e3fbSopenharmony_ci * the argument in a drm_agp_binding structure. 2352d722e3fbSopenharmony_ci */ 2353d722e3fbSopenharmony_cidrm_public int drmAgpUnbind(int fd, drm_handle_t handle) 2354d722e3fbSopenharmony_ci{ 2355d722e3fbSopenharmony_ci drm_agp_binding_t b; 2356d722e3fbSopenharmony_ci 2357d722e3fbSopenharmony_ci memclear(b); 2358d722e3fbSopenharmony_ci b.handle = handle; 2359d722e3fbSopenharmony_ci if (drmIoctl(fd, DRM_IOCTL_AGP_UNBIND, &b)) 2360d722e3fbSopenharmony_ci return -errno; 2361d722e3fbSopenharmony_ci return 0; 2362d722e3fbSopenharmony_ci} 2363d722e3fbSopenharmony_ci 2364d722e3fbSopenharmony_ci 2365d722e3fbSopenharmony_ci/** 2366d722e3fbSopenharmony_ci * Get AGP driver major version number. 2367d722e3fbSopenharmony_ci * 2368d722e3fbSopenharmony_ci * \param fd file descriptor. 2369d722e3fbSopenharmony_ci * 2370d722e3fbSopenharmony_ci * \return major version number on success, or a negative value on failure.. 2371d722e3fbSopenharmony_ci * 2372d722e3fbSopenharmony_ci * \internal 2373d722e3fbSopenharmony_ci * This function is a wrapper around the DRM_IOCTL_AGP_INFO ioctl, getting the 2374d722e3fbSopenharmony_ci * necessary information in a drm_agp_info structure. 2375d722e3fbSopenharmony_ci */ 2376d722e3fbSopenharmony_cidrm_public int drmAgpVersionMajor(int fd) 2377d722e3fbSopenharmony_ci{ 2378d722e3fbSopenharmony_ci drm_agp_info_t i; 2379d722e3fbSopenharmony_ci 2380d722e3fbSopenharmony_ci memclear(i); 2381d722e3fbSopenharmony_ci 2382d722e3fbSopenharmony_ci if (drmIoctl(fd, DRM_IOCTL_AGP_INFO, &i)) 2383d722e3fbSopenharmony_ci return -errno; 2384d722e3fbSopenharmony_ci return i.agp_version_major; 2385d722e3fbSopenharmony_ci} 2386d722e3fbSopenharmony_ci 2387d722e3fbSopenharmony_ci 2388d722e3fbSopenharmony_ci/** 2389d722e3fbSopenharmony_ci * Get AGP driver minor version number. 2390d722e3fbSopenharmony_ci * 2391d722e3fbSopenharmony_ci * \param fd file descriptor. 2392d722e3fbSopenharmony_ci * 2393d722e3fbSopenharmony_ci * \return minor version number on success, or a negative value on failure. 2394d722e3fbSopenharmony_ci * 2395d722e3fbSopenharmony_ci * \internal 2396d722e3fbSopenharmony_ci * This function is a wrapper around the DRM_IOCTL_AGP_INFO ioctl, getting the 2397d722e3fbSopenharmony_ci * necessary information in a drm_agp_info structure. 2398d722e3fbSopenharmony_ci */ 2399d722e3fbSopenharmony_cidrm_public int drmAgpVersionMinor(int fd) 2400d722e3fbSopenharmony_ci{ 2401d722e3fbSopenharmony_ci drm_agp_info_t i; 2402d722e3fbSopenharmony_ci 2403d722e3fbSopenharmony_ci memclear(i); 2404d722e3fbSopenharmony_ci 2405d722e3fbSopenharmony_ci if (drmIoctl(fd, DRM_IOCTL_AGP_INFO, &i)) 2406d722e3fbSopenharmony_ci return -errno; 2407d722e3fbSopenharmony_ci return i.agp_version_minor; 2408d722e3fbSopenharmony_ci} 2409d722e3fbSopenharmony_ci 2410d722e3fbSopenharmony_ci 2411d722e3fbSopenharmony_ci/** 2412d722e3fbSopenharmony_ci * Get AGP mode. 2413d722e3fbSopenharmony_ci * 2414d722e3fbSopenharmony_ci * \param fd file descriptor. 2415d722e3fbSopenharmony_ci * 2416d722e3fbSopenharmony_ci * \return mode on success, or zero on failure. 2417d722e3fbSopenharmony_ci * 2418d722e3fbSopenharmony_ci * \internal 2419d722e3fbSopenharmony_ci * This function is a wrapper around the DRM_IOCTL_AGP_INFO ioctl, getting the 2420d722e3fbSopenharmony_ci * necessary information in a drm_agp_info structure. 2421d722e3fbSopenharmony_ci */ 2422d722e3fbSopenharmony_cidrm_public unsigned long drmAgpGetMode(int fd) 2423d722e3fbSopenharmony_ci{ 2424d722e3fbSopenharmony_ci drm_agp_info_t i; 2425d722e3fbSopenharmony_ci 2426d722e3fbSopenharmony_ci memclear(i); 2427d722e3fbSopenharmony_ci 2428d722e3fbSopenharmony_ci if (drmIoctl(fd, DRM_IOCTL_AGP_INFO, &i)) 2429d722e3fbSopenharmony_ci return 0; 2430d722e3fbSopenharmony_ci return i.mode; 2431d722e3fbSopenharmony_ci} 2432d722e3fbSopenharmony_ci 2433d722e3fbSopenharmony_ci 2434d722e3fbSopenharmony_ci/** 2435d722e3fbSopenharmony_ci * Get AGP aperture base. 2436d722e3fbSopenharmony_ci * 2437d722e3fbSopenharmony_ci * \param fd file descriptor. 2438d722e3fbSopenharmony_ci * 2439d722e3fbSopenharmony_ci * \return aperture base on success, zero on failure. 2440d722e3fbSopenharmony_ci * 2441d722e3fbSopenharmony_ci * \internal 2442d722e3fbSopenharmony_ci * This function is a wrapper around the DRM_IOCTL_AGP_INFO ioctl, getting the 2443d722e3fbSopenharmony_ci * necessary information in a drm_agp_info structure. 2444d722e3fbSopenharmony_ci */ 2445d722e3fbSopenharmony_cidrm_public unsigned long drmAgpBase(int fd) 2446d722e3fbSopenharmony_ci{ 2447d722e3fbSopenharmony_ci drm_agp_info_t i; 2448d722e3fbSopenharmony_ci 2449d722e3fbSopenharmony_ci memclear(i); 2450d722e3fbSopenharmony_ci 2451d722e3fbSopenharmony_ci if (drmIoctl(fd, DRM_IOCTL_AGP_INFO, &i)) 2452d722e3fbSopenharmony_ci return 0; 2453d722e3fbSopenharmony_ci return i.aperture_base; 2454d722e3fbSopenharmony_ci} 2455d722e3fbSopenharmony_ci 2456d722e3fbSopenharmony_ci 2457d722e3fbSopenharmony_ci/** 2458d722e3fbSopenharmony_ci * Get AGP aperture size. 2459d722e3fbSopenharmony_ci * 2460d722e3fbSopenharmony_ci * \param fd file descriptor. 2461d722e3fbSopenharmony_ci * 2462d722e3fbSopenharmony_ci * \return aperture size on success, zero on failure. 2463d722e3fbSopenharmony_ci * 2464d722e3fbSopenharmony_ci * \internal 2465d722e3fbSopenharmony_ci * This function is a wrapper around the DRM_IOCTL_AGP_INFO ioctl, getting the 2466d722e3fbSopenharmony_ci * necessary information in a drm_agp_info structure. 2467d722e3fbSopenharmony_ci */ 2468d722e3fbSopenharmony_cidrm_public unsigned long drmAgpSize(int fd) 2469d722e3fbSopenharmony_ci{ 2470d722e3fbSopenharmony_ci drm_agp_info_t i; 2471d722e3fbSopenharmony_ci 2472d722e3fbSopenharmony_ci memclear(i); 2473d722e3fbSopenharmony_ci 2474d722e3fbSopenharmony_ci if (drmIoctl(fd, DRM_IOCTL_AGP_INFO, &i)) 2475d722e3fbSopenharmony_ci return 0; 2476d722e3fbSopenharmony_ci return i.aperture_size; 2477d722e3fbSopenharmony_ci} 2478d722e3fbSopenharmony_ci 2479d722e3fbSopenharmony_ci 2480d722e3fbSopenharmony_ci/** 2481d722e3fbSopenharmony_ci * Get used AGP memory. 2482d722e3fbSopenharmony_ci * 2483d722e3fbSopenharmony_ci * \param fd file descriptor. 2484d722e3fbSopenharmony_ci * 2485d722e3fbSopenharmony_ci * \return memory used on success, or zero on failure. 2486d722e3fbSopenharmony_ci * 2487d722e3fbSopenharmony_ci * \internal 2488d722e3fbSopenharmony_ci * This function is a wrapper around the DRM_IOCTL_AGP_INFO ioctl, getting the 2489d722e3fbSopenharmony_ci * necessary information in a drm_agp_info structure. 2490d722e3fbSopenharmony_ci */ 2491d722e3fbSopenharmony_cidrm_public unsigned long drmAgpMemoryUsed(int fd) 2492d722e3fbSopenharmony_ci{ 2493d722e3fbSopenharmony_ci drm_agp_info_t i; 2494d722e3fbSopenharmony_ci 2495d722e3fbSopenharmony_ci memclear(i); 2496d722e3fbSopenharmony_ci 2497d722e3fbSopenharmony_ci if (drmIoctl(fd, DRM_IOCTL_AGP_INFO, &i)) 2498d722e3fbSopenharmony_ci return 0; 2499d722e3fbSopenharmony_ci return i.memory_used; 2500d722e3fbSopenharmony_ci} 2501d722e3fbSopenharmony_ci 2502d722e3fbSopenharmony_ci 2503d722e3fbSopenharmony_ci/** 2504d722e3fbSopenharmony_ci * Get available AGP memory. 2505d722e3fbSopenharmony_ci * 2506d722e3fbSopenharmony_ci * \param fd file descriptor. 2507d722e3fbSopenharmony_ci * 2508d722e3fbSopenharmony_ci * \return memory available on success, or zero on failure. 2509d722e3fbSopenharmony_ci * 2510d722e3fbSopenharmony_ci * \internal 2511d722e3fbSopenharmony_ci * This function is a wrapper around the DRM_IOCTL_AGP_INFO ioctl, getting the 2512d722e3fbSopenharmony_ci * necessary information in a drm_agp_info structure. 2513d722e3fbSopenharmony_ci */ 2514d722e3fbSopenharmony_cidrm_public unsigned long drmAgpMemoryAvail(int fd) 2515d722e3fbSopenharmony_ci{ 2516d722e3fbSopenharmony_ci drm_agp_info_t i; 2517d722e3fbSopenharmony_ci 2518d722e3fbSopenharmony_ci memclear(i); 2519d722e3fbSopenharmony_ci 2520d722e3fbSopenharmony_ci if (drmIoctl(fd, DRM_IOCTL_AGP_INFO, &i)) 2521d722e3fbSopenharmony_ci return 0; 2522d722e3fbSopenharmony_ci return i.memory_allowed; 2523d722e3fbSopenharmony_ci} 2524d722e3fbSopenharmony_ci 2525d722e3fbSopenharmony_ci 2526d722e3fbSopenharmony_ci/** 2527d722e3fbSopenharmony_ci * Get hardware vendor ID. 2528d722e3fbSopenharmony_ci * 2529d722e3fbSopenharmony_ci * \param fd file descriptor. 2530d722e3fbSopenharmony_ci * 2531d722e3fbSopenharmony_ci * \return vendor ID on success, or zero on failure. 2532d722e3fbSopenharmony_ci * 2533d722e3fbSopenharmony_ci * \internal 2534d722e3fbSopenharmony_ci * This function is a wrapper around the DRM_IOCTL_AGP_INFO ioctl, getting the 2535d722e3fbSopenharmony_ci * necessary information in a drm_agp_info structure. 2536d722e3fbSopenharmony_ci */ 2537d722e3fbSopenharmony_cidrm_public unsigned int drmAgpVendorId(int fd) 2538d722e3fbSopenharmony_ci{ 2539d722e3fbSopenharmony_ci drm_agp_info_t i; 2540d722e3fbSopenharmony_ci 2541d722e3fbSopenharmony_ci memclear(i); 2542d722e3fbSopenharmony_ci 2543d722e3fbSopenharmony_ci if (drmIoctl(fd, DRM_IOCTL_AGP_INFO, &i)) 2544d722e3fbSopenharmony_ci return 0; 2545d722e3fbSopenharmony_ci return i.id_vendor; 2546d722e3fbSopenharmony_ci} 2547d722e3fbSopenharmony_ci 2548d722e3fbSopenharmony_ci 2549d722e3fbSopenharmony_ci/** 2550d722e3fbSopenharmony_ci * Get hardware device ID. 2551d722e3fbSopenharmony_ci * 2552d722e3fbSopenharmony_ci * \param fd file descriptor. 2553d722e3fbSopenharmony_ci * 2554d722e3fbSopenharmony_ci * \return zero on success, or zero on failure. 2555d722e3fbSopenharmony_ci * 2556d722e3fbSopenharmony_ci * \internal 2557d722e3fbSopenharmony_ci * This function is a wrapper around the DRM_IOCTL_AGP_INFO ioctl, getting the 2558d722e3fbSopenharmony_ci * necessary information in a drm_agp_info structure. 2559d722e3fbSopenharmony_ci */ 2560d722e3fbSopenharmony_cidrm_public unsigned int drmAgpDeviceId(int fd) 2561d722e3fbSopenharmony_ci{ 2562d722e3fbSopenharmony_ci drm_agp_info_t i; 2563d722e3fbSopenharmony_ci 2564d722e3fbSopenharmony_ci memclear(i); 2565d722e3fbSopenharmony_ci 2566d722e3fbSopenharmony_ci if (drmIoctl(fd, DRM_IOCTL_AGP_INFO, &i)) 2567d722e3fbSopenharmony_ci return 0; 2568d722e3fbSopenharmony_ci return i.id_device; 2569d722e3fbSopenharmony_ci} 2570d722e3fbSopenharmony_ci 2571d722e3fbSopenharmony_cidrm_public int drmScatterGatherAlloc(int fd, unsigned long size, 2572d722e3fbSopenharmony_ci drm_handle_t *handle) 2573d722e3fbSopenharmony_ci{ 2574d722e3fbSopenharmony_ci drm_scatter_gather_t sg; 2575d722e3fbSopenharmony_ci 2576d722e3fbSopenharmony_ci memclear(sg); 2577d722e3fbSopenharmony_ci 2578d722e3fbSopenharmony_ci *handle = 0; 2579d722e3fbSopenharmony_ci sg.size = size; 2580d722e3fbSopenharmony_ci if (drmIoctl(fd, DRM_IOCTL_SG_ALLOC, &sg)) 2581d722e3fbSopenharmony_ci return -errno; 2582d722e3fbSopenharmony_ci *handle = sg.handle; 2583d722e3fbSopenharmony_ci return 0; 2584d722e3fbSopenharmony_ci} 2585d722e3fbSopenharmony_ci 2586d722e3fbSopenharmony_cidrm_public int drmScatterGatherFree(int fd, drm_handle_t handle) 2587d722e3fbSopenharmony_ci{ 2588d722e3fbSopenharmony_ci drm_scatter_gather_t sg; 2589d722e3fbSopenharmony_ci 2590d722e3fbSopenharmony_ci memclear(sg); 2591d722e3fbSopenharmony_ci sg.handle = handle; 2592d722e3fbSopenharmony_ci if (drmIoctl(fd, DRM_IOCTL_SG_FREE, &sg)) 2593d722e3fbSopenharmony_ci return -errno; 2594d722e3fbSopenharmony_ci return 0; 2595d722e3fbSopenharmony_ci} 2596d722e3fbSopenharmony_ci 2597d722e3fbSopenharmony_ci/** 2598d722e3fbSopenharmony_ci * Wait for VBLANK. 2599d722e3fbSopenharmony_ci * 2600d722e3fbSopenharmony_ci * \param fd file descriptor. 2601d722e3fbSopenharmony_ci * \param vbl pointer to a drmVBlank structure. 2602d722e3fbSopenharmony_ci * 2603d722e3fbSopenharmony_ci * \return zero on success, or a negative value on failure. 2604d722e3fbSopenharmony_ci * 2605d722e3fbSopenharmony_ci * \internal 2606d722e3fbSopenharmony_ci * This function is a wrapper around the DRM_IOCTL_WAIT_VBLANK ioctl. 2607d722e3fbSopenharmony_ci */ 2608d722e3fbSopenharmony_cidrm_public int drmWaitVBlank(int fd, drmVBlankPtr vbl) 2609d722e3fbSopenharmony_ci{ 2610d722e3fbSopenharmony_ci struct timespec timeout, cur; 2611d722e3fbSopenharmony_ci int ret; 2612d722e3fbSopenharmony_ci 2613d722e3fbSopenharmony_ci ret = clock_gettime(CLOCK_MONOTONIC, &timeout); 2614d722e3fbSopenharmony_ci if (ret < 0) { 2615d722e3fbSopenharmony_ci fprintf(stderr, "clock_gettime failed: %s\n", strerror(errno)); 2616d722e3fbSopenharmony_ci goto out; 2617d722e3fbSopenharmony_ci } 2618d722e3fbSopenharmony_ci timeout.tv_sec++; 2619d722e3fbSopenharmony_ci 2620d722e3fbSopenharmony_ci do { 2621d722e3fbSopenharmony_ci ret = ioctl(fd, DRM_IOCTL_WAIT_VBLANK, vbl); 2622d722e3fbSopenharmony_ci vbl->request.type &= ~DRM_VBLANK_RELATIVE; 2623d722e3fbSopenharmony_ci if (ret && errno == EINTR) { 2624d722e3fbSopenharmony_ci clock_gettime(CLOCK_MONOTONIC, &cur); 2625d722e3fbSopenharmony_ci /* Timeout after 1s */ 2626d722e3fbSopenharmony_ci if (cur.tv_sec > timeout.tv_sec + 1 || 2627d722e3fbSopenharmony_ci (cur.tv_sec == timeout.tv_sec && cur.tv_nsec >= 2628d722e3fbSopenharmony_ci timeout.tv_nsec)) { 2629d722e3fbSopenharmony_ci errno = EBUSY; 2630d722e3fbSopenharmony_ci ret = -1; 2631d722e3fbSopenharmony_ci break; 2632d722e3fbSopenharmony_ci } 2633d722e3fbSopenharmony_ci } 2634d722e3fbSopenharmony_ci } while (ret && errno == EINTR); 2635d722e3fbSopenharmony_ci 2636d722e3fbSopenharmony_ciout: 2637d722e3fbSopenharmony_ci return ret; 2638d722e3fbSopenharmony_ci} 2639d722e3fbSopenharmony_ci 2640d722e3fbSopenharmony_cidrm_public int drmError(int err, const char *label) 2641d722e3fbSopenharmony_ci{ 2642d722e3fbSopenharmony_ci switch (err) { 2643d722e3fbSopenharmony_ci case DRM_ERR_NO_DEVICE: 2644d722e3fbSopenharmony_ci fprintf(stderr, "%s: no device\n", label); 2645d722e3fbSopenharmony_ci break; 2646d722e3fbSopenharmony_ci case DRM_ERR_NO_ACCESS: 2647d722e3fbSopenharmony_ci fprintf(stderr, "%s: no access\n", label); 2648d722e3fbSopenharmony_ci break; 2649d722e3fbSopenharmony_ci case DRM_ERR_NOT_ROOT: 2650d722e3fbSopenharmony_ci fprintf(stderr, "%s: not root\n", label); 2651d722e3fbSopenharmony_ci break; 2652d722e3fbSopenharmony_ci case DRM_ERR_INVALID: 2653d722e3fbSopenharmony_ci fprintf(stderr, "%s: invalid args\n", label); 2654d722e3fbSopenharmony_ci break; 2655d722e3fbSopenharmony_ci default: 2656d722e3fbSopenharmony_ci if (err < 0) 2657d722e3fbSopenharmony_ci err = -err; 2658d722e3fbSopenharmony_ci fprintf( stderr, "%s: error %d (%s)\n", label, err, strerror(err) ); 2659d722e3fbSopenharmony_ci break; 2660d722e3fbSopenharmony_ci } 2661d722e3fbSopenharmony_ci 2662d722e3fbSopenharmony_ci return 1; 2663d722e3fbSopenharmony_ci} 2664d722e3fbSopenharmony_ci 2665d722e3fbSopenharmony_ci/** 2666d722e3fbSopenharmony_ci * Install IRQ handler. 2667d722e3fbSopenharmony_ci * 2668d722e3fbSopenharmony_ci * \param fd file descriptor. 2669d722e3fbSopenharmony_ci * \param irq IRQ number. 2670d722e3fbSopenharmony_ci * 2671d722e3fbSopenharmony_ci * \return zero on success, or a negative value on failure. 2672d722e3fbSopenharmony_ci * 2673d722e3fbSopenharmony_ci * \internal 2674d722e3fbSopenharmony_ci * This function is a wrapper around the DRM_IOCTL_CONTROL ioctl, passing the 2675d722e3fbSopenharmony_ci * argument in a drm_control structure. 2676d722e3fbSopenharmony_ci */ 2677d722e3fbSopenharmony_cidrm_public int drmCtlInstHandler(int fd, int irq) 2678d722e3fbSopenharmony_ci{ 2679d722e3fbSopenharmony_ci drm_control_t ctl; 2680d722e3fbSopenharmony_ci 2681d722e3fbSopenharmony_ci memclear(ctl); 2682d722e3fbSopenharmony_ci ctl.func = DRM_INST_HANDLER; 2683d722e3fbSopenharmony_ci ctl.irq = irq; 2684d722e3fbSopenharmony_ci if (drmIoctl(fd, DRM_IOCTL_CONTROL, &ctl)) 2685d722e3fbSopenharmony_ci return -errno; 2686d722e3fbSopenharmony_ci return 0; 2687d722e3fbSopenharmony_ci} 2688d722e3fbSopenharmony_ci 2689d722e3fbSopenharmony_ci 2690d722e3fbSopenharmony_ci/** 2691d722e3fbSopenharmony_ci * Uninstall IRQ handler. 2692d722e3fbSopenharmony_ci * 2693d722e3fbSopenharmony_ci * \param fd file descriptor. 2694d722e3fbSopenharmony_ci * 2695d722e3fbSopenharmony_ci * \return zero on success, or a negative value on failure. 2696d722e3fbSopenharmony_ci * 2697d722e3fbSopenharmony_ci * \internal 2698d722e3fbSopenharmony_ci * This function is a wrapper around the DRM_IOCTL_CONTROL ioctl, passing the 2699d722e3fbSopenharmony_ci * argument in a drm_control structure. 2700d722e3fbSopenharmony_ci */ 2701d722e3fbSopenharmony_cidrm_public int drmCtlUninstHandler(int fd) 2702d722e3fbSopenharmony_ci{ 2703d722e3fbSopenharmony_ci drm_control_t ctl; 2704d722e3fbSopenharmony_ci 2705d722e3fbSopenharmony_ci memclear(ctl); 2706d722e3fbSopenharmony_ci ctl.func = DRM_UNINST_HANDLER; 2707d722e3fbSopenharmony_ci ctl.irq = 0; 2708d722e3fbSopenharmony_ci if (drmIoctl(fd, DRM_IOCTL_CONTROL, &ctl)) 2709d722e3fbSopenharmony_ci return -errno; 2710d722e3fbSopenharmony_ci return 0; 2711d722e3fbSopenharmony_ci} 2712d722e3fbSopenharmony_ci 2713d722e3fbSopenharmony_cidrm_public int drmFinish(int fd, int context, drmLockFlags flags) 2714d722e3fbSopenharmony_ci{ 2715d722e3fbSopenharmony_ci drm_lock_t lock; 2716d722e3fbSopenharmony_ci 2717d722e3fbSopenharmony_ci memclear(lock); 2718d722e3fbSopenharmony_ci lock.context = context; 2719d722e3fbSopenharmony_ci if (flags & DRM_LOCK_READY) lock.flags |= _DRM_LOCK_READY; 2720d722e3fbSopenharmony_ci if (flags & DRM_LOCK_QUIESCENT) lock.flags |= _DRM_LOCK_QUIESCENT; 2721d722e3fbSopenharmony_ci if (flags & DRM_LOCK_FLUSH) lock.flags |= _DRM_LOCK_FLUSH; 2722d722e3fbSopenharmony_ci if (flags & DRM_LOCK_FLUSH_ALL) lock.flags |= _DRM_LOCK_FLUSH_ALL; 2723d722e3fbSopenharmony_ci if (flags & DRM_HALT_ALL_QUEUES) lock.flags |= _DRM_HALT_ALL_QUEUES; 2724d722e3fbSopenharmony_ci if (flags & DRM_HALT_CUR_QUEUES) lock.flags |= _DRM_HALT_CUR_QUEUES; 2725d722e3fbSopenharmony_ci if (drmIoctl(fd, DRM_IOCTL_FINISH, &lock)) 2726d722e3fbSopenharmony_ci return -errno; 2727d722e3fbSopenharmony_ci return 0; 2728d722e3fbSopenharmony_ci} 2729d722e3fbSopenharmony_ci 2730d722e3fbSopenharmony_ci/** 2731d722e3fbSopenharmony_ci * Get IRQ from bus ID. 2732d722e3fbSopenharmony_ci * 2733d722e3fbSopenharmony_ci * \param fd file descriptor. 2734d722e3fbSopenharmony_ci * \param busnum bus number. 2735d722e3fbSopenharmony_ci * \param devnum device number. 2736d722e3fbSopenharmony_ci * \param funcnum function number. 2737d722e3fbSopenharmony_ci * 2738d722e3fbSopenharmony_ci * \return IRQ number on success, or a negative value on failure. 2739d722e3fbSopenharmony_ci * 2740d722e3fbSopenharmony_ci * \internal 2741d722e3fbSopenharmony_ci * This function is a wrapper around the DRM_IOCTL_IRQ_BUSID ioctl, passing the 2742d722e3fbSopenharmony_ci * arguments in a drm_irq_busid structure. 2743d722e3fbSopenharmony_ci */ 2744d722e3fbSopenharmony_cidrm_public int drmGetInterruptFromBusID(int fd, int busnum, int devnum, 2745d722e3fbSopenharmony_ci int funcnum) 2746d722e3fbSopenharmony_ci{ 2747d722e3fbSopenharmony_ci drm_irq_busid_t p; 2748d722e3fbSopenharmony_ci 2749d722e3fbSopenharmony_ci memclear(p); 2750d722e3fbSopenharmony_ci p.busnum = busnum; 2751d722e3fbSopenharmony_ci p.devnum = devnum; 2752d722e3fbSopenharmony_ci p.funcnum = funcnum; 2753d722e3fbSopenharmony_ci if (drmIoctl(fd, DRM_IOCTL_IRQ_BUSID, &p)) 2754d722e3fbSopenharmony_ci return -errno; 2755d722e3fbSopenharmony_ci return p.irq; 2756d722e3fbSopenharmony_ci} 2757d722e3fbSopenharmony_ci 2758d722e3fbSopenharmony_cidrm_public int drmAddContextTag(int fd, drm_context_t context, void *tag) 2759d722e3fbSopenharmony_ci{ 2760d722e3fbSopenharmony_ci drmHashEntry *entry = drmGetEntry(fd); 2761d722e3fbSopenharmony_ci 2762d722e3fbSopenharmony_ci if (drmHashInsert(entry->tagTable, context, tag)) { 2763d722e3fbSopenharmony_ci drmHashDelete(entry->tagTable, context); 2764d722e3fbSopenharmony_ci drmHashInsert(entry->tagTable, context, tag); 2765d722e3fbSopenharmony_ci } 2766d722e3fbSopenharmony_ci return 0; 2767d722e3fbSopenharmony_ci} 2768d722e3fbSopenharmony_ci 2769d722e3fbSopenharmony_cidrm_public int drmDelContextTag(int fd, drm_context_t context) 2770d722e3fbSopenharmony_ci{ 2771d722e3fbSopenharmony_ci drmHashEntry *entry = drmGetEntry(fd); 2772d722e3fbSopenharmony_ci 2773d722e3fbSopenharmony_ci return drmHashDelete(entry->tagTable, context); 2774d722e3fbSopenharmony_ci} 2775d722e3fbSopenharmony_ci 2776d722e3fbSopenharmony_cidrm_public void *drmGetContextTag(int fd, drm_context_t context) 2777d722e3fbSopenharmony_ci{ 2778d722e3fbSopenharmony_ci drmHashEntry *entry = drmGetEntry(fd); 2779d722e3fbSopenharmony_ci void *value; 2780d722e3fbSopenharmony_ci 2781d722e3fbSopenharmony_ci if (drmHashLookup(entry->tagTable, context, &value)) 2782d722e3fbSopenharmony_ci return NULL; 2783d722e3fbSopenharmony_ci 2784d722e3fbSopenharmony_ci return value; 2785d722e3fbSopenharmony_ci} 2786d722e3fbSopenharmony_ci 2787d722e3fbSopenharmony_cidrm_public int drmAddContextPrivateMapping(int fd, drm_context_t ctx_id, 2788d722e3fbSopenharmony_ci drm_handle_t handle) 2789d722e3fbSopenharmony_ci{ 2790d722e3fbSopenharmony_ci drm_ctx_priv_map_t map; 2791d722e3fbSopenharmony_ci 2792d722e3fbSopenharmony_ci memclear(map); 2793d722e3fbSopenharmony_ci map.ctx_id = ctx_id; 2794d722e3fbSopenharmony_ci map.handle = (void *)(uintptr_t)handle; 2795d722e3fbSopenharmony_ci 2796d722e3fbSopenharmony_ci if (drmIoctl(fd, DRM_IOCTL_SET_SAREA_CTX, &map)) 2797d722e3fbSopenharmony_ci return -errno; 2798d722e3fbSopenharmony_ci return 0; 2799d722e3fbSopenharmony_ci} 2800d722e3fbSopenharmony_ci 2801d722e3fbSopenharmony_cidrm_public int drmGetContextPrivateMapping(int fd, drm_context_t ctx_id, 2802d722e3fbSopenharmony_ci drm_handle_t *handle) 2803d722e3fbSopenharmony_ci{ 2804d722e3fbSopenharmony_ci drm_ctx_priv_map_t map; 2805d722e3fbSopenharmony_ci 2806d722e3fbSopenharmony_ci memclear(map); 2807d722e3fbSopenharmony_ci map.ctx_id = ctx_id; 2808d722e3fbSopenharmony_ci 2809d722e3fbSopenharmony_ci if (drmIoctl(fd, DRM_IOCTL_GET_SAREA_CTX, &map)) 2810d722e3fbSopenharmony_ci return -errno; 2811d722e3fbSopenharmony_ci if (handle) 2812d722e3fbSopenharmony_ci *handle = (drm_handle_t)(uintptr_t)map.handle; 2813d722e3fbSopenharmony_ci 2814d722e3fbSopenharmony_ci return 0; 2815d722e3fbSopenharmony_ci} 2816d722e3fbSopenharmony_ci 2817d722e3fbSopenharmony_cidrm_public int drmGetMap(int fd, int idx, drm_handle_t *offset, drmSize *size, 2818d722e3fbSopenharmony_ci drmMapType *type, drmMapFlags *flags, 2819d722e3fbSopenharmony_ci drm_handle_t *handle, int *mtrr) 2820d722e3fbSopenharmony_ci{ 2821d722e3fbSopenharmony_ci drm_map_t map; 2822d722e3fbSopenharmony_ci 2823d722e3fbSopenharmony_ci memclear(map); 2824d722e3fbSopenharmony_ci map.offset = idx; 2825d722e3fbSopenharmony_ci if (drmIoctl(fd, DRM_IOCTL_GET_MAP, &map)) 2826d722e3fbSopenharmony_ci return -errno; 2827d722e3fbSopenharmony_ci *offset = map.offset; 2828d722e3fbSopenharmony_ci *size = map.size; 2829d722e3fbSopenharmony_ci *type = (drmMapType)map.type; 2830d722e3fbSopenharmony_ci *flags = (drmMapFlags)map.flags; 2831d722e3fbSopenharmony_ci *handle = (unsigned long)map.handle; 2832d722e3fbSopenharmony_ci *mtrr = map.mtrr; 2833d722e3fbSopenharmony_ci return 0; 2834d722e3fbSopenharmony_ci} 2835d722e3fbSopenharmony_ci 2836d722e3fbSopenharmony_cidrm_public int drmGetClient(int fd, int idx, int *auth, int *pid, int *uid, 2837d722e3fbSopenharmony_ci unsigned long *magic, unsigned long *iocs) 2838d722e3fbSopenharmony_ci{ 2839d722e3fbSopenharmony_ci drm_client_t client; 2840d722e3fbSopenharmony_ci 2841d722e3fbSopenharmony_ci memclear(client); 2842d722e3fbSopenharmony_ci client.idx = idx; 2843d722e3fbSopenharmony_ci if (drmIoctl(fd, DRM_IOCTL_GET_CLIENT, &client)) 2844d722e3fbSopenharmony_ci return -errno; 2845d722e3fbSopenharmony_ci *auth = client.auth; 2846d722e3fbSopenharmony_ci *pid = client.pid; 2847d722e3fbSopenharmony_ci *uid = client.uid; 2848d722e3fbSopenharmony_ci *magic = client.magic; 2849d722e3fbSopenharmony_ci *iocs = client.iocs; 2850d722e3fbSopenharmony_ci return 0; 2851d722e3fbSopenharmony_ci} 2852d722e3fbSopenharmony_ci 2853d722e3fbSopenharmony_cidrm_public int drmGetStats(int fd, drmStatsT *stats) 2854d722e3fbSopenharmony_ci{ 2855d722e3fbSopenharmony_ci drm_stats_t s; 2856d722e3fbSopenharmony_ci unsigned i; 2857d722e3fbSopenharmony_ci 2858d722e3fbSopenharmony_ci memclear(s); 2859d722e3fbSopenharmony_ci if (drmIoctl(fd, DRM_IOCTL_GET_STATS, &s)) 2860d722e3fbSopenharmony_ci return -errno; 2861d722e3fbSopenharmony_ci 2862d722e3fbSopenharmony_ci stats->count = 0; 2863d722e3fbSopenharmony_ci memset(stats, 0, sizeof(*stats)); 2864d722e3fbSopenharmony_ci if (s.count > sizeof(stats->data)/sizeof(stats->data[0])) 2865d722e3fbSopenharmony_ci return -1; 2866d722e3fbSopenharmony_ci 2867d722e3fbSopenharmony_ci#define SET_VALUE \ 2868d722e3fbSopenharmony_ci stats->data[i].long_format = "%-20.20s"; \ 2869d722e3fbSopenharmony_ci stats->data[i].rate_format = "%8.8s"; \ 2870d722e3fbSopenharmony_ci stats->data[i].isvalue = 1; \ 2871d722e3fbSopenharmony_ci stats->data[i].verbose = 0 2872d722e3fbSopenharmony_ci 2873d722e3fbSopenharmony_ci#define SET_COUNT \ 2874d722e3fbSopenharmony_ci stats->data[i].long_format = "%-20.20s"; \ 2875d722e3fbSopenharmony_ci stats->data[i].rate_format = "%5.5s"; \ 2876d722e3fbSopenharmony_ci stats->data[i].isvalue = 0; \ 2877d722e3fbSopenharmony_ci stats->data[i].mult_names = "kgm"; \ 2878d722e3fbSopenharmony_ci stats->data[i].mult = 1000; \ 2879d722e3fbSopenharmony_ci stats->data[i].verbose = 0 2880d722e3fbSopenharmony_ci 2881d722e3fbSopenharmony_ci#define SET_BYTE \ 2882d722e3fbSopenharmony_ci stats->data[i].long_format = "%-20.20s"; \ 2883d722e3fbSopenharmony_ci stats->data[i].rate_format = "%5.5s"; \ 2884d722e3fbSopenharmony_ci stats->data[i].isvalue = 0; \ 2885d722e3fbSopenharmony_ci stats->data[i].mult_names = "KGM"; \ 2886d722e3fbSopenharmony_ci stats->data[i].mult = 1024; \ 2887d722e3fbSopenharmony_ci stats->data[i].verbose = 0 2888d722e3fbSopenharmony_ci 2889d722e3fbSopenharmony_ci 2890d722e3fbSopenharmony_ci stats->count = s.count; 2891d722e3fbSopenharmony_ci for (i = 0; i < s.count; i++) { 2892d722e3fbSopenharmony_ci stats->data[i].value = s.data[i].value; 2893d722e3fbSopenharmony_ci switch (s.data[i].type) { 2894d722e3fbSopenharmony_ci case _DRM_STAT_LOCK: 2895d722e3fbSopenharmony_ci stats->data[i].long_name = "Lock"; 2896d722e3fbSopenharmony_ci stats->data[i].rate_name = "Lock"; 2897d722e3fbSopenharmony_ci SET_VALUE; 2898d722e3fbSopenharmony_ci break; 2899d722e3fbSopenharmony_ci case _DRM_STAT_OPENS: 2900d722e3fbSopenharmony_ci stats->data[i].long_name = "Opens"; 2901d722e3fbSopenharmony_ci stats->data[i].rate_name = "O"; 2902d722e3fbSopenharmony_ci SET_COUNT; 2903d722e3fbSopenharmony_ci stats->data[i].verbose = 1; 2904d722e3fbSopenharmony_ci break; 2905d722e3fbSopenharmony_ci case _DRM_STAT_CLOSES: 2906d722e3fbSopenharmony_ci stats->data[i].long_name = "Closes"; 2907d722e3fbSopenharmony_ci stats->data[i].rate_name = "Lock"; 2908d722e3fbSopenharmony_ci SET_COUNT; 2909d722e3fbSopenharmony_ci stats->data[i].verbose = 1; 2910d722e3fbSopenharmony_ci break; 2911d722e3fbSopenharmony_ci case _DRM_STAT_IOCTLS: 2912d722e3fbSopenharmony_ci stats->data[i].long_name = "Ioctls"; 2913d722e3fbSopenharmony_ci stats->data[i].rate_name = "Ioc/s"; 2914d722e3fbSopenharmony_ci SET_COUNT; 2915d722e3fbSopenharmony_ci break; 2916d722e3fbSopenharmony_ci case _DRM_STAT_LOCKS: 2917d722e3fbSopenharmony_ci stats->data[i].long_name = "Locks"; 2918d722e3fbSopenharmony_ci stats->data[i].rate_name = "Lck/s"; 2919d722e3fbSopenharmony_ci SET_COUNT; 2920d722e3fbSopenharmony_ci break; 2921d722e3fbSopenharmony_ci case _DRM_STAT_UNLOCKS: 2922d722e3fbSopenharmony_ci stats->data[i].long_name = "Unlocks"; 2923d722e3fbSopenharmony_ci stats->data[i].rate_name = "Unl/s"; 2924d722e3fbSopenharmony_ci SET_COUNT; 2925d722e3fbSopenharmony_ci break; 2926d722e3fbSopenharmony_ci case _DRM_STAT_IRQ: 2927d722e3fbSopenharmony_ci stats->data[i].long_name = "IRQs"; 2928d722e3fbSopenharmony_ci stats->data[i].rate_name = "IRQ/s"; 2929d722e3fbSopenharmony_ci SET_COUNT; 2930d722e3fbSopenharmony_ci break; 2931d722e3fbSopenharmony_ci case _DRM_STAT_PRIMARY: 2932d722e3fbSopenharmony_ci stats->data[i].long_name = "Primary Bytes"; 2933d722e3fbSopenharmony_ci stats->data[i].rate_name = "PB/s"; 2934d722e3fbSopenharmony_ci SET_BYTE; 2935d722e3fbSopenharmony_ci break; 2936d722e3fbSopenharmony_ci case _DRM_STAT_SECONDARY: 2937d722e3fbSopenharmony_ci stats->data[i].long_name = "Secondary Bytes"; 2938d722e3fbSopenharmony_ci stats->data[i].rate_name = "SB/s"; 2939d722e3fbSopenharmony_ci SET_BYTE; 2940d722e3fbSopenharmony_ci break; 2941d722e3fbSopenharmony_ci case _DRM_STAT_DMA: 2942d722e3fbSopenharmony_ci stats->data[i].long_name = "DMA"; 2943d722e3fbSopenharmony_ci stats->data[i].rate_name = "DMA/s"; 2944d722e3fbSopenharmony_ci SET_COUNT; 2945d722e3fbSopenharmony_ci break; 2946d722e3fbSopenharmony_ci case _DRM_STAT_SPECIAL: 2947d722e3fbSopenharmony_ci stats->data[i].long_name = "Special DMA"; 2948d722e3fbSopenharmony_ci stats->data[i].rate_name = "dma/s"; 2949d722e3fbSopenharmony_ci SET_COUNT; 2950d722e3fbSopenharmony_ci break; 2951d722e3fbSopenharmony_ci case _DRM_STAT_MISSED: 2952d722e3fbSopenharmony_ci stats->data[i].long_name = "Miss"; 2953d722e3fbSopenharmony_ci stats->data[i].rate_name = "Ms/s"; 2954d722e3fbSopenharmony_ci SET_COUNT; 2955d722e3fbSopenharmony_ci break; 2956d722e3fbSopenharmony_ci case _DRM_STAT_VALUE: 2957d722e3fbSopenharmony_ci stats->data[i].long_name = "Value"; 2958d722e3fbSopenharmony_ci stats->data[i].rate_name = "Value"; 2959d722e3fbSopenharmony_ci SET_VALUE; 2960d722e3fbSopenharmony_ci break; 2961d722e3fbSopenharmony_ci case _DRM_STAT_BYTE: 2962d722e3fbSopenharmony_ci stats->data[i].long_name = "Bytes"; 2963d722e3fbSopenharmony_ci stats->data[i].rate_name = "B/s"; 2964d722e3fbSopenharmony_ci SET_BYTE; 2965d722e3fbSopenharmony_ci break; 2966d722e3fbSopenharmony_ci case _DRM_STAT_COUNT: 2967d722e3fbSopenharmony_ci default: 2968d722e3fbSopenharmony_ci stats->data[i].long_name = "Count"; 2969d722e3fbSopenharmony_ci stats->data[i].rate_name = "Cnt/s"; 2970d722e3fbSopenharmony_ci SET_COUNT; 2971d722e3fbSopenharmony_ci break; 2972d722e3fbSopenharmony_ci } 2973d722e3fbSopenharmony_ci } 2974d722e3fbSopenharmony_ci return 0; 2975d722e3fbSopenharmony_ci} 2976d722e3fbSopenharmony_ci 2977d722e3fbSopenharmony_ci/** 2978d722e3fbSopenharmony_ci * Issue a set-version ioctl. 2979d722e3fbSopenharmony_ci * 2980d722e3fbSopenharmony_ci * \param fd file descriptor. 2981d722e3fbSopenharmony_ci * \param drmCommandIndex command index 2982d722e3fbSopenharmony_ci * \param data source pointer of the data to be read and written. 2983d722e3fbSopenharmony_ci * \param size size of the data to be read and written. 2984d722e3fbSopenharmony_ci * 2985d722e3fbSopenharmony_ci * \return zero on success, or a negative value on failure. 2986d722e3fbSopenharmony_ci * 2987d722e3fbSopenharmony_ci * \internal 2988d722e3fbSopenharmony_ci * It issues a read-write ioctl given by 2989d722e3fbSopenharmony_ci * \code DRM_COMMAND_BASE + drmCommandIndex \endcode. 2990d722e3fbSopenharmony_ci */ 2991d722e3fbSopenharmony_cidrm_public int drmSetInterfaceVersion(int fd, drmSetVersion *version) 2992d722e3fbSopenharmony_ci{ 2993d722e3fbSopenharmony_ci int retcode = 0; 2994d722e3fbSopenharmony_ci drm_set_version_t sv; 2995d722e3fbSopenharmony_ci 2996d722e3fbSopenharmony_ci memclear(sv); 2997d722e3fbSopenharmony_ci sv.drm_di_major = version->drm_di_major; 2998d722e3fbSopenharmony_ci sv.drm_di_minor = version->drm_di_minor; 2999d722e3fbSopenharmony_ci sv.drm_dd_major = version->drm_dd_major; 3000d722e3fbSopenharmony_ci sv.drm_dd_minor = version->drm_dd_minor; 3001d722e3fbSopenharmony_ci 3002d722e3fbSopenharmony_ci if (drmIoctl(fd, DRM_IOCTL_SET_VERSION, &sv)) { 3003d722e3fbSopenharmony_ci retcode = -errno; 3004d722e3fbSopenharmony_ci } 3005d722e3fbSopenharmony_ci 3006d722e3fbSopenharmony_ci version->drm_di_major = sv.drm_di_major; 3007d722e3fbSopenharmony_ci version->drm_di_minor = sv.drm_di_minor; 3008d722e3fbSopenharmony_ci version->drm_dd_major = sv.drm_dd_major; 3009d722e3fbSopenharmony_ci version->drm_dd_minor = sv.drm_dd_minor; 3010d722e3fbSopenharmony_ci 3011d722e3fbSopenharmony_ci return retcode; 3012d722e3fbSopenharmony_ci} 3013d722e3fbSopenharmony_ci 3014d722e3fbSopenharmony_ci/** 3015d722e3fbSopenharmony_ci * Send a device-specific command. 3016d722e3fbSopenharmony_ci * 3017d722e3fbSopenharmony_ci * \param fd file descriptor. 3018d722e3fbSopenharmony_ci * \param drmCommandIndex command index 3019d722e3fbSopenharmony_ci * 3020d722e3fbSopenharmony_ci * \return zero on success, or a negative value on failure. 3021d722e3fbSopenharmony_ci * 3022d722e3fbSopenharmony_ci * \internal 3023d722e3fbSopenharmony_ci * It issues a ioctl given by 3024d722e3fbSopenharmony_ci * \code DRM_COMMAND_BASE + drmCommandIndex \endcode. 3025d722e3fbSopenharmony_ci */ 3026d722e3fbSopenharmony_cidrm_public int drmCommandNone(int fd, unsigned long drmCommandIndex) 3027d722e3fbSopenharmony_ci{ 3028d722e3fbSopenharmony_ci unsigned long request; 3029d722e3fbSopenharmony_ci 3030d722e3fbSopenharmony_ci request = DRM_IO( DRM_COMMAND_BASE + drmCommandIndex); 3031d722e3fbSopenharmony_ci 3032d722e3fbSopenharmony_ci if (drmIoctl(fd, request, NULL)) { 3033d722e3fbSopenharmony_ci return -errno; 3034d722e3fbSopenharmony_ci } 3035d722e3fbSopenharmony_ci return 0; 3036d722e3fbSopenharmony_ci} 3037d722e3fbSopenharmony_ci 3038d722e3fbSopenharmony_ci 3039d722e3fbSopenharmony_ci/** 3040d722e3fbSopenharmony_ci * Send a device-specific read command. 3041d722e3fbSopenharmony_ci * 3042d722e3fbSopenharmony_ci * \param fd file descriptor. 3043d722e3fbSopenharmony_ci * \param drmCommandIndex command index 3044d722e3fbSopenharmony_ci * \param data destination pointer of the data to be read. 3045d722e3fbSopenharmony_ci * \param size size of the data to be read. 3046d722e3fbSopenharmony_ci * 3047d722e3fbSopenharmony_ci * \return zero on success, or a negative value on failure. 3048d722e3fbSopenharmony_ci * 3049d722e3fbSopenharmony_ci * \internal 3050d722e3fbSopenharmony_ci * It issues a read ioctl given by 3051d722e3fbSopenharmony_ci * \code DRM_COMMAND_BASE + drmCommandIndex \endcode. 3052d722e3fbSopenharmony_ci */ 3053d722e3fbSopenharmony_cidrm_public int drmCommandRead(int fd, unsigned long drmCommandIndex, 3054d722e3fbSopenharmony_ci void *data, unsigned long size) 3055d722e3fbSopenharmony_ci{ 3056d722e3fbSopenharmony_ci unsigned long request; 3057d722e3fbSopenharmony_ci 3058d722e3fbSopenharmony_ci request = DRM_IOC( DRM_IOC_READ, DRM_IOCTL_BASE, 3059d722e3fbSopenharmony_ci DRM_COMMAND_BASE + drmCommandIndex, size); 3060d722e3fbSopenharmony_ci 3061d722e3fbSopenharmony_ci if (drmIoctl(fd, request, data)) { 3062d722e3fbSopenharmony_ci return -errno; 3063d722e3fbSopenharmony_ci } 3064d722e3fbSopenharmony_ci return 0; 3065d722e3fbSopenharmony_ci} 3066d722e3fbSopenharmony_ci 3067d722e3fbSopenharmony_ci 3068d722e3fbSopenharmony_ci/** 3069d722e3fbSopenharmony_ci * Send a device-specific write command. 3070d722e3fbSopenharmony_ci * 3071d722e3fbSopenharmony_ci * \param fd file descriptor. 3072d722e3fbSopenharmony_ci * \param drmCommandIndex command index 3073d722e3fbSopenharmony_ci * \param data source pointer of the data to be written. 3074d722e3fbSopenharmony_ci * \param size size of the data to be written. 3075d722e3fbSopenharmony_ci * 3076d722e3fbSopenharmony_ci * \return zero on success, or a negative value on failure. 3077d722e3fbSopenharmony_ci * 3078d722e3fbSopenharmony_ci * \internal 3079d722e3fbSopenharmony_ci * It issues a write ioctl given by 3080d722e3fbSopenharmony_ci * \code DRM_COMMAND_BASE + drmCommandIndex \endcode. 3081d722e3fbSopenharmony_ci */ 3082d722e3fbSopenharmony_cidrm_public int drmCommandWrite(int fd, unsigned long drmCommandIndex, 3083d722e3fbSopenharmony_ci void *data, unsigned long size) 3084d722e3fbSopenharmony_ci{ 3085d722e3fbSopenharmony_ci unsigned long request; 3086d722e3fbSopenharmony_ci 3087d722e3fbSopenharmony_ci request = DRM_IOC( DRM_IOC_WRITE, DRM_IOCTL_BASE, 3088d722e3fbSopenharmony_ci DRM_COMMAND_BASE + drmCommandIndex, size); 3089d722e3fbSopenharmony_ci 3090d722e3fbSopenharmony_ci if (drmIoctl(fd, request, data)) { 3091d722e3fbSopenharmony_ci return -errno; 3092d722e3fbSopenharmony_ci } 3093d722e3fbSopenharmony_ci return 0; 3094d722e3fbSopenharmony_ci} 3095d722e3fbSopenharmony_ci 3096d722e3fbSopenharmony_ci 3097d722e3fbSopenharmony_ci/** 3098d722e3fbSopenharmony_ci * Send a device-specific read-write command. 3099d722e3fbSopenharmony_ci * 3100d722e3fbSopenharmony_ci * \param fd file descriptor. 3101d722e3fbSopenharmony_ci * \param drmCommandIndex command index 3102d722e3fbSopenharmony_ci * \param data source pointer of the data to be read and written. 3103d722e3fbSopenharmony_ci * \param size size of the data to be read and written. 3104d722e3fbSopenharmony_ci * 3105d722e3fbSopenharmony_ci * \return zero on success, or a negative value on failure. 3106d722e3fbSopenharmony_ci * 3107d722e3fbSopenharmony_ci * \internal 3108d722e3fbSopenharmony_ci * It issues a read-write ioctl given by 3109d722e3fbSopenharmony_ci * \code DRM_COMMAND_BASE + drmCommandIndex \endcode. 3110d722e3fbSopenharmony_ci */ 3111d722e3fbSopenharmony_cidrm_public int drmCommandWriteRead(int fd, unsigned long drmCommandIndex, 3112d722e3fbSopenharmony_ci void *data, unsigned long size) 3113d722e3fbSopenharmony_ci{ 3114d722e3fbSopenharmony_ci unsigned long request; 3115d722e3fbSopenharmony_ci 3116d722e3fbSopenharmony_ci request = DRM_IOC( DRM_IOC_READ|DRM_IOC_WRITE, DRM_IOCTL_BASE, 3117d722e3fbSopenharmony_ci DRM_COMMAND_BASE + drmCommandIndex, size); 3118d722e3fbSopenharmony_ci 3119d722e3fbSopenharmony_ci if (drmIoctl(fd, request, data)) 3120d722e3fbSopenharmony_ci return -errno; 3121d722e3fbSopenharmony_ci return 0; 3122d722e3fbSopenharmony_ci} 3123d722e3fbSopenharmony_ci 3124d722e3fbSopenharmony_ci#define DRM_MAX_FDS 16 3125d722e3fbSopenharmony_cistatic struct { 3126d722e3fbSopenharmony_ci char *BusID; 3127d722e3fbSopenharmony_ci int fd; 3128d722e3fbSopenharmony_ci int refcount; 3129d722e3fbSopenharmony_ci int type; 3130d722e3fbSopenharmony_ci} connection[DRM_MAX_FDS]; 3131d722e3fbSopenharmony_ci 3132d722e3fbSopenharmony_cistatic int nr_fds = 0; 3133d722e3fbSopenharmony_ci 3134d722e3fbSopenharmony_cidrm_public int drmOpenOnce(void *unused, const char *BusID, int *newlyopened) 3135d722e3fbSopenharmony_ci{ 3136d722e3fbSopenharmony_ci return drmOpenOnceWithType(BusID, newlyopened, DRM_NODE_PRIMARY); 3137d722e3fbSopenharmony_ci} 3138d722e3fbSopenharmony_ci 3139d722e3fbSopenharmony_cidrm_public int drmOpenOnceWithType(const char *BusID, int *newlyopened, 3140d722e3fbSopenharmony_ci int type) 3141d722e3fbSopenharmony_ci{ 3142d722e3fbSopenharmony_ci int i; 3143d722e3fbSopenharmony_ci int fd; 3144d722e3fbSopenharmony_ci 3145d722e3fbSopenharmony_ci for (i = 0; i < nr_fds; i++) 3146d722e3fbSopenharmony_ci if ((strcmp(BusID, connection[i].BusID) == 0) && 3147d722e3fbSopenharmony_ci (connection[i].type == type)) { 3148d722e3fbSopenharmony_ci connection[i].refcount++; 3149d722e3fbSopenharmony_ci *newlyopened = 0; 3150d722e3fbSopenharmony_ci return connection[i].fd; 3151d722e3fbSopenharmony_ci } 3152d722e3fbSopenharmony_ci 3153d722e3fbSopenharmony_ci fd = drmOpenWithType(NULL, BusID, type); 3154d722e3fbSopenharmony_ci if (fd < 0 || nr_fds == DRM_MAX_FDS) 3155d722e3fbSopenharmony_ci return fd; 3156d722e3fbSopenharmony_ci 3157d722e3fbSopenharmony_ci connection[nr_fds].BusID = strdup(BusID); 3158d722e3fbSopenharmony_ci connection[nr_fds].fd = fd; 3159d722e3fbSopenharmony_ci connection[nr_fds].refcount = 1; 3160d722e3fbSopenharmony_ci connection[nr_fds].type = type; 3161d722e3fbSopenharmony_ci *newlyopened = 1; 3162d722e3fbSopenharmony_ci 3163d722e3fbSopenharmony_ci if (0) 3164d722e3fbSopenharmony_ci fprintf(stderr, "saved connection %d for %s %d\n", 3165d722e3fbSopenharmony_ci nr_fds, connection[nr_fds].BusID, 3166d722e3fbSopenharmony_ci strcmp(BusID, connection[nr_fds].BusID)); 3167d722e3fbSopenharmony_ci 3168d722e3fbSopenharmony_ci nr_fds++; 3169d722e3fbSopenharmony_ci 3170d722e3fbSopenharmony_ci return fd; 3171d722e3fbSopenharmony_ci} 3172d722e3fbSopenharmony_ci 3173d722e3fbSopenharmony_cidrm_public void drmCloseOnce(int fd) 3174d722e3fbSopenharmony_ci{ 3175d722e3fbSopenharmony_ci int i; 3176d722e3fbSopenharmony_ci 3177d722e3fbSopenharmony_ci for (i = 0; i < nr_fds; i++) { 3178d722e3fbSopenharmony_ci if (fd == connection[i].fd) { 3179d722e3fbSopenharmony_ci if (--connection[i].refcount == 0) { 3180d722e3fbSopenharmony_ci drmClose(connection[i].fd); 3181d722e3fbSopenharmony_ci free(connection[i].BusID); 3182d722e3fbSopenharmony_ci 3183d722e3fbSopenharmony_ci if (i < --nr_fds) 3184d722e3fbSopenharmony_ci connection[i] = connection[nr_fds]; 3185d722e3fbSopenharmony_ci 3186d722e3fbSopenharmony_ci return; 3187d722e3fbSopenharmony_ci } 3188d722e3fbSopenharmony_ci } 3189d722e3fbSopenharmony_ci } 3190d722e3fbSopenharmony_ci} 3191d722e3fbSopenharmony_ci 3192d722e3fbSopenharmony_cidrm_public int drmSetMaster(int fd) 3193d722e3fbSopenharmony_ci{ 3194d722e3fbSopenharmony_ci return drmIoctl(fd, DRM_IOCTL_SET_MASTER, NULL); 3195d722e3fbSopenharmony_ci} 3196d722e3fbSopenharmony_ci 3197d722e3fbSopenharmony_cidrm_public int drmDropMaster(int fd) 3198d722e3fbSopenharmony_ci{ 3199d722e3fbSopenharmony_ci return drmIoctl(fd, DRM_IOCTL_DROP_MASTER, NULL); 3200d722e3fbSopenharmony_ci} 3201d722e3fbSopenharmony_ci 3202d722e3fbSopenharmony_cidrm_public int drmIsMaster(int fd) 3203d722e3fbSopenharmony_ci{ 3204d722e3fbSopenharmony_ci /* Detect master by attempting something that requires master. 3205d722e3fbSopenharmony_ci * 3206d722e3fbSopenharmony_ci * Authenticating magic tokens requires master and 0 is an 3207d722e3fbSopenharmony_ci * internal kernel detail which we could use. Attempting this on 3208d722e3fbSopenharmony_ci * a master fd would fail therefore fail with EINVAL because 0 3209d722e3fbSopenharmony_ci * is invalid. 3210d722e3fbSopenharmony_ci * 3211d722e3fbSopenharmony_ci * A non-master fd will fail with EACCES, as the kernel checks 3212d722e3fbSopenharmony_ci * for master before attempting to do anything else. 3213d722e3fbSopenharmony_ci * 3214d722e3fbSopenharmony_ci * Since we don't want to leak implementation details, use 3215d722e3fbSopenharmony_ci * EACCES. 3216d722e3fbSopenharmony_ci */ 3217d722e3fbSopenharmony_ci return drmAuthMagic(fd, 0) != -EACCES; 3218d722e3fbSopenharmony_ci} 3219d722e3fbSopenharmony_ci 3220d722e3fbSopenharmony_cidrm_public char *drmGetDeviceNameFromFd(int fd) 3221d722e3fbSopenharmony_ci{ 3222d722e3fbSopenharmony_ci#ifdef __FreeBSD__ 3223d722e3fbSopenharmony_ci struct stat sbuf; 3224d722e3fbSopenharmony_ci int maj, min; 3225d722e3fbSopenharmony_ci int nodetype; 3226d722e3fbSopenharmony_ci 3227d722e3fbSopenharmony_ci if (fstat(fd, &sbuf)) 3228d722e3fbSopenharmony_ci return NULL; 3229d722e3fbSopenharmony_ci 3230d722e3fbSopenharmony_ci maj = major(sbuf.st_rdev); 3231d722e3fbSopenharmony_ci min = minor(sbuf.st_rdev); 3232d722e3fbSopenharmony_ci nodetype = drmGetMinorType(maj, min); 3233d722e3fbSopenharmony_ci return drmGetMinorNameForFD(fd, nodetype); 3234d722e3fbSopenharmony_ci#else 3235d722e3fbSopenharmony_ci char name[128]; 3236d722e3fbSopenharmony_ci struct stat sbuf; 3237d722e3fbSopenharmony_ci dev_t d; 3238d722e3fbSopenharmony_ci int i; 3239d722e3fbSopenharmony_ci 3240d722e3fbSopenharmony_ci /* The whole drmOpen thing is a fiasco and we need to find a way 3241d722e3fbSopenharmony_ci * back to just using open(2). For now, however, lets just make 3242d722e3fbSopenharmony_ci * things worse with even more ad hoc directory walking code to 3243d722e3fbSopenharmony_ci * discover the device file name. */ 3244d722e3fbSopenharmony_ci 3245d722e3fbSopenharmony_ci fstat(fd, &sbuf); 3246d722e3fbSopenharmony_ci d = sbuf.st_rdev; 3247d722e3fbSopenharmony_ci 3248d722e3fbSopenharmony_ci for (i = 0; i < DRM_MAX_MINOR; i++) { 3249d722e3fbSopenharmony_ci snprintf(name, sizeof name, DRM_DEV_NAME, DRM_DIR_NAME, i); 3250d722e3fbSopenharmony_ci if (stat(name, &sbuf) == 0 && sbuf.st_rdev == d) 3251d722e3fbSopenharmony_ci break; 3252d722e3fbSopenharmony_ci } 3253d722e3fbSopenharmony_ci if (i == DRM_MAX_MINOR) 3254d722e3fbSopenharmony_ci return NULL; 3255d722e3fbSopenharmony_ci 3256d722e3fbSopenharmony_ci return strdup(name); 3257d722e3fbSopenharmony_ci#endif 3258d722e3fbSopenharmony_ci} 3259d722e3fbSopenharmony_ci 3260d722e3fbSopenharmony_cistatic bool drmNodeIsDRM(int maj, int min) 3261d722e3fbSopenharmony_ci{ 3262d722e3fbSopenharmony_ci#ifdef __linux__ 3263d722e3fbSopenharmony_ci char path[64]; 3264d722e3fbSopenharmony_ci struct stat sbuf; 3265d722e3fbSopenharmony_ci 3266d722e3fbSopenharmony_ci snprintf(path, sizeof(path), "/sys/dev/char/%d:%d/device/drm", 3267d722e3fbSopenharmony_ci maj, min); 3268d722e3fbSopenharmony_ci return stat(path, &sbuf) == 0; 3269d722e3fbSopenharmony_ci#elif defined(__FreeBSD__) 3270d722e3fbSopenharmony_ci char name[SPECNAMELEN]; 3271d722e3fbSopenharmony_ci 3272d722e3fbSopenharmony_ci if (!devname_r(makedev(maj, min), S_IFCHR, name, sizeof(name))) 3273d722e3fbSopenharmony_ci return 0; 3274d722e3fbSopenharmony_ci /* Handle drm/ and dri/ as both are present in different FreeBSD version 3275d722e3fbSopenharmony_ci * FreeBSD on amd64/i386/powerpc external kernel modules create node in 3276d722e3fbSopenharmony_ci * in /dev/drm/ and links in /dev/dri while a WIP in kernel driver creates 3277d722e3fbSopenharmony_ci * only device nodes in /dev/dri/ */ 3278d722e3fbSopenharmony_ci return (!strncmp(name, "drm/", 4) || !strncmp(name, "dri/", 4)); 3279d722e3fbSopenharmony_ci#else 3280d722e3fbSopenharmony_ci return maj == DRM_MAJOR; 3281d722e3fbSopenharmony_ci#endif 3282d722e3fbSopenharmony_ci} 3283d722e3fbSopenharmony_ci 3284d722e3fbSopenharmony_cidrm_public int drmGetNodeTypeFromFd(int fd) 3285d722e3fbSopenharmony_ci{ 3286d722e3fbSopenharmony_ci struct stat sbuf; 3287d722e3fbSopenharmony_ci int maj, min, type; 3288d722e3fbSopenharmony_ci 3289d722e3fbSopenharmony_ci if (fstat(fd, &sbuf)) 3290d722e3fbSopenharmony_ci return -1; 3291d722e3fbSopenharmony_ci 3292d722e3fbSopenharmony_ci maj = major(sbuf.st_rdev); 3293d722e3fbSopenharmony_ci min = minor(sbuf.st_rdev); 3294d722e3fbSopenharmony_ci 3295d722e3fbSopenharmony_ci if (!drmNodeIsDRM(maj, min) || !S_ISCHR(sbuf.st_mode)) { 3296d722e3fbSopenharmony_ci errno = EINVAL; 3297d722e3fbSopenharmony_ci return -1; 3298d722e3fbSopenharmony_ci } 3299d722e3fbSopenharmony_ci 3300d722e3fbSopenharmony_ci type = drmGetMinorType(maj, min); 3301d722e3fbSopenharmony_ci if (type == -1) 3302d722e3fbSopenharmony_ci errno = ENODEV; 3303d722e3fbSopenharmony_ci return type; 3304d722e3fbSopenharmony_ci} 3305d722e3fbSopenharmony_ci 3306d722e3fbSopenharmony_cidrm_public int drmPrimeHandleToFD(int fd, uint32_t handle, uint32_t flags, 3307d722e3fbSopenharmony_ci int *prime_fd) 3308d722e3fbSopenharmony_ci{ 3309d722e3fbSopenharmony_ci struct drm_prime_handle args; 3310d722e3fbSopenharmony_ci int ret; 3311d722e3fbSopenharmony_ci 3312d722e3fbSopenharmony_ci memclear(args); 3313d722e3fbSopenharmony_ci args.fd = -1; 3314d722e3fbSopenharmony_ci args.handle = handle; 3315d722e3fbSopenharmony_ci args.flags = flags; 3316d722e3fbSopenharmony_ci ret = drmIoctl(fd, DRM_IOCTL_PRIME_HANDLE_TO_FD, &args); 3317d722e3fbSopenharmony_ci if (ret) 3318d722e3fbSopenharmony_ci return ret; 3319d722e3fbSopenharmony_ci 3320d722e3fbSopenharmony_ci *prime_fd = args.fd; 3321d722e3fbSopenharmony_ci return 0; 3322d722e3fbSopenharmony_ci} 3323d722e3fbSopenharmony_ci 3324d722e3fbSopenharmony_cidrm_public int drmPrimeFDToHandle(int fd, int prime_fd, uint32_t *handle) 3325d722e3fbSopenharmony_ci{ 3326d722e3fbSopenharmony_ci struct drm_prime_handle args; 3327d722e3fbSopenharmony_ci int ret; 3328d722e3fbSopenharmony_ci 3329d722e3fbSopenharmony_ci memclear(args); 3330d722e3fbSopenharmony_ci args.fd = prime_fd; 3331d722e3fbSopenharmony_ci ret = drmIoctl(fd, DRM_IOCTL_PRIME_FD_TO_HANDLE, &args); 3332d722e3fbSopenharmony_ci if (ret) 3333d722e3fbSopenharmony_ci return ret; 3334d722e3fbSopenharmony_ci 3335d722e3fbSopenharmony_ci *handle = args.handle; 3336d722e3fbSopenharmony_ci return 0; 3337d722e3fbSopenharmony_ci} 3338d722e3fbSopenharmony_ci 3339d722e3fbSopenharmony_cidrm_public int drmCloseBufferHandle(int fd, uint32_t handle) 3340d722e3fbSopenharmony_ci{ 3341d722e3fbSopenharmony_ci struct drm_gem_close args; 3342d722e3fbSopenharmony_ci 3343d722e3fbSopenharmony_ci memclear(args); 3344d722e3fbSopenharmony_ci args.handle = handle; 3345d722e3fbSopenharmony_ci return drmIoctl(fd, DRM_IOCTL_GEM_CLOSE, &args); 3346d722e3fbSopenharmony_ci} 3347d722e3fbSopenharmony_ci 3348d722e3fbSopenharmony_cistatic char *drmGetMinorNameForFD(int fd, int type) 3349d722e3fbSopenharmony_ci{ 3350d722e3fbSopenharmony_ci#ifdef __linux__ 3351d722e3fbSopenharmony_ci DIR *sysdir; 3352d722e3fbSopenharmony_ci struct dirent *ent; 3353d722e3fbSopenharmony_ci struct stat sbuf; 3354d722e3fbSopenharmony_ci const char *name = drmGetMinorName(type); 3355d722e3fbSopenharmony_ci int len; 3356d722e3fbSopenharmony_ci char dev_name[64], buf[64]; 3357d722e3fbSopenharmony_ci int maj, min; 3358d722e3fbSopenharmony_ci 3359d722e3fbSopenharmony_ci if (!name) 3360d722e3fbSopenharmony_ci return NULL; 3361d722e3fbSopenharmony_ci 3362d722e3fbSopenharmony_ci len = strlen(name); 3363d722e3fbSopenharmony_ci 3364d722e3fbSopenharmony_ci if (fstat(fd, &sbuf)) 3365d722e3fbSopenharmony_ci return NULL; 3366d722e3fbSopenharmony_ci 3367d722e3fbSopenharmony_ci maj = major(sbuf.st_rdev); 3368d722e3fbSopenharmony_ci min = minor(sbuf.st_rdev); 3369d722e3fbSopenharmony_ci 3370d722e3fbSopenharmony_ci if (!drmNodeIsDRM(maj, min) || !S_ISCHR(sbuf.st_mode)) 3371d722e3fbSopenharmony_ci return NULL; 3372d722e3fbSopenharmony_ci 3373d722e3fbSopenharmony_ci snprintf(buf, sizeof(buf), "/sys/dev/char/%d:%d/device/drm", maj, min); 3374d722e3fbSopenharmony_ci 3375d722e3fbSopenharmony_ci sysdir = opendir(buf); 3376d722e3fbSopenharmony_ci if (!sysdir) 3377d722e3fbSopenharmony_ci return NULL; 3378d722e3fbSopenharmony_ci 3379d722e3fbSopenharmony_ci while ((ent = readdir(sysdir))) { 3380d722e3fbSopenharmony_ci if (strncmp(ent->d_name, name, len) == 0) { 3381d722e3fbSopenharmony_ci if (snprintf(dev_name, sizeof(dev_name), DRM_DIR_NAME "/%s", 3382d722e3fbSopenharmony_ci ent->d_name) < 0) 3383d722e3fbSopenharmony_ci return NULL; 3384d722e3fbSopenharmony_ci 3385d722e3fbSopenharmony_ci closedir(sysdir); 3386d722e3fbSopenharmony_ci return strdup(dev_name); 3387d722e3fbSopenharmony_ci } 3388d722e3fbSopenharmony_ci } 3389d722e3fbSopenharmony_ci 3390d722e3fbSopenharmony_ci closedir(sysdir); 3391d722e3fbSopenharmony_ci return NULL; 3392d722e3fbSopenharmony_ci#elif defined(__FreeBSD__) 3393d722e3fbSopenharmony_ci struct stat sbuf; 3394d722e3fbSopenharmony_ci char dname[SPECNAMELEN]; 3395d722e3fbSopenharmony_ci const char *mname; 3396d722e3fbSopenharmony_ci char name[SPECNAMELEN]; 3397d722e3fbSopenharmony_ci int id, maj, min, nodetype, i; 3398d722e3fbSopenharmony_ci 3399d722e3fbSopenharmony_ci if (fstat(fd, &sbuf)) 3400d722e3fbSopenharmony_ci return NULL; 3401d722e3fbSopenharmony_ci 3402d722e3fbSopenharmony_ci maj = major(sbuf.st_rdev); 3403d722e3fbSopenharmony_ci min = minor(sbuf.st_rdev); 3404d722e3fbSopenharmony_ci 3405d722e3fbSopenharmony_ci if (!drmNodeIsDRM(maj, min) || !S_ISCHR(sbuf.st_mode)) 3406d722e3fbSopenharmony_ci return NULL; 3407d722e3fbSopenharmony_ci 3408d722e3fbSopenharmony_ci if (!devname_r(sbuf.st_rdev, S_IFCHR, dname, sizeof(dname))) 3409d722e3fbSopenharmony_ci return NULL; 3410d722e3fbSopenharmony_ci 3411d722e3fbSopenharmony_ci /* Handle both /dev/drm and /dev/dri 3412d722e3fbSopenharmony_ci * FreeBSD on amd64/i386/powerpc external kernel modules create node in 3413d722e3fbSopenharmony_ci * in /dev/drm/ and links in /dev/dri while a WIP in kernel driver creates 3414d722e3fbSopenharmony_ci * only device nodes in /dev/dri/ */ 3415d722e3fbSopenharmony_ci 3416d722e3fbSopenharmony_ci /* Get the node type represented by fd so we can deduce the target name */ 3417d722e3fbSopenharmony_ci nodetype = drmGetMinorType(maj, min); 3418d722e3fbSopenharmony_ci if (nodetype == -1) 3419d722e3fbSopenharmony_ci return (NULL); 3420d722e3fbSopenharmony_ci mname = drmGetMinorName(type); 3421d722e3fbSopenharmony_ci 3422d722e3fbSopenharmony_ci for (i = 0; i < SPECNAMELEN; i++) { 3423d722e3fbSopenharmony_ci if (isalpha(dname[i]) == 0 && dname[i] != '/') 3424d722e3fbSopenharmony_ci break; 3425d722e3fbSopenharmony_ci } 3426d722e3fbSopenharmony_ci if (dname[i] == '\0') 3427d722e3fbSopenharmony_ci return (NULL); 3428d722e3fbSopenharmony_ci 3429d722e3fbSopenharmony_ci id = (int)strtol(&dname[i], NULL, 10); 3430d722e3fbSopenharmony_ci id -= drmGetMinorBase(nodetype); 3431d722e3fbSopenharmony_ci snprintf(name, sizeof(name), DRM_DIR_NAME "/%s%d", mname, 3432d722e3fbSopenharmony_ci id + drmGetMinorBase(type)); 3433d722e3fbSopenharmony_ci 3434d722e3fbSopenharmony_ci return strdup(name); 3435d722e3fbSopenharmony_ci#else 3436d722e3fbSopenharmony_ci struct stat sbuf; 3437d722e3fbSopenharmony_ci char buf[PATH_MAX + 1]; 3438d722e3fbSopenharmony_ci const char *dev_name = drmGetDeviceName(type); 3439d722e3fbSopenharmony_ci unsigned int maj, min; 3440d722e3fbSopenharmony_ci int n; 3441d722e3fbSopenharmony_ci 3442d722e3fbSopenharmony_ci if (fstat(fd, &sbuf)) 3443d722e3fbSopenharmony_ci return NULL; 3444d722e3fbSopenharmony_ci 3445d722e3fbSopenharmony_ci maj = major(sbuf.st_rdev); 3446d722e3fbSopenharmony_ci min = minor(sbuf.st_rdev); 3447d722e3fbSopenharmony_ci 3448d722e3fbSopenharmony_ci if (!drmNodeIsDRM(maj, min) || !S_ISCHR(sbuf.st_mode)) 3449d722e3fbSopenharmony_ci return NULL; 3450d722e3fbSopenharmony_ci 3451d722e3fbSopenharmony_ci if (!dev_name) 3452d722e3fbSopenharmony_ci return NULL; 3453d722e3fbSopenharmony_ci 3454d722e3fbSopenharmony_ci n = snprintf(buf, sizeof(buf), dev_name, DRM_DIR_NAME, min); 3455d722e3fbSopenharmony_ci if (n == -1 || n >= sizeof(buf)) 3456d722e3fbSopenharmony_ci return NULL; 3457d722e3fbSopenharmony_ci 3458d722e3fbSopenharmony_ci return strdup(buf); 3459d722e3fbSopenharmony_ci#endif 3460d722e3fbSopenharmony_ci} 3461d722e3fbSopenharmony_ci 3462d722e3fbSopenharmony_cidrm_public char *drmGetPrimaryDeviceNameFromFd(int fd) 3463d722e3fbSopenharmony_ci{ 3464d722e3fbSopenharmony_ci return drmGetMinorNameForFD(fd, DRM_NODE_PRIMARY); 3465d722e3fbSopenharmony_ci} 3466d722e3fbSopenharmony_ci 3467d722e3fbSopenharmony_cidrm_public char *drmGetRenderDeviceNameFromFd(int fd) 3468d722e3fbSopenharmony_ci{ 3469d722e3fbSopenharmony_ci return drmGetMinorNameForFD(fd, DRM_NODE_RENDER); 3470d722e3fbSopenharmony_ci} 3471d722e3fbSopenharmony_ci 3472d722e3fbSopenharmony_ci#ifdef __linux__ 3473d722e3fbSopenharmony_cistatic char * DRM_PRINTFLIKE(2, 3) 3474d722e3fbSopenharmony_cisysfs_uevent_get(const char *path, const char *fmt, ...) 3475d722e3fbSopenharmony_ci{ 3476d722e3fbSopenharmony_ci char filename[PATH_MAX + 1], *key, *line = NULL, *value = NULL; 3477d722e3fbSopenharmony_ci size_t size = 0, len; 3478d722e3fbSopenharmony_ci ssize_t num; 3479d722e3fbSopenharmony_ci va_list ap; 3480d722e3fbSopenharmony_ci FILE *fp; 3481d722e3fbSopenharmony_ci 3482d722e3fbSopenharmony_ci va_start(ap, fmt); 3483d722e3fbSopenharmony_ci num = vasprintf(&key, fmt, ap); 3484d722e3fbSopenharmony_ci va_end(ap); 3485d722e3fbSopenharmony_ci len = num; 3486d722e3fbSopenharmony_ci 3487d722e3fbSopenharmony_ci snprintf(filename, sizeof(filename), "%s/uevent", path); 3488d722e3fbSopenharmony_ci 3489d722e3fbSopenharmony_ci fp = fopen(filename, "r"); 3490d722e3fbSopenharmony_ci if (!fp) { 3491d722e3fbSopenharmony_ci free(key); 3492d722e3fbSopenharmony_ci return NULL; 3493d722e3fbSopenharmony_ci } 3494d722e3fbSopenharmony_ci 3495d722e3fbSopenharmony_ci while ((num = getline(&line, &size, fp)) >= 0) { 3496d722e3fbSopenharmony_ci if ((strncmp(line, key, len) == 0) && (line[len] == '=')) { 3497d722e3fbSopenharmony_ci char *start = line + len + 1, *end = line + num - 1; 3498d722e3fbSopenharmony_ci 3499d722e3fbSopenharmony_ci if (*end != '\n') 3500d722e3fbSopenharmony_ci end++; 3501d722e3fbSopenharmony_ci 3502d722e3fbSopenharmony_ci value = strndup(start, end - start); 3503d722e3fbSopenharmony_ci break; 3504d722e3fbSopenharmony_ci } 3505d722e3fbSopenharmony_ci } 3506d722e3fbSopenharmony_ci 3507d722e3fbSopenharmony_ci free(line); 3508d722e3fbSopenharmony_ci fclose(fp); 3509d722e3fbSopenharmony_ci 3510d722e3fbSopenharmony_ci free(key); 3511d722e3fbSopenharmony_ci 3512d722e3fbSopenharmony_ci return value; 3513d722e3fbSopenharmony_ci} 3514d722e3fbSopenharmony_ci#endif 3515d722e3fbSopenharmony_ci 3516d722e3fbSopenharmony_ci/* Little white lie to avoid major rework of the existing code */ 3517d722e3fbSopenharmony_ci#define DRM_BUS_VIRTIO 0x10 3518d722e3fbSopenharmony_ci 3519d722e3fbSopenharmony_ci#ifdef __linux__ 3520d722e3fbSopenharmony_cistatic int get_subsystem_type(const char *device_path) 3521d722e3fbSopenharmony_ci{ 3522d722e3fbSopenharmony_ci char path[PATH_MAX + 1] = ""; 3523d722e3fbSopenharmony_ci char link[PATH_MAX + 1] = ""; 3524d722e3fbSopenharmony_ci char *name; 3525d722e3fbSopenharmony_ci struct { 3526d722e3fbSopenharmony_ci const char *name; 3527d722e3fbSopenharmony_ci int bus_type; 3528d722e3fbSopenharmony_ci } bus_types[] = { 3529d722e3fbSopenharmony_ci { "/pci", DRM_BUS_PCI }, 3530d722e3fbSopenharmony_ci { "/usb", DRM_BUS_USB }, 3531d722e3fbSopenharmony_ci { "/platform", DRM_BUS_PLATFORM }, 3532d722e3fbSopenharmony_ci { "/spi", DRM_BUS_PLATFORM }, 3533d722e3fbSopenharmony_ci { "/host1x", DRM_BUS_HOST1X }, 3534d722e3fbSopenharmony_ci { "/virtio", DRM_BUS_VIRTIO }, 3535d722e3fbSopenharmony_ci }; 3536d722e3fbSopenharmony_ci 3537d722e3fbSopenharmony_ci strncpy(path, device_path, PATH_MAX); 3538d722e3fbSopenharmony_ci strncat(path, "/subsystem", PATH_MAX); 3539d722e3fbSopenharmony_ci 3540d722e3fbSopenharmony_ci if (readlink(path, link, PATH_MAX) < 0) 3541d722e3fbSopenharmony_ci return -errno; 3542d722e3fbSopenharmony_ci 3543d722e3fbSopenharmony_ci name = strrchr(link, '/'); 3544d722e3fbSopenharmony_ci if (!name) 3545d722e3fbSopenharmony_ci return -EINVAL; 3546d722e3fbSopenharmony_ci 3547d722e3fbSopenharmony_ci for (unsigned i = 0; i < ARRAY_SIZE(bus_types); i++) { 3548d722e3fbSopenharmony_ci if (strncmp(name, bus_types[i].name, strlen(bus_types[i].name)) == 0) 3549d722e3fbSopenharmony_ci return bus_types[i].bus_type; 3550d722e3fbSopenharmony_ci } 3551d722e3fbSopenharmony_ci 3552d722e3fbSopenharmony_ci return -EINVAL; 3553d722e3fbSopenharmony_ci} 3554d722e3fbSopenharmony_ci#endif 3555d722e3fbSopenharmony_ci 3556d722e3fbSopenharmony_cistatic int drmParseSubsystemType(int maj, int min) 3557d722e3fbSopenharmony_ci{ 3558d722e3fbSopenharmony_ci#ifdef __linux__ 3559d722e3fbSopenharmony_ci char path[PATH_MAX + 1] = ""; 3560d722e3fbSopenharmony_ci char real_path[PATH_MAX + 1] = ""; 3561d722e3fbSopenharmony_ci int subsystem_type; 3562d722e3fbSopenharmony_ci 3563d722e3fbSopenharmony_ci snprintf(path, sizeof(path), "/sys/dev/char/%d:%d/device", maj, min); 3564d722e3fbSopenharmony_ci 3565d722e3fbSopenharmony_ci subsystem_type = get_subsystem_type(path); 3566d722e3fbSopenharmony_ci /* Try to get the parent (underlying) device type */ 3567d722e3fbSopenharmony_ci if (subsystem_type == DRM_BUS_VIRTIO) { 3568d722e3fbSopenharmony_ci /* Assume virtio-pci on error */ 3569d722e3fbSopenharmony_ci if (!realpath(path, real_path)) 3570d722e3fbSopenharmony_ci return DRM_BUS_VIRTIO; 3571d722e3fbSopenharmony_ci strncat(path, "/..", PATH_MAX); 3572d722e3fbSopenharmony_ci subsystem_type = get_subsystem_type(path); 3573d722e3fbSopenharmony_ci if (subsystem_type < 0) 3574d722e3fbSopenharmony_ci return DRM_BUS_VIRTIO; 3575d722e3fbSopenharmony_ci } 3576d722e3fbSopenharmony_ci return subsystem_type; 3577d722e3fbSopenharmony_ci#elif defined(__OpenBSD__) || defined(__DragonFly__) || defined(__FreeBSD__) 3578d722e3fbSopenharmony_ci return DRM_BUS_PCI; 3579d722e3fbSopenharmony_ci#else 3580d722e3fbSopenharmony_ci#warning "Missing implementation of drmParseSubsystemType" 3581d722e3fbSopenharmony_ci return -EINVAL; 3582d722e3fbSopenharmony_ci#endif 3583d722e3fbSopenharmony_ci} 3584d722e3fbSopenharmony_ci 3585d722e3fbSopenharmony_ci#ifdef __linux__ 3586d722e3fbSopenharmony_cistatic void 3587d722e3fbSopenharmony_ciget_pci_path(int maj, int min, char *pci_path) 3588d722e3fbSopenharmony_ci{ 3589d722e3fbSopenharmony_ci char path[PATH_MAX + 1], *term; 3590d722e3fbSopenharmony_ci 3591d722e3fbSopenharmony_ci snprintf(path, sizeof(path), "/sys/dev/char/%d:%d/device", maj, min); 3592d722e3fbSopenharmony_ci if (!realpath(path, pci_path)) { 3593d722e3fbSopenharmony_ci strcpy(pci_path, path); 3594d722e3fbSopenharmony_ci return; 3595d722e3fbSopenharmony_ci } 3596d722e3fbSopenharmony_ci 3597d722e3fbSopenharmony_ci term = strrchr(pci_path, '/'); 3598d722e3fbSopenharmony_ci if (term && strncmp(term, "/virtio", 7) == 0) 3599d722e3fbSopenharmony_ci *term = 0; 3600d722e3fbSopenharmony_ci} 3601d722e3fbSopenharmony_ci#endif 3602d722e3fbSopenharmony_ci 3603d722e3fbSopenharmony_ci#ifdef __FreeBSD__ 3604d722e3fbSopenharmony_cistatic int get_sysctl_pci_bus_info(int maj, int min, drmPciBusInfoPtr info) 3605d722e3fbSopenharmony_ci{ 3606d722e3fbSopenharmony_ci char dname[SPECNAMELEN]; 3607d722e3fbSopenharmony_ci char sysctl_name[16]; 3608d722e3fbSopenharmony_ci char sysctl_val[256]; 3609d722e3fbSopenharmony_ci size_t sysctl_len; 3610d722e3fbSopenharmony_ci int id, type, nelem; 3611d722e3fbSopenharmony_ci unsigned int rdev, majmin, domain, bus, dev, func; 3612d722e3fbSopenharmony_ci 3613d722e3fbSopenharmony_ci rdev = makedev(maj, min); 3614d722e3fbSopenharmony_ci if (!devname_r(rdev, S_IFCHR, dname, sizeof(dname))) 3615d722e3fbSopenharmony_ci return -EINVAL; 3616d722e3fbSopenharmony_ci 3617d722e3fbSopenharmony_ci if (sscanf(dname, "drm/%d\n", &id) != 1) 3618d722e3fbSopenharmony_ci return -EINVAL; 3619d722e3fbSopenharmony_ci type = drmGetMinorType(maj, min); 3620d722e3fbSopenharmony_ci if (type == -1) 3621d722e3fbSopenharmony_ci return -EINVAL; 3622d722e3fbSopenharmony_ci 3623d722e3fbSopenharmony_ci /* BUG: This above section is iffy, since it mandates that a driver will 3624d722e3fbSopenharmony_ci * create both card and render node. 3625d722e3fbSopenharmony_ci * If it does not, the next DRM device will create card#X and 3626d722e3fbSopenharmony_ci * renderD#(128+X)-1. 3627d722e3fbSopenharmony_ci * This is a possibility in FreeBSD but for now there is no good way for 3628d722e3fbSopenharmony_ci * obtaining the info. 3629d722e3fbSopenharmony_ci */ 3630d722e3fbSopenharmony_ci switch (type) { 3631d722e3fbSopenharmony_ci case DRM_NODE_PRIMARY: 3632d722e3fbSopenharmony_ci break; 3633d722e3fbSopenharmony_ci case DRM_NODE_CONTROL: 3634d722e3fbSopenharmony_ci id -= 64; 3635d722e3fbSopenharmony_ci break; 3636d722e3fbSopenharmony_ci case DRM_NODE_RENDER: 3637d722e3fbSopenharmony_ci id -= 128; 3638d722e3fbSopenharmony_ci break; 3639d722e3fbSopenharmony_ci } 3640d722e3fbSopenharmony_ci if (id < 0) 3641d722e3fbSopenharmony_ci return -EINVAL; 3642d722e3fbSopenharmony_ci 3643d722e3fbSopenharmony_ci if (snprintf(sysctl_name, sizeof(sysctl_name), "hw.dri.%d.busid", id) <= 0) 3644d722e3fbSopenharmony_ci return -EINVAL; 3645d722e3fbSopenharmony_ci sysctl_len = sizeof(sysctl_val); 3646d722e3fbSopenharmony_ci if (sysctlbyname(sysctl_name, sysctl_val, &sysctl_len, NULL, 0)) 3647d722e3fbSopenharmony_ci return -EINVAL; 3648d722e3fbSopenharmony_ci 3649d722e3fbSopenharmony_ci #define bus_fmt "pci:%04x:%02x:%02x.%u" 3650d722e3fbSopenharmony_ci 3651d722e3fbSopenharmony_ci nelem = sscanf(sysctl_val, bus_fmt, &domain, &bus, &dev, &func); 3652d722e3fbSopenharmony_ci if (nelem != 4) 3653d722e3fbSopenharmony_ci return -EINVAL; 3654d722e3fbSopenharmony_ci info->domain = domain; 3655d722e3fbSopenharmony_ci info->bus = bus; 3656d722e3fbSopenharmony_ci info->dev = dev; 3657d722e3fbSopenharmony_ci info->func = func; 3658d722e3fbSopenharmony_ci 3659d722e3fbSopenharmony_ci return 0; 3660d722e3fbSopenharmony_ci} 3661d722e3fbSopenharmony_ci#endif 3662d722e3fbSopenharmony_ci 3663d722e3fbSopenharmony_cistatic int drmParsePciBusInfo(int maj, int min, drmPciBusInfoPtr info) 3664d722e3fbSopenharmony_ci{ 3665d722e3fbSopenharmony_ci#ifdef __linux__ 3666d722e3fbSopenharmony_ci unsigned int domain, bus, dev, func; 3667d722e3fbSopenharmony_ci char pci_path[PATH_MAX + 1], *value; 3668d722e3fbSopenharmony_ci int num; 3669d722e3fbSopenharmony_ci 3670d722e3fbSopenharmony_ci get_pci_path(maj, min, pci_path); 3671d722e3fbSopenharmony_ci 3672d722e3fbSopenharmony_ci value = sysfs_uevent_get(pci_path, "PCI_SLOT_NAME"); 3673d722e3fbSopenharmony_ci if (!value) 3674d722e3fbSopenharmony_ci return -ENOENT; 3675d722e3fbSopenharmony_ci 3676d722e3fbSopenharmony_ci num = sscanf(value, "%04x:%02x:%02x.%1u", &domain, &bus, &dev, &func); 3677d722e3fbSopenharmony_ci free(value); 3678d722e3fbSopenharmony_ci 3679d722e3fbSopenharmony_ci if (num != 4) 3680d722e3fbSopenharmony_ci return -EINVAL; 3681d722e3fbSopenharmony_ci 3682d722e3fbSopenharmony_ci info->domain = domain; 3683d722e3fbSopenharmony_ci info->bus = bus; 3684d722e3fbSopenharmony_ci info->dev = dev; 3685d722e3fbSopenharmony_ci info->func = func; 3686d722e3fbSopenharmony_ci 3687d722e3fbSopenharmony_ci return 0; 3688d722e3fbSopenharmony_ci#elif defined(__OpenBSD__) || defined(__DragonFly__) 3689d722e3fbSopenharmony_ci struct drm_pciinfo pinfo; 3690d722e3fbSopenharmony_ci int fd, type; 3691d722e3fbSopenharmony_ci 3692d722e3fbSopenharmony_ci type = drmGetMinorType(maj, min); 3693d722e3fbSopenharmony_ci if (type == -1) 3694d722e3fbSopenharmony_ci return -ENODEV; 3695d722e3fbSopenharmony_ci 3696d722e3fbSopenharmony_ci fd = drmOpenMinor(min, 0, type); 3697d722e3fbSopenharmony_ci if (fd < 0) 3698d722e3fbSopenharmony_ci return -errno; 3699d722e3fbSopenharmony_ci 3700d722e3fbSopenharmony_ci if (drmIoctl(fd, DRM_IOCTL_GET_PCIINFO, &pinfo)) { 3701d722e3fbSopenharmony_ci close(fd); 3702d722e3fbSopenharmony_ci return -errno; 3703d722e3fbSopenharmony_ci } 3704d722e3fbSopenharmony_ci close(fd); 3705d722e3fbSopenharmony_ci 3706d722e3fbSopenharmony_ci info->domain = pinfo.domain; 3707d722e3fbSopenharmony_ci info->bus = pinfo.bus; 3708d722e3fbSopenharmony_ci info->dev = pinfo.dev; 3709d722e3fbSopenharmony_ci info->func = pinfo.func; 3710d722e3fbSopenharmony_ci 3711d722e3fbSopenharmony_ci return 0; 3712d722e3fbSopenharmony_ci#elif defined(__FreeBSD__) 3713d722e3fbSopenharmony_ci return get_sysctl_pci_bus_info(maj, min, info); 3714d722e3fbSopenharmony_ci#else 3715d722e3fbSopenharmony_ci#warning "Missing implementation of drmParsePciBusInfo" 3716d722e3fbSopenharmony_ci return -EINVAL; 3717d722e3fbSopenharmony_ci#endif 3718d722e3fbSopenharmony_ci} 3719d722e3fbSopenharmony_ci 3720d722e3fbSopenharmony_cidrm_public int drmDevicesEqual(drmDevicePtr a, drmDevicePtr b) 3721d722e3fbSopenharmony_ci{ 3722d722e3fbSopenharmony_ci if (a == NULL || b == NULL) 3723d722e3fbSopenharmony_ci return 0; 3724d722e3fbSopenharmony_ci 3725d722e3fbSopenharmony_ci if (a->bustype != b->bustype) 3726d722e3fbSopenharmony_ci return 0; 3727d722e3fbSopenharmony_ci 3728d722e3fbSopenharmony_ci switch (a->bustype) { 3729d722e3fbSopenharmony_ci case DRM_BUS_PCI: 3730d722e3fbSopenharmony_ci return memcmp(a->businfo.pci, b->businfo.pci, sizeof(drmPciBusInfo)) == 0; 3731d722e3fbSopenharmony_ci 3732d722e3fbSopenharmony_ci case DRM_BUS_USB: 3733d722e3fbSopenharmony_ci return memcmp(a->businfo.usb, b->businfo.usb, sizeof(drmUsbBusInfo)) == 0; 3734d722e3fbSopenharmony_ci 3735d722e3fbSopenharmony_ci case DRM_BUS_PLATFORM: 3736d722e3fbSopenharmony_ci return memcmp(a->businfo.platform, b->businfo.platform, sizeof(drmPlatformBusInfo)) == 0; 3737d722e3fbSopenharmony_ci 3738d722e3fbSopenharmony_ci case DRM_BUS_HOST1X: 3739d722e3fbSopenharmony_ci return memcmp(a->businfo.host1x, b->businfo.host1x, sizeof(drmHost1xBusInfo)) == 0; 3740d722e3fbSopenharmony_ci 3741d722e3fbSopenharmony_ci default: 3742d722e3fbSopenharmony_ci break; 3743d722e3fbSopenharmony_ci } 3744d722e3fbSopenharmony_ci 3745d722e3fbSopenharmony_ci return 0; 3746d722e3fbSopenharmony_ci} 3747d722e3fbSopenharmony_ci 3748d722e3fbSopenharmony_cistatic int drmGetNodeType(const char *name) 3749d722e3fbSopenharmony_ci{ 3750d722e3fbSopenharmony_ci if (strncmp(name, DRM_CONTROL_MINOR_NAME, 3751d722e3fbSopenharmony_ci sizeof(DRM_CONTROL_MINOR_NAME ) - 1) == 0) 3752d722e3fbSopenharmony_ci return DRM_NODE_CONTROL; 3753d722e3fbSopenharmony_ci 3754d722e3fbSopenharmony_ci if (strncmp(name, DRM_RENDER_MINOR_NAME, 3755d722e3fbSopenharmony_ci sizeof(DRM_RENDER_MINOR_NAME) - 1) == 0) 3756d722e3fbSopenharmony_ci return DRM_NODE_RENDER; 3757d722e3fbSopenharmony_ci 3758d722e3fbSopenharmony_ci if (strncmp(name, DRM_PRIMARY_MINOR_NAME, 3759d722e3fbSopenharmony_ci sizeof(DRM_PRIMARY_MINOR_NAME) - 1) == 0) 3760d722e3fbSopenharmony_ci return DRM_NODE_PRIMARY; 3761d722e3fbSopenharmony_ci 3762d722e3fbSopenharmony_ci return -EINVAL; 3763d722e3fbSopenharmony_ci} 3764d722e3fbSopenharmony_ci 3765d722e3fbSopenharmony_cistatic int drmGetMaxNodeName(void) 3766d722e3fbSopenharmony_ci{ 3767d722e3fbSopenharmony_ci return sizeof(DRM_DIR_NAME) + 3768d722e3fbSopenharmony_ci MAX3(sizeof(DRM_PRIMARY_MINOR_NAME), 3769d722e3fbSopenharmony_ci sizeof(DRM_CONTROL_MINOR_NAME), 3770d722e3fbSopenharmony_ci sizeof(DRM_RENDER_MINOR_NAME)) + 3771d722e3fbSopenharmony_ci 3 /* length of the node number */; 3772d722e3fbSopenharmony_ci} 3773d722e3fbSopenharmony_ci 3774d722e3fbSopenharmony_ci#ifdef __linux__ 3775d722e3fbSopenharmony_cistatic int parse_separate_sysfs_files(int maj, int min, 3776d722e3fbSopenharmony_ci drmPciDeviceInfoPtr device, 3777d722e3fbSopenharmony_ci bool ignore_revision) 3778d722e3fbSopenharmony_ci{ 3779d722e3fbSopenharmony_ci static const char *attrs[] = { 3780d722e3fbSopenharmony_ci "revision", /* Older kernels are missing the file, so check for it first */ 3781d722e3fbSopenharmony_ci "vendor", 3782d722e3fbSopenharmony_ci "device", 3783d722e3fbSopenharmony_ci "subsystem_vendor", 3784d722e3fbSopenharmony_ci "subsystem_device", 3785d722e3fbSopenharmony_ci }; 3786d722e3fbSopenharmony_ci char path[PATH_MAX + 1], pci_path[PATH_MAX + 1]; 3787d722e3fbSopenharmony_ci unsigned int data[ARRAY_SIZE(attrs)]; 3788d722e3fbSopenharmony_ci FILE *fp; 3789d722e3fbSopenharmony_ci int ret; 3790d722e3fbSopenharmony_ci 3791d722e3fbSopenharmony_ci get_pci_path(maj, min, pci_path); 3792d722e3fbSopenharmony_ci 3793d722e3fbSopenharmony_ci for (unsigned i = ignore_revision ? 1 : 0; i < ARRAY_SIZE(attrs); i++) { 3794d722e3fbSopenharmony_ci if (snprintf(path, PATH_MAX, "%s/%s", pci_path, attrs[i]) < 0) 3795d722e3fbSopenharmony_ci return -errno; 3796d722e3fbSopenharmony_ci 3797d722e3fbSopenharmony_ci fp = fopen(path, "r"); 3798d722e3fbSopenharmony_ci if (!fp) 3799d722e3fbSopenharmony_ci return -errno; 3800d722e3fbSopenharmony_ci 3801d722e3fbSopenharmony_ci ret = fscanf(fp, "%x", &data[i]); 3802d722e3fbSopenharmony_ci fclose(fp); 3803d722e3fbSopenharmony_ci if (ret != 1) 3804d722e3fbSopenharmony_ci return -errno; 3805d722e3fbSopenharmony_ci 3806d722e3fbSopenharmony_ci } 3807d722e3fbSopenharmony_ci 3808d722e3fbSopenharmony_ci device->revision_id = ignore_revision ? 0xff : data[0] & 0xff; 3809d722e3fbSopenharmony_ci device->vendor_id = data[1] & 0xffff; 3810d722e3fbSopenharmony_ci device->device_id = data[2] & 0xffff; 3811d722e3fbSopenharmony_ci device->subvendor_id = data[3] & 0xffff; 3812d722e3fbSopenharmony_ci device->subdevice_id = data[4] & 0xffff; 3813d722e3fbSopenharmony_ci 3814d722e3fbSopenharmony_ci return 0; 3815d722e3fbSopenharmony_ci} 3816d722e3fbSopenharmony_ci 3817d722e3fbSopenharmony_cistatic int parse_config_sysfs_file(int maj, int min, 3818d722e3fbSopenharmony_ci drmPciDeviceInfoPtr device) 3819d722e3fbSopenharmony_ci{ 3820d722e3fbSopenharmony_ci char path[PATH_MAX + 1], pci_path[PATH_MAX + 1]; 3821d722e3fbSopenharmony_ci unsigned char config[64]; 3822d722e3fbSopenharmony_ci int fd, ret; 3823d722e3fbSopenharmony_ci 3824d722e3fbSopenharmony_ci get_pci_path(maj, min, pci_path); 3825d722e3fbSopenharmony_ci 3826d722e3fbSopenharmony_ci if (snprintf(path, PATH_MAX, "%s/config", pci_path) < 0) 3827d722e3fbSopenharmony_ci return -errno; 3828d722e3fbSopenharmony_ci 3829d722e3fbSopenharmony_ci fd = open(path, O_RDONLY); 3830d722e3fbSopenharmony_ci if (fd < 0) 3831d722e3fbSopenharmony_ci return -errno; 3832d722e3fbSopenharmony_ci 3833d722e3fbSopenharmony_ci ret = read(fd, config, sizeof(config)); 3834d722e3fbSopenharmony_ci close(fd); 3835d722e3fbSopenharmony_ci if (ret < 0) 3836d722e3fbSopenharmony_ci return -errno; 3837d722e3fbSopenharmony_ci 3838d722e3fbSopenharmony_ci device->vendor_id = config[0] | (config[1] << 8); 3839d722e3fbSopenharmony_ci device->device_id = config[2] | (config[3] << 8); 3840d722e3fbSopenharmony_ci device->revision_id = config[8]; 3841d722e3fbSopenharmony_ci device->subvendor_id = config[44] | (config[45] << 8); 3842d722e3fbSopenharmony_ci device->subdevice_id = config[46] | (config[47] << 8); 3843d722e3fbSopenharmony_ci 3844d722e3fbSopenharmony_ci return 0; 3845d722e3fbSopenharmony_ci} 3846d722e3fbSopenharmony_ci#endif 3847d722e3fbSopenharmony_ci 3848d722e3fbSopenharmony_cistatic int drmParsePciDeviceInfo(int maj, int min, 3849d722e3fbSopenharmony_ci drmPciDeviceInfoPtr device, 3850d722e3fbSopenharmony_ci uint32_t flags) 3851d722e3fbSopenharmony_ci{ 3852d722e3fbSopenharmony_ci#ifdef __linux__ 3853d722e3fbSopenharmony_ci if (!(flags & DRM_DEVICE_GET_PCI_REVISION)) 3854d722e3fbSopenharmony_ci return parse_separate_sysfs_files(maj, min, device, true); 3855d722e3fbSopenharmony_ci 3856d722e3fbSopenharmony_ci if (parse_separate_sysfs_files(maj, min, device, false)) 3857d722e3fbSopenharmony_ci return parse_config_sysfs_file(maj, min, device); 3858d722e3fbSopenharmony_ci 3859d722e3fbSopenharmony_ci return 0; 3860d722e3fbSopenharmony_ci#elif defined(__OpenBSD__) || defined(__DragonFly__) 3861d722e3fbSopenharmony_ci struct drm_pciinfo pinfo; 3862d722e3fbSopenharmony_ci int fd, type; 3863d722e3fbSopenharmony_ci 3864d722e3fbSopenharmony_ci type = drmGetMinorType(maj, min); 3865d722e3fbSopenharmony_ci if (type == -1) 3866d722e3fbSopenharmony_ci return -ENODEV; 3867d722e3fbSopenharmony_ci 3868d722e3fbSopenharmony_ci fd = drmOpenMinor(min, 0, type); 3869d722e3fbSopenharmony_ci if (fd < 0) 3870d722e3fbSopenharmony_ci return -errno; 3871d722e3fbSopenharmony_ci 3872d722e3fbSopenharmony_ci if (drmIoctl(fd, DRM_IOCTL_GET_PCIINFO, &pinfo)) { 3873d722e3fbSopenharmony_ci close(fd); 3874d722e3fbSopenharmony_ci return -errno; 3875d722e3fbSopenharmony_ci } 3876d722e3fbSopenharmony_ci close(fd); 3877d722e3fbSopenharmony_ci 3878d722e3fbSopenharmony_ci device->vendor_id = pinfo.vendor_id; 3879d722e3fbSopenharmony_ci device->device_id = pinfo.device_id; 3880d722e3fbSopenharmony_ci device->revision_id = pinfo.revision_id; 3881d722e3fbSopenharmony_ci device->subvendor_id = pinfo.subvendor_id; 3882d722e3fbSopenharmony_ci device->subdevice_id = pinfo.subdevice_id; 3883d722e3fbSopenharmony_ci 3884d722e3fbSopenharmony_ci return 0; 3885d722e3fbSopenharmony_ci#elif defined(__FreeBSD__) 3886d722e3fbSopenharmony_ci drmPciBusInfo info; 3887d722e3fbSopenharmony_ci struct pci_conf_io pc; 3888d722e3fbSopenharmony_ci struct pci_match_conf patterns[1]; 3889d722e3fbSopenharmony_ci struct pci_conf results[1]; 3890d722e3fbSopenharmony_ci int fd, error; 3891d722e3fbSopenharmony_ci 3892d722e3fbSopenharmony_ci if (get_sysctl_pci_bus_info(maj, min, &info) != 0) 3893d722e3fbSopenharmony_ci return -EINVAL; 3894d722e3fbSopenharmony_ci 3895d722e3fbSopenharmony_ci fd = open("/dev/pci", O_RDONLY, 0); 3896d722e3fbSopenharmony_ci if (fd < 0) 3897d722e3fbSopenharmony_ci return -errno; 3898d722e3fbSopenharmony_ci 3899d722e3fbSopenharmony_ci bzero(&patterns, sizeof(patterns)); 3900d722e3fbSopenharmony_ci patterns[0].pc_sel.pc_domain = info.domain; 3901d722e3fbSopenharmony_ci patterns[0].pc_sel.pc_bus = info.bus; 3902d722e3fbSopenharmony_ci patterns[0].pc_sel.pc_dev = info.dev; 3903d722e3fbSopenharmony_ci patterns[0].pc_sel.pc_func = info.func; 3904d722e3fbSopenharmony_ci patterns[0].flags = PCI_GETCONF_MATCH_DOMAIN | PCI_GETCONF_MATCH_BUS 3905d722e3fbSopenharmony_ci | PCI_GETCONF_MATCH_DEV | PCI_GETCONF_MATCH_FUNC; 3906d722e3fbSopenharmony_ci bzero(&pc, sizeof(struct pci_conf_io)); 3907d722e3fbSopenharmony_ci pc.num_patterns = 1; 3908d722e3fbSopenharmony_ci pc.pat_buf_len = sizeof(patterns); 3909d722e3fbSopenharmony_ci pc.patterns = patterns; 3910d722e3fbSopenharmony_ci pc.match_buf_len = sizeof(results); 3911d722e3fbSopenharmony_ci pc.matches = results; 3912d722e3fbSopenharmony_ci 3913d722e3fbSopenharmony_ci if (ioctl(fd, PCIOCGETCONF, &pc) || pc.status == PCI_GETCONF_ERROR) { 3914d722e3fbSopenharmony_ci error = errno; 3915d722e3fbSopenharmony_ci close(fd); 3916d722e3fbSopenharmony_ci return -error; 3917d722e3fbSopenharmony_ci } 3918d722e3fbSopenharmony_ci close(fd); 3919d722e3fbSopenharmony_ci 3920d722e3fbSopenharmony_ci device->vendor_id = results[0].pc_vendor; 3921d722e3fbSopenharmony_ci device->device_id = results[0].pc_device; 3922d722e3fbSopenharmony_ci device->subvendor_id = results[0].pc_subvendor; 3923d722e3fbSopenharmony_ci device->subdevice_id = results[0].pc_subdevice; 3924d722e3fbSopenharmony_ci device->revision_id = results[0].pc_revid; 3925d722e3fbSopenharmony_ci 3926d722e3fbSopenharmony_ci return 0; 3927d722e3fbSopenharmony_ci#else 3928d722e3fbSopenharmony_ci#warning "Missing implementation of drmParsePciDeviceInfo" 3929d722e3fbSopenharmony_ci return -EINVAL; 3930d722e3fbSopenharmony_ci#endif 3931d722e3fbSopenharmony_ci} 3932d722e3fbSopenharmony_ci 3933d722e3fbSopenharmony_cistatic void drmFreePlatformDevice(drmDevicePtr device) 3934d722e3fbSopenharmony_ci{ 3935d722e3fbSopenharmony_ci if (device->deviceinfo.platform) { 3936d722e3fbSopenharmony_ci if (device->deviceinfo.platform->compatible) { 3937d722e3fbSopenharmony_ci char **compatible = device->deviceinfo.platform->compatible; 3938d722e3fbSopenharmony_ci 3939d722e3fbSopenharmony_ci while (*compatible) { 3940d722e3fbSopenharmony_ci free(*compatible); 3941d722e3fbSopenharmony_ci compatible++; 3942d722e3fbSopenharmony_ci } 3943d722e3fbSopenharmony_ci 3944d722e3fbSopenharmony_ci free(device->deviceinfo.platform->compatible); 3945d722e3fbSopenharmony_ci } 3946d722e3fbSopenharmony_ci } 3947d722e3fbSopenharmony_ci} 3948d722e3fbSopenharmony_ci 3949d722e3fbSopenharmony_cistatic void drmFreeHost1xDevice(drmDevicePtr device) 3950d722e3fbSopenharmony_ci{ 3951d722e3fbSopenharmony_ci if (device->deviceinfo.host1x) { 3952d722e3fbSopenharmony_ci if (device->deviceinfo.host1x->compatible) { 3953d722e3fbSopenharmony_ci char **compatible = device->deviceinfo.host1x->compatible; 3954d722e3fbSopenharmony_ci 3955d722e3fbSopenharmony_ci while (*compatible) { 3956d722e3fbSopenharmony_ci free(*compatible); 3957d722e3fbSopenharmony_ci compatible++; 3958d722e3fbSopenharmony_ci } 3959d722e3fbSopenharmony_ci 3960d722e3fbSopenharmony_ci free(device->deviceinfo.host1x->compatible); 3961d722e3fbSopenharmony_ci } 3962d722e3fbSopenharmony_ci } 3963d722e3fbSopenharmony_ci} 3964d722e3fbSopenharmony_ci 3965d722e3fbSopenharmony_cidrm_public void drmFreeDevice(drmDevicePtr *device) 3966d722e3fbSopenharmony_ci{ 3967d722e3fbSopenharmony_ci if (device == NULL) 3968d722e3fbSopenharmony_ci return; 3969d722e3fbSopenharmony_ci 3970d722e3fbSopenharmony_ci if (*device) { 3971d722e3fbSopenharmony_ci switch ((*device)->bustype) { 3972d722e3fbSopenharmony_ci case DRM_BUS_PLATFORM: 3973d722e3fbSopenharmony_ci drmFreePlatformDevice(*device); 3974d722e3fbSopenharmony_ci break; 3975d722e3fbSopenharmony_ci 3976d722e3fbSopenharmony_ci case DRM_BUS_HOST1X: 3977d722e3fbSopenharmony_ci drmFreeHost1xDevice(*device); 3978d722e3fbSopenharmony_ci break; 3979d722e3fbSopenharmony_ci } 3980d722e3fbSopenharmony_ci } 3981d722e3fbSopenharmony_ci 3982d722e3fbSopenharmony_ci free(*device); 3983d722e3fbSopenharmony_ci *device = NULL; 3984d722e3fbSopenharmony_ci} 3985d722e3fbSopenharmony_ci 3986d722e3fbSopenharmony_cidrm_public void drmFreeDevices(drmDevicePtr devices[], int count) 3987d722e3fbSopenharmony_ci{ 3988d722e3fbSopenharmony_ci int i; 3989d722e3fbSopenharmony_ci 3990d722e3fbSopenharmony_ci if (devices == NULL) 3991d722e3fbSopenharmony_ci return; 3992d722e3fbSopenharmony_ci 3993d722e3fbSopenharmony_ci for (i = 0; i < count; i++) 3994d722e3fbSopenharmony_ci if (devices[i]) 3995d722e3fbSopenharmony_ci drmFreeDevice(&devices[i]); 3996d722e3fbSopenharmony_ci} 3997d722e3fbSopenharmony_ci 3998d722e3fbSopenharmony_cistatic drmDevicePtr drmDeviceAlloc(unsigned int type, const char *node, 3999d722e3fbSopenharmony_ci size_t bus_size, size_t device_size, 4000d722e3fbSopenharmony_ci char **ptrp) 4001d722e3fbSopenharmony_ci{ 4002d722e3fbSopenharmony_ci size_t max_node_length, extra, size; 4003d722e3fbSopenharmony_ci drmDevicePtr device; 4004d722e3fbSopenharmony_ci unsigned int i; 4005d722e3fbSopenharmony_ci char *ptr; 4006d722e3fbSopenharmony_ci 4007d722e3fbSopenharmony_ci max_node_length = ALIGN(drmGetMaxNodeName(), sizeof(void *)); 4008d722e3fbSopenharmony_ci extra = DRM_NODE_MAX * (sizeof(void *) + max_node_length); 4009d722e3fbSopenharmony_ci 4010d722e3fbSopenharmony_ci size = sizeof(*device) + extra + bus_size + device_size; 4011d722e3fbSopenharmony_ci 4012d722e3fbSopenharmony_ci device = calloc(1, size); 4013d722e3fbSopenharmony_ci if (!device) 4014d722e3fbSopenharmony_ci return NULL; 4015d722e3fbSopenharmony_ci 4016d722e3fbSopenharmony_ci device->available_nodes = 1 << type; 4017d722e3fbSopenharmony_ci 4018d722e3fbSopenharmony_ci ptr = (char *)device + sizeof(*device); 4019d722e3fbSopenharmony_ci device->nodes = (char **)ptr; 4020d722e3fbSopenharmony_ci 4021d722e3fbSopenharmony_ci ptr += DRM_NODE_MAX * sizeof(void *); 4022d722e3fbSopenharmony_ci 4023d722e3fbSopenharmony_ci for (i = 0; i < DRM_NODE_MAX; i++) { 4024d722e3fbSopenharmony_ci device->nodes[i] = ptr; 4025d722e3fbSopenharmony_ci ptr += max_node_length; 4026d722e3fbSopenharmony_ci } 4027d722e3fbSopenharmony_ci 4028d722e3fbSopenharmony_ci memcpy(device->nodes[type], node, max_node_length); 4029d722e3fbSopenharmony_ci 4030d722e3fbSopenharmony_ci *ptrp = ptr; 4031d722e3fbSopenharmony_ci 4032d722e3fbSopenharmony_ci return device; 4033d722e3fbSopenharmony_ci} 4034d722e3fbSopenharmony_ci 4035d722e3fbSopenharmony_cistatic int drmProcessPciDevice(drmDevicePtr *device, 4036d722e3fbSopenharmony_ci const char *node, int node_type, 4037d722e3fbSopenharmony_ci int maj, int min, bool fetch_deviceinfo, 4038d722e3fbSopenharmony_ci uint32_t flags) 4039d722e3fbSopenharmony_ci{ 4040d722e3fbSopenharmony_ci drmDevicePtr dev; 4041d722e3fbSopenharmony_ci char *addr; 4042d722e3fbSopenharmony_ci int ret; 4043d722e3fbSopenharmony_ci 4044d722e3fbSopenharmony_ci dev = drmDeviceAlloc(node_type, node, sizeof(drmPciBusInfo), 4045d722e3fbSopenharmony_ci sizeof(drmPciDeviceInfo), &addr); 4046d722e3fbSopenharmony_ci if (!dev) 4047d722e3fbSopenharmony_ci return -ENOMEM; 4048d722e3fbSopenharmony_ci 4049d722e3fbSopenharmony_ci dev->bustype = DRM_BUS_PCI; 4050d722e3fbSopenharmony_ci 4051d722e3fbSopenharmony_ci dev->businfo.pci = (drmPciBusInfoPtr)addr; 4052d722e3fbSopenharmony_ci 4053d722e3fbSopenharmony_ci ret = drmParsePciBusInfo(maj, min, dev->businfo.pci); 4054d722e3fbSopenharmony_ci if (ret) 4055d722e3fbSopenharmony_ci goto free_device; 4056d722e3fbSopenharmony_ci 4057d722e3fbSopenharmony_ci // Fetch the device info if the user has requested it 4058d722e3fbSopenharmony_ci if (fetch_deviceinfo) { 4059d722e3fbSopenharmony_ci addr += sizeof(drmPciBusInfo); 4060d722e3fbSopenharmony_ci dev->deviceinfo.pci = (drmPciDeviceInfoPtr)addr; 4061d722e3fbSopenharmony_ci 4062d722e3fbSopenharmony_ci ret = drmParsePciDeviceInfo(maj, min, dev->deviceinfo.pci, flags); 4063d722e3fbSopenharmony_ci if (ret) 4064d722e3fbSopenharmony_ci goto free_device; 4065d722e3fbSopenharmony_ci } 4066d722e3fbSopenharmony_ci 4067d722e3fbSopenharmony_ci *device = dev; 4068d722e3fbSopenharmony_ci 4069d722e3fbSopenharmony_ci return 0; 4070d722e3fbSopenharmony_ci 4071d722e3fbSopenharmony_cifree_device: 4072d722e3fbSopenharmony_ci free(dev); 4073d722e3fbSopenharmony_ci return ret; 4074d722e3fbSopenharmony_ci} 4075d722e3fbSopenharmony_ci 4076d722e3fbSopenharmony_ci#ifdef __linux__ 4077d722e3fbSopenharmony_cistatic int drm_usb_dev_path(int maj, int min, char *path, size_t len) 4078d722e3fbSopenharmony_ci{ 4079d722e3fbSopenharmony_ci char *value, *tmp_path, *slash; 4080d722e3fbSopenharmony_ci bool usb_device, usb_interface; 4081d722e3fbSopenharmony_ci 4082d722e3fbSopenharmony_ci snprintf(path, len, "/sys/dev/char/%d:%d/device", maj, min); 4083d722e3fbSopenharmony_ci 4084d722e3fbSopenharmony_ci value = sysfs_uevent_get(path, "DEVTYPE"); 4085d722e3fbSopenharmony_ci if (!value) 4086d722e3fbSopenharmony_ci return -ENOENT; 4087d722e3fbSopenharmony_ci 4088d722e3fbSopenharmony_ci usb_device = strcmp(value, "usb_device") == 0; 4089d722e3fbSopenharmony_ci usb_interface = strcmp(value, "usb_interface") == 0; 4090d722e3fbSopenharmony_ci free(value); 4091d722e3fbSopenharmony_ci 4092d722e3fbSopenharmony_ci if (usb_device) 4093d722e3fbSopenharmony_ci return 0; 4094d722e3fbSopenharmony_ci if (!usb_interface) 4095d722e3fbSopenharmony_ci return -ENOTSUP; 4096d722e3fbSopenharmony_ci 4097d722e3fbSopenharmony_ci /* The parent of a usb_interface is a usb_device */ 4098d722e3fbSopenharmony_ci 4099d722e3fbSopenharmony_ci tmp_path = realpath(path, NULL); 4100d722e3fbSopenharmony_ci if (!tmp_path) 4101d722e3fbSopenharmony_ci return -errno; 4102d722e3fbSopenharmony_ci 4103d722e3fbSopenharmony_ci slash = strrchr(tmp_path, '/'); 4104d722e3fbSopenharmony_ci if (!slash) { 4105d722e3fbSopenharmony_ci free(tmp_path); 4106d722e3fbSopenharmony_ci return -EINVAL; 4107d722e3fbSopenharmony_ci } 4108d722e3fbSopenharmony_ci 4109d722e3fbSopenharmony_ci *slash = '\0'; 4110d722e3fbSopenharmony_ci 4111d722e3fbSopenharmony_ci if (snprintf(path, len, "%s", tmp_path) >= (int)len) { 4112d722e3fbSopenharmony_ci free(tmp_path); 4113d722e3fbSopenharmony_ci return -EINVAL; 4114d722e3fbSopenharmony_ci } 4115d722e3fbSopenharmony_ci 4116d722e3fbSopenharmony_ci free(tmp_path); 4117d722e3fbSopenharmony_ci return 0; 4118d722e3fbSopenharmony_ci} 4119d722e3fbSopenharmony_ci#endif 4120d722e3fbSopenharmony_ci 4121d722e3fbSopenharmony_cistatic int drmParseUsbBusInfo(int maj, int min, drmUsbBusInfoPtr info) 4122d722e3fbSopenharmony_ci{ 4123d722e3fbSopenharmony_ci#ifdef __linux__ 4124d722e3fbSopenharmony_ci char path[PATH_MAX + 1], *value; 4125d722e3fbSopenharmony_ci unsigned int bus, dev; 4126d722e3fbSopenharmony_ci int ret; 4127d722e3fbSopenharmony_ci 4128d722e3fbSopenharmony_ci ret = drm_usb_dev_path(maj, min, path, sizeof(path)); 4129d722e3fbSopenharmony_ci if (ret < 0) 4130d722e3fbSopenharmony_ci return ret; 4131d722e3fbSopenharmony_ci 4132d722e3fbSopenharmony_ci value = sysfs_uevent_get(path, "BUSNUM"); 4133d722e3fbSopenharmony_ci if (!value) 4134d722e3fbSopenharmony_ci return -ENOENT; 4135d722e3fbSopenharmony_ci 4136d722e3fbSopenharmony_ci ret = sscanf(value, "%03u", &bus); 4137d722e3fbSopenharmony_ci free(value); 4138d722e3fbSopenharmony_ci 4139d722e3fbSopenharmony_ci if (ret <= 0) 4140d722e3fbSopenharmony_ci return -errno; 4141d722e3fbSopenharmony_ci 4142d722e3fbSopenharmony_ci value = sysfs_uevent_get(path, "DEVNUM"); 4143d722e3fbSopenharmony_ci if (!value) 4144d722e3fbSopenharmony_ci return -ENOENT; 4145d722e3fbSopenharmony_ci 4146d722e3fbSopenharmony_ci ret = sscanf(value, "%03u", &dev); 4147d722e3fbSopenharmony_ci free(value); 4148d722e3fbSopenharmony_ci 4149d722e3fbSopenharmony_ci if (ret <= 0) 4150d722e3fbSopenharmony_ci return -errno; 4151d722e3fbSopenharmony_ci 4152d722e3fbSopenharmony_ci info->bus = bus; 4153d722e3fbSopenharmony_ci info->dev = dev; 4154d722e3fbSopenharmony_ci 4155d722e3fbSopenharmony_ci return 0; 4156d722e3fbSopenharmony_ci#else 4157d722e3fbSopenharmony_ci#warning "Missing implementation of drmParseUsbBusInfo" 4158d722e3fbSopenharmony_ci return -EINVAL; 4159d722e3fbSopenharmony_ci#endif 4160d722e3fbSopenharmony_ci} 4161d722e3fbSopenharmony_ci 4162d722e3fbSopenharmony_cistatic int drmParseUsbDeviceInfo(int maj, int min, drmUsbDeviceInfoPtr info) 4163d722e3fbSopenharmony_ci{ 4164d722e3fbSopenharmony_ci#ifdef __linux__ 4165d722e3fbSopenharmony_ci char path[PATH_MAX + 1], *value; 4166d722e3fbSopenharmony_ci unsigned int vendor, product; 4167d722e3fbSopenharmony_ci int ret; 4168d722e3fbSopenharmony_ci 4169d722e3fbSopenharmony_ci ret = drm_usb_dev_path(maj, min, path, sizeof(path)); 4170d722e3fbSopenharmony_ci if (ret < 0) 4171d722e3fbSopenharmony_ci return ret; 4172d722e3fbSopenharmony_ci 4173d722e3fbSopenharmony_ci value = sysfs_uevent_get(path, "PRODUCT"); 4174d722e3fbSopenharmony_ci if (!value) 4175d722e3fbSopenharmony_ci return -ENOENT; 4176d722e3fbSopenharmony_ci 4177d722e3fbSopenharmony_ci ret = sscanf(value, "%x/%x", &vendor, &product); 4178d722e3fbSopenharmony_ci free(value); 4179d722e3fbSopenharmony_ci 4180d722e3fbSopenharmony_ci if (ret <= 0) 4181d722e3fbSopenharmony_ci return -errno; 4182d722e3fbSopenharmony_ci 4183d722e3fbSopenharmony_ci info->vendor = vendor; 4184d722e3fbSopenharmony_ci info->product = product; 4185d722e3fbSopenharmony_ci 4186d722e3fbSopenharmony_ci return 0; 4187d722e3fbSopenharmony_ci#else 4188d722e3fbSopenharmony_ci#warning "Missing implementation of drmParseUsbDeviceInfo" 4189d722e3fbSopenharmony_ci return -EINVAL; 4190d722e3fbSopenharmony_ci#endif 4191d722e3fbSopenharmony_ci} 4192d722e3fbSopenharmony_ci 4193d722e3fbSopenharmony_cistatic int drmProcessUsbDevice(drmDevicePtr *device, const char *node, 4194d722e3fbSopenharmony_ci int node_type, int maj, int min, 4195d722e3fbSopenharmony_ci bool fetch_deviceinfo, uint32_t flags) 4196d722e3fbSopenharmony_ci{ 4197d722e3fbSopenharmony_ci drmDevicePtr dev; 4198d722e3fbSopenharmony_ci char *ptr; 4199d722e3fbSopenharmony_ci int ret; 4200d722e3fbSopenharmony_ci 4201d722e3fbSopenharmony_ci dev = drmDeviceAlloc(node_type, node, sizeof(drmUsbBusInfo), 4202d722e3fbSopenharmony_ci sizeof(drmUsbDeviceInfo), &ptr); 4203d722e3fbSopenharmony_ci if (!dev) 4204d722e3fbSopenharmony_ci return -ENOMEM; 4205d722e3fbSopenharmony_ci 4206d722e3fbSopenharmony_ci dev->bustype = DRM_BUS_USB; 4207d722e3fbSopenharmony_ci 4208d722e3fbSopenharmony_ci dev->businfo.usb = (drmUsbBusInfoPtr)ptr; 4209d722e3fbSopenharmony_ci 4210d722e3fbSopenharmony_ci ret = drmParseUsbBusInfo(maj, min, dev->businfo.usb); 4211d722e3fbSopenharmony_ci if (ret < 0) 4212d722e3fbSopenharmony_ci goto free_device; 4213d722e3fbSopenharmony_ci 4214d722e3fbSopenharmony_ci if (fetch_deviceinfo) { 4215d722e3fbSopenharmony_ci ptr += sizeof(drmUsbBusInfo); 4216d722e3fbSopenharmony_ci dev->deviceinfo.usb = (drmUsbDeviceInfoPtr)ptr; 4217d722e3fbSopenharmony_ci 4218d722e3fbSopenharmony_ci ret = drmParseUsbDeviceInfo(maj, min, dev->deviceinfo.usb); 4219d722e3fbSopenharmony_ci if (ret < 0) 4220d722e3fbSopenharmony_ci goto free_device; 4221d722e3fbSopenharmony_ci } 4222d722e3fbSopenharmony_ci 4223d722e3fbSopenharmony_ci *device = dev; 4224d722e3fbSopenharmony_ci 4225d722e3fbSopenharmony_ci return 0; 4226d722e3fbSopenharmony_ci 4227d722e3fbSopenharmony_cifree_device: 4228d722e3fbSopenharmony_ci free(dev); 4229d722e3fbSopenharmony_ci return ret; 4230d722e3fbSopenharmony_ci} 4231d722e3fbSopenharmony_ci 4232d722e3fbSopenharmony_cistatic int drmParseOFBusInfo(int maj, int min, char *fullname) 4233d722e3fbSopenharmony_ci{ 4234d722e3fbSopenharmony_ci#ifdef __linux__ 4235d722e3fbSopenharmony_ci char path[PATH_MAX + 1], *name, *tmp_name; 4236d722e3fbSopenharmony_ci 4237d722e3fbSopenharmony_ci snprintf(path, sizeof(path), "/sys/dev/char/%d:%d/device", maj, min); 4238d722e3fbSopenharmony_ci 4239d722e3fbSopenharmony_ci name = sysfs_uevent_get(path, "OF_FULLNAME"); 4240d722e3fbSopenharmony_ci tmp_name = name; 4241d722e3fbSopenharmony_ci if (!name) { 4242d722e3fbSopenharmony_ci /* If the device lacks OF data, pick the MODALIAS info */ 4243d722e3fbSopenharmony_ci name = sysfs_uevent_get(path, "MODALIAS"); 4244d722e3fbSopenharmony_ci if (!name) 4245d722e3fbSopenharmony_ci return -ENOENT; 4246d722e3fbSopenharmony_ci 4247d722e3fbSopenharmony_ci /* .. and strip the MODALIAS=[platform,usb...]: part. */ 4248d722e3fbSopenharmony_ci tmp_name = strrchr(name, ':'); 4249d722e3fbSopenharmony_ci if (!tmp_name) { 4250d722e3fbSopenharmony_ci free(name); 4251d722e3fbSopenharmony_ci return -ENOENT; 4252d722e3fbSopenharmony_ci } 4253d722e3fbSopenharmony_ci tmp_name++; 4254d722e3fbSopenharmony_ci } 4255d722e3fbSopenharmony_ci 4256d722e3fbSopenharmony_ci strncpy(fullname, tmp_name, DRM_PLATFORM_DEVICE_NAME_LEN); 4257d722e3fbSopenharmony_ci fullname[DRM_PLATFORM_DEVICE_NAME_LEN - 1] = '\0'; 4258d722e3fbSopenharmony_ci free(name); 4259d722e3fbSopenharmony_ci 4260d722e3fbSopenharmony_ci return 0; 4261d722e3fbSopenharmony_ci#else 4262d722e3fbSopenharmony_ci#warning "Missing implementation of drmParseOFBusInfo" 4263d722e3fbSopenharmony_ci return -EINVAL; 4264d722e3fbSopenharmony_ci#endif 4265d722e3fbSopenharmony_ci} 4266d722e3fbSopenharmony_ci 4267d722e3fbSopenharmony_cistatic int drmParseOFDeviceInfo(int maj, int min, char ***compatible) 4268d722e3fbSopenharmony_ci{ 4269d722e3fbSopenharmony_ci#ifdef __linux__ 4270d722e3fbSopenharmony_ci char path[PATH_MAX + 1], *value, *tmp_name; 4271d722e3fbSopenharmony_ci unsigned int count, i; 4272d722e3fbSopenharmony_ci int err; 4273d722e3fbSopenharmony_ci 4274d722e3fbSopenharmony_ci snprintf(path, sizeof(path), "/sys/dev/char/%d:%d/device", maj, min); 4275d722e3fbSopenharmony_ci 4276d722e3fbSopenharmony_ci value = sysfs_uevent_get(path, "OF_COMPATIBLE_N"); 4277d722e3fbSopenharmony_ci if (value) { 4278d722e3fbSopenharmony_ci sscanf(value, "%u", &count); 4279d722e3fbSopenharmony_ci free(value); 4280d722e3fbSopenharmony_ci } else { 4281d722e3fbSopenharmony_ci /* Assume one entry if the device lack OF data */ 4282d722e3fbSopenharmony_ci count = 1; 4283d722e3fbSopenharmony_ci } 4284d722e3fbSopenharmony_ci 4285d722e3fbSopenharmony_ci *compatible = calloc(count + 1, sizeof(char *)); 4286d722e3fbSopenharmony_ci if (!*compatible) 4287d722e3fbSopenharmony_ci return -ENOMEM; 4288d722e3fbSopenharmony_ci 4289d722e3fbSopenharmony_ci for (i = 0; i < count; i++) { 4290d722e3fbSopenharmony_ci value = sysfs_uevent_get(path, "OF_COMPATIBLE_%u", i); 4291d722e3fbSopenharmony_ci tmp_name = value; 4292d722e3fbSopenharmony_ci if (!value) { 4293d722e3fbSopenharmony_ci /* If the device lacks OF data, pick the MODALIAS info */ 4294d722e3fbSopenharmony_ci value = sysfs_uevent_get(path, "MODALIAS"); 4295d722e3fbSopenharmony_ci if (!value) { 4296d722e3fbSopenharmony_ci err = -ENOENT; 4297d722e3fbSopenharmony_ci goto free; 4298d722e3fbSopenharmony_ci } 4299d722e3fbSopenharmony_ci 4300d722e3fbSopenharmony_ci /* .. and strip the MODALIAS=[platform,usb...]: part. */ 4301d722e3fbSopenharmony_ci tmp_name = strrchr(value, ':'); 4302d722e3fbSopenharmony_ci if (!tmp_name) { 4303d722e3fbSopenharmony_ci free(value); 4304d722e3fbSopenharmony_ci return -ENOENT; 4305d722e3fbSopenharmony_ci } 4306d722e3fbSopenharmony_ci tmp_name = strdup(tmp_name + 1); 4307d722e3fbSopenharmony_ci free(value); 4308d722e3fbSopenharmony_ci } 4309d722e3fbSopenharmony_ci 4310d722e3fbSopenharmony_ci (*compatible)[i] = tmp_name; 4311d722e3fbSopenharmony_ci } 4312d722e3fbSopenharmony_ci 4313d722e3fbSopenharmony_ci return 0; 4314d722e3fbSopenharmony_ci 4315d722e3fbSopenharmony_cifree: 4316d722e3fbSopenharmony_ci while (i--) 4317d722e3fbSopenharmony_ci free((*compatible)[i]); 4318d722e3fbSopenharmony_ci 4319d722e3fbSopenharmony_ci free(*compatible); 4320d722e3fbSopenharmony_ci return err; 4321d722e3fbSopenharmony_ci#else 4322d722e3fbSopenharmony_ci#warning "Missing implementation of drmParseOFDeviceInfo" 4323d722e3fbSopenharmony_ci return -EINVAL; 4324d722e3fbSopenharmony_ci#endif 4325d722e3fbSopenharmony_ci} 4326d722e3fbSopenharmony_ci 4327d722e3fbSopenharmony_cistatic int drmProcessPlatformDevice(drmDevicePtr *device, 4328d722e3fbSopenharmony_ci const char *node, int node_type, 4329d722e3fbSopenharmony_ci int maj, int min, bool fetch_deviceinfo, 4330d722e3fbSopenharmony_ci uint32_t flags) 4331d722e3fbSopenharmony_ci{ 4332d722e3fbSopenharmony_ci drmDevicePtr dev; 4333d722e3fbSopenharmony_ci char *ptr; 4334d722e3fbSopenharmony_ci int ret; 4335d722e3fbSopenharmony_ci 4336d722e3fbSopenharmony_ci dev = drmDeviceAlloc(node_type, node, sizeof(drmPlatformBusInfo), 4337d722e3fbSopenharmony_ci sizeof(drmPlatformDeviceInfo), &ptr); 4338d722e3fbSopenharmony_ci if (!dev) 4339d722e3fbSopenharmony_ci return -ENOMEM; 4340d722e3fbSopenharmony_ci 4341d722e3fbSopenharmony_ci dev->bustype = DRM_BUS_PLATFORM; 4342d722e3fbSopenharmony_ci 4343d722e3fbSopenharmony_ci dev->businfo.platform = (drmPlatformBusInfoPtr)ptr; 4344d722e3fbSopenharmony_ci 4345d722e3fbSopenharmony_ci ret = drmParseOFBusInfo(maj, min, dev->businfo.platform->fullname); 4346d722e3fbSopenharmony_ci if (ret < 0) 4347d722e3fbSopenharmony_ci goto free_device; 4348d722e3fbSopenharmony_ci 4349d722e3fbSopenharmony_ci if (fetch_deviceinfo) { 4350d722e3fbSopenharmony_ci ptr += sizeof(drmPlatformBusInfo); 4351d722e3fbSopenharmony_ci dev->deviceinfo.platform = (drmPlatformDeviceInfoPtr)ptr; 4352d722e3fbSopenharmony_ci 4353d722e3fbSopenharmony_ci ret = drmParseOFDeviceInfo(maj, min, &dev->deviceinfo.platform->compatible); 4354d722e3fbSopenharmony_ci if (ret < 0) 4355d722e3fbSopenharmony_ci goto free_device; 4356d722e3fbSopenharmony_ci } 4357d722e3fbSopenharmony_ci 4358d722e3fbSopenharmony_ci *device = dev; 4359d722e3fbSopenharmony_ci 4360d722e3fbSopenharmony_ci return 0; 4361d722e3fbSopenharmony_ci 4362d722e3fbSopenharmony_cifree_device: 4363d722e3fbSopenharmony_ci free(dev); 4364d722e3fbSopenharmony_ci return ret; 4365d722e3fbSopenharmony_ci} 4366d722e3fbSopenharmony_ci 4367d722e3fbSopenharmony_cistatic int drmProcessHost1xDevice(drmDevicePtr *device, 4368d722e3fbSopenharmony_ci const char *node, int node_type, 4369d722e3fbSopenharmony_ci int maj, int min, bool fetch_deviceinfo, 4370d722e3fbSopenharmony_ci uint32_t flags) 4371d722e3fbSopenharmony_ci{ 4372d722e3fbSopenharmony_ci drmDevicePtr dev; 4373d722e3fbSopenharmony_ci char *ptr; 4374d722e3fbSopenharmony_ci int ret; 4375d722e3fbSopenharmony_ci 4376d722e3fbSopenharmony_ci dev = drmDeviceAlloc(node_type, node, sizeof(drmHost1xBusInfo), 4377d722e3fbSopenharmony_ci sizeof(drmHost1xDeviceInfo), &ptr); 4378d722e3fbSopenharmony_ci if (!dev) 4379d722e3fbSopenharmony_ci return -ENOMEM; 4380d722e3fbSopenharmony_ci 4381d722e3fbSopenharmony_ci dev->bustype = DRM_BUS_HOST1X; 4382d722e3fbSopenharmony_ci 4383d722e3fbSopenharmony_ci dev->businfo.host1x = (drmHost1xBusInfoPtr)ptr; 4384d722e3fbSopenharmony_ci 4385d722e3fbSopenharmony_ci ret = drmParseOFBusInfo(maj, min, dev->businfo.host1x->fullname); 4386d722e3fbSopenharmony_ci if (ret < 0) 4387d722e3fbSopenharmony_ci goto free_device; 4388d722e3fbSopenharmony_ci 4389d722e3fbSopenharmony_ci if (fetch_deviceinfo) { 4390d722e3fbSopenharmony_ci ptr += sizeof(drmHost1xBusInfo); 4391d722e3fbSopenharmony_ci dev->deviceinfo.host1x = (drmHost1xDeviceInfoPtr)ptr; 4392d722e3fbSopenharmony_ci 4393d722e3fbSopenharmony_ci ret = drmParseOFDeviceInfo(maj, min, &dev->deviceinfo.host1x->compatible); 4394d722e3fbSopenharmony_ci if (ret < 0) 4395d722e3fbSopenharmony_ci goto free_device; 4396d722e3fbSopenharmony_ci } 4397d722e3fbSopenharmony_ci 4398d722e3fbSopenharmony_ci *device = dev; 4399d722e3fbSopenharmony_ci 4400d722e3fbSopenharmony_ci return 0; 4401d722e3fbSopenharmony_ci 4402d722e3fbSopenharmony_cifree_device: 4403d722e3fbSopenharmony_ci free(dev); 4404d722e3fbSopenharmony_ci return ret; 4405d722e3fbSopenharmony_ci} 4406d722e3fbSopenharmony_ci 4407d722e3fbSopenharmony_cistatic int 4408d722e3fbSopenharmony_ciprocess_device(drmDevicePtr *device, const char *d_name, 4409d722e3fbSopenharmony_ci int req_subsystem_type, 4410d722e3fbSopenharmony_ci bool fetch_deviceinfo, uint32_t flags) 4411d722e3fbSopenharmony_ci{ 4412d722e3fbSopenharmony_ci struct stat sbuf; 4413d722e3fbSopenharmony_ci char node[PATH_MAX + 1]; 4414d722e3fbSopenharmony_ci int node_type, subsystem_type; 4415d722e3fbSopenharmony_ci unsigned int maj, min; 4416d722e3fbSopenharmony_ci 4417d722e3fbSopenharmony_ci node_type = drmGetNodeType(d_name); 4418d722e3fbSopenharmony_ci if (node_type < 0) 4419d722e3fbSopenharmony_ci return -1; 4420d722e3fbSopenharmony_ci 4421d722e3fbSopenharmony_ci snprintf(node, PATH_MAX, "%s/%s", DRM_DIR_NAME, d_name); 4422d722e3fbSopenharmony_ci if (stat(node, &sbuf)) 4423d722e3fbSopenharmony_ci return -1; 4424d722e3fbSopenharmony_ci 4425d722e3fbSopenharmony_ci maj = major(sbuf.st_rdev); 4426d722e3fbSopenharmony_ci min = minor(sbuf.st_rdev); 4427d722e3fbSopenharmony_ci 4428d722e3fbSopenharmony_ci if (!drmNodeIsDRM(maj, min) || !S_ISCHR(sbuf.st_mode)) 4429d722e3fbSopenharmony_ci return -1; 4430d722e3fbSopenharmony_ci 4431d722e3fbSopenharmony_ci subsystem_type = drmParseSubsystemType(maj, min); 4432d722e3fbSopenharmony_ci if (req_subsystem_type != -1 && req_subsystem_type != subsystem_type) 4433d722e3fbSopenharmony_ci return -1; 4434d722e3fbSopenharmony_ci 4435d722e3fbSopenharmony_ci switch (subsystem_type) { 4436d722e3fbSopenharmony_ci case DRM_BUS_PCI: 4437d722e3fbSopenharmony_ci case DRM_BUS_VIRTIO: 4438d722e3fbSopenharmony_ci return drmProcessPciDevice(device, node, node_type, maj, min, 4439d722e3fbSopenharmony_ci fetch_deviceinfo, flags); 4440d722e3fbSopenharmony_ci case DRM_BUS_USB: 4441d722e3fbSopenharmony_ci return drmProcessUsbDevice(device, node, node_type, maj, min, 4442d722e3fbSopenharmony_ci fetch_deviceinfo, flags); 4443d722e3fbSopenharmony_ci case DRM_BUS_PLATFORM: 4444d722e3fbSopenharmony_ci return drmProcessPlatformDevice(device, node, node_type, maj, min, 4445d722e3fbSopenharmony_ci fetch_deviceinfo, flags); 4446d722e3fbSopenharmony_ci case DRM_BUS_HOST1X: 4447d722e3fbSopenharmony_ci return drmProcessHost1xDevice(device, node, node_type, maj, min, 4448d722e3fbSopenharmony_ci fetch_deviceinfo, flags); 4449d722e3fbSopenharmony_ci default: 4450d722e3fbSopenharmony_ci return -1; 4451d722e3fbSopenharmony_ci } 4452d722e3fbSopenharmony_ci} 4453d722e3fbSopenharmony_ci 4454d722e3fbSopenharmony_ci/* Consider devices located on the same bus as duplicate and fold the respective 4455d722e3fbSopenharmony_ci * entries into a single one. 4456d722e3fbSopenharmony_ci * 4457d722e3fbSopenharmony_ci * Note: this leaves "gaps" in the array, while preserving the length. 4458d722e3fbSopenharmony_ci */ 4459d722e3fbSopenharmony_cistatic void drmFoldDuplicatedDevices(drmDevicePtr local_devices[], int count) 4460d722e3fbSopenharmony_ci{ 4461d722e3fbSopenharmony_ci int node_type, i, j; 4462d722e3fbSopenharmony_ci 4463d722e3fbSopenharmony_ci for (i = 0; i < count; i++) { 4464d722e3fbSopenharmony_ci for (j = i + 1; j < count; j++) { 4465d722e3fbSopenharmony_ci if (drmDevicesEqual(local_devices[i], local_devices[j])) { 4466d722e3fbSopenharmony_ci local_devices[i]->available_nodes |= local_devices[j]->available_nodes; 4467d722e3fbSopenharmony_ci node_type = log2_int(local_devices[j]->available_nodes); 4468d722e3fbSopenharmony_ci memcpy(local_devices[i]->nodes[node_type], 4469d722e3fbSopenharmony_ci local_devices[j]->nodes[node_type], drmGetMaxNodeName()); 4470d722e3fbSopenharmony_ci drmFreeDevice(&local_devices[j]); 4471d722e3fbSopenharmony_ci } 4472d722e3fbSopenharmony_ci } 4473d722e3fbSopenharmony_ci } 4474d722e3fbSopenharmony_ci} 4475d722e3fbSopenharmony_ci 4476d722e3fbSopenharmony_ci/* Check that the given flags are valid returning 0 on success */ 4477d722e3fbSopenharmony_cistatic int 4478d722e3fbSopenharmony_cidrm_device_validate_flags(uint32_t flags) 4479d722e3fbSopenharmony_ci{ 4480d722e3fbSopenharmony_ci return (flags & ~DRM_DEVICE_GET_PCI_REVISION); 4481d722e3fbSopenharmony_ci} 4482d722e3fbSopenharmony_ci 4483d722e3fbSopenharmony_cistatic bool 4484d722e3fbSopenharmony_cidrm_device_has_rdev(drmDevicePtr device, dev_t find_rdev) 4485d722e3fbSopenharmony_ci{ 4486d722e3fbSopenharmony_ci struct stat sbuf; 4487d722e3fbSopenharmony_ci 4488d722e3fbSopenharmony_ci for (int i = 0; i < DRM_NODE_MAX; i++) { 4489d722e3fbSopenharmony_ci if (device->available_nodes & 1 << i) { 4490d722e3fbSopenharmony_ci if (stat(device->nodes[i], &sbuf) == 0 && 4491d722e3fbSopenharmony_ci sbuf.st_rdev == find_rdev) 4492d722e3fbSopenharmony_ci return true; 4493d722e3fbSopenharmony_ci } 4494d722e3fbSopenharmony_ci } 4495d722e3fbSopenharmony_ci return false; 4496d722e3fbSopenharmony_ci} 4497d722e3fbSopenharmony_ci 4498d722e3fbSopenharmony_ci/* 4499d722e3fbSopenharmony_ci * The kernel drm core has a number of places that assume maximum of 4500d722e3fbSopenharmony_ci * 3x64 devices nodes. That's 64 for each of primary, control and 4501d722e3fbSopenharmony_ci * render nodes. Rounded it up to 256 for simplicity. 4502d722e3fbSopenharmony_ci */ 4503d722e3fbSopenharmony_ci#define MAX_DRM_NODES 256 4504d722e3fbSopenharmony_ci 4505d722e3fbSopenharmony_ci/** 4506d722e3fbSopenharmony_ci * Get information about a device from its dev_t identifier 4507d722e3fbSopenharmony_ci * 4508d722e3fbSopenharmony_ci * \param find_rdev dev_t identifier of the device 4509d722e3fbSopenharmony_ci * \param flags feature/behaviour bitmask 4510d722e3fbSopenharmony_ci * \param device the address of a drmDevicePtr where the information 4511d722e3fbSopenharmony_ci * will be allocated in stored 4512d722e3fbSopenharmony_ci * 4513d722e3fbSopenharmony_ci * \return zero on success, negative error code otherwise. 4514d722e3fbSopenharmony_ci */ 4515d722e3fbSopenharmony_cidrm_public int drmGetDeviceFromDevId(dev_t find_rdev, uint32_t flags, drmDevicePtr *device) 4516d722e3fbSopenharmony_ci{ 4517d722e3fbSopenharmony_ci#ifdef __OpenBSD__ 4518d722e3fbSopenharmony_ci /* 4519d722e3fbSopenharmony_ci * DRI device nodes on OpenBSD are not in their own directory, they reside 4520d722e3fbSopenharmony_ci * in /dev along with a large number of statically generated /dev nodes. 4521d722e3fbSopenharmony_ci * Avoid stat'ing all of /dev needlessly by implementing this custom path. 4522d722e3fbSopenharmony_ci */ 4523d722e3fbSopenharmony_ci drmDevicePtr d; 4524d722e3fbSopenharmony_ci char node[PATH_MAX + 1]; 4525d722e3fbSopenharmony_ci const char *dev_name; 4526d722e3fbSopenharmony_ci int node_type, subsystem_type; 4527d722e3fbSopenharmony_ci int maj, min, n, ret; 4528d722e3fbSopenharmony_ci 4529d722e3fbSopenharmony_ci if (device == NULL) 4530d722e3fbSopenharmony_ci return -EINVAL; 4531d722e3fbSopenharmony_ci 4532d722e3fbSopenharmony_ci maj = major(find_rdev); 4533d722e3fbSopenharmony_ci min = minor(find_rdev); 4534d722e3fbSopenharmony_ci 4535d722e3fbSopenharmony_ci if (!drmNodeIsDRM(maj, min)) 4536d722e3fbSopenharmony_ci return -EINVAL; 4537d722e3fbSopenharmony_ci 4538d722e3fbSopenharmony_ci node_type = drmGetMinorType(maj, min); 4539d722e3fbSopenharmony_ci if (node_type == -1) 4540d722e3fbSopenharmony_ci return -ENODEV; 4541d722e3fbSopenharmony_ci 4542d722e3fbSopenharmony_ci dev_name = drmGetDeviceName(node_type); 4543d722e3fbSopenharmony_ci if (!dev_name) 4544d722e3fbSopenharmony_ci return -EINVAL; 4545d722e3fbSopenharmony_ci 4546d722e3fbSopenharmony_ci n = snprintf(node, PATH_MAX, dev_name, DRM_DIR_NAME, min); 4547d722e3fbSopenharmony_ci if (n == -1 || n >= PATH_MAX) 4548d722e3fbSopenharmony_ci return -errno; 4549d722e3fbSopenharmony_ci if (stat(node, &sbuf)) 4550d722e3fbSopenharmony_ci return -EINVAL; 4551d722e3fbSopenharmony_ci 4552d722e3fbSopenharmony_ci subsystem_type = drmParseSubsystemType(maj, min); 4553d722e3fbSopenharmony_ci if (subsystem_type != DRM_BUS_PCI) 4554d722e3fbSopenharmony_ci return -ENODEV; 4555d722e3fbSopenharmony_ci 4556d722e3fbSopenharmony_ci ret = drmProcessPciDevice(&d, node, node_type, maj, min, true, flags); 4557d722e3fbSopenharmony_ci if (ret) 4558d722e3fbSopenharmony_ci return ret; 4559d722e3fbSopenharmony_ci 4560d722e3fbSopenharmony_ci *device = d; 4561d722e3fbSopenharmony_ci 4562d722e3fbSopenharmony_ci return 0; 4563d722e3fbSopenharmony_ci#else 4564d722e3fbSopenharmony_ci drmDevicePtr local_devices[MAX_DRM_NODES]; 4565d722e3fbSopenharmony_ci drmDevicePtr d; 4566d722e3fbSopenharmony_ci DIR *sysdir; 4567d722e3fbSopenharmony_ci struct dirent *dent; 4568d722e3fbSopenharmony_ci int subsystem_type; 4569d722e3fbSopenharmony_ci int maj, min; 4570d722e3fbSopenharmony_ci int ret, i, node_count; 4571d722e3fbSopenharmony_ci 4572d722e3fbSopenharmony_ci if (drm_device_validate_flags(flags)) 4573d722e3fbSopenharmony_ci return -EINVAL; 4574d722e3fbSopenharmony_ci 4575d722e3fbSopenharmony_ci if (device == NULL) 4576d722e3fbSopenharmony_ci return -EINVAL; 4577d722e3fbSopenharmony_ci 4578d722e3fbSopenharmony_ci maj = major(find_rdev); 4579d722e3fbSopenharmony_ci min = minor(find_rdev); 4580d722e3fbSopenharmony_ci 4581d722e3fbSopenharmony_ci if (!drmNodeIsDRM(maj, min)) 4582d722e3fbSopenharmony_ci return -EINVAL; 4583d722e3fbSopenharmony_ci 4584d722e3fbSopenharmony_ci subsystem_type = drmParseSubsystemType(maj, min); 4585d722e3fbSopenharmony_ci if (subsystem_type < 0) 4586d722e3fbSopenharmony_ci return subsystem_type; 4587d722e3fbSopenharmony_ci 4588d722e3fbSopenharmony_ci sysdir = opendir(DRM_DIR_NAME); 4589d722e3fbSopenharmony_ci if (!sysdir) 4590d722e3fbSopenharmony_ci return -errno; 4591d722e3fbSopenharmony_ci 4592d722e3fbSopenharmony_ci i = 0; 4593d722e3fbSopenharmony_ci while ((dent = readdir(sysdir))) { 4594d722e3fbSopenharmony_ci ret = process_device(&d, dent->d_name, subsystem_type, true, flags); 4595d722e3fbSopenharmony_ci if (ret) 4596d722e3fbSopenharmony_ci continue; 4597d722e3fbSopenharmony_ci 4598d722e3fbSopenharmony_ci if (i >= MAX_DRM_NODES) { 4599d722e3fbSopenharmony_ci fprintf(stderr, "More than %d drm nodes detected. " 4600d722e3fbSopenharmony_ci "Please report a bug - that should not happen.\n" 4601d722e3fbSopenharmony_ci "Skipping extra nodes\n", MAX_DRM_NODES); 4602d722e3fbSopenharmony_ci break; 4603d722e3fbSopenharmony_ci } 4604d722e3fbSopenharmony_ci local_devices[i] = d; 4605d722e3fbSopenharmony_ci i++; 4606d722e3fbSopenharmony_ci } 4607d722e3fbSopenharmony_ci node_count = i; 4608d722e3fbSopenharmony_ci 4609d722e3fbSopenharmony_ci drmFoldDuplicatedDevices(local_devices, node_count); 4610d722e3fbSopenharmony_ci 4611d722e3fbSopenharmony_ci *device = NULL; 4612d722e3fbSopenharmony_ci 4613d722e3fbSopenharmony_ci for (i = 0; i < node_count; i++) { 4614d722e3fbSopenharmony_ci if (!local_devices[i]) 4615d722e3fbSopenharmony_ci continue; 4616d722e3fbSopenharmony_ci 4617d722e3fbSopenharmony_ci if (drm_device_has_rdev(local_devices[i], find_rdev)) 4618d722e3fbSopenharmony_ci *device = local_devices[i]; 4619d722e3fbSopenharmony_ci else 4620d722e3fbSopenharmony_ci drmFreeDevice(&local_devices[i]); 4621d722e3fbSopenharmony_ci } 4622d722e3fbSopenharmony_ci 4623d722e3fbSopenharmony_ci closedir(sysdir); 4624d722e3fbSopenharmony_ci if (*device == NULL) 4625d722e3fbSopenharmony_ci return -ENODEV; 4626d722e3fbSopenharmony_ci return 0; 4627d722e3fbSopenharmony_ci#endif 4628d722e3fbSopenharmony_ci} 4629d722e3fbSopenharmony_ci 4630d722e3fbSopenharmony_ci/** 4631d722e3fbSopenharmony_ci * Get information about the opened drm device 4632d722e3fbSopenharmony_ci * 4633d722e3fbSopenharmony_ci * \param fd file descriptor of the drm device 4634d722e3fbSopenharmony_ci * \param flags feature/behaviour bitmask 4635d722e3fbSopenharmony_ci * \param device the address of a drmDevicePtr where the information 4636d722e3fbSopenharmony_ci * will be allocated in stored 4637d722e3fbSopenharmony_ci * 4638d722e3fbSopenharmony_ci * \return zero on success, negative error code otherwise. 4639d722e3fbSopenharmony_ci * 4640d722e3fbSopenharmony_ci * \note Unlike drmGetDevice it does not retrieve the pci device revision field 4641d722e3fbSopenharmony_ci * unless the DRM_DEVICE_GET_PCI_REVISION \p flag is set. 4642d722e3fbSopenharmony_ci */ 4643d722e3fbSopenharmony_cidrm_public int drmGetDevice2(int fd, uint32_t flags, drmDevicePtr *device) 4644d722e3fbSopenharmony_ci{ 4645d722e3fbSopenharmony_ci struct stat sbuf; 4646d722e3fbSopenharmony_ci 4647d722e3fbSopenharmony_ci if (fd == -1) 4648d722e3fbSopenharmony_ci return -EINVAL; 4649d722e3fbSopenharmony_ci 4650d722e3fbSopenharmony_ci if (fstat(fd, &sbuf)) 4651d722e3fbSopenharmony_ci return -errno; 4652d722e3fbSopenharmony_ci 4653d722e3fbSopenharmony_ci if (!S_ISCHR(sbuf.st_mode)) 4654d722e3fbSopenharmony_ci return -EINVAL; 4655d722e3fbSopenharmony_ci 4656d722e3fbSopenharmony_ci return drmGetDeviceFromDevId(sbuf.st_rdev, flags, device); 4657d722e3fbSopenharmony_ci} 4658d722e3fbSopenharmony_ci 4659d722e3fbSopenharmony_ci/** 4660d722e3fbSopenharmony_ci * Get information about the opened drm device 4661d722e3fbSopenharmony_ci * 4662d722e3fbSopenharmony_ci * \param fd file descriptor of the drm device 4663d722e3fbSopenharmony_ci * \param device the address of a drmDevicePtr where the information 4664d722e3fbSopenharmony_ci * will be allocated in stored 4665d722e3fbSopenharmony_ci * 4666d722e3fbSopenharmony_ci * \return zero on success, negative error code otherwise. 4667d722e3fbSopenharmony_ci */ 4668d722e3fbSopenharmony_cidrm_public int drmGetDevice(int fd, drmDevicePtr *device) 4669d722e3fbSopenharmony_ci{ 4670d722e3fbSopenharmony_ci return drmGetDevice2(fd, DRM_DEVICE_GET_PCI_REVISION, device); 4671d722e3fbSopenharmony_ci} 4672d722e3fbSopenharmony_ci 4673d722e3fbSopenharmony_ci/** 4674d722e3fbSopenharmony_ci * Get drm devices on the system 4675d722e3fbSopenharmony_ci * 4676d722e3fbSopenharmony_ci * \param flags feature/behaviour bitmask 4677d722e3fbSopenharmony_ci * \param devices the array of devices with drmDevicePtr elements 4678d722e3fbSopenharmony_ci * can be NULL to get the device number first 4679d722e3fbSopenharmony_ci * \param max_devices the maximum number of devices for the array 4680d722e3fbSopenharmony_ci * 4681d722e3fbSopenharmony_ci * \return on error - negative error code, 4682d722e3fbSopenharmony_ci * if devices is NULL - total number of devices available on the system, 4683d722e3fbSopenharmony_ci * alternatively the number of devices stored in devices[], which is 4684d722e3fbSopenharmony_ci * capped by the max_devices. 4685d722e3fbSopenharmony_ci * 4686d722e3fbSopenharmony_ci * \note Unlike drmGetDevices it does not retrieve the pci device revision field 4687d722e3fbSopenharmony_ci * unless the DRM_DEVICE_GET_PCI_REVISION \p flag is set. 4688d722e3fbSopenharmony_ci */ 4689d722e3fbSopenharmony_cidrm_public int drmGetDevices2(uint32_t flags, drmDevicePtr devices[], 4690d722e3fbSopenharmony_ci int max_devices) 4691d722e3fbSopenharmony_ci{ 4692d722e3fbSopenharmony_ci drmDevicePtr local_devices[MAX_DRM_NODES]; 4693d722e3fbSopenharmony_ci drmDevicePtr device; 4694d722e3fbSopenharmony_ci DIR *sysdir; 4695d722e3fbSopenharmony_ci struct dirent *dent; 4696d722e3fbSopenharmony_ci int ret, i, node_count, device_count; 4697d722e3fbSopenharmony_ci 4698d722e3fbSopenharmony_ci if (drm_device_validate_flags(flags)) 4699d722e3fbSopenharmony_ci return -EINVAL; 4700d722e3fbSopenharmony_ci 4701d722e3fbSopenharmony_ci sysdir = opendir(DRM_DIR_NAME); 4702d722e3fbSopenharmony_ci if (!sysdir) 4703d722e3fbSopenharmony_ci return -errno; 4704d722e3fbSopenharmony_ci 4705d722e3fbSopenharmony_ci i = 0; 4706d722e3fbSopenharmony_ci while ((dent = readdir(sysdir))) { 4707d722e3fbSopenharmony_ci ret = process_device(&device, dent->d_name, -1, devices != NULL, flags); 4708d722e3fbSopenharmony_ci if (ret) 4709d722e3fbSopenharmony_ci continue; 4710d722e3fbSopenharmony_ci 4711d722e3fbSopenharmony_ci if (i >= MAX_DRM_NODES) { 4712d722e3fbSopenharmony_ci fprintf(stderr, "More than %d drm nodes detected. " 4713d722e3fbSopenharmony_ci "Please report a bug - that should not happen.\n" 4714d722e3fbSopenharmony_ci "Skipping extra nodes\n", MAX_DRM_NODES); 4715d722e3fbSopenharmony_ci break; 4716d722e3fbSopenharmony_ci } 4717d722e3fbSopenharmony_ci local_devices[i] = device; 4718d722e3fbSopenharmony_ci i++; 4719d722e3fbSopenharmony_ci } 4720d722e3fbSopenharmony_ci node_count = i; 4721d722e3fbSopenharmony_ci 4722d722e3fbSopenharmony_ci drmFoldDuplicatedDevices(local_devices, node_count); 4723d722e3fbSopenharmony_ci 4724d722e3fbSopenharmony_ci device_count = 0; 4725d722e3fbSopenharmony_ci for (i = 0; i < node_count; i++) { 4726d722e3fbSopenharmony_ci if (!local_devices[i]) 4727d722e3fbSopenharmony_ci continue; 4728d722e3fbSopenharmony_ci 4729d722e3fbSopenharmony_ci if ((devices != NULL) && (device_count < max_devices)) 4730d722e3fbSopenharmony_ci devices[device_count] = local_devices[i]; 4731d722e3fbSopenharmony_ci else 4732d722e3fbSopenharmony_ci drmFreeDevice(&local_devices[i]); 4733d722e3fbSopenharmony_ci 4734d722e3fbSopenharmony_ci device_count++; 4735d722e3fbSopenharmony_ci } 4736d722e3fbSopenharmony_ci 4737d722e3fbSopenharmony_ci closedir(sysdir); 4738d722e3fbSopenharmony_ci 4739d722e3fbSopenharmony_ci if (devices != NULL) 4740d722e3fbSopenharmony_ci return MIN2(device_count, max_devices); 4741d722e3fbSopenharmony_ci 4742d722e3fbSopenharmony_ci return device_count; 4743d722e3fbSopenharmony_ci} 4744d722e3fbSopenharmony_ci 4745d722e3fbSopenharmony_ci/** 4746d722e3fbSopenharmony_ci * Get drm devices on the system 4747d722e3fbSopenharmony_ci * 4748d722e3fbSopenharmony_ci * \param devices the array of devices with drmDevicePtr elements 4749d722e3fbSopenharmony_ci * can be NULL to get the device number first 4750d722e3fbSopenharmony_ci * \param max_devices the maximum number of devices for the array 4751d722e3fbSopenharmony_ci * 4752d722e3fbSopenharmony_ci * \return on error - negative error code, 4753d722e3fbSopenharmony_ci * if devices is NULL - total number of devices available on the system, 4754d722e3fbSopenharmony_ci * alternatively the number of devices stored in devices[], which is 4755d722e3fbSopenharmony_ci * capped by the max_devices. 4756d722e3fbSopenharmony_ci */ 4757d722e3fbSopenharmony_cidrm_public int drmGetDevices(drmDevicePtr devices[], int max_devices) 4758d722e3fbSopenharmony_ci{ 4759d722e3fbSopenharmony_ci return drmGetDevices2(DRM_DEVICE_GET_PCI_REVISION, devices, max_devices); 4760d722e3fbSopenharmony_ci} 4761d722e3fbSopenharmony_ci 4762d722e3fbSopenharmony_cidrm_public char *drmGetDeviceNameFromFd2(int fd) 4763d722e3fbSopenharmony_ci{ 4764d722e3fbSopenharmony_ci#ifdef __linux__ 4765d722e3fbSopenharmony_ci struct stat sbuf; 4766d722e3fbSopenharmony_ci char path[PATH_MAX + 1], *value; 4767d722e3fbSopenharmony_ci unsigned int maj, min; 4768d722e3fbSopenharmony_ci 4769d722e3fbSopenharmony_ci if (fstat(fd, &sbuf)) 4770d722e3fbSopenharmony_ci return NULL; 4771d722e3fbSopenharmony_ci 4772d722e3fbSopenharmony_ci maj = major(sbuf.st_rdev); 4773d722e3fbSopenharmony_ci min = minor(sbuf.st_rdev); 4774d722e3fbSopenharmony_ci 4775d722e3fbSopenharmony_ci if (!drmNodeIsDRM(maj, min) || !S_ISCHR(sbuf.st_mode)) 4776d722e3fbSopenharmony_ci return NULL; 4777d722e3fbSopenharmony_ci 4778d722e3fbSopenharmony_ci snprintf(path, sizeof(path), "/sys/dev/char/%d:%d", maj, min); 4779d722e3fbSopenharmony_ci 4780d722e3fbSopenharmony_ci value = sysfs_uevent_get(path, "DEVNAME"); 4781d722e3fbSopenharmony_ci if (!value) 4782d722e3fbSopenharmony_ci return NULL; 4783d722e3fbSopenharmony_ci 4784d722e3fbSopenharmony_ci snprintf(path, sizeof(path), "/dev/%s", value); 4785d722e3fbSopenharmony_ci free(value); 4786d722e3fbSopenharmony_ci 4787d722e3fbSopenharmony_ci return strdup(path); 4788d722e3fbSopenharmony_ci#elif defined(__FreeBSD__) 4789d722e3fbSopenharmony_ci return drmGetDeviceNameFromFd(fd); 4790d722e3fbSopenharmony_ci#else 4791d722e3fbSopenharmony_ci struct stat sbuf; 4792d722e3fbSopenharmony_ci char node[PATH_MAX + 1]; 4793d722e3fbSopenharmony_ci const char *dev_name; 4794d722e3fbSopenharmony_ci int node_type; 4795d722e3fbSopenharmony_ci int maj, min, n; 4796d722e3fbSopenharmony_ci 4797d722e3fbSopenharmony_ci if (fstat(fd, &sbuf)) 4798d722e3fbSopenharmony_ci return NULL; 4799d722e3fbSopenharmony_ci 4800d722e3fbSopenharmony_ci maj = major(sbuf.st_rdev); 4801d722e3fbSopenharmony_ci min = minor(sbuf.st_rdev); 4802d722e3fbSopenharmony_ci 4803d722e3fbSopenharmony_ci if (!drmNodeIsDRM(maj, min) || !S_ISCHR(sbuf.st_mode)) 4804d722e3fbSopenharmony_ci return NULL; 4805d722e3fbSopenharmony_ci 4806d722e3fbSopenharmony_ci node_type = drmGetMinorType(maj, min); 4807d722e3fbSopenharmony_ci if (node_type == -1) 4808d722e3fbSopenharmony_ci return NULL; 4809d722e3fbSopenharmony_ci 4810d722e3fbSopenharmony_ci dev_name = drmGetDeviceName(node_type); 4811d722e3fbSopenharmony_ci if (!dev_name) 4812d722e3fbSopenharmony_ci return NULL; 4813d722e3fbSopenharmony_ci 4814d722e3fbSopenharmony_ci n = snprintf(node, PATH_MAX, dev_name, DRM_DIR_NAME, min); 4815d722e3fbSopenharmony_ci if (n == -1 || n >= PATH_MAX) 4816d722e3fbSopenharmony_ci return NULL; 4817d722e3fbSopenharmony_ci 4818d722e3fbSopenharmony_ci return strdup(node); 4819d722e3fbSopenharmony_ci#endif 4820d722e3fbSopenharmony_ci} 4821d722e3fbSopenharmony_ci 4822d722e3fbSopenharmony_cidrm_public int drmSyncobjCreate(int fd, uint32_t flags, uint32_t *handle) 4823d722e3fbSopenharmony_ci{ 4824d722e3fbSopenharmony_ci struct drm_syncobj_create args; 4825d722e3fbSopenharmony_ci int ret; 4826d722e3fbSopenharmony_ci 4827d722e3fbSopenharmony_ci memclear(args); 4828d722e3fbSopenharmony_ci args.flags = flags; 4829d722e3fbSopenharmony_ci args.handle = 0; 4830d722e3fbSopenharmony_ci ret = drmIoctl(fd, DRM_IOCTL_SYNCOBJ_CREATE, &args); 4831d722e3fbSopenharmony_ci if (ret) 4832d722e3fbSopenharmony_ci return ret; 4833d722e3fbSopenharmony_ci *handle = args.handle; 4834d722e3fbSopenharmony_ci return 0; 4835d722e3fbSopenharmony_ci} 4836d722e3fbSopenharmony_ci 4837d722e3fbSopenharmony_cidrm_public int drmSyncobjDestroy(int fd, uint32_t handle) 4838d722e3fbSopenharmony_ci{ 4839d722e3fbSopenharmony_ci struct drm_syncobj_destroy args; 4840d722e3fbSopenharmony_ci 4841d722e3fbSopenharmony_ci memclear(args); 4842d722e3fbSopenharmony_ci args.handle = handle; 4843d722e3fbSopenharmony_ci return drmIoctl(fd, DRM_IOCTL_SYNCOBJ_DESTROY, &args); 4844d722e3fbSopenharmony_ci} 4845d722e3fbSopenharmony_ci 4846d722e3fbSopenharmony_cidrm_public int drmSyncobjHandleToFD(int fd, uint32_t handle, int *obj_fd) 4847d722e3fbSopenharmony_ci{ 4848d722e3fbSopenharmony_ci struct drm_syncobj_handle args; 4849d722e3fbSopenharmony_ci int ret; 4850d722e3fbSopenharmony_ci 4851d722e3fbSopenharmony_ci memclear(args); 4852d722e3fbSopenharmony_ci args.fd = -1; 4853d722e3fbSopenharmony_ci args.handle = handle; 4854d722e3fbSopenharmony_ci ret = drmIoctl(fd, DRM_IOCTL_SYNCOBJ_HANDLE_TO_FD, &args); 4855d722e3fbSopenharmony_ci if (ret) 4856d722e3fbSopenharmony_ci return ret; 4857d722e3fbSopenharmony_ci *obj_fd = args.fd; 4858d722e3fbSopenharmony_ci return 0; 4859d722e3fbSopenharmony_ci} 4860d722e3fbSopenharmony_ci 4861d722e3fbSopenharmony_cidrm_public int drmSyncobjFDToHandle(int fd, int obj_fd, uint32_t *handle) 4862d722e3fbSopenharmony_ci{ 4863d722e3fbSopenharmony_ci struct drm_syncobj_handle args; 4864d722e3fbSopenharmony_ci int ret; 4865d722e3fbSopenharmony_ci 4866d722e3fbSopenharmony_ci memclear(args); 4867d722e3fbSopenharmony_ci args.fd = obj_fd; 4868d722e3fbSopenharmony_ci args.handle = 0; 4869d722e3fbSopenharmony_ci ret = drmIoctl(fd, DRM_IOCTL_SYNCOBJ_FD_TO_HANDLE, &args); 4870d722e3fbSopenharmony_ci if (ret) 4871d722e3fbSopenharmony_ci return ret; 4872d722e3fbSopenharmony_ci *handle = args.handle; 4873d722e3fbSopenharmony_ci return 0; 4874d722e3fbSopenharmony_ci} 4875d722e3fbSopenharmony_ci 4876d722e3fbSopenharmony_cidrm_public int drmSyncobjImportSyncFile(int fd, uint32_t handle, 4877d722e3fbSopenharmony_ci int sync_file_fd) 4878d722e3fbSopenharmony_ci{ 4879d722e3fbSopenharmony_ci struct drm_syncobj_handle args; 4880d722e3fbSopenharmony_ci 4881d722e3fbSopenharmony_ci memclear(args); 4882d722e3fbSopenharmony_ci args.fd = sync_file_fd; 4883d722e3fbSopenharmony_ci args.handle = handle; 4884d722e3fbSopenharmony_ci args.flags = DRM_SYNCOBJ_FD_TO_HANDLE_FLAGS_IMPORT_SYNC_FILE; 4885d722e3fbSopenharmony_ci return drmIoctl(fd, DRM_IOCTL_SYNCOBJ_FD_TO_HANDLE, &args); 4886d722e3fbSopenharmony_ci} 4887d722e3fbSopenharmony_ci 4888d722e3fbSopenharmony_cidrm_public int drmSyncobjExportSyncFile(int fd, uint32_t handle, 4889d722e3fbSopenharmony_ci int *sync_file_fd) 4890d722e3fbSopenharmony_ci{ 4891d722e3fbSopenharmony_ci struct drm_syncobj_handle args; 4892d722e3fbSopenharmony_ci int ret; 4893d722e3fbSopenharmony_ci 4894d722e3fbSopenharmony_ci memclear(args); 4895d722e3fbSopenharmony_ci args.fd = -1; 4896d722e3fbSopenharmony_ci args.handle = handle; 4897d722e3fbSopenharmony_ci args.flags = DRM_SYNCOBJ_HANDLE_TO_FD_FLAGS_EXPORT_SYNC_FILE; 4898d722e3fbSopenharmony_ci ret = drmIoctl(fd, DRM_IOCTL_SYNCOBJ_HANDLE_TO_FD, &args); 4899d722e3fbSopenharmony_ci if (ret) 4900d722e3fbSopenharmony_ci return ret; 4901d722e3fbSopenharmony_ci *sync_file_fd = args.fd; 4902d722e3fbSopenharmony_ci return 0; 4903d722e3fbSopenharmony_ci} 4904d722e3fbSopenharmony_ci 4905d722e3fbSopenharmony_cidrm_public int drmSyncobjWait(int fd, uint32_t *handles, unsigned num_handles, 4906d722e3fbSopenharmony_ci int64_t timeout_nsec, unsigned flags, 4907d722e3fbSopenharmony_ci uint32_t *first_signaled) 4908d722e3fbSopenharmony_ci{ 4909d722e3fbSopenharmony_ci struct drm_syncobj_wait args; 4910d722e3fbSopenharmony_ci int ret; 4911d722e3fbSopenharmony_ci 4912d722e3fbSopenharmony_ci memclear(args); 4913d722e3fbSopenharmony_ci args.handles = (uintptr_t)handles; 4914d722e3fbSopenharmony_ci args.timeout_nsec = timeout_nsec; 4915d722e3fbSopenharmony_ci args.count_handles = num_handles; 4916d722e3fbSopenharmony_ci args.flags = flags; 4917d722e3fbSopenharmony_ci 4918d722e3fbSopenharmony_ci ret = drmIoctl(fd, DRM_IOCTL_SYNCOBJ_WAIT, &args); 4919d722e3fbSopenharmony_ci if (ret < 0) 4920d722e3fbSopenharmony_ci return -errno; 4921d722e3fbSopenharmony_ci 4922d722e3fbSopenharmony_ci if (first_signaled) 4923d722e3fbSopenharmony_ci *first_signaled = args.first_signaled; 4924d722e3fbSopenharmony_ci return ret; 4925d722e3fbSopenharmony_ci} 4926d722e3fbSopenharmony_ci 4927d722e3fbSopenharmony_cidrm_public int drmSyncobjReset(int fd, const uint32_t *handles, 4928d722e3fbSopenharmony_ci uint32_t handle_count) 4929d722e3fbSopenharmony_ci{ 4930d722e3fbSopenharmony_ci struct drm_syncobj_array args; 4931d722e3fbSopenharmony_ci int ret; 4932d722e3fbSopenharmony_ci 4933d722e3fbSopenharmony_ci memclear(args); 4934d722e3fbSopenharmony_ci args.handles = (uintptr_t)handles; 4935d722e3fbSopenharmony_ci args.count_handles = handle_count; 4936d722e3fbSopenharmony_ci 4937d722e3fbSopenharmony_ci ret = drmIoctl(fd, DRM_IOCTL_SYNCOBJ_RESET, &args); 4938d722e3fbSopenharmony_ci return ret; 4939d722e3fbSopenharmony_ci} 4940d722e3fbSopenharmony_ci 4941d722e3fbSopenharmony_cidrm_public int drmSyncobjSignal(int fd, const uint32_t *handles, 4942d722e3fbSopenharmony_ci uint32_t handle_count) 4943d722e3fbSopenharmony_ci{ 4944d722e3fbSopenharmony_ci struct drm_syncobj_array args; 4945d722e3fbSopenharmony_ci int ret; 4946d722e3fbSopenharmony_ci 4947d722e3fbSopenharmony_ci memclear(args); 4948d722e3fbSopenharmony_ci args.handles = (uintptr_t)handles; 4949d722e3fbSopenharmony_ci args.count_handles = handle_count; 4950d722e3fbSopenharmony_ci 4951d722e3fbSopenharmony_ci ret = drmIoctl(fd, DRM_IOCTL_SYNCOBJ_SIGNAL, &args); 4952d722e3fbSopenharmony_ci return ret; 4953d722e3fbSopenharmony_ci} 4954d722e3fbSopenharmony_ci 4955d722e3fbSopenharmony_cidrm_public int drmSyncobjTimelineSignal(int fd, const uint32_t *handles, 4956d722e3fbSopenharmony_ci uint64_t *points, uint32_t handle_count) 4957d722e3fbSopenharmony_ci{ 4958d722e3fbSopenharmony_ci struct drm_syncobj_timeline_array args; 4959d722e3fbSopenharmony_ci int ret; 4960d722e3fbSopenharmony_ci 4961d722e3fbSopenharmony_ci memclear(args); 4962d722e3fbSopenharmony_ci args.handles = (uintptr_t)handles; 4963d722e3fbSopenharmony_ci args.points = (uintptr_t)points; 4964d722e3fbSopenharmony_ci args.count_handles = handle_count; 4965d722e3fbSopenharmony_ci 4966d722e3fbSopenharmony_ci ret = drmIoctl(fd, DRM_IOCTL_SYNCOBJ_TIMELINE_SIGNAL, &args); 4967d722e3fbSopenharmony_ci return ret; 4968d722e3fbSopenharmony_ci} 4969d722e3fbSopenharmony_ci 4970d722e3fbSopenharmony_cidrm_public int drmSyncobjTimelineWait(int fd, uint32_t *handles, uint64_t *points, 4971d722e3fbSopenharmony_ci unsigned num_handles, 4972d722e3fbSopenharmony_ci int64_t timeout_nsec, unsigned flags, 4973d722e3fbSopenharmony_ci uint32_t *first_signaled) 4974d722e3fbSopenharmony_ci{ 4975d722e3fbSopenharmony_ci struct drm_syncobj_timeline_wait args; 4976d722e3fbSopenharmony_ci int ret; 4977d722e3fbSopenharmony_ci 4978d722e3fbSopenharmony_ci memclear(args); 4979d722e3fbSopenharmony_ci args.handles = (uintptr_t)handles; 4980d722e3fbSopenharmony_ci args.points = (uintptr_t)points; 4981d722e3fbSopenharmony_ci args.timeout_nsec = timeout_nsec; 4982d722e3fbSopenharmony_ci args.count_handles = num_handles; 4983d722e3fbSopenharmony_ci args.flags = flags; 4984d722e3fbSopenharmony_ci 4985d722e3fbSopenharmony_ci ret = drmIoctl(fd, DRM_IOCTL_SYNCOBJ_TIMELINE_WAIT, &args); 4986d722e3fbSopenharmony_ci if (ret < 0) 4987d722e3fbSopenharmony_ci return -errno; 4988d722e3fbSopenharmony_ci 4989d722e3fbSopenharmony_ci if (first_signaled) 4990d722e3fbSopenharmony_ci *first_signaled = args.first_signaled; 4991d722e3fbSopenharmony_ci return ret; 4992d722e3fbSopenharmony_ci} 4993d722e3fbSopenharmony_ci 4994d722e3fbSopenharmony_ci 4995d722e3fbSopenharmony_cidrm_public int drmSyncobjQuery(int fd, uint32_t *handles, uint64_t *points, 4996d722e3fbSopenharmony_ci uint32_t handle_count) 4997d722e3fbSopenharmony_ci{ 4998d722e3fbSopenharmony_ci struct drm_syncobj_timeline_array args; 4999d722e3fbSopenharmony_ci int ret; 5000d722e3fbSopenharmony_ci 5001d722e3fbSopenharmony_ci memclear(args); 5002d722e3fbSopenharmony_ci args.handles = (uintptr_t)handles; 5003d722e3fbSopenharmony_ci args.points = (uintptr_t)points; 5004d722e3fbSopenharmony_ci args.count_handles = handle_count; 5005d722e3fbSopenharmony_ci 5006d722e3fbSopenharmony_ci ret = drmIoctl(fd, DRM_IOCTL_SYNCOBJ_QUERY, &args); 5007d722e3fbSopenharmony_ci if (ret) 5008d722e3fbSopenharmony_ci return ret; 5009d722e3fbSopenharmony_ci return 0; 5010d722e3fbSopenharmony_ci} 5011d722e3fbSopenharmony_ci 5012d722e3fbSopenharmony_cidrm_public int drmSyncobjQuery2(int fd, uint32_t *handles, uint64_t *points, 5013d722e3fbSopenharmony_ci uint32_t handle_count, uint32_t flags) 5014d722e3fbSopenharmony_ci{ 5015d722e3fbSopenharmony_ci struct drm_syncobj_timeline_array args; 5016d722e3fbSopenharmony_ci 5017d722e3fbSopenharmony_ci memclear(args); 5018d722e3fbSopenharmony_ci args.handles = (uintptr_t)handles; 5019d722e3fbSopenharmony_ci args.points = (uintptr_t)points; 5020d722e3fbSopenharmony_ci args.count_handles = handle_count; 5021d722e3fbSopenharmony_ci args.flags = flags; 5022d722e3fbSopenharmony_ci 5023d722e3fbSopenharmony_ci return drmIoctl(fd, DRM_IOCTL_SYNCOBJ_QUERY, &args); 5024d722e3fbSopenharmony_ci} 5025d722e3fbSopenharmony_ci 5026d722e3fbSopenharmony_ci 5027d722e3fbSopenharmony_cidrm_public int drmSyncobjTransfer(int fd, 5028d722e3fbSopenharmony_ci uint32_t dst_handle, uint64_t dst_point, 5029d722e3fbSopenharmony_ci uint32_t src_handle, uint64_t src_point, 5030d722e3fbSopenharmony_ci uint32_t flags) 5031d722e3fbSopenharmony_ci{ 5032d722e3fbSopenharmony_ci struct drm_syncobj_transfer args; 5033d722e3fbSopenharmony_ci int ret; 5034d722e3fbSopenharmony_ci 5035d722e3fbSopenharmony_ci memclear(args); 5036d722e3fbSopenharmony_ci args.src_handle = src_handle; 5037d722e3fbSopenharmony_ci args.dst_handle = dst_handle; 5038d722e3fbSopenharmony_ci args.src_point = src_point; 5039d722e3fbSopenharmony_ci args.dst_point = dst_point; 5040d722e3fbSopenharmony_ci args.flags = flags; 5041d722e3fbSopenharmony_ci 5042d722e3fbSopenharmony_ci ret = drmIoctl(fd, DRM_IOCTL_SYNCOBJ_TRANSFER, &args); 5043d722e3fbSopenharmony_ci 5044d722e3fbSopenharmony_ci return ret; 5045d722e3fbSopenharmony_ci} 5046d722e3fbSopenharmony_ci 5047d722e3fbSopenharmony_cistatic char * 5048d722e3fbSopenharmony_cidrmGetFormatModifierFromSimpleTokens(uint64_t modifier) 5049d722e3fbSopenharmony_ci{ 5050d722e3fbSopenharmony_ci unsigned int i; 5051d722e3fbSopenharmony_ci 5052d722e3fbSopenharmony_ci for (i = 0; i < ARRAY_SIZE(drm_format_modifier_table); i++) { 5053d722e3fbSopenharmony_ci if (drm_format_modifier_table[i].modifier == modifier) 5054d722e3fbSopenharmony_ci return strdup(drm_format_modifier_table[i].modifier_name); 5055d722e3fbSopenharmony_ci } 5056d722e3fbSopenharmony_ci 5057d722e3fbSopenharmony_ci return NULL; 5058d722e3fbSopenharmony_ci} 5059d722e3fbSopenharmony_ci 5060d722e3fbSopenharmony_ci/** Retrieves a human-readable representation of a vendor (as a string) from 5061d722e3fbSopenharmony_ci * the format token modifier 5062d722e3fbSopenharmony_ci * 5063d722e3fbSopenharmony_ci * \param modifier the format modifier token 5064d722e3fbSopenharmony_ci * \return a char pointer to the human-readable form of the vendor. Caller is 5065d722e3fbSopenharmony_ci * responsible for freeing it. 5066d722e3fbSopenharmony_ci */ 5067d722e3fbSopenharmony_cidrm_public char * 5068d722e3fbSopenharmony_cidrmGetFormatModifierVendor(uint64_t modifier) 5069d722e3fbSopenharmony_ci{ 5070d722e3fbSopenharmony_ci unsigned int i; 5071d722e3fbSopenharmony_ci uint8_t vendor = fourcc_mod_get_vendor(modifier); 5072d722e3fbSopenharmony_ci 5073d722e3fbSopenharmony_ci for (i = 0; i < ARRAY_SIZE(drm_format_modifier_vendor_table); i++) { 5074d722e3fbSopenharmony_ci if (drm_format_modifier_vendor_table[i].vendor == vendor) 5075d722e3fbSopenharmony_ci return strdup(drm_format_modifier_vendor_table[i].vendor_name); 5076d722e3fbSopenharmony_ci } 5077d722e3fbSopenharmony_ci 5078d722e3fbSopenharmony_ci return NULL; 5079d722e3fbSopenharmony_ci} 5080d722e3fbSopenharmony_ci 5081d722e3fbSopenharmony_ci/** Retrieves a human-readable representation string from a format token 5082d722e3fbSopenharmony_ci * modifier 5083d722e3fbSopenharmony_ci * 5084d722e3fbSopenharmony_ci * If the dedicated function was not able to extract a valid name or searching 5085d722e3fbSopenharmony_ci * the format modifier was not in the table, this function would return NULL. 5086d722e3fbSopenharmony_ci * 5087d722e3fbSopenharmony_ci * \param modifier the token format 5088d722e3fbSopenharmony_ci * \return a malloc'ed string representation of the modifier. Caller is 5089d722e3fbSopenharmony_ci * responsible for freeing the string returned. 5090d722e3fbSopenharmony_ci * 5091d722e3fbSopenharmony_ci */ 5092d722e3fbSopenharmony_cidrm_public char * 5093d722e3fbSopenharmony_cidrmGetFormatModifierName(uint64_t modifier) 5094d722e3fbSopenharmony_ci{ 5095d722e3fbSopenharmony_ci uint8_t vendorid = fourcc_mod_get_vendor(modifier); 5096d722e3fbSopenharmony_ci char *modifier_found = NULL; 5097d722e3fbSopenharmony_ci unsigned int i; 5098d722e3fbSopenharmony_ci 5099d722e3fbSopenharmony_ci for (i = 0; i < ARRAY_SIZE(modifier_format_vendor_table); i++) { 5100d722e3fbSopenharmony_ci if (modifier_format_vendor_table[i].vendor == vendorid) 5101d722e3fbSopenharmony_ci modifier_found = modifier_format_vendor_table[i].vendor_cb(modifier); 5102d722e3fbSopenharmony_ci } 5103d722e3fbSopenharmony_ci 5104d722e3fbSopenharmony_ci if (!modifier_found) 5105d722e3fbSopenharmony_ci return drmGetFormatModifierFromSimpleTokens(modifier); 5106d722e3fbSopenharmony_ci 5107d722e3fbSopenharmony_ci return modifier_found; 5108d722e3fbSopenharmony_ci} 5109