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