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