xref: /aosp_15_r20/external/intel-media-driver/cmrtlib/linux/hardware/drm_device.h (revision ba62d9d3abf0e404f2022b4cd7a85e107f48596f)
1*ba62d9d3SAndroid Build Coastguard Worker /*
2*ba62d9d3SAndroid Build Coastguard Worker * Copyright 1999 Precision Insight, Inc., Cedar Park, Texas.
3*ba62d9d3SAndroid Build Coastguard Worker * Copyright 2000 VA Linux Systems, Inc., Sunnyvale, California.
4*ba62d9d3SAndroid Build Coastguard Worker * Copyright(c) 2019-2023, Intel Corporation
5*ba62d9d3SAndroid Build Coastguard Worker *
6*ba62d9d3SAndroid Build Coastguard Worker * Permission is hereby granted, free of charge, to any person obtaining a
7*ba62d9d3SAndroid Build Coastguard Worker * copy of this software and associated documentation files(the "Software"),
8*ba62d9d3SAndroid Build Coastguard Worker *to deal in the Software without restriction, including without limitation
9*ba62d9d3SAndroid Build Coastguard Worker * the rights to use, copy, modify, merge, publish, distribute, sublicense,
10*ba62d9d3SAndroid Build Coastguard Worker *and/or sell copies of the Software, and to permit persons to whom the
11*ba62d9d3SAndroid Build Coastguard Worker * Software is furnished to do so, subject to the following conditions :
12*ba62d9d3SAndroid Build Coastguard Worker *
13*ba62d9d3SAndroid Build Coastguard Worker * The above copyright notice and this permission notice(including the next
14*ba62d9d3SAndroid Build Coastguard Worker * paragraph) shall be included in all copies or substantial portions of the
15*ba62d9d3SAndroid Build Coastguard Worker * Software.
16*ba62d9d3SAndroid Build Coastguard Worker *
17*ba62d9d3SAndroid Build Coastguard Worker * THE SOFTWARE IS PROVIDED "AS IS", WITHOUT WARRANTY OF ANY KIND, EXPRESS OR
18*ba62d9d3SAndroid Build Coastguard Worker * IMPLIED, INCLUDING BUT NOT LIMITED TO THE WARRANTIES OF MERCHANTABILITY,
19*ba62d9d3SAndroid Build Coastguard Worker *FITNESS FOR A PARTICULAR PURPOSE AND NONINFRINGEMENT.IN NO EVENT SHALL
20*ba62d9d3SAndroid Build Coastguard Worker * PRECISION INSIGHT AND / OR ITS SUPPLIERS BE LIABLE FOR ANY CLAIM, DAMAGES OR
21*ba62d9d3SAndroid Build Coastguard Worker * OTHER LIABILITY, WHETHER IN AN ACTION OF CONTRACT, TORT OR OTHERWISE,
22*ba62d9d3SAndroid Build Coastguard Worker *ARISING FROM, OUT OF OR IN CONNECTION WITH THE SOFTWARE OR THE USE OR OTHER
23*ba62d9d3SAndroid Build Coastguard Worker * DEALINGS IN THE SOFTWARE.
24*ba62d9d3SAndroid Build Coastguard Worker */
25*ba62d9d3SAndroid Build Coastguard Worker 
26*ba62d9d3SAndroid Build Coastguard Worker #ifndef DRM_DEVICE_H_
27*ba62d9d3SAndroid Build Coastguard Worker #define DRM_DEVICE_H_
28*ba62d9d3SAndroid Build Coastguard Worker #include <stdio.h>
29*ba62d9d3SAndroid Build Coastguard Worker #include <stdlib.h>
30*ba62d9d3SAndroid Build Coastguard Worker #include <stdbool.h>
31*ba62d9d3SAndroid Build Coastguard Worker #include <unistd.h>
32*ba62d9d3SAndroid Build Coastguard Worker #include <string.h>
33*ba62d9d3SAndroid Build Coastguard Worker #include <strings.h>
34*ba62d9d3SAndroid Build Coastguard Worker #include <ctype.h>
35*ba62d9d3SAndroid Build Coastguard Worker #include <dirent.h>
36*ba62d9d3SAndroid Build Coastguard Worker #include <stddef.h>
37*ba62d9d3SAndroid Build Coastguard Worker #include <fcntl.h>
38*ba62d9d3SAndroid Build Coastguard Worker #include <errno.h>
39*ba62d9d3SAndroid Build Coastguard Worker #include <limits.h>
40*ba62d9d3SAndroid Build Coastguard Worker #include <signal.h>
41*ba62d9d3SAndroid Build Coastguard Worker #include <time.h>
42*ba62d9d3SAndroid Build Coastguard Worker #include <sys/sysmacros.h>   //<sys/types.h>
43*ba62d9d3SAndroid Build Coastguard Worker #include <sys/stat.h>
44*ba62d9d3SAndroid Build Coastguard Worker #define stat_t struct stat
45*ba62d9d3SAndroid Build Coastguard Worker #include <sys/ioctl.h>
46*ba62d9d3SAndroid Build Coastguard Worker #include <sys/time.h>
47*ba62d9d3SAndroid Build Coastguard Worker #include <stdarg.h>
48*ba62d9d3SAndroid Build Coastguard Worker #ifdef MAJOR_IN_MKDEV
49*ba62d9d3SAndroid Build Coastguard Worker #include <sys/mkdev.h>
50*ba62d9d3SAndroid Build Coastguard Worker #endif
51*ba62d9d3SAndroid Build Coastguard Worker #ifdef MAJOR_IN_SYSMACROS
52*ba62d9d3SAndroid Build Coastguard Worker #include <sys/sysmacros.h>
53*ba62d9d3SAndroid Build Coastguard Worker #endif
54*ba62d9d3SAndroid Build Coastguard Worker #include <math.h>
55*ba62d9d3SAndroid Build Coastguard Worker #include <string>
56*ba62d9d3SAndroid Build Coastguard Worker #include <cstring>
57*ba62d9d3SAndroid Build Coastguard Worker 
58*ba62d9d3SAndroid Build Coastguard Worker #define ARRAY_SIZE(a) (sizeof(a) / sizeof((a)[0]))
59*ba62d9d3SAndroid Build Coastguard Worker 
60*ba62d9d3SAndroid Build Coastguard Worker /* Not all systems have MAP_FAILED defined */
61*ba62d9d3SAndroid Build Coastguard Worker #ifndef MAP_FAILED
62*ba62d9d3SAndroid Build Coastguard Worker #define MAP_FAILED ((void *)-1)
63*ba62d9d3SAndroid Build Coastguard Worker #endif
64*ba62d9d3SAndroid Build Coastguard Worker 
65*ba62d9d3SAndroid Build Coastguard Worker #define DRM_DEV_UID  0
66*ba62d9d3SAndroid Build Coastguard Worker #define DRM_DEV_GID  0
67*ba62d9d3SAndroid Build Coastguard Worker /* Default /dev/dri directory permissions 0755 */
68*ba62d9d3SAndroid Build Coastguard Worker #define DRM_DEV_DIRMODE  (S_IRUSR|S_IWUSR|S_IXUSR|S_IRGRP|S_IXGRP|S_IROTH|S_IXOTH)
69*ba62d9d3SAndroid Build Coastguard Worker #define DRM_DEV_MODE     (S_IRUSR|S_IWUSR|S_IRGRP|S_IWGRP)
70*ba62d9d3SAndroid Build Coastguard Worker #define DRM_DEVICE_GET_PCI_REVISION (1 << 0)
71*ba62d9d3SAndroid Build Coastguard Worker 
72*ba62d9d3SAndroid Build Coastguard Worker #ifdef __OpenBSD__
73*ba62d9d3SAndroid Build Coastguard Worker #define DRM_DIR_NAME  "/dev"
74*ba62d9d3SAndroid Build Coastguard Worker #define DRM_DEV_NAME  "%s/drm%d"
75*ba62d9d3SAndroid Build Coastguard Worker #define DRM_CONTROL_DEV_NAME  "%s/drmC%d"
76*ba62d9d3SAndroid Build Coastguard Worker #define DRM_RENDER_DEV_NAME  "%s/drmR%d"
77*ba62d9d3SAndroid Build Coastguard Worker #else
78*ba62d9d3SAndroid Build Coastguard Worker #define DRM_DIR_NAME  "/dev/dri"
79*ba62d9d3SAndroid Build Coastguard Worker #define DRM_DEV_NAME  "%s/card%d"
80*ba62d9d3SAndroid Build Coastguard Worker #define DRM_CONTROL_DEV_NAME  "%s/controlD%d"
81*ba62d9d3SAndroid Build Coastguard Worker #define DRM_RENDER_DEV_NAME  "%s/renderD%d"
82*ba62d9d3SAndroid Build Coastguard Worker #define DRM_PROC_NAME "/proc/dri/" /* For backward Linux compatibility */
83*ba62d9d3SAndroid Build Coastguard Worker #endif
84*ba62d9d3SAndroid Build Coastguard Worker 
85*ba62d9d3SAndroid Build Coastguard Worker #ifdef __OpenBSD__
86*ba62d9d3SAndroid Build Coastguard Worker #define DRM_PRIMARY_MINOR_NAME  "drm"
87*ba62d9d3SAndroid Build Coastguard Worker #define DRM_CONTROL_MINOR_NAME  "drmC"
88*ba62d9d3SAndroid Build Coastguard Worker #define DRM_RENDER_MINOR_NAME   "drmR"
89*ba62d9d3SAndroid Build Coastguard Worker #else
90*ba62d9d3SAndroid Build Coastguard Worker #define DRM_PRIMARY_MINOR_NAME  "card"
91*ba62d9d3SAndroid Build Coastguard Worker #define DRM_CONTROL_MINOR_NAME  "controlD"
92*ba62d9d3SAndroid Build Coastguard Worker #define DRM_RENDER_MINOR_NAME   "renderD"
93*ba62d9d3SAndroid Build Coastguard Worker #endif
94*ba62d9d3SAndroid Build Coastguard Worker 
95*ba62d9d3SAndroid Build Coastguard Worker #define DRM_ERR_NO_DEVICE  (-1001)
96*ba62d9d3SAndroid Build Coastguard Worker #define DRM_ERR_NO_ACCESS  (-1002)
97*ba62d9d3SAndroid Build Coastguard Worker #define DRM_ERR_NOT_ROOT   (-1003)
98*ba62d9d3SAndroid Build Coastguard Worker #define DRM_ERR_INVALID    (-1004)
99*ba62d9d3SAndroid Build Coastguard Worker #define DRM_ERR_NO_FD      (-1005)
100*ba62d9d3SAndroid Build Coastguard Worker 
101*ba62d9d3SAndroid Build Coastguard Worker #define DRM_AGP_NO_HANDLE 0
102*ba62d9d3SAndroid Build Coastguard Worker 
103*ba62d9d3SAndroid Build Coastguard Worker #define DRM_BUS_PCI       0
104*ba62d9d3SAndroid Build Coastguard Worker #define DRM_BUS_USB       1
105*ba62d9d3SAndroid Build Coastguard Worker #define DRM_BUS_PLATFORM  2
106*ba62d9d3SAndroid Build Coastguard Worker #define DRM_BUS_HOST1X    3
107*ba62d9d3SAndroid Build Coastguard Worker #define DRM_BUS_VIRTIO 0x10
108*ba62d9d3SAndroid Build Coastguard Worker 
109*ba62d9d3SAndroid Build Coastguard Worker #define DRM_NODE_PRIMARY 0
110*ba62d9d3SAndroid Build Coastguard Worker #define DRM_NODE_CONTROL 1
111*ba62d9d3SAndroid Build Coastguard Worker #define DRM_NODE_RENDER  2
112*ba62d9d3SAndroid Build Coastguard Worker #define DRM_NODE_MAX     3
113*ba62d9d3SAndroid Build Coastguard Worker 
114*ba62d9d3SAndroid Build Coastguard Worker typedef unsigned int  drmSize, *drmSizePtr;         /**< For mapped regions */
115*ba62d9d3SAndroid Build Coastguard Worker typedef void          *drmAddress, **drmAddressPtr; /**< For mapped regions */
116*ba62d9d3SAndroid Build Coastguard Worker 
117*ba62d9d3SAndroid Build Coastguard Worker #if (__GNUC__ >= 3)
118*ba62d9d3SAndroid Build Coastguard Worker #define DRM_PRINTFLIKE(f, a) __attribute__ ((format(__printf__, f, a)))
119*ba62d9d3SAndroid Build Coastguard Worker #else
120*ba62d9d3SAndroid Build Coastguard Worker #define DRM_PRINTFLIKE(f, a)
121*ba62d9d3SAndroid Build Coastguard Worker #endif
122*ba62d9d3SAndroid Build Coastguard Worker 
123*ba62d9d3SAndroid Build Coastguard Worker #define MIN2( A, B )   ( (A)<(B) ? (A) : (B) )
124*ba62d9d3SAndroid Build Coastguard Worker #define MAX2( A, B )   ( (A)>(B) ? (A) : (B) )
125*ba62d9d3SAndroid Build Coastguard Worker #define MAX3( A, B, C ) ((A) > (B) ? MAX2(A, C) : MAX2(B, C))
126*ba62d9d3SAndroid Build Coastguard Worker 
127*ba62d9d3SAndroid Build Coastguard Worker #define __align_mask(value, mask)  (((value) + (mask)) & ~(mask))
128*ba62d9d3SAndroid Build Coastguard Worker #define ALIGN_CEIL(value, alignment)    __align_mask(value, (__typeof__(value))((alignment) - 1))
129*ba62d9d3SAndroid Build Coastguard Worker #define DRM_PLATFORM_DEVICE_NAME_LEN 512
130*ba62d9d3SAndroid Build Coastguard Worker 
131*ba62d9d3SAndroid Build Coastguard Worker typedef struct _drmPciBusInfo {
132*ba62d9d3SAndroid Build Coastguard Worker     uint16_t domain;
133*ba62d9d3SAndroid Build Coastguard Worker     uint8_t bus;
134*ba62d9d3SAndroid Build Coastguard Worker     uint8_t dev;
135*ba62d9d3SAndroid Build Coastguard Worker     uint8_t func;
136*ba62d9d3SAndroid Build Coastguard Worker } drmPciBusInfo, *drmPciBusInfoPtr;
137*ba62d9d3SAndroid Build Coastguard Worker 
138*ba62d9d3SAndroid Build Coastguard Worker typedef struct _drmPciDeviceInfo {
139*ba62d9d3SAndroid Build Coastguard Worker     uint32_t vendor_id;
140*ba62d9d3SAndroid Build Coastguard Worker     uint32_t device_id;
141*ba62d9d3SAndroid Build Coastguard Worker     uint32_t subvendor_id;
142*ba62d9d3SAndroid Build Coastguard Worker     uint32_t subdevice_id;
143*ba62d9d3SAndroid Build Coastguard Worker     uint32_t revision_id;
144*ba62d9d3SAndroid Build Coastguard Worker     char     driverInfo[1024];
145*ba62d9d3SAndroid Build Coastguard Worker     uint64_t videoMem[4] = {};
146*ba62d9d3SAndroid Build Coastguard Worker     uint64_t systemMem[4] = {};
147*ba62d9d3SAndroid Build Coastguard Worker     uint64_t sharedMem[4] = {};
148*ba62d9d3SAndroid Build Coastguard Worker     uint64_t ioportMem[4] = {};
149*ba62d9d3SAndroid Build Coastguard Worker     uint64_t ioMem[4] = {};
150*ba62d9d3SAndroid Build Coastguard Worker } drmPciDeviceInfo, *drmPciDeviceInfoPtr;
151*ba62d9d3SAndroid Build Coastguard Worker 
152*ba62d9d3SAndroid Build Coastguard Worker 
153*ba62d9d3SAndroid Build Coastguard Worker typedef struct _drmUsbBusInfo {
154*ba62d9d3SAndroid Build Coastguard Worker     uint8_t bus;
155*ba62d9d3SAndroid Build Coastguard Worker     uint8_t dev;
156*ba62d9d3SAndroid Build Coastguard Worker } drmUsbBusInfo, *drmUsbBusInfoPtr;
157*ba62d9d3SAndroid Build Coastguard Worker 
158*ba62d9d3SAndroid Build Coastguard Worker typedef struct _drmUsbDeviceInfo {
159*ba62d9d3SAndroid Build Coastguard Worker     uint16_t vendor;
160*ba62d9d3SAndroid Build Coastguard Worker     uint16_t product;
161*ba62d9d3SAndroid Build Coastguard Worker } drmUsbDeviceInfo, *drmUsbDeviceInfoPtr;
162*ba62d9d3SAndroid Build Coastguard Worker 
163*ba62d9d3SAndroid Build Coastguard Worker 
164*ba62d9d3SAndroid Build Coastguard Worker 
165*ba62d9d3SAndroid Build Coastguard Worker typedef struct _drmPlatformBusInfo {
166*ba62d9d3SAndroid Build Coastguard Worker     char fullname[DRM_PLATFORM_DEVICE_NAME_LEN + 1];
167*ba62d9d3SAndroid Build Coastguard Worker } drmPlatformBusInfo, *drmPlatformBusInfoPtr;
168*ba62d9d3SAndroid Build Coastguard Worker 
169*ba62d9d3SAndroid Build Coastguard Worker typedef struct _drmPlatformDeviceInfo {
170*ba62d9d3SAndroid Build Coastguard Worker     char **compatible; /* NULL terminated list of compatible strings */
171*ba62d9d3SAndroid Build Coastguard Worker } drmPlatformDeviceInfo, *drmPlatformDeviceInfoPtr;
172*ba62d9d3SAndroid Build Coastguard Worker 
173*ba62d9d3SAndroid Build Coastguard Worker #define DRM_HOST1X_DEVICE_NAME_LEN 512
174*ba62d9d3SAndroid Build Coastguard Worker 
175*ba62d9d3SAndroid Build Coastguard Worker typedef struct _drmHost1xBusInfo {
176*ba62d9d3SAndroid Build Coastguard Worker     char fullname[DRM_HOST1X_DEVICE_NAME_LEN + 1];
177*ba62d9d3SAndroid Build Coastguard Worker } drmHost1xBusInfo, *drmHost1xBusInfoPtr;
178*ba62d9d3SAndroid Build Coastguard Worker 
179*ba62d9d3SAndroid Build Coastguard Worker typedef struct _drmHost1xDeviceInfo {
180*ba62d9d3SAndroid Build Coastguard Worker     char **compatible; /* NULL terminated list of compatible strings */
181*ba62d9d3SAndroid Build Coastguard Worker } drmHost1xDeviceInfo, *drmHost1xDeviceInfoPtr;
182*ba62d9d3SAndroid Build Coastguard Worker 
183*ba62d9d3SAndroid Build Coastguard Worker typedef struct _drmDevice {
184*ba62d9d3SAndroid Build Coastguard Worker     char **nodes; /* DRM_NODE_MAX sized array */
185*ba62d9d3SAndroid Build Coastguard Worker     int available_nodes; /* DRM_NODE_* bitmask */
186*ba62d9d3SAndroid Build Coastguard Worker     int bustype;
187*ba62d9d3SAndroid Build Coastguard Worker     union {
188*ba62d9d3SAndroid Build Coastguard Worker         drmPciBusInfoPtr pci;
189*ba62d9d3SAndroid Build Coastguard Worker         drmUsbBusInfoPtr usb;
190*ba62d9d3SAndroid Build Coastguard Worker         drmPlatformBusInfoPtr platform;
191*ba62d9d3SAndroid Build Coastguard Worker         drmHost1xBusInfoPtr host1x;
192*ba62d9d3SAndroid Build Coastguard Worker     } businfo;
193*ba62d9d3SAndroid Build Coastguard Worker     union {
194*ba62d9d3SAndroid Build Coastguard Worker         drmPciDeviceInfoPtr pci;
195*ba62d9d3SAndroid Build Coastguard Worker         drmUsbDeviceInfoPtr usb;
196*ba62d9d3SAndroid Build Coastguard Worker         drmPlatformDeviceInfoPtr platform;
197*ba62d9d3SAndroid Build Coastguard Worker         drmHost1xDeviceInfoPtr host1x;
198*ba62d9d3SAndroid Build Coastguard Worker     } deviceinfo;
199*ba62d9d3SAndroid Build Coastguard Worker 
200*ba62d9d3SAndroid Build Coastguard Worker     unsigned int MaxThread = 0;
201*ba62d9d3SAndroid Build Coastguard Worker     unsigned int EuNumber = 0;
202*ba62d9d3SAndroid Build Coastguard Worker     unsigned int TileNumber = 0;
203*ba62d9d3SAndroid Build Coastguard Worker     unsigned int reserved[16];
204*ba62d9d3SAndroid Build Coastguard Worker } drmDevice, *drmDevicePtr;
205*ba62d9d3SAndroid Build Coastguard Worker 
206*ba62d9d3SAndroid Build Coastguard Worker /*
207*ba62d9d3SAndroid Build Coastguard Worker  * The kernel drm core has a number of places that assume maximum of
208*ba62d9d3SAndroid Build Coastguard Worker  * 3x64 devices nodes. That's 64 for each of primary, control and
209*ba62d9d3SAndroid Build Coastguard Worker  * render nodes. Rounded it up to 256 for simplicity.
210*ba62d9d3SAndroid Build Coastguard Worker  */
211*ba62d9d3SAndroid Build Coastguard Worker #define MAX_DRM_NODES 256
212*ba62d9d3SAndroid Build Coastguard Worker 
memcpy_s(void * dst,size_t numberOfElements,const void * src,size_t count)213*ba62d9d3SAndroid Build Coastguard Worker inline int memcpy_s(void *dst, size_t numberOfElements, const void *src, size_t count)
214*ba62d9d3SAndroid Build Coastguard Worker {
215*ba62d9d3SAndroid Build Coastguard Worker     if ((dst == nullptr) || (src == nullptr))
216*ba62d9d3SAndroid Build Coastguard Worker     {
217*ba62d9d3SAndroid Build Coastguard Worker         return EINVAL;
218*ba62d9d3SAndroid Build Coastguard Worker     }
219*ba62d9d3SAndroid Build Coastguard Worker     if (numberOfElements < count)
220*ba62d9d3SAndroid Build Coastguard Worker     {
221*ba62d9d3SAndroid Build Coastguard Worker         return ERANGE;
222*ba62d9d3SAndroid Build Coastguard Worker     }
223*ba62d9d3SAndroid Build Coastguard Worker     std::memcpy(dst, src, count);
224*ba62d9d3SAndroid Build Coastguard Worker     return 0;
225*ba62d9d3SAndroid Build Coastguard Worker }
226*ba62d9d3SAndroid Build Coastguard Worker 
227*ba62d9d3SAndroid Build Coastguard Worker  /* Check that the given flags are valid returning 0 on success */
228*ba62d9d3SAndroid Build Coastguard Worker static int
drm_device_validate_flags(uint32_t flags)229*ba62d9d3SAndroid Build Coastguard Worker drm_device_validate_flags(uint32_t flags)
230*ba62d9d3SAndroid Build Coastguard Worker {
231*ba62d9d3SAndroid Build Coastguard Worker     return (flags & ~DRM_DEVICE_GET_PCI_REVISION);
232*ba62d9d3SAndroid Build Coastguard Worker }
233*ba62d9d3SAndroid Build Coastguard Worker 
234*ba62d9d3SAndroid Build Coastguard Worker static bool
drm_device_has_rdev(drmDevicePtr device,dev_t find_rdev)235*ba62d9d3SAndroid Build Coastguard Worker drm_device_has_rdev(drmDevicePtr device, dev_t find_rdev)
236*ba62d9d3SAndroid Build Coastguard Worker {
237*ba62d9d3SAndroid Build Coastguard Worker     struct stat sbuf;
238*ba62d9d3SAndroid Build Coastguard Worker 
239*ba62d9d3SAndroid Build Coastguard Worker     for (int i = 0; i < DRM_NODE_MAX; i++) {
240*ba62d9d3SAndroid Build Coastguard Worker         if (device->available_nodes & 1 << i) {
241*ba62d9d3SAndroid Build Coastguard Worker             if (stat(device->nodes[i], &sbuf) == 0 &&
242*ba62d9d3SAndroid Build Coastguard Worker                 sbuf.st_rdev == find_rdev)
243*ba62d9d3SAndroid Build Coastguard Worker                 return true;
244*ba62d9d3SAndroid Build Coastguard Worker         }
245*ba62d9d3SAndroid Build Coastguard Worker     }
246*ba62d9d3SAndroid Build Coastguard Worker     return false;
247*ba62d9d3SAndroid Build Coastguard Worker }
248*ba62d9d3SAndroid Build Coastguard Worker 
drmGetMaxNodeName(void)249*ba62d9d3SAndroid Build Coastguard Worker static int drmGetMaxNodeName(void)
250*ba62d9d3SAndroid Build Coastguard Worker {
251*ba62d9d3SAndroid Build Coastguard Worker     return sizeof(DRM_DIR_NAME) +
252*ba62d9d3SAndroid Build Coastguard Worker         MAX3(sizeof(DRM_PRIMARY_MINOR_NAME),
253*ba62d9d3SAndroid Build Coastguard Worker             sizeof(DRM_CONTROL_MINOR_NAME),
254*ba62d9d3SAndroid Build Coastguard Worker             sizeof(DRM_RENDER_MINOR_NAME)) +
255*ba62d9d3SAndroid Build Coastguard Worker         3 /* length of the node number */;
256*ba62d9d3SAndroid Build Coastguard Worker }
257*ba62d9d3SAndroid Build Coastguard Worker 
drmNodeIsDRM(int maj,int min)258*ba62d9d3SAndroid Build Coastguard Worker static bool drmNodeIsDRM(int maj, int min)
259*ba62d9d3SAndroid Build Coastguard Worker {
260*ba62d9d3SAndroid Build Coastguard Worker #ifdef __linux__
261*ba62d9d3SAndroid Build Coastguard Worker     char path[64];
262*ba62d9d3SAndroid Build Coastguard Worker     struct stat sbuf;
263*ba62d9d3SAndroid Build Coastguard Worker 
264*ba62d9d3SAndroid Build Coastguard Worker     snprintf(path, sizeof(path), "/sys/dev/char/%d:%d/device/drm",
265*ba62d9d3SAndroid Build Coastguard Worker         maj, min);
266*ba62d9d3SAndroid Build Coastguard Worker     return stat(path, &sbuf) == 0;
267*ba62d9d3SAndroid Build Coastguard Worker #else
268*ba62d9d3SAndroid Build Coastguard Worker     return maj == DRM_MAJOR;
269*ba62d9d3SAndroid Build Coastguard Worker #endif
270*ba62d9d3SAndroid Build Coastguard Worker }
271*ba62d9d3SAndroid Build Coastguard Worker 
drmDevicesEqual(drmDevicePtr a,drmDevicePtr b)272*ba62d9d3SAndroid Build Coastguard Worker static int drmDevicesEqual(drmDevicePtr a, drmDevicePtr b)
273*ba62d9d3SAndroid Build Coastguard Worker {
274*ba62d9d3SAndroid Build Coastguard Worker     if (a == NULL || b == NULL)
275*ba62d9d3SAndroid Build Coastguard Worker         return 0;
276*ba62d9d3SAndroid Build Coastguard Worker 
277*ba62d9d3SAndroid Build Coastguard Worker     if (a->bustype != b->bustype)
278*ba62d9d3SAndroid Build Coastguard Worker         return 0;
279*ba62d9d3SAndroid Build Coastguard Worker 
280*ba62d9d3SAndroid Build Coastguard Worker     switch (a->bustype) {
281*ba62d9d3SAndroid Build Coastguard Worker     case DRM_BUS_PCI:
282*ba62d9d3SAndroid Build Coastguard Worker         return memcmp(a->businfo.pci, b->businfo.pci, sizeof(drmPciBusInfo)) == 0;
283*ba62d9d3SAndroid Build Coastguard Worker 
284*ba62d9d3SAndroid Build Coastguard Worker     case DRM_BUS_USB:
285*ba62d9d3SAndroid Build Coastguard Worker         return memcmp(a->businfo.usb, b->businfo.usb, sizeof(drmUsbBusInfo)) == 0;
286*ba62d9d3SAndroid Build Coastguard Worker 
287*ba62d9d3SAndroid Build Coastguard Worker     case DRM_BUS_PLATFORM:
288*ba62d9d3SAndroid Build Coastguard Worker         return memcmp(a->businfo.platform, b->businfo.platform, sizeof(drmPlatformBusInfo)) == 0;
289*ba62d9d3SAndroid Build Coastguard Worker 
290*ba62d9d3SAndroid Build Coastguard Worker     case DRM_BUS_HOST1X:
291*ba62d9d3SAndroid Build Coastguard Worker         return memcmp(a->businfo.host1x, b->businfo.host1x, sizeof(drmHost1xBusInfo)) == 0;
292*ba62d9d3SAndroid Build Coastguard Worker 
293*ba62d9d3SAndroid Build Coastguard Worker     default:
294*ba62d9d3SAndroid Build Coastguard Worker         break;
295*ba62d9d3SAndroid Build Coastguard Worker     }
296*ba62d9d3SAndroid Build Coastguard Worker     return 0;
297*ba62d9d3SAndroid Build Coastguard Worker }
298*ba62d9d3SAndroid Build Coastguard Worker 
drmDeviceAlloc(unsigned int type,const char * node,size_t bus_size,size_t device_size,char ** ptrp)299*ba62d9d3SAndroid Build Coastguard Worker static drmDevicePtr drmDeviceAlloc(unsigned int type, const char *node,
300*ba62d9d3SAndroid Build Coastguard Worker     size_t bus_size, size_t device_size,
301*ba62d9d3SAndroid Build Coastguard Worker     char **ptrp)
302*ba62d9d3SAndroid Build Coastguard Worker {
303*ba62d9d3SAndroid Build Coastguard Worker     size_t max_node_length, extra, size;
304*ba62d9d3SAndroid Build Coastguard Worker     drmDevicePtr device;
305*ba62d9d3SAndroid Build Coastguard Worker     unsigned int i;
306*ba62d9d3SAndroid Build Coastguard Worker     char *ptr;
307*ba62d9d3SAndroid Build Coastguard Worker 
308*ba62d9d3SAndroid Build Coastguard Worker     max_node_length = ALIGN_CEIL(drmGetMaxNodeName(), sizeof(void *));
309*ba62d9d3SAndroid Build Coastguard Worker 
310*ba62d9d3SAndroid Build Coastguard Worker     extra = DRM_NODE_MAX * (sizeof(void *) + max_node_length);
311*ba62d9d3SAndroid Build Coastguard Worker 
312*ba62d9d3SAndroid Build Coastguard Worker      size = sizeof(*device) + extra + bus_size + device_size;
313*ba62d9d3SAndroid Build Coastguard Worker 
314*ba62d9d3SAndroid Build Coastguard Worker     device = (drmDevicePtr)calloc(1, size);
315*ba62d9d3SAndroid Build Coastguard Worker     if (!device)
316*ba62d9d3SAndroid Build Coastguard Worker         return NULL;
317*ba62d9d3SAndroid Build Coastguard Worker 
318*ba62d9d3SAndroid Build Coastguard Worker     device->available_nodes = 1 << type;
319*ba62d9d3SAndroid Build Coastguard Worker 
320*ba62d9d3SAndroid Build Coastguard Worker     ptr = (char *)device + sizeof(*device);
321*ba62d9d3SAndroid Build Coastguard Worker     device->nodes = (char **)ptr;
322*ba62d9d3SAndroid Build Coastguard Worker 
323*ba62d9d3SAndroid Build Coastguard Worker     ptr += DRM_NODE_MAX * sizeof(void *);
324*ba62d9d3SAndroid Build Coastguard Worker 
325*ba62d9d3SAndroid Build Coastguard Worker     for (i = 0; i < DRM_NODE_MAX; i++) {
326*ba62d9d3SAndroid Build Coastguard Worker         device->nodes[i] = ptr;
327*ba62d9d3SAndroid Build Coastguard Worker         ptr += max_node_length;
328*ba62d9d3SAndroid Build Coastguard Worker     }
329*ba62d9d3SAndroid Build Coastguard Worker 
330*ba62d9d3SAndroid Build Coastguard Worker     memcpy(device->nodes[type], node, max_node_length);
331*ba62d9d3SAndroid Build Coastguard Worker     *ptrp = ptr;
332*ba62d9d3SAndroid Build Coastguard Worker 
333*ba62d9d3SAndroid Build Coastguard Worker     return device;
334*ba62d9d3SAndroid Build Coastguard Worker }
335*ba62d9d3SAndroid Build Coastguard Worker 
336*ba62d9d3SAndroid Build Coastguard Worker static char * DRM_PRINTFLIKE(2, 3)
sysfs_uevent_get(const char * path,const char * fmt,...)337*ba62d9d3SAndroid Build Coastguard Worker sysfs_uevent_get(const char *path, const char *fmt, ...)
338*ba62d9d3SAndroid Build Coastguard Worker {
339*ba62d9d3SAndroid Build Coastguard Worker     char filename[PATH_MAX + 1], *key, *line = NULL, *value = NULL;
340*ba62d9d3SAndroid Build Coastguard Worker     size_t size = 0, len;
341*ba62d9d3SAndroid Build Coastguard Worker     ssize_t num;
342*ba62d9d3SAndroid Build Coastguard Worker     va_list ap;
343*ba62d9d3SAndroid Build Coastguard Worker     FILE *fp;
344*ba62d9d3SAndroid Build Coastguard Worker 
345*ba62d9d3SAndroid Build Coastguard Worker     va_start(ap, fmt);
346*ba62d9d3SAndroid Build Coastguard Worker     num = vasprintf(&key, fmt, ap);
347*ba62d9d3SAndroid Build Coastguard Worker     va_end(ap);
348*ba62d9d3SAndroid Build Coastguard Worker     len = num;
349*ba62d9d3SAndroid Build Coastguard Worker 
350*ba62d9d3SAndroid Build Coastguard Worker     snprintf(filename, sizeof(filename), "%s/uevent", path);
351*ba62d9d3SAndroid Build Coastguard Worker 
352*ba62d9d3SAndroid Build Coastguard Worker     fp = fopen(filename, "r");
353*ba62d9d3SAndroid Build Coastguard Worker     if (!fp) {
354*ba62d9d3SAndroid Build Coastguard Worker         free(key);
355*ba62d9d3SAndroid Build Coastguard Worker         return NULL;
356*ba62d9d3SAndroid Build Coastguard Worker     }
357*ba62d9d3SAndroid Build Coastguard Worker 
358*ba62d9d3SAndroid Build Coastguard Worker     while ((num = getline(&line, &size, fp)) >= 0) {
359*ba62d9d3SAndroid Build Coastguard Worker         if ((strncmp(line, key, len) == 0) && (line[len] == '=')) {
360*ba62d9d3SAndroid Build Coastguard Worker             char *start = line + len + 1, *end = line + num - 1;
361*ba62d9d3SAndroid Build Coastguard Worker 
362*ba62d9d3SAndroid Build Coastguard Worker             if (*end != '\n')
363*ba62d9d3SAndroid Build Coastguard Worker                 end++;
364*ba62d9d3SAndroid Build Coastguard Worker 
365*ba62d9d3SAndroid Build Coastguard Worker             value = strndup(start, end - start);
366*ba62d9d3SAndroid Build Coastguard Worker             break;
367*ba62d9d3SAndroid Build Coastguard Worker         }
368*ba62d9d3SAndroid Build Coastguard Worker     }
369*ba62d9d3SAndroid Build Coastguard Worker 
370*ba62d9d3SAndroid Build Coastguard Worker     free(line);
371*ba62d9d3SAndroid Build Coastguard Worker     fclose(fp);
372*ba62d9d3SAndroid Build Coastguard Worker 
373*ba62d9d3SAndroid Build Coastguard Worker     free(key);
374*ba62d9d3SAndroid Build Coastguard Worker 
375*ba62d9d3SAndroid Build Coastguard Worker     return value;
376*ba62d9d3SAndroid Build Coastguard Worker }
377*ba62d9d3SAndroid Build Coastguard Worker 
drmParseHost1xDeviceInfo(int maj,int min,drmHost1xDeviceInfoPtr info)378*ba62d9d3SAndroid Build Coastguard Worker static int drmParseHost1xDeviceInfo(int maj,
379*ba62d9d3SAndroid Build Coastguard Worker                                     int min,
380*ba62d9d3SAndroid Build Coastguard Worker                                     drmHost1xDeviceInfoPtr info)
381*ba62d9d3SAndroid Build Coastguard Worker {
382*ba62d9d3SAndroid Build Coastguard Worker     char path[PATH_MAX + 1];
383*ba62d9d3SAndroid Build Coastguard Worker     int err = 0;
384*ba62d9d3SAndroid Build Coastguard Worker 
385*ba62d9d3SAndroid Build Coastguard Worker     snprintf(path, sizeof(path), "/sys/dev/char/%d:%d/device", maj, min);
386*ba62d9d3SAndroid Build Coastguard Worker 
387*ba62d9d3SAndroid Build Coastguard Worker     char *value = sysfs_uevent_get(path, "OF_COMPATIBLE_N");
388*ba62d9d3SAndroid Build Coastguard Worker     if (!value)
389*ba62d9d3SAndroid Build Coastguard Worker     {
390*ba62d9d3SAndroid Build Coastguard Worker         return -ENOENT;
391*ba62d9d3SAndroid Build Coastguard Worker     }
392*ba62d9d3SAndroid Build Coastguard Worker     unsigned int count = 0;
393*ba62d9d3SAndroid Build Coastguard Worker     int scanned_value_count = sscanf(value, "%u", &count);
394*ba62d9d3SAndroid Build Coastguard Worker     free(value);
395*ba62d9d3SAndroid Build Coastguard Worker     if (scanned_value_count <= 0 || 0 == count)
396*ba62d9d3SAndroid Build Coastguard Worker     {
397*ba62d9d3SAndroid Build Coastguard Worker         return -ENOENT;
398*ba62d9d3SAndroid Build Coastguard Worker     }
399*ba62d9d3SAndroid Build Coastguard Worker 
400*ba62d9d3SAndroid Build Coastguard Worker     info->compatible = (char**)calloc(count + 1, sizeof(*info->compatible));
401*ba62d9d3SAndroid Build Coastguard Worker     if (!info->compatible)
402*ba62d9d3SAndroid Build Coastguard Worker     {
403*ba62d9d3SAndroid Build Coastguard Worker         return -ENOMEM;
404*ba62d9d3SAndroid Build Coastguard Worker     }
405*ba62d9d3SAndroid Build Coastguard Worker 
406*ba62d9d3SAndroid Build Coastguard Worker     unsigned int i = 0;
407*ba62d9d3SAndroid Build Coastguard Worker     for (; i < count; i++)
408*ba62d9d3SAndroid Build Coastguard Worker     {
409*ba62d9d3SAndroid Build Coastguard Worker         value = sysfs_uevent_get(path, "OF_COMPATIBLE_%u", i);
410*ba62d9d3SAndroid Build Coastguard Worker         if (!value)
411*ba62d9d3SAndroid Build Coastguard Worker         {
412*ba62d9d3SAndroid Build Coastguard Worker             err = -ENOENT;
413*ba62d9d3SAndroid Build Coastguard Worker             goto free;
414*ba62d9d3SAndroid Build Coastguard Worker         }
415*ba62d9d3SAndroid Build Coastguard Worker         info->compatible[i] = value;
416*ba62d9d3SAndroid Build Coastguard Worker     }
417*ba62d9d3SAndroid Build Coastguard Worker     return 0;
418*ba62d9d3SAndroid Build Coastguard Worker 
419*ba62d9d3SAndroid Build Coastguard Worker free:
420*ba62d9d3SAndroid Build Coastguard Worker     while (i--)
421*ba62d9d3SAndroid Build Coastguard Worker     {
422*ba62d9d3SAndroid Build Coastguard Worker         free(info->compatible[i]);
423*ba62d9d3SAndroid Build Coastguard Worker     }
424*ba62d9d3SAndroid Build Coastguard Worker     free(info->compatible);
425*ba62d9d3SAndroid Build Coastguard Worker     return err;
426*ba62d9d3SAndroid Build Coastguard Worker }
427*ba62d9d3SAndroid Build Coastguard Worker 
drmParseHost1xBusInfo(int maj,int min,drmHost1xBusInfoPtr info)428*ba62d9d3SAndroid Build Coastguard Worker static int drmParseHost1xBusInfo(int maj, int min, drmHost1xBusInfoPtr info)
429*ba62d9d3SAndroid Build Coastguard Worker {
430*ba62d9d3SAndroid Build Coastguard Worker     char path[PATH_MAX + 1], *name;
431*ba62d9d3SAndroid Build Coastguard Worker     snprintf(path, sizeof(path), "/sys/dev/char/%d:%d/device", maj, min);
432*ba62d9d3SAndroid Build Coastguard Worker     name = sysfs_uevent_get(path, "OF_FULLNAME");
433*ba62d9d3SAndroid Build Coastguard Worker     if (!name)
434*ba62d9d3SAndroid Build Coastguard Worker         return -ENOENT;
435*ba62d9d3SAndroid Build Coastguard Worker     strncpy(info->fullname, name, DRM_HOST1X_DEVICE_NAME_LEN);
436*ba62d9d3SAndroid Build Coastguard Worker     info->fullname[DRM_HOST1X_DEVICE_NAME_LEN - 1] = '\0';
437*ba62d9d3SAndroid Build Coastguard Worker     free(name);
438*ba62d9d3SAndroid Build Coastguard Worker     return 0;
439*ba62d9d3SAndroid Build Coastguard Worker }
440*ba62d9d3SAndroid Build Coastguard Worker 
drmProcessHost1xDevice(drmDevicePtr * device,const char * node,int node_type,int maj,int min,bool fetch_deviceinfo,uint32_t flags)441*ba62d9d3SAndroid Build Coastguard Worker static int drmProcessHost1xDevice(drmDevicePtr *device,
442*ba62d9d3SAndroid Build Coastguard Worker     const char *node, int node_type,
443*ba62d9d3SAndroid Build Coastguard Worker     int maj, int min, bool fetch_deviceinfo,
444*ba62d9d3SAndroid Build Coastguard Worker     uint32_t flags)
445*ba62d9d3SAndroid Build Coastguard Worker {
446*ba62d9d3SAndroid Build Coastguard Worker     drmDevicePtr dev;
447*ba62d9d3SAndroid Build Coastguard Worker     char *ptr;
448*ba62d9d3SAndroid Build Coastguard Worker     int ret;
449*ba62d9d3SAndroid Build Coastguard Worker 
450*ba62d9d3SAndroid Build Coastguard Worker     dev = drmDeviceAlloc(node_type, node, sizeof(drmHost1xBusInfo),
451*ba62d9d3SAndroid Build Coastguard Worker         sizeof(drmHost1xDeviceInfo), &ptr);
452*ba62d9d3SAndroid Build Coastguard Worker     if (!dev)
453*ba62d9d3SAndroid Build Coastguard Worker         return -ENOMEM;
454*ba62d9d3SAndroid Build Coastguard Worker 
455*ba62d9d3SAndroid Build Coastguard Worker     dev->bustype = DRM_BUS_HOST1X;
456*ba62d9d3SAndroid Build Coastguard Worker 
457*ba62d9d3SAndroid Build Coastguard Worker     dev->businfo.host1x = (drmHost1xBusInfoPtr)ptr;
458*ba62d9d3SAndroid Build Coastguard Worker 
459*ba62d9d3SAndroid Build Coastguard Worker     ret = drmParseHost1xBusInfo(maj, min, dev->businfo.host1x);
460*ba62d9d3SAndroid Build Coastguard Worker     if (ret < 0)
461*ba62d9d3SAndroid Build Coastguard Worker         goto free_device;
462*ba62d9d3SAndroid Build Coastguard Worker 
463*ba62d9d3SAndroid Build Coastguard Worker     if (fetch_deviceinfo) {
464*ba62d9d3SAndroid Build Coastguard Worker         ptr += sizeof(drmHost1xBusInfo);
465*ba62d9d3SAndroid Build Coastguard Worker         dev->deviceinfo.host1x = (drmHost1xDeviceInfoPtr)ptr;
466*ba62d9d3SAndroid Build Coastguard Worker 
467*ba62d9d3SAndroid Build Coastguard Worker         ret = drmParseHost1xDeviceInfo(maj, min, dev->deviceinfo.host1x);
468*ba62d9d3SAndroid Build Coastguard Worker         if (ret < 0)
469*ba62d9d3SAndroid Build Coastguard Worker             goto free_device;
470*ba62d9d3SAndroid Build Coastguard Worker     }
471*ba62d9d3SAndroid Build Coastguard Worker 
472*ba62d9d3SAndroid Build Coastguard Worker     *device = dev;
473*ba62d9d3SAndroid Build Coastguard Worker 
474*ba62d9d3SAndroid Build Coastguard Worker     return 0;
475*ba62d9d3SAndroid Build Coastguard Worker 
476*ba62d9d3SAndroid Build Coastguard Worker free_device:
477*ba62d9d3SAndroid Build Coastguard Worker     free(dev);
478*ba62d9d3SAndroid Build Coastguard Worker     return ret;
479*ba62d9d3SAndroid Build Coastguard Worker }
480*ba62d9d3SAndroid Build Coastguard Worker 
drmParsePlatformBusInfo(int maj,int min,drmPlatformBusInfoPtr info)481*ba62d9d3SAndroid Build Coastguard Worker static int drmParsePlatformBusInfo(int maj, int min, drmPlatformBusInfoPtr info)
482*ba62d9d3SAndroid Build Coastguard Worker {
483*ba62d9d3SAndroid Build Coastguard Worker     char path[PATH_MAX + 1], *name;
484*ba62d9d3SAndroid Build Coastguard Worker     snprintf(path, sizeof(path), "/sys/dev/char/%d:%d/device", maj, min);
485*ba62d9d3SAndroid Build Coastguard Worker     name = sysfs_uevent_get(path, "OF_FULLNAME");
486*ba62d9d3SAndroid Build Coastguard Worker     if (!name)
487*ba62d9d3SAndroid Build Coastguard Worker         return -ENOENT;
488*ba62d9d3SAndroid Build Coastguard Worker     strncpy(info->fullname, name, DRM_PLATFORM_DEVICE_NAME_LEN);
489*ba62d9d3SAndroid Build Coastguard Worker     info->fullname[DRM_PLATFORM_DEVICE_NAME_LEN - 1] = '\0';
490*ba62d9d3SAndroid Build Coastguard Worker     free(name);
491*ba62d9d3SAndroid Build Coastguard Worker     return 0;
492*ba62d9d3SAndroid Build Coastguard Worker }
493*ba62d9d3SAndroid Build Coastguard Worker 
drmParsePlatformDeviceInfo(int maj,int min,drmPlatformDeviceInfoPtr info)494*ba62d9d3SAndroid Build Coastguard Worker static int drmParsePlatformDeviceInfo(int maj, int min,
495*ba62d9d3SAndroid Build Coastguard Worker     drmPlatformDeviceInfoPtr info)
496*ba62d9d3SAndroid Build Coastguard Worker {
497*ba62d9d3SAndroid Build Coastguard Worker     char path[PATH_MAX + 1], *value;
498*ba62d9d3SAndroid Build Coastguard Worker     unsigned int count, i;
499*ba62d9d3SAndroid Build Coastguard Worker     int err;
500*ba62d9d3SAndroid Build Coastguard Worker 
501*ba62d9d3SAndroid Build Coastguard Worker     snprintf(path, sizeof(path), "/sys/dev/char/%d:%d/device", maj, min);
502*ba62d9d3SAndroid Build Coastguard Worker     value = sysfs_uevent_get(path, "OF_COMPATIBLE_N");
503*ba62d9d3SAndroid Build Coastguard Worker     if (!value)
504*ba62d9d3SAndroid Build Coastguard Worker         return -ENOENT;
505*ba62d9d3SAndroid Build Coastguard Worker 
506*ba62d9d3SAndroid Build Coastguard Worker     int scanned_value_count = sscanf(value, "%u", &count);
507*ba62d9d3SAndroid Build Coastguard Worker     free(value);
508*ba62d9d3SAndroid Build Coastguard Worker     if (scanned_value_count <= 0 || 0 == count)
509*ba62d9d3SAndroid Build Coastguard Worker     {
510*ba62d9d3SAndroid Build Coastguard Worker         return -ENOENT;
511*ba62d9d3SAndroid Build Coastguard Worker     }
512*ba62d9d3SAndroid Build Coastguard Worker 
513*ba62d9d3SAndroid Build Coastguard Worker     if (count <= MAX_DRM_NODES)
514*ba62d9d3SAndroid Build Coastguard Worker     {
515*ba62d9d3SAndroid Build Coastguard Worker         info->compatible = (char**)calloc(count + 1, sizeof(*info->compatible));
516*ba62d9d3SAndroid Build Coastguard Worker     }else
517*ba62d9d3SAndroid Build Coastguard Worker         return -ENOENT;
518*ba62d9d3SAndroid Build Coastguard Worker 
519*ba62d9d3SAndroid Build Coastguard Worker     if (!info->compatible)
520*ba62d9d3SAndroid Build Coastguard Worker         return -ENOMEM;
521*ba62d9d3SAndroid Build Coastguard Worker     for (i = 0; i < count; i++) {
522*ba62d9d3SAndroid Build Coastguard Worker         value = sysfs_uevent_get(path, "OF_COMPATIBLE_%u", i);
523*ba62d9d3SAndroid Build Coastguard Worker         if (!value) {
524*ba62d9d3SAndroid Build Coastguard Worker             err = -ENOENT;
525*ba62d9d3SAndroid Build Coastguard Worker             goto free;
526*ba62d9d3SAndroid Build Coastguard Worker         }
527*ba62d9d3SAndroid Build Coastguard Worker         info->compatible[i] = value;
528*ba62d9d3SAndroid Build Coastguard Worker     }
529*ba62d9d3SAndroid Build Coastguard Worker     return 0;
530*ba62d9d3SAndroid Build Coastguard Worker free:
531*ba62d9d3SAndroid Build Coastguard Worker     while (i--)
532*ba62d9d3SAndroid Build Coastguard Worker         free(info->compatible[i]);
533*ba62d9d3SAndroid Build Coastguard Worker     free(info->compatible);
534*ba62d9d3SAndroid Build Coastguard Worker     return err;
535*ba62d9d3SAndroid Build Coastguard Worker }
536*ba62d9d3SAndroid Build Coastguard Worker 
537*ba62d9d3SAndroid Build Coastguard Worker static void
get_pci_path(int maj,int min,char * pci_path)538*ba62d9d3SAndroid Build Coastguard Worker get_pci_path(int maj, int min, char *pci_path)
539*ba62d9d3SAndroid Build Coastguard Worker {
540*ba62d9d3SAndroid Build Coastguard Worker     char path[PATH_MAX + 1], *term;
541*ba62d9d3SAndroid Build Coastguard Worker 
542*ba62d9d3SAndroid Build Coastguard Worker     snprintf(path, sizeof(path), "/sys/dev/char/%d:%d/device", maj, min);
543*ba62d9d3SAndroid Build Coastguard Worker     if (!realpath(path, pci_path)) {
544*ba62d9d3SAndroid Build Coastguard Worker         strcpy(pci_path, path);
545*ba62d9d3SAndroid Build Coastguard Worker         return;
546*ba62d9d3SAndroid Build Coastguard Worker     }
547*ba62d9d3SAndroid Build Coastguard Worker 
548*ba62d9d3SAndroid Build Coastguard Worker     term = strrchr(pci_path, '/');
549*ba62d9d3SAndroid Build Coastguard Worker     if (term && strncmp(term, "/virtio", 7) == 0)
550*ba62d9d3SAndroid Build Coastguard Worker         *term = 0;
551*ba62d9d3SAndroid Build Coastguard Worker }
552*ba62d9d3SAndroid Build Coastguard Worker 
parse_separate_sysfs_files(int maj,int min,drmPciDeviceInfoPtr device,bool ignore_revision)553*ba62d9d3SAndroid Build Coastguard Worker static int parse_separate_sysfs_files(int maj, int min,
554*ba62d9d3SAndroid Build Coastguard Worker     drmPciDeviceInfoPtr device,
555*ba62d9d3SAndroid Build Coastguard Worker     bool ignore_revision)
556*ba62d9d3SAndroid Build Coastguard Worker {
557*ba62d9d3SAndroid Build Coastguard Worker     static const char *attrs[] = {
558*ba62d9d3SAndroid Build Coastguard Worker         "revision", /* Older kernels are missing the file, so check for it first */
559*ba62d9d3SAndroid Build Coastguard Worker         "vendor",
560*ba62d9d3SAndroid Build Coastguard Worker         "device",
561*ba62d9d3SAndroid Build Coastguard Worker         "subsystem_vendor",
562*ba62d9d3SAndroid Build Coastguard Worker         "subsystem_device",
563*ba62d9d3SAndroid Build Coastguard Worker     };
564*ba62d9d3SAndroid Build Coastguard Worker     char path[PATH_MAX + 128], pci_path[PATH_MAX];
565*ba62d9d3SAndroid Build Coastguard Worker     char resourcename[PATH_MAX + 64], driverpath[PATH_MAX + 64], drivername[PATH_MAX + 64], irqpath[PATH_MAX + 64];
566*ba62d9d3SAndroid Build Coastguard Worker 
567*ba62d9d3SAndroid Build Coastguard Worker     unsigned int data[ARRAY_SIZE(attrs)];
568*ba62d9d3SAndroid Build Coastguard Worker     FILE *fp;
569*ba62d9d3SAndroid Build Coastguard Worker     int ret;
570*ba62d9d3SAndroid Build Coastguard Worker     char *dev_path;
571*ba62d9d3SAndroid Build Coastguard Worker     char *driver_name;
572*ba62d9d3SAndroid Build Coastguard Worker 
573*ba62d9d3SAndroid Build Coastguard Worker     get_pci_path(maj, min, pci_path);
574*ba62d9d3SAndroid Build Coastguard Worker     dev_path = strrchr(pci_path, '/');
575*ba62d9d3SAndroid Build Coastguard Worker     dev_path++;
576*ba62d9d3SAndroid Build Coastguard Worker 
577*ba62d9d3SAndroid Build Coastguard Worker     snprintf(driverpath, sizeof(driverpath), "%s/driver", pci_path);
578*ba62d9d3SAndroid Build Coastguard Worker     snprintf(irqpath, sizeof(irqpath), "%s/irq", pci_path);
579*ba62d9d3SAndroid Build Coastguard Worker     int fd = open(irqpath, O_RDONLY);
580*ba62d9d3SAndroid Build Coastguard Worker 
581*ba62d9d3SAndroid Build Coastguard Worker     char buffer[512] ;
582*ba62d9d3SAndroid Build Coastguard Worker     memset(buffer, 0, sizeof(buffer));
583*ba62d9d3SAndroid Build Coastguard Worker     if (fd >= 0)
584*ba62d9d3SAndroid Build Coastguard Worker     {
585*ba62d9d3SAndroid Build Coastguard Worker         int count = 0;
586*ba62d9d3SAndroid Build Coastguard Worker         count = read(fd, buffer, sizeof(buffer));
587*ba62d9d3SAndroid Build Coastguard Worker         close(fd);
588*ba62d9d3SAndroid Build Coastguard Worker     }
589*ba62d9d3SAndroid Build Coastguard Worker 
590*ba62d9d3SAndroid Build Coastguard Worker     snprintf(resourcename, sizeof(resourcename), "%s/resource", pci_path);
591*ba62d9d3SAndroid Build Coastguard Worker 
592*ba62d9d3SAndroid Build Coastguard Worker     memset(drivername, 0, sizeof(drivername));
593*ba62d9d3SAndroid Build Coastguard Worker     if (readlink(driverpath, drivername, PATH_MAX) < 0)
594*ba62d9d3SAndroid Build Coastguard Worker     {
595*ba62d9d3SAndroid Build Coastguard Worker         /* Some devices might not be bound to a driver */
596*ba62d9d3SAndroid Build Coastguard Worker         if (errno == ENOENT)
597*ba62d9d3SAndroid Build Coastguard Worker             return -errno;
598*ba62d9d3SAndroid Build Coastguard Worker         else
599*ba62d9d3SAndroid Build Coastguard Worker             printf("   readlink -errno %d\n", errno);
600*ba62d9d3SAndroid Build Coastguard Worker     }
601*ba62d9d3SAndroid Build Coastguard Worker 
602*ba62d9d3SAndroid Build Coastguard Worker     driver_name = strrchr(drivername, '/');
603*ba62d9d3SAndroid Build Coastguard Worker     driver_name++;
604*ba62d9d3SAndroid Build Coastguard Worker     snprintf(device->driverInfo, sizeof(device->driverInfo), "Driver Module %s  Bus %s IRQ %s", driver_name, dev_path, buffer);
605*ba62d9d3SAndroid Build Coastguard Worker 
606*ba62d9d3SAndroid Build Coastguard Worker     FILE*resource = fopen(resourcename, "r");
607*ba62d9d3SAndroid Build Coastguard Worker 
608*ba62d9d3SAndroid Build Coastguard Worker     if (resource)
609*ba62d9d3SAndroid Build Coastguard Worker     {
610*ba62d9d3SAndroid Build Coastguard Worker         while (!feof(resource))
611*ba62d9d3SAndroid Build Coastguard Worker         {
612*ba62d9d3SAndroid Build Coastguard Worker             unsigned long long start, end, flags;
613*ba62d9d3SAndroid Build Coastguard Worker 
614*ba62d9d3SAndroid Build Coastguard Worker             start = end = flags = 0;
615*ba62d9d3SAndroid Build Coastguard Worker 
616*ba62d9d3SAndroid Build Coastguard Worker             if (fscanf(resource, "%llx %llx %llx", &start, &end, &flags) != 3)
617*ba62d9d3SAndroid Build Coastguard Worker                 break;
618*ba62d9d3SAndroid Build Coastguard Worker 
619*ba62d9d3SAndroid Build Coastguard Worker             if (flags & 0x101)
620*ba62d9d3SAndroid Build Coastguard Worker             {
621*ba62d9d3SAndroid Build Coastguard Worker                 device->ioportMem[0] = end - start + 1;
622*ba62d9d3SAndroid Build Coastguard Worker             }
623*ba62d9d3SAndroid Build Coastguard Worker             else
624*ba62d9d3SAndroid Build Coastguard Worker                 if (flags & 0x100)
625*ba62d9d3SAndroid Build Coastguard Worker                 {
626*ba62d9d3SAndroid Build Coastguard Worker                     device->ioMem[0] = end - start + 1;
627*ba62d9d3SAndroid Build Coastguard Worker                 }
628*ba62d9d3SAndroid Build Coastguard Worker                 else
629*ba62d9d3SAndroid Build Coastguard Worker                     if (flags & 0x200)
630*ba62d9d3SAndroid Build Coastguard Worker                     {
631*ba62d9d3SAndroid Build Coastguard Worker                         int i;
632*ba62d9d3SAndroid Build Coastguard Worker                         for ( i = 0; i < 4; i++)
633*ba62d9d3SAndroid Build Coastguard Worker                         {
634*ba62d9d3SAndroid Build Coastguard Worker                             if (device->videoMem[i] == 0)
635*ba62d9d3SAndroid Build Coastguard Worker                             {
636*ba62d9d3SAndroid Build Coastguard Worker                                 device->videoMem[i] = end - start + 1;
637*ba62d9d3SAndroid Build Coastguard Worker                                 break;
638*ba62d9d3SAndroid Build Coastguard Worker                             }
639*ba62d9d3SAndroid Build Coastguard Worker                         }
640*ba62d9d3SAndroid Build Coastguard Worker 
641*ba62d9d3SAndroid Build Coastguard Worker                     }
642*ba62d9d3SAndroid Build Coastguard Worker         }
643*ba62d9d3SAndroid Build Coastguard Worker         fclose(resource);
644*ba62d9d3SAndroid Build Coastguard Worker     }
645*ba62d9d3SAndroid Build Coastguard Worker 
646*ba62d9d3SAndroid Build Coastguard Worker 
647*ba62d9d3SAndroid Build Coastguard Worker     for (unsigned i = ignore_revision ? 1 : 0; i < ARRAY_SIZE(attrs); i++) {
648*ba62d9d3SAndroid Build Coastguard Worker         snprintf(path, PATH_MAX + 128, "%s/%s", pci_path, attrs[i]);
649*ba62d9d3SAndroid Build Coastguard Worker 
650*ba62d9d3SAndroid Build Coastguard Worker         fp = fopen(path, "r");
651*ba62d9d3SAndroid Build Coastguard Worker         if (!fp)
652*ba62d9d3SAndroid Build Coastguard Worker             return -errno;
653*ba62d9d3SAndroid Build Coastguard Worker 
654*ba62d9d3SAndroid Build Coastguard Worker         ret = fscanf(fp, "%x", &data[i]);
655*ba62d9d3SAndroid Build Coastguard Worker         fclose(fp);
656*ba62d9d3SAndroid Build Coastguard Worker         if (ret != 1)
657*ba62d9d3SAndroid Build Coastguard Worker             return -errno;
658*ba62d9d3SAndroid Build Coastguard Worker     }
659*ba62d9d3SAndroid Build Coastguard Worker 
660*ba62d9d3SAndroid Build Coastguard Worker     device->revision_id = ignore_revision ? 0xff : data[0] & 0xff;
661*ba62d9d3SAndroid Build Coastguard Worker     device->vendor_id = data[1] & 0xffff;
662*ba62d9d3SAndroid Build Coastguard Worker     device->device_id = data[2] & 0xffff;
663*ba62d9d3SAndroid Build Coastguard Worker     device->subvendor_id = data[3] & 0xffff;
664*ba62d9d3SAndroid Build Coastguard Worker     device->subdevice_id = data[4] & 0xffff;
665*ba62d9d3SAndroid Build Coastguard Worker     return 0;
666*ba62d9d3SAndroid Build Coastguard Worker }
667*ba62d9d3SAndroid Build Coastguard Worker 
parse_config_sysfs_file(int maj,int min,drmPciDeviceInfoPtr device)668*ba62d9d3SAndroid Build Coastguard Worker static int parse_config_sysfs_file(int maj, int min,
669*ba62d9d3SAndroid Build Coastguard Worker     drmPciDeviceInfoPtr device)
670*ba62d9d3SAndroid Build Coastguard Worker {
671*ba62d9d3SAndroid Build Coastguard Worker     char path[PATH_MAX + 128], pci_path[PATH_MAX + 1];
672*ba62d9d3SAndroid Build Coastguard Worker     unsigned char config[64];
673*ba62d9d3SAndroid Build Coastguard Worker     int fd, ret;
674*ba62d9d3SAndroid Build Coastguard Worker 
675*ba62d9d3SAndroid Build Coastguard Worker     get_pci_path(maj, min, pci_path);
676*ba62d9d3SAndroid Build Coastguard Worker 
677*ba62d9d3SAndroid Build Coastguard Worker     snprintf(path, PATH_MAX + 128, "%s/config", pci_path);
678*ba62d9d3SAndroid Build Coastguard Worker 
679*ba62d9d3SAndroid Build Coastguard Worker     fd = open(path, O_RDONLY);
680*ba62d9d3SAndroid Build Coastguard Worker     if (fd < 0)
681*ba62d9d3SAndroid Build Coastguard Worker         return -errno;
682*ba62d9d3SAndroid Build Coastguard Worker 
683*ba62d9d3SAndroid Build Coastguard Worker     ret = read(fd, config, sizeof(config));
684*ba62d9d3SAndroid Build Coastguard Worker     close(fd);
685*ba62d9d3SAndroid Build Coastguard Worker     if (ret < 0)
686*ba62d9d3SAndroid Build Coastguard Worker         return -errno;
687*ba62d9d3SAndroid Build Coastguard Worker 
688*ba62d9d3SAndroid Build Coastguard Worker     device->vendor_id = config[0] | (config[1] << 8);
689*ba62d9d3SAndroid Build Coastguard Worker     device->device_id = config[2] | (config[3] << 8);
690*ba62d9d3SAndroid Build Coastguard Worker     device->revision_id = config[8];
691*ba62d9d3SAndroid Build Coastguard Worker     device->subvendor_id = config[44] | (config[45] << 8);
692*ba62d9d3SAndroid Build Coastguard Worker     device->subdevice_id = config[46] | (config[47] << 8);
693*ba62d9d3SAndroid Build Coastguard Worker 
694*ba62d9d3SAndroid Build Coastguard Worker     return 0;
695*ba62d9d3SAndroid Build Coastguard Worker }
696*ba62d9d3SAndroid Build Coastguard Worker 
drmParsePciDeviceInfo(int maj,int min,drmPciDeviceInfoPtr device,uint32_t flags)697*ba62d9d3SAndroid Build Coastguard Worker static int drmParsePciDeviceInfo(int maj, int min,
698*ba62d9d3SAndroid Build Coastguard Worker     drmPciDeviceInfoPtr device,
699*ba62d9d3SAndroid Build Coastguard Worker     uint32_t flags)
700*ba62d9d3SAndroid Build Coastguard Worker {
701*ba62d9d3SAndroid Build Coastguard Worker //#ifdef __linux__
702*ba62d9d3SAndroid Build Coastguard Worker     if (!(flags & DRM_DEVICE_GET_PCI_REVISION))
703*ba62d9d3SAndroid Build Coastguard Worker         return parse_separate_sysfs_files(maj, min, device, true);
704*ba62d9d3SAndroid Build Coastguard Worker 
705*ba62d9d3SAndroid Build Coastguard Worker     if (parse_separate_sysfs_files(maj, min, device, false))
706*ba62d9d3SAndroid Build Coastguard Worker         return parse_config_sysfs_file(maj, min, device);
707*ba62d9d3SAndroid Build Coastguard Worker     return 0;
708*ba62d9d3SAndroid Build Coastguard Worker /*
709*ba62d9d3SAndroid Build Coastguard Worker #elif defined(__OpenBSD__) || defined(__DragonFly__)
710*ba62d9d3SAndroid Build Coastguard Worker     struct drm_pciinfo pinfo;
711*ba62d9d3SAndroid Build Coastguard Worker     int fd, type;
712*ba62d9d3SAndroid Build Coastguard Worker 
713*ba62d9d3SAndroid Build Coastguard Worker     type = drmGetMinorType(min);
714*ba62d9d3SAndroid Build Coastguard Worker     if (type == -1)
715*ba62d9d3SAndroid Build Coastguard Worker         return -ENODEV;
716*ba62d9d3SAndroid Build Coastguard Worker 
717*ba62d9d3SAndroid Build Coastguard Worker     fd = drmOpenMinor(min, 0, type);
718*ba62d9d3SAndroid Build Coastguard Worker     if (fd < 0)
719*ba62d9d3SAndroid Build Coastguard Worker         return -errno;
720*ba62d9d3SAndroid Build Coastguard Worker 
721*ba62d9d3SAndroid Build Coastguard Worker     if (drmIoctl(fd, DRM_IOCTL_GET_PCIINFO, &pinfo)) {
722*ba62d9d3SAndroid Build Coastguard Worker         close(fd);
723*ba62d9d3SAndroid Build Coastguard Worker         return -errno;
724*ba62d9d3SAndroid Build Coastguard Worker     }
725*ba62d9d3SAndroid Build Coastguard Worker     close(fd);
726*ba62d9d3SAndroid Build Coastguard Worker 
727*ba62d9d3SAndroid Build Coastguard Worker     device->vendor_id = pinfo.vendor_id;
728*ba62d9d3SAndroid Build Coastguard Worker     device->device_id = pinfo.device_id;
729*ba62d9d3SAndroid Build Coastguard Worker     device->revision_id = pinfo.revision_id;
730*ba62d9d3SAndroid Build Coastguard Worker     device->subvendor_id = pinfo.subvendor_id;
731*ba62d9d3SAndroid Build Coastguard Worker     device->subdevice_id = pinfo.subdevice_id;
732*ba62d9d3SAndroid Build Coastguard Worker 
733*ba62d9d3SAndroid Build Coastguard Worker     return 0;
734*ba62d9d3SAndroid Build Coastguard Worker #else
735*ba62d9d3SAndroid Build Coastguard Worker     #warning "Missing implementation of drmParsePciDeviceInfo"
736*ba62d9d3SAndroid Build Coastguard Worker         return -EINVAL;
737*ba62d9d3SAndroid Build Coastguard Worker #endif
738*ba62d9d3SAndroid Build Coastguard Worker */
739*ba62d9d3SAndroid Build Coastguard Worker }
740*ba62d9d3SAndroid Build Coastguard Worker 
drmParsePciBusInfo(int maj,int min,drmPciBusInfoPtr info)741*ba62d9d3SAndroid Build Coastguard Worker static int drmParsePciBusInfo(int maj, int min, drmPciBusInfoPtr info)
742*ba62d9d3SAndroid Build Coastguard Worker {
743*ba62d9d3SAndroid Build Coastguard Worker     unsigned int domain, bus, dev, func;
744*ba62d9d3SAndroid Build Coastguard Worker     char pci_path[PATH_MAX + 1], *value;
745*ba62d9d3SAndroid Build Coastguard Worker     int num;
746*ba62d9d3SAndroid Build Coastguard Worker     get_pci_path(maj, min, pci_path);
747*ba62d9d3SAndroid Build Coastguard Worker     value = sysfs_uevent_get(pci_path, "PCI_SLOT_NAME");
748*ba62d9d3SAndroid Build Coastguard Worker     if (!value)
749*ba62d9d3SAndroid Build Coastguard Worker         return -ENOENT;
750*ba62d9d3SAndroid Build Coastguard Worker 
751*ba62d9d3SAndroid Build Coastguard Worker     num = sscanf(value, "%04x:%02x:%02x.%1u", &domain, &bus, &dev, &func);
752*ba62d9d3SAndroid Build Coastguard Worker     free(value);
753*ba62d9d3SAndroid Build Coastguard Worker     if (num != 4)
754*ba62d9d3SAndroid Build Coastguard Worker         return -EINVAL;
755*ba62d9d3SAndroid Build Coastguard Worker     info->domain = domain;
756*ba62d9d3SAndroid Build Coastguard Worker     info->bus = bus;
757*ba62d9d3SAndroid Build Coastguard Worker     info->dev = dev;
758*ba62d9d3SAndroid Build Coastguard Worker     info->func = func;
759*ba62d9d3SAndroid Build Coastguard Worker     return 0;
760*ba62d9d3SAndroid Build Coastguard Worker }
761*ba62d9d3SAndroid Build Coastguard Worker 
drmProcessPlatformDevice(drmDevicePtr * device,const char * node,int node_type,int maj,int min,bool fetch_deviceinfo,uint32_t flags)762*ba62d9d3SAndroid Build Coastguard Worker static int drmProcessPlatformDevice(drmDevicePtr *device,
763*ba62d9d3SAndroid Build Coastguard Worker     const char *node, int node_type,
764*ba62d9d3SAndroid Build Coastguard Worker     int maj, int min, bool fetch_deviceinfo,
765*ba62d9d3SAndroid Build Coastguard Worker     uint32_t flags)
766*ba62d9d3SAndroid Build Coastguard Worker {
767*ba62d9d3SAndroid Build Coastguard Worker     drmDevicePtr dev;
768*ba62d9d3SAndroid Build Coastguard Worker     char *ptr;
769*ba62d9d3SAndroid Build Coastguard Worker     int ret;
770*ba62d9d3SAndroid Build Coastguard Worker 
771*ba62d9d3SAndroid Build Coastguard Worker     dev = drmDeviceAlloc(node_type, node, sizeof(drmPlatformBusInfo),
772*ba62d9d3SAndroid Build Coastguard Worker         sizeof(drmPlatformDeviceInfo), &ptr);
773*ba62d9d3SAndroid Build Coastguard Worker     if (!dev)
774*ba62d9d3SAndroid Build Coastguard Worker         return -ENOMEM;
775*ba62d9d3SAndroid Build Coastguard Worker 
776*ba62d9d3SAndroid Build Coastguard Worker     dev->bustype = DRM_BUS_PLATFORM;
777*ba62d9d3SAndroid Build Coastguard Worker 
778*ba62d9d3SAndroid Build Coastguard Worker     dev->businfo.platform = (drmPlatformBusInfoPtr)ptr;
779*ba62d9d3SAndroid Build Coastguard Worker 
780*ba62d9d3SAndroid Build Coastguard Worker     ret = drmParsePlatformBusInfo(maj, min, dev->businfo.platform);
781*ba62d9d3SAndroid Build Coastguard Worker     if (ret < 0)
782*ba62d9d3SAndroid Build Coastguard Worker         goto free_device;
783*ba62d9d3SAndroid Build Coastguard Worker 
784*ba62d9d3SAndroid Build Coastguard Worker     if (fetch_deviceinfo) {
785*ba62d9d3SAndroid Build Coastguard Worker         ptr += sizeof(drmPlatformBusInfo);
786*ba62d9d3SAndroid Build Coastguard Worker         dev->deviceinfo.platform = (drmPlatformDeviceInfoPtr)ptr;
787*ba62d9d3SAndroid Build Coastguard Worker 
788*ba62d9d3SAndroid Build Coastguard Worker         ret = drmParsePlatformDeviceInfo(maj, min, dev->deviceinfo.platform);
789*ba62d9d3SAndroid Build Coastguard Worker         if (ret < 0)
790*ba62d9d3SAndroid Build Coastguard Worker             goto free_device;
791*ba62d9d3SAndroid Build Coastguard Worker     }
792*ba62d9d3SAndroid Build Coastguard Worker 
793*ba62d9d3SAndroid Build Coastguard Worker     *device = dev;
794*ba62d9d3SAndroid Build Coastguard Worker 
795*ba62d9d3SAndroid Build Coastguard Worker     return 0;
796*ba62d9d3SAndroid Build Coastguard Worker 
797*ba62d9d3SAndroid Build Coastguard Worker free_device:
798*ba62d9d3SAndroid Build Coastguard Worker     free(dev);
799*ba62d9d3SAndroid Build Coastguard Worker     return ret;
800*ba62d9d3SAndroid Build Coastguard Worker }
801*ba62d9d3SAndroid Build Coastguard Worker 
drmProcessPciDevice(drmDevicePtr * device,const char * node,int node_type,int maj,int min,bool fetch_deviceinfo,uint32_t flags)802*ba62d9d3SAndroid Build Coastguard Worker static int drmProcessPciDevice(drmDevicePtr *device,
803*ba62d9d3SAndroid Build Coastguard Worker     const char *node, int node_type,
804*ba62d9d3SAndroid Build Coastguard Worker     int maj, int min, bool fetch_deviceinfo,
805*ba62d9d3SAndroid Build Coastguard Worker     uint32_t flags)
806*ba62d9d3SAndroid Build Coastguard Worker {
807*ba62d9d3SAndroid Build Coastguard Worker     drmDevicePtr dev;
808*ba62d9d3SAndroid Build Coastguard Worker     char *addr;
809*ba62d9d3SAndroid Build Coastguard Worker     int ret;
810*ba62d9d3SAndroid Build Coastguard Worker 
811*ba62d9d3SAndroid Build Coastguard Worker     dev = drmDeviceAlloc(node_type, node, sizeof(drmPciBusInfo),
812*ba62d9d3SAndroid Build Coastguard Worker         sizeof(drmPciDeviceInfo), &addr);
813*ba62d9d3SAndroid Build Coastguard Worker 
814*ba62d9d3SAndroid Build Coastguard Worker     if (!dev)
815*ba62d9d3SAndroid Build Coastguard Worker         return -ENOMEM;
816*ba62d9d3SAndroid Build Coastguard Worker 
817*ba62d9d3SAndroid Build Coastguard Worker     dev->bustype = DRM_BUS_PCI;
818*ba62d9d3SAndroid Build Coastguard Worker 
819*ba62d9d3SAndroid Build Coastguard Worker     dev->businfo.pci = (drmPciBusInfoPtr)addr;
820*ba62d9d3SAndroid Build Coastguard Worker 
821*ba62d9d3SAndroid Build Coastguard Worker     ret = drmParsePciBusInfo(maj, min, dev->businfo.pci);
822*ba62d9d3SAndroid Build Coastguard Worker     if (ret)
823*ba62d9d3SAndroid Build Coastguard Worker         goto free_device;
824*ba62d9d3SAndroid Build Coastguard Worker 
825*ba62d9d3SAndroid Build Coastguard Worker     // Fetch the device info if the user has requested it
826*ba62d9d3SAndroid Build Coastguard Worker     if (fetch_deviceinfo) {
827*ba62d9d3SAndroid Build Coastguard Worker         addr += sizeof(drmPciBusInfo);
828*ba62d9d3SAndroid Build Coastguard Worker         dev->deviceinfo.pci = (drmPciDeviceInfoPtr)addr;
829*ba62d9d3SAndroid Build Coastguard Worker         ret = drmParsePciDeviceInfo(maj, min, dev->deviceinfo.pci, flags);
830*ba62d9d3SAndroid Build Coastguard Worker 
831*ba62d9d3SAndroid Build Coastguard Worker         if (ret)
832*ba62d9d3SAndroid Build Coastguard Worker             goto free_device;
833*ba62d9d3SAndroid Build Coastguard Worker     }
834*ba62d9d3SAndroid Build Coastguard Worker 
835*ba62d9d3SAndroid Build Coastguard Worker     *device = dev;
836*ba62d9d3SAndroid Build Coastguard Worker 
837*ba62d9d3SAndroid Build Coastguard Worker     return 0;
838*ba62d9d3SAndroid Build Coastguard Worker 
839*ba62d9d3SAndroid Build Coastguard Worker free_device:
840*ba62d9d3SAndroid Build Coastguard Worker     free(dev);
841*ba62d9d3SAndroid Build Coastguard Worker     return ret;
842*ba62d9d3SAndroid Build Coastguard Worker }
843*ba62d9d3SAndroid Build Coastguard Worker 
drmParseUsbBusInfo(int maj,int min,drmUsbBusInfoPtr info)844*ba62d9d3SAndroid Build Coastguard Worker static int drmParseUsbBusInfo(int maj, int min, drmUsbBusInfoPtr info)
845*ba62d9d3SAndroid Build Coastguard Worker {
846*ba62d9d3SAndroid Build Coastguard Worker     char path[PATH_MAX + 1], *value;
847*ba62d9d3SAndroid Build Coastguard Worker     unsigned int bus, dev;
848*ba62d9d3SAndroid Build Coastguard Worker     int ret;
849*ba62d9d3SAndroid Build Coastguard Worker 
850*ba62d9d3SAndroid Build Coastguard Worker     snprintf(path, sizeof(path), "/sys/dev/char/%d:%d/device", maj, min);
851*ba62d9d3SAndroid Build Coastguard Worker     value = sysfs_uevent_get(path, "BUSNUM");
852*ba62d9d3SAndroid Build Coastguard Worker     if (!value)
853*ba62d9d3SAndroid Build Coastguard Worker         return -ENOENT;
854*ba62d9d3SAndroid Build Coastguard Worker 
855*ba62d9d3SAndroid Build Coastguard Worker     ret = sscanf(value, "%03u", &bus);
856*ba62d9d3SAndroid Build Coastguard Worker     free(value);
857*ba62d9d3SAndroid Build Coastguard Worker 
858*ba62d9d3SAndroid Build Coastguard Worker     if (ret <= 0)
859*ba62d9d3SAndroid Build Coastguard Worker         return -errno;
860*ba62d9d3SAndroid Build Coastguard Worker 
861*ba62d9d3SAndroid Build Coastguard Worker     value = sysfs_uevent_get(path, "DEVNUM");
862*ba62d9d3SAndroid Build Coastguard Worker     if (!value)
863*ba62d9d3SAndroid Build Coastguard Worker         return -ENOENT;
864*ba62d9d3SAndroid Build Coastguard Worker 
865*ba62d9d3SAndroid Build Coastguard Worker     ret = sscanf(value, "%03u", &dev);
866*ba62d9d3SAndroid Build Coastguard Worker     free(value);
867*ba62d9d3SAndroid Build Coastguard Worker 
868*ba62d9d3SAndroid Build Coastguard Worker     if (ret <= 0)
869*ba62d9d3SAndroid Build Coastguard Worker         return -errno;
870*ba62d9d3SAndroid Build Coastguard Worker 
871*ba62d9d3SAndroid Build Coastguard Worker     info->bus = bus;
872*ba62d9d3SAndroid Build Coastguard Worker     info->dev = dev;
873*ba62d9d3SAndroid Build Coastguard Worker     return 0;
874*ba62d9d3SAndroid Build Coastguard Worker }
875*ba62d9d3SAndroid Build Coastguard Worker 
drmParseUsbDeviceInfo(int maj,int min,drmUsbDeviceInfoPtr info)876*ba62d9d3SAndroid Build Coastguard Worker static int drmParseUsbDeviceInfo(int maj, int min, drmUsbDeviceInfoPtr info)
877*ba62d9d3SAndroid Build Coastguard Worker {
878*ba62d9d3SAndroid Build Coastguard Worker     char path[PATH_MAX + 1], *value;
879*ba62d9d3SAndroid Build Coastguard Worker     unsigned int vendor, product;
880*ba62d9d3SAndroid Build Coastguard Worker     int ret;
881*ba62d9d3SAndroid Build Coastguard Worker 
882*ba62d9d3SAndroid Build Coastguard Worker     snprintf(path, sizeof(path), "/sys/dev/char/%d:%d/device", maj, min);
883*ba62d9d3SAndroid Build Coastguard Worker     value = sysfs_uevent_get(path, "PRODUCT");
884*ba62d9d3SAndroid Build Coastguard Worker     if (!value)
885*ba62d9d3SAndroid Build Coastguard Worker         return -ENOENT;
886*ba62d9d3SAndroid Build Coastguard Worker 
887*ba62d9d3SAndroid Build Coastguard Worker     ret = sscanf(value, "%x/%x", &vendor, &product);
888*ba62d9d3SAndroid Build Coastguard Worker     free(value);
889*ba62d9d3SAndroid Build Coastguard Worker 
890*ba62d9d3SAndroid Build Coastguard Worker     if (ret <= 0)
891*ba62d9d3SAndroid Build Coastguard Worker         return -errno;
892*ba62d9d3SAndroid Build Coastguard Worker 
893*ba62d9d3SAndroid Build Coastguard Worker     info->vendor = vendor;
894*ba62d9d3SAndroid Build Coastguard Worker     info->product = product;
895*ba62d9d3SAndroid Build Coastguard Worker     return 0;
896*ba62d9d3SAndroid Build Coastguard Worker }
897*ba62d9d3SAndroid Build Coastguard Worker 
drmProcessUsbDevice(drmDevicePtr * device,const char * node,int node_type,int maj,int min,bool fetch_deviceinfo,uint32_t flags)898*ba62d9d3SAndroid Build Coastguard Worker static int drmProcessUsbDevice(drmDevicePtr *device, const char *node,
899*ba62d9d3SAndroid Build Coastguard Worker     int node_type, int maj, int min,
900*ba62d9d3SAndroid Build Coastguard Worker     bool fetch_deviceinfo, uint32_t flags)
901*ba62d9d3SAndroid Build Coastguard Worker {
902*ba62d9d3SAndroid Build Coastguard Worker     drmDevicePtr dev;
903*ba62d9d3SAndroid Build Coastguard Worker     char *ptr;
904*ba62d9d3SAndroid Build Coastguard Worker     int ret;
905*ba62d9d3SAndroid Build Coastguard Worker 
906*ba62d9d3SAndroid Build Coastguard Worker     dev = drmDeviceAlloc(node_type, node, sizeof(drmUsbBusInfo),
907*ba62d9d3SAndroid Build Coastguard Worker         sizeof(drmUsbDeviceInfo), &ptr);
908*ba62d9d3SAndroid Build Coastguard Worker     if (!dev)
909*ba62d9d3SAndroid Build Coastguard Worker         return -ENOMEM;
910*ba62d9d3SAndroid Build Coastguard Worker 
911*ba62d9d3SAndroid Build Coastguard Worker     dev->bustype = DRM_BUS_USB;
912*ba62d9d3SAndroid Build Coastguard Worker 
913*ba62d9d3SAndroid Build Coastguard Worker     dev->businfo.usb = (drmUsbBusInfoPtr)ptr;
914*ba62d9d3SAndroid Build Coastguard Worker 
915*ba62d9d3SAndroid Build Coastguard Worker     ret = drmParseUsbBusInfo(maj, min, dev->businfo.usb);
916*ba62d9d3SAndroid Build Coastguard Worker     if (ret < 0)
917*ba62d9d3SAndroid Build Coastguard Worker         goto free_device;
918*ba62d9d3SAndroid Build Coastguard Worker 
919*ba62d9d3SAndroid Build Coastguard Worker     if (fetch_deviceinfo) {
920*ba62d9d3SAndroid Build Coastguard Worker         ptr += sizeof(drmUsbBusInfo);
921*ba62d9d3SAndroid Build Coastguard Worker         dev->deviceinfo.usb = (drmUsbDeviceInfoPtr)ptr;
922*ba62d9d3SAndroid Build Coastguard Worker 
923*ba62d9d3SAndroid Build Coastguard Worker         ret = drmParseUsbDeviceInfo(maj, min, dev->deviceinfo.usb);
924*ba62d9d3SAndroid Build Coastguard Worker         if (ret < 0)
925*ba62d9d3SAndroid Build Coastguard Worker             goto free_device;
926*ba62d9d3SAndroid Build Coastguard Worker     }
927*ba62d9d3SAndroid Build Coastguard Worker 
928*ba62d9d3SAndroid Build Coastguard Worker     *device = dev;
929*ba62d9d3SAndroid Build Coastguard Worker 
930*ba62d9d3SAndroid Build Coastguard Worker     return 0;
931*ba62d9d3SAndroid Build Coastguard Worker 
932*ba62d9d3SAndroid Build Coastguard Worker free_device:
933*ba62d9d3SAndroid Build Coastguard Worker     free(dev);
934*ba62d9d3SAndroid Build Coastguard Worker     return ret;
935*ba62d9d3SAndroid Build Coastguard Worker }
936*ba62d9d3SAndroid Build Coastguard Worker 
937*ba62d9d3SAndroid Build Coastguard Worker 
drmParseSubsystemType(int maj,int min)938*ba62d9d3SAndroid Build Coastguard Worker static int drmParseSubsystemType(int maj, int min)
939*ba62d9d3SAndroid Build Coastguard Worker {
940*ba62d9d3SAndroid Build Coastguard Worker #ifdef __linux__
941*ba62d9d3SAndroid Build Coastguard Worker     char path[PATH_MAX + 1];
942*ba62d9d3SAndroid Build Coastguard Worker     char link[PATH_MAX + 1] = "";
943*ba62d9d3SAndroid Build Coastguard Worker     char *name;
944*ba62d9d3SAndroid Build Coastguard Worker     struct {
945*ba62d9d3SAndroid Build Coastguard Worker         const char *name;
946*ba62d9d3SAndroid Build Coastguard Worker         int bus_type;
947*ba62d9d3SAndroid Build Coastguard Worker     } bus_types[] = {
948*ba62d9d3SAndroid Build Coastguard Worker         { "/pci", DRM_BUS_PCI },
949*ba62d9d3SAndroid Build Coastguard Worker     { "/usb", DRM_BUS_USB },
950*ba62d9d3SAndroid Build Coastguard Worker     { "/platform", DRM_BUS_PLATFORM },
951*ba62d9d3SAndroid Build Coastguard Worker     { "/spi", DRM_BUS_PLATFORM },
952*ba62d9d3SAndroid Build Coastguard Worker     { "/host1x", DRM_BUS_HOST1X },
953*ba62d9d3SAndroid Build Coastguard Worker     { "/virtio", DRM_BUS_VIRTIO },
954*ba62d9d3SAndroid Build Coastguard Worker     };
955*ba62d9d3SAndroid Build Coastguard Worker 
956*ba62d9d3SAndroid Build Coastguard Worker     snprintf(path, PATH_MAX, "/sys/dev/char/%d:%d/device/subsystem",
957*ba62d9d3SAndroid Build Coastguard Worker         maj, min);
958*ba62d9d3SAndroid Build Coastguard Worker 
959*ba62d9d3SAndroid Build Coastguard Worker     memset(link, 0, sizeof(link));
960*ba62d9d3SAndroid Build Coastguard Worker     if (readlink(path, link, PATH_MAX) < 0)
961*ba62d9d3SAndroid Build Coastguard Worker         return -errno;
962*ba62d9d3SAndroid Build Coastguard Worker 
963*ba62d9d3SAndroid Build Coastguard Worker     name = strrchr(link, '/');
964*ba62d9d3SAndroid Build Coastguard Worker     if (!name)
965*ba62d9d3SAndroid Build Coastguard Worker         return -EINVAL;
966*ba62d9d3SAndroid Build Coastguard Worker 
967*ba62d9d3SAndroid Build Coastguard Worker     for (unsigned i = 0; i < ARRAY_SIZE(bus_types); i++) {
968*ba62d9d3SAndroid Build Coastguard Worker         if (strncmp(name, bus_types[i].name, strlen(bus_types[i].name)) == 0)
969*ba62d9d3SAndroid Build Coastguard Worker             return bus_types[i].bus_type;
970*ba62d9d3SAndroid Build Coastguard Worker     }
971*ba62d9d3SAndroid Build Coastguard Worker 
972*ba62d9d3SAndroid Build Coastguard Worker     return -EINVAL;
973*ba62d9d3SAndroid Build Coastguard Worker #elif defined(__OpenBSD__) || defined(__DragonFly__)
974*ba62d9d3SAndroid Build Coastguard Worker     return DRM_BUS_PCI;
975*ba62d9d3SAndroid Build Coastguard Worker #else
976*ba62d9d3SAndroid Build Coastguard Worker     #warning "Missing implementation of drmParseSubsystemType"
977*ba62d9d3SAndroid Build Coastguard Worker         return -EINVAL;
978*ba62d9d3SAndroid Build Coastguard Worker #endif
979*ba62d9d3SAndroid Build Coastguard Worker }
980*ba62d9d3SAndroid Build Coastguard Worker 
drmFreePlatformDevice(drmDevicePtr device)981*ba62d9d3SAndroid Build Coastguard Worker static void drmFreePlatformDevice(drmDevicePtr device)
982*ba62d9d3SAndroid Build Coastguard Worker {
983*ba62d9d3SAndroid Build Coastguard Worker     if (device->deviceinfo.platform) {
984*ba62d9d3SAndroid Build Coastguard Worker         if (device->deviceinfo.platform->compatible) {
985*ba62d9d3SAndroid Build Coastguard Worker             char **compatible = device->deviceinfo.platform->compatible;
986*ba62d9d3SAndroid Build Coastguard Worker 
987*ba62d9d3SAndroid Build Coastguard Worker             while (*compatible) {
988*ba62d9d3SAndroid Build Coastguard Worker                 free(*compatible);
989*ba62d9d3SAndroid Build Coastguard Worker                 compatible++;
990*ba62d9d3SAndroid Build Coastguard Worker             }
991*ba62d9d3SAndroid Build Coastguard Worker 
992*ba62d9d3SAndroid Build Coastguard Worker             free(device->deviceinfo.platform->compatible);
993*ba62d9d3SAndroid Build Coastguard Worker         }
994*ba62d9d3SAndroid Build Coastguard Worker     }
995*ba62d9d3SAndroid Build Coastguard Worker }
996*ba62d9d3SAndroid Build Coastguard Worker 
drmFreeHost1xDevice(drmDevicePtr device)997*ba62d9d3SAndroid Build Coastguard Worker static void drmFreeHost1xDevice(drmDevicePtr device)
998*ba62d9d3SAndroid Build Coastguard Worker {
999*ba62d9d3SAndroid Build Coastguard Worker     if (device->deviceinfo.host1x) {
1000*ba62d9d3SAndroid Build Coastguard Worker         if (device->deviceinfo.host1x->compatible) {
1001*ba62d9d3SAndroid Build Coastguard Worker             char **compatible = device->deviceinfo.host1x->compatible;
1002*ba62d9d3SAndroid Build Coastguard Worker 
1003*ba62d9d3SAndroid Build Coastguard Worker             while (*compatible) {
1004*ba62d9d3SAndroid Build Coastguard Worker                 free(*compatible);
1005*ba62d9d3SAndroid Build Coastguard Worker                 compatible++;
1006*ba62d9d3SAndroid Build Coastguard Worker             }
1007*ba62d9d3SAndroid Build Coastguard Worker 
1008*ba62d9d3SAndroid Build Coastguard Worker             free(device->deviceinfo.host1x->compatible);
1009*ba62d9d3SAndroid Build Coastguard Worker         }
1010*ba62d9d3SAndroid Build Coastguard Worker     }
1011*ba62d9d3SAndroid Build Coastguard Worker }
1012*ba62d9d3SAndroid Build Coastguard Worker 
drmGetNodeType(const char * name)1013*ba62d9d3SAndroid Build Coastguard Worker static int drmGetNodeType(const char *name)
1014*ba62d9d3SAndroid Build Coastguard Worker {
1015*ba62d9d3SAndroid Build Coastguard Worker     if (strncmp(name, DRM_PRIMARY_MINOR_NAME,
1016*ba62d9d3SAndroid Build Coastguard Worker         sizeof(DRM_PRIMARY_MINOR_NAME) - 1) == 0)
1017*ba62d9d3SAndroid Build Coastguard Worker         return DRM_NODE_PRIMARY;
1018*ba62d9d3SAndroid Build Coastguard Worker 
1019*ba62d9d3SAndroid Build Coastguard Worker     if (strncmp(name, DRM_CONTROL_MINOR_NAME,
1020*ba62d9d3SAndroid Build Coastguard Worker         sizeof(DRM_CONTROL_MINOR_NAME) - 1) == 0)
1021*ba62d9d3SAndroid Build Coastguard Worker         return DRM_NODE_CONTROL;
1022*ba62d9d3SAndroid Build Coastguard Worker 
1023*ba62d9d3SAndroid Build Coastguard Worker     if (strncmp(name, DRM_RENDER_MINOR_NAME,
1024*ba62d9d3SAndroid Build Coastguard Worker         sizeof(DRM_RENDER_MINOR_NAME) - 1) == 0)
1025*ba62d9d3SAndroid Build Coastguard Worker         return DRM_NODE_RENDER;
1026*ba62d9d3SAndroid Build Coastguard Worker 
1027*ba62d9d3SAndroid Build Coastguard Worker     return -EINVAL;
1028*ba62d9d3SAndroid Build Coastguard Worker }
1029*ba62d9d3SAndroid Build Coastguard Worker 
drmFreeDevice(drmDevicePtr * device)1030*ba62d9d3SAndroid Build Coastguard Worker void drmFreeDevice(drmDevicePtr *device)
1031*ba62d9d3SAndroid Build Coastguard Worker {
1032*ba62d9d3SAndroid Build Coastguard Worker     if (device == NULL)
1033*ba62d9d3SAndroid Build Coastguard Worker         return;
1034*ba62d9d3SAndroid Build Coastguard Worker 
1035*ba62d9d3SAndroid Build Coastguard Worker     if (*device) {
1036*ba62d9d3SAndroid Build Coastguard Worker         switch ((*device)->bustype) {
1037*ba62d9d3SAndroid Build Coastguard Worker         case DRM_BUS_PLATFORM:
1038*ba62d9d3SAndroid Build Coastguard Worker             drmFreePlatformDevice(*device);
1039*ba62d9d3SAndroid Build Coastguard Worker             break;
1040*ba62d9d3SAndroid Build Coastguard Worker 
1041*ba62d9d3SAndroid Build Coastguard Worker         case DRM_BUS_HOST1X:
1042*ba62d9d3SAndroid Build Coastguard Worker             drmFreeHost1xDevice(*device);
1043*ba62d9d3SAndroid Build Coastguard Worker             break;
1044*ba62d9d3SAndroid Build Coastguard Worker         }
1045*ba62d9d3SAndroid Build Coastguard Worker     }
1046*ba62d9d3SAndroid Build Coastguard Worker 
1047*ba62d9d3SAndroid Build Coastguard Worker     free(*device);
1048*ba62d9d3SAndroid Build Coastguard Worker     *device = NULL;
1049*ba62d9d3SAndroid Build Coastguard Worker }
1050*ba62d9d3SAndroid Build Coastguard Worker 
1051*ba62d9d3SAndroid Build Coastguard Worker static int
process_device(drmDevicePtr * device,const char * d_name,int req_subsystem_type,bool fetch_deviceinfo,uint32_t flags)1052*ba62d9d3SAndroid Build Coastguard Worker process_device(drmDevicePtr *device, const char *d_name,
1053*ba62d9d3SAndroid Build Coastguard Worker     int req_subsystem_type,
1054*ba62d9d3SAndroid Build Coastguard Worker     bool fetch_deviceinfo, uint32_t flags)
1055*ba62d9d3SAndroid Build Coastguard Worker {
1056*ba62d9d3SAndroid Build Coastguard Worker     struct stat sbuf;
1057*ba62d9d3SAndroid Build Coastguard Worker     char node[PATH_MAX + 1];
1058*ba62d9d3SAndroid Build Coastguard Worker     int node_type, subsystem_type;
1059*ba62d9d3SAndroid Build Coastguard Worker     unsigned int maj, min;
1060*ba62d9d3SAndroid Build Coastguard Worker 
1061*ba62d9d3SAndroid Build Coastguard Worker     node_type = drmGetNodeType(d_name);
1062*ba62d9d3SAndroid Build Coastguard Worker     if (node_type < 0)
1063*ba62d9d3SAndroid Build Coastguard Worker         return -1;
1064*ba62d9d3SAndroid Build Coastguard Worker 
1065*ba62d9d3SAndroid Build Coastguard Worker     snprintf(node, PATH_MAX, "%s/%s", DRM_DIR_NAME, d_name);
1066*ba62d9d3SAndroid Build Coastguard Worker 
1067*ba62d9d3SAndroid Build Coastguard Worker     if (stat(node, &sbuf))
1068*ba62d9d3SAndroid Build Coastguard Worker         return -1;
1069*ba62d9d3SAndroid Build Coastguard Worker 
1070*ba62d9d3SAndroid Build Coastguard Worker     maj = major(sbuf.st_rdev);
1071*ba62d9d3SAndroid Build Coastguard Worker     min = minor(sbuf.st_rdev);
1072*ba62d9d3SAndroid Build Coastguard Worker 
1073*ba62d9d3SAndroid Build Coastguard Worker     if (!drmNodeIsDRM(maj, min) || !S_ISCHR(sbuf.st_mode))
1074*ba62d9d3SAndroid Build Coastguard Worker     {
1075*ba62d9d3SAndroid Build Coastguard Worker         return -1;
1076*ba62d9d3SAndroid Build Coastguard Worker     }
1077*ba62d9d3SAndroid Build Coastguard Worker 
1078*ba62d9d3SAndroid Build Coastguard Worker     subsystem_type = drmParseSubsystemType(maj, min);
1079*ba62d9d3SAndroid Build Coastguard Worker 
1080*ba62d9d3SAndroid Build Coastguard Worker     if (req_subsystem_type != -1 && req_subsystem_type != subsystem_type)
1081*ba62d9d3SAndroid Build Coastguard Worker         return -1;
1082*ba62d9d3SAndroid Build Coastguard Worker 
1083*ba62d9d3SAndroid Build Coastguard Worker     switch (subsystem_type) {
1084*ba62d9d3SAndroid Build Coastguard Worker     case DRM_BUS_PCI:
1085*ba62d9d3SAndroid Build Coastguard Worker     case DRM_BUS_VIRTIO:
1086*ba62d9d3SAndroid Build Coastguard Worker         return drmProcessPciDevice(device, node, node_type, maj, min,
1087*ba62d9d3SAndroid Build Coastguard Worker             fetch_deviceinfo, flags);
1088*ba62d9d3SAndroid Build Coastguard Worker     case DRM_BUS_USB:
1089*ba62d9d3SAndroid Build Coastguard Worker         return drmProcessUsbDevice(device, node, node_type, maj, min,
1090*ba62d9d3SAndroid Build Coastguard Worker             fetch_deviceinfo, flags);
1091*ba62d9d3SAndroid Build Coastguard Worker     case DRM_BUS_PLATFORM:
1092*ba62d9d3SAndroid Build Coastguard Worker         return drmProcessPlatformDevice(device, node, node_type, maj, min,
1093*ba62d9d3SAndroid Build Coastguard Worker             fetch_deviceinfo, flags);
1094*ba62d9d3SAndroid Build Coastguard Worker     case DRM_BUS_HOST1X:
1095*ba62d9d3SAndroid Build Coastguard Worker         return drmProcessHost1xDevice(device, node, node_type, maj, min,
1096*ba62d9d3SAndroid Build Coastguard Worker             fetch_deviceinfo, flags);
1097*ba62d9d3SAndroid Build Coastguard Worker     default:
1098*ba62d9d3SAndroid Build Coastguard Worker         return -1;
1099*ba62d9d3SAndroid Build Coastguard Worker     }
1100*ba62d9d3SAndroid Build Coastguard Worker }
1101*ba62d9d3SAndroid Build Coastguard Worker 
1102*ba62d9d3SAndroid Build Coastguard Worker /* Consider devices located on the same bus as duplicate and fold the respective
1103*ba62d9d3SAndroid Build Coastguard Worker * entries into a single one.
1104*ba62d9d3SAndroid Build Coastguard Worker *
1105*ba62d9d3SAndroid Build Coastguard Worker * Note: this leaves "gaps" in the array, while preserving the length.
1106*ba62d9d3SAndroid Build Coastguard Worker */
drmFoldDuplicatedDevices(drmDevicePtr local_devices[],int count)1107*ba62d9d3SAndroid Build Coastguard Worker static void drmFoldDuplicatedDevices(drmDevicePtr local_devices[], int count)
1108*ba62d9d3SAndroid Build Coastguard Worker {
1109*ba62d9d3SAndroid Build Coastguard Worker     int node_type, i, j;
1110*ba62d9d3SAndroid Build Coastguard Worker 
1111*ba62d9d3SAndroid Build Coastguard Worker     for (i = 0; i < count; i++) {
1112*ba62d9d3SAndroid Build Coastguard Worker         for (j = i + 1; j < count; j++) {
1113*ba62d9d3SAndroid Build Coastguard Worker             if (drmDevicesEqual(local_devices[i], local_devices[j])) {
1114*ba62d9d3SAndroid Build Coastguard Worker                 local_devices[i]->available_nodes |= local_devices[j]->available_nodes;
1115*ba62d9d3SAndroid Build Coastguard Worker                 node_type = log2(local_devices[j]->available_nodes);
1116*ba62d9d3SAndroid Build Coastguard Worker                 memcpy(local_devices[i]->nodes[node_type],
1117*ba62d9d3SAndroid Build Coastguard Worker                     local_devices[j]->nodes[node_type], drmGetMaxNodeName());
1118*ba62d9d3SAndroid Build Coastguard Worker                 drmFreeDevice(&local_devices[j]);
1119*ba62d9d3SAndroid Build Coastguard Worker             }
1120*ba62d9d3SAndroid Build Coastguard Worker         }
1121*ba62d9d3SAndroid Build Coastguard Worker     }
1122*ba62d9d3SAndroid Build Coastguard Worker }
1123*ba62d9d3SAndroid Build Coastguard Worker 
1124*ba62d9d3SAndroid Build Coastguard Worker /**
1125*ba62d9d3SAndroid Build Coastguard Worker  * Get drm devices on the system
1126*ba62d9d3SAndroid Build Coastguard Worker  *
1127*ba62d9d3SAndroid Build Coastguard Worker  * \param flags feature/behaviour bitmask
1128*ba62d9d3SAndroid Build Coastguard Worker  * \param devices the array of devices with drmDevicePtr elements
1129*ba62d9d3SAndroid Build Coastguard Worker  *                can be NULL to get the device number first
1130*ba62d9d3SAndroid Build Coastguard Worker  * \param max_devices the maximum number of devices for the array
1131*ba62d9d3SAndroid Build Coastguard Worker  *
1132*ba62d9d3SAndroid Build Coastguard Worker  * \return on error - negative error code,
1133*ba62d9d3SAndroid Build Coastguard Worker  *         if devices is NULL - total number of devices available on the system,
1134*ba62d9d3SAndroid Build Coastguard Worker  *         alternatively the number of devices stored in devices[], which is
1135*ba62d9d3SAndroid Build Coastguard Worker  *         capped by the max_devices.
1136*ba62d9d3SAndroid Build Coastguard Worker  *
1137*ba62d9d3SAndroid Build Coastguard Worker  * \note Unlike drmGetDevices it does not retrieve the pci device revision field
1138*ba62d9d3SAndroid Build Coastguard Worker  * unless the DRM_DEVICE_GET_PCI_REVISION \p flag is set.
1139*ba62d9d3SAndroid Build Coastguard Worker  */
drmGetDevices2(uint32_t flags,drmDevicePtr devices[],int max_devices)1140*ba62d9d3SAndroid Build Coastguard Worker int drmGetDevices2(uint32_t flags, drmDevicePtr devices[],
1141*ba62d9d3SAndroid Build Coastguard Worker                               int max_devices)
1142*ba62d9d3SAndroid Build Coastguard Worker {
1143*ba62d9d3SAndroid Build Coastguard Worker     drmDevicePtr local_devices[MAX_DRM_NODES];
1144*ba62d9d3SAndroid Build Coastguard Worker     drmDevicePtr device;
1145*ba62d9d3SAndroid Build Coastguard Worker     DIR *sysdir;
1146*ba62d9d3SAndroid Build Coastguard Worker     struct dirent *dent;
1147*ba62d9d3SAndroid Build Coastguard Worker     int ret, i, node_count, device_count;
1148*ba62d9d3SAndroid Build Coastguard Worker 
1149*ba62d9d3SAndroid Build Coastguard Worker     if (drm_device_validate_flags(flags))
1150*ba62d9d3SAndroid Build Coastguard Worker         return -EINVAL;
1151*ba62d9d3SAndroid Build Coastguard Worker 
1152*ba62d9d3SAndroid Build Coastguard Worker     sysdir = opendir(DRM_DIR_NAME);
1153*ba62d9d3SAndroid Build Coastguard Worker     if (!sysdir)
1154*ba62d9d3SAndroid Build Coastguard Worker         return -errno;
1155*ba62d9d3SAndroid Build Coastguard Worker 
1156*ba62d9d3SAndroid Build Coastguard Worker     i = 0;
1157*ba62d9d3SAndroid Build Coastguard Worker     while ((dent = readdir(sysdir))) {
1158*ba62d9d3SAndroid Build Coastguard Worker         ret = process_device(&device, dent->d_name, -1, devices != NULL, flags);
1159*ba62d9d3SAndroid Build Coastguard Worker         if (ret)
1160*ba62d9d3SAndroid Build Coastguard Worker             continue;
1161*ba62d9d3SAndroid Build Coastguard Worker 
1162*ba62d9d3SAndroid Build Coastguard Worker         if (i >= MAX_DRM_NODES) {
1163*ba62d9d3SAndroid Build Coastguard Worker             fprintf(stderr, "More than %d drm nodes detected. "
1164*ba62d9d3SAndroid Build Coastguard Worker                     "Please report  - that should not happen.\n"
1165*ba62d9d3SAndroid Build Coastguard Worker                     "Skipping extra nodes\n", MAX_DRM_NODES);
1166*ba62d9d3SAndroid Build Coastguard Worker             break;
1167*ba62d9d3SAndroid Build Coastguard Worker         }
1168*ba62d9d3SAndroid Build Coastguard Worker         local_devices[i] = device;
1169*ba62d9d3SAndroid Build Coastguard Worker         i++;
1170*ba62d9d3SAndroid Build Coastguard Worker     }
1171*ba62d9d3SAndroid Build Coastguard Worker     node_count = i;
1172*ba62d9d3SAndroid Build Coastguard Worker     drmFoldDuplicatedDevices(local_devices, node_count);
1173*ba62d9d3SAndroid Build Coastguard Worker 
1174*ba62d9d3SAndroid Build Coastguard Worker     device_count = 0;
1175*ba62d9d3SAndroid Build Coastguard Worker     for (i = 0; i < node_count; i++) {
1176*ba62d9d3SAndroid Build Coastguard Worker         if (!local_devices[i])
1177*ba62d9d3SAndroid Build Coastguard Worker             continue;
1178*ba62d9d3SAndroid Build Coastguard Worker 
1179*ba62d9d3SAndroid Build Coastguard Worker         if ((devices != NULL) && (device_count < max_devices))
1180*ba62d9d3SAndroid Build Coastguard Worker             devices[device_count] = local_devices[i];
1181*ba62d9d3SAndroid Build Coastguard Worker         else
1182*ba62d9d3SAndroid Build Coastguard Worker             drmFreeDevice(&local_devices[i]);
1183*ba62d9d3SAndroid Build Coastguard Worker 
1184*ba62d9d3SAndroid Build Coastguard Worker         device_count++;
1185*ba62d9d3SAndroid Build Coastguard Worker     }
1186*ba62d9d3SAndroid Build Coastguard Worker 
1187*ba62d9d3SAndroid Build Coastguard Worker     closedir(sysdir);
1188*ba62d9d3SAndroid Build Coastguard Worker     return device_count;
1189*ba62d9d3SAndroid Build Coastguard Worker }
1190*ba62d9d3SAndroid Build Coastguard Worker 
1191*ba62d9d3SAndroid Build Coastguard Worker /**
1192*ba62d9d3SAndroid Build Coastguard Worker  * Get drm devices on the system
1193*ba62d9d3SAndroid Build Coastguard Worker  *
1194*ba62d9d3SAndroid Build Coastguard Worker  * \param devices the array of devices with drmDevicePtr elements
1195*ba62d9d3SAndroid Build Coastguard Worker  *                can be NULL to get the device number first
1196*ba62d9d3SAndroid Build Coastguard Worker  * \param max_devices the maximum number of devices for the array
1197*ba62d9d3SAndroid Build Coastguard Worker  *
1198*ba62d9d3SAndroid Build Coastguard Worker  * \return on error - negative error code,
1199*ba62d9d3SAndroid Build Coastguard Worker  *         if devices is NULL - total number of devices available on the system,
1200*ba62d9d3SAndroid Build Coastguard Worker  *         alternatively the number of devices stored in devices[], which is
1201*ba62d9d3SAndroid Build Coastguard Worker  *         capped by the max_devices.
1202*ba62d9d3SAndroid Build Coastguard Worker  */
drmGetDevices(drmDevicePtr devices[],int max_devices)1203*ba62d9d3SAndroid Build Coastguard Worker int drmGetDevices(drmDevicePtr devices[], int max_devices)
1204*ba62d9d3SAndroid Build Coastguard Worker {
1205*ba62d9d3SAndroid Build Coastguard Worker     return drmGetDevices2(DRM_DEVICE_GET_PCI_REVISION, devices, max_devices);
1206*ba62d9d3SAndroid Build Coastguard Worker }
1207*ba62d9d3SAndroid Build Coastguard Worker 
1208*ba62d9d3SAndroid Build Coastguard Worker /**
1209*ba62d9d3SAndroid Build Coastguard Worker  * Get information about the opened drm device
1210*ba62d9d3SAndroid Build Coastguard Worker  *
1211*ba62d9d3SAndroid Build Coastguard Worker  * \param fd file descriptor of the drm device
1212*ba62d9d3SAndroid Build Coastguard Worker  * \param flags feature/behaviour bitmask
1213*ba62d9d3SAndroid Build Coastguard Worker  * \param device the address of a drmDevicePtr where the information
1214*ba62d9d3SAndroid Build Coastguard Worker  *               will be allocated in stored
1215*ba62d9d3SAndroid Build Coastguard Worker  *
1216*ba62d9d3SAndroid Build Coastguard Worker  * \return zero on success, negative error code otherwise.
1217*ba62d9d3SAndroid Build Coastguard Worker  *
1218*ba62d9d3SAndroid Build Coastguard Worker  * \note Unlike drmGetDevice it does not retrieve the pci device revision field
1219*ba62d9d3SAndroid Build Coastguard Worker  * unless the DRM_DEVICE_GET_PCI_REVISION \p flag is set.
1220*ba62d9d3SAndroid Build Coastguard Worker  */
drmGetDevice2(int fd,uint32_t flags,drmDevicePtr * device)1221*ba62d9d3SAndroid Build Coastguard Worker int drmGetDevice2(int fd, uint32_t flags, drmDevicePtr *device)
1222*ba62d9d3SAndroid Build Coastguard Worker {
1223*ba62d9d3SAndroid Build Coastguard Worker     drmDevicePtr local_devices[MAX_DRM_NODES];
1224*ba62d9d3SAndroid Build Coastguard Worker     drmDevicePtr d;
1225*ba62d9d3SAndroid Build Coastguard Worker     DIR *sysdir;
1226*ba62d9d3SAndroid Build Coastguard Worker     struct dirent *dent;
1227*ba62d9d3SAndroid Build Coastguard Worker     struct stat sbuf;
1228*ba62d9d3SAndroid Build Coastguard Worker     int subsystem_type;
1229*ba62d9d3SAndroid Build Coastguard Worker     int maj, min;
1230*ba62d9d3SAndroid Build Coastguard Worker     int ret, i, node_count;
1231*ba62d9d3SAndroid Build Coastguard Worker     dev_t find_rdev;
1232*ba62d9d3SAndroid Build Coastguard Worker 
1233*ba62d9d3SAndroid Build Coastguard Worker     if (drm_device_validate_flags(flags))
1234*ba62d9d3SAndroid Build Coastguard Worker         return -EINVAL;
1235*ba62d9d3SAndroid Build Coastguard Worker 
1236*ba62d9d3SAndroid Build Coastguard Worker     if (fd == -1 || device == NULL)
1237*ba62d9d3SAndroid Build Coastguard Worker         return -EINVAL;
1238*ba62d9d3SAndroid Build Coastguard Worker 
1239*ba62d9d3SAndroid Build Coastguard Worker     if (fstat(fd, &sbuf))
1240*ba62d9d3SAndroid Build Coastguard Worker         return -errno;
1241*ba62d9d3SAndroid Build Coastguard Worker 
1242*ba62d9d3SAndroid Build Coastguard Worker     find_rdev = sbuf.st_rdev;
1243*ba62d9d3SAndroid Build Coastguard Worker     maj = major(sbuf.st_rdev);
1244*ba62d9d3SAndroid Build Coastguard Worker     min = minor(sbuf.st_rdev);
1245*ba62d9d3SAndroid Build Coastguard Worker 
1246*ba62d9d3SAndroid Build Coastguard Worker     if (!drmNodeIsDRM(maj, min) || !S_ISCHR(sbuf.st_mode))
1247*ba62d9d3SAndroid Build Coastguard Worker         return -EINVAL;
1248*ba62d9d3SAndroid Build Coastguard Worker 
1249*ba62d9d3SAndroid Build Coastguard Worker     subsystem_type = drmParseSubsystemType(maj, min);
1250*ba62d9d3SAndroid Build Coastguard Worker     if (subsystem_type < 0)
1251*ba62d9d3SAndroid Build Coastguard Worker         return subsystem_type;
1252*ba62d9d3SAndroid Build Coastguard Worker 
1253*ba62d9d3SAndroid Build Coastguard Worker     sysdir = opendir(DRM_DIR_NAME);
1254*ba62d9d3SAndroid Build Coastguard Worker     if (!sysdir)
1255*ba62d9d3SAndroid Build Coastguard Worker         return -errno;
1256*ba62d9d3SAndroid Build Coastguard Worker 
1257*ba62d9d3SAndroid Build Coastguard Worker     i = 0;
1258*ba62d9d3SAndroid Build Coastguard Worker     while ((dent = readdir(sysdir))) {
1259*ba62d9d3SAndroid Build Coastguard Worker         ret = process_device(&d, dent->d_name, subsystem_type, true, flags);
1260*ba62d9d3SAndroid Build Coastguard Worker         if (ret)
1261*ba62d9d3SAndroid Build Coastguard Worker             continue;
1262*ba62d9d3SAndroid Build Coastguard Worker 
1263*ba62d9d3SAndroid Build Coastguard Worker         if (i >= MAX_DRM_NODES) {
1264*ba62d9d3SAndroid Build Coastguard Worker             fprintf(stderr, "More than %d drm nodes detected. "
1265*ba62d9d3SAndroid Build Coastguard Worker                     "Please report a bug - that should not happen.\n"
1266*ba62d9d3SAndroid Build Coastguard Worker                     "Skipping extra nodes\n", MAX_DRM_NODES);
1267*ba62d9d3SAndroid Build Coastguard Worker             break;
1268*ba62d9d3SAndroid Build Coastguard Worker         }
1269*ba62d9d3SAndroid Build Coastguard Worker         local_devices[i] = d;
1270*ba62d9d3SAndroid Build Coastguard Worker         i++;
1271*ba62d9d3SAndroid Build Coastguard Worker     }
1272*ba62d9d3SAndroid Build Coastguard Worker     node_count = i;
1273*ba62d9d3SAndroid Build Coastguard Worker 
1274*ba62d9d3SAndroid Build Coastguard Worker     drmFoldDuplicatedDevices(local_devices, node_count);
1275*ba62d9d3SAndroid Build Coastguard Worker 
1276*ba62d9d3SAndroid Build Coastguard Worker     *device = NULL;
1277*ba62d9d3SAndroid Build Coastguard Worker 
1278*ba62d9d3SAndroid Build Coastguard Worker     for (i = 0; i < node_count; i++) {
1279*ba62d9d3SAndroid Build Coastguard Worker         if (!local_devices[i])
1280*ba62d9d3SAndroid Build Coastguard Worker             continue;
1281*ba62d9d3SAndroid Build Coastguard Worker 
1282*ba62d9d3SAndroid Build Coastguard Worker         if (drm_device_has_rdev(local_devices[i], find_rdev))
1283*ba62d9d3SAndroid Build Coastguard Worker             *device = local_devices[i];
1284*ba62d9d3SAndroid Build Coastguard Worker         else
1285*ba62d9d3SAndroid Build Coastguard Worker             drmFreeDevice(&local_devices[i]);
1286*ba62d9d3SAndroid Build Coastguard Worker     }
1287*ba62d9d3SAndroid Build Coastguard Worker 
1288*ba62d9d3SAndroid Build Coastguard Worker     closedir(sysdir);
1289*ba62d9d3SAndroid Build Coastguard Worker     if (*device == NULL)
1290*ba62d9d3SAndroid Build Coastguard Worker         return -ENODEV;
1291*ba62d9d3SAndroid Build Coastguard Worker     return 0;
1292*ba62d9d3SAndroid Build Coastguard Worker }
1293*ba62d9d3SAndroid Build Coastguard Worker 
1294*ba62d9d3SAndroid Build Coastguard Worker /**
1295*ba62d9d3SAndroid Build Coastguard Worker  * Get information about the opened drm device
1296*ba62d9d3SAndroid Build Coastguard Worker  *
1297*ba62d9d3SAndroid Build Coastguard Worker  * \param fd file descriptor of the drm device
1298*ba62d9d3SAndroid Build Coastguard Worker  * \param device the address of a drmDevicePtr where the information
1299*ba62d9d3SAndroid Build Coastguard Worker  *               will be allocated in stored
1300*ba62d9d3SAndroid Build Coastguard Worker  *
1301*ba62d9d3SAndroid Build Coastguard Worker  * \return zero on success, negative error code otherwise.
1302*ba62d9d3SAndroid Build Coastguard Worker  */
drmGetDevice(int fd,drmDevicePtr * device)1303*ba62d9d3SAndroid Build Coastguard Worker int drmGetDevice(int fd, drmDevicePtr *device)
1304*ba62d9d3SAndroid Build Coastguard Worker {
1305*ba62d9d3SAndroid Build Coastguard Worker     return drmGetDevice2(fd, DRM_DEVICE_GET_PCI_REVISION, device);
1306*ba62d9d3SAndroid Build Coastguard Worker }
1307*ba62d9d3SAndroid Build Coastguard Worker 
GetRendererFileDescriptor(char * drm_node)1308*ba62d9d3SAndroid Build Coastguard Worker static int32_t GetRendererFileDescriptor(char * drm_node)
1309*ba62d9d3SAndroid Build Coastguard Worker {
1310*ba62d9d3SAndroid Build Coastguard Worker     int32_t driFileDescriptor = -1;
1311*ba62d9d3SAndroid Build Coastguard Worker 
1312*ba62d9d3SAndroid Build Coastguard Worker     driFileDescriptor = open(drm_node, O_RDWR);
1313*ba62d9d3SAndroid Build Coastguard Worker     return driFileDescriptor;
1314*ba62d9d3SAndroid Build Coastguard Worker }
1315*ba62d9d3SAndroid Build Coastguard Worker 
1316*ba62d9d3SAndroid Build Coastguard Worker #endif  // #ifndef DRM_DEVICE_H_
1317