blob: 63a90d75aab7e67dadb440cc8c494876913eca06 [file] [log] [blame]
Courtney Goeltzenleuchtere06e72d2014-08-01 12:44:23 -06001/*
2 * XGL 3-D graphics library
3 *
4 * Copyright (C) 2014 LunarG, Inc.
5 *
6 * Permission is hereby granted, free of charge, to any person obtaining a
7 * copy of this software and associated documentation files (the "Software"),
8 * to deal in the Software without restriction, including without limitation
9 * the rights to use, copy, modify, merge, publish, distribute, sublicense,
10 * and/or sell copies of the Software, and to permit persons to whom the
11 * Software is furnished to do so, subject to the following conditions:
12 *
13 * The above copyright notice and this permission notice shall be included
14 * in all copies or substantial portions of the Software.
15 *
16 * THE SOFTWARE IS PROVIDED "AS IS", WITHOUT WARRANTY OF ANY KIND, EXPRESS OR
17 * IMPLIED, INCLUDING BUT NOT LIMITED TO THE WARRANTIES OF MERCHANTABILITY,
18 * FITNESS FOR A PARTICULAR PURPOSE AND NONINFRINGEMENT. IN NO EVENT SHALL
19 * THE AUTHORS OR COPYRIGHT HOLDERS BE LIABLE FOR ANY CLAIM, DAMAGES OR OTHER
20 * LIABILITY, WHETHER IN AN ACTION OF CONTRACT, TORT OR OTHERWISE, ARISING
21 * FROM, OUT OF OR IN CONNECTION WITH THE SOFTWARE OR THE USE OR OTHER
22 * DEALINGS IN THE SOFTWARE.
23 *
24 * Authors:
25 * Courtney Goeltzenleuchter <courtney@lunarg.com>
26 */
27
28#ifdef HAVE_CONFIG_H
29#include "config.h"
30#endif
31
32#include <sys/types.h>
33#include <sys/stat.h>
34#include <assert.h>
35#include <string.h>
36#include <unistd.h>
37#include <fcntl.h>
38#include <stdio.h>
39#include <stdlib.h>
40#include <dirent.h>
41#include <errno.h>
42#include <fnmatch.h>
43
44#include <pciaccess.h>
45
46#include <xf86drm.h>
Chia-I Wu155be032014-08-02 09:14:28 +080047#include <i915_drm.h>
Courtney Goeltzenleuchtere06e72d2014-08-01 12:44:23 -060048
49#include <libudev.h>
50#include <dlfcn.h>
51
52#ifdef HAVE_VALGRIND
53#include <valgrind.h>
54#include <memcheck.h>
55#define VG(x) x
56#else
57#define VG(x)
58#endif
59
60#define VG_CLEAR(s) VG(memset(&s, 0, sizeof(s)))
61
62#include "xgl.h"
63#include "xglDbg.h"
64
65#include "driver.h"
66#include "intel_chipset.h"
67#include "gen7_functions.h"
Chia-I Wu6051cf82014-08-04 10:41:45 +080068#include "dispatch_tables.h"
Courtney Goeltzenleuchtere06e72d2014-08-01 12:44:23 -060069
70
Courtney Goeltzenleuchtere06e72d2014-08-01 12:44:23 -060071/*
72 * Global to contain application allocation call-backs
73 * and GPU enumeration info.
74 */
75struct _xgl_config icd_data;
76
Chia-I Wu3065c9c2014-08-04 06:28:31 +080077static void loader_err(XGL_INT msg_code, const char *msg)
Courtney Goeltzenleuchtere06e72d2014-08-01 12:44:23 -060078{
Chia-I Wu3065c9c2014-08-04 06:28:31 +080079 icd_log(XGL_DBG_MSG_ERROR, XGL_VALIDATION_LEVEL_0,
80 XGL_NULL_HANDLE, 0, msg_code, msg);
Courtney Goeltzenleuchtere06e72d2014-08-01 12:44:23 -060081}
82
Courtney Goeltzenleuchtere06e72d2014-08-01 12:44:23 -060083static int is_render_node(int fd, struct stat *st)
84{
85 if (fstat(fd, st))
86 return 0;
87
88 if (!S_ISCHR(st->st_mode))
89 return 0;
90
91 return st->st_rdev & 0x80;
92}
93
Chia-I Wu468e3c32014-08-04 08:03:57 +080094ICD_EXPORT XGL_RESULT XGLAPI xglInitAndEnumerateGpus(const XGL_APPLICATION_INFO *
Courtney Goeltzenleuchtere06e72d2014-08-01 12:44:23 -060095 pAppInfo,
96 const XGL_ALLOC_CALLBACKS *
97 pAllocCb, XGL_UINT maxGpus,
98 XGL_UINT * pGpuCount,
99 XGL_PHYSICAL_GPU * pGpus)
100{
101 struct udev *udev;
102 struct udev_enumerate *e;
103 struct udev_device *device, *parent;
104 struct udev_list_entry *entry;
105 const char *pci_id, *path;
106 const char *usub, *dnode;
107 int fd;
108 struct stat st;
109 char *pci_glob = "*:*";
Chia-I Wu3065c9c2014-08-04 06:28:31 +0800110 XGL_RESULT ret;
Courtney Goeltzenleuchtere06e72d2014-08-01 12:44:23 -0600111 XGL_UINT count = 0;
112 struct _xgl_device *pXglDev;
113
Chia-I Wu3065c9c2014-08-04 06:28:31 +0800114 ret = icd_set_alloc_callbacks(pAllocCb);
115 if (ret != XGL_SUCCESS)
116 return ret;
117
118 ret = XGL_ERROR_UNAVAILABLE;
119
Courtney Goeltzenleuchtere06e72d2014-08-01 12:44:23 -0600120 // TODO: Do we need to keep track of previous calls to xglInitAndEnumerageGpus?
121 /*
122 * xglInitAndEnumerateGpus() can be called multiple times. Calling it more than once
123 * forces driver reinitialization.
124 */
125
126 if (icd_data.num_gpus > 0) {
Courtney Goeltzenleuchtere06e72d2014-08-01 12:44:23 -0600127 // TODO: Free resources and re-initialize
128 }
129 // TODO: Do we need any other validation for incoming pointers?
130
Courtney Goeltzenleuchtere06e72d2014-08-01 12:44:23 -0600131 udev = udev_new();
132 if (udev == NULL) {
133 loader_err(0, "failed to initialize udev context");
134 abort();
135 }
136
137 memset(icd_data.gpu_info, 0,
138 sizeof(icd_data.gpu_info[XGL_MAX_PHYSICAL_GPUS]));
139 memset(icd_data.render_node_list, 0,
140 sizeof(icd_data.render_node_list[XGL_MAX_PHYSICAL_GPUS]));
141
142 fd = -1;
143 e = udev_enumerate_new(udev);
144 udev_enumerate_add_match_subsystem(e, "drm");
145 udev_enumerate_scan_devices(e);
146 udev_list_entry_foreach(entry, udev_enumerate_get_list_entry(e)) {
147 path = udev_list_entry_get_name(entry);
148 device = udev_device_new_from_syspath(udev, path);
149 parent = udev_device_get_parent(device);
150 usub = udev_device_get_subsystem(parent);
151 /* Filter out KMS output devices. */
152 if (!usub || (strcmp(usub, "pci") != 0))
153 continue;
154 pci_id = udev_device_get_property_value(parent, "PCI_ID");
155 if (fnmatch(pci_glob, pci_id, 0) != 0)
156 continue;
157 dnode = udev_device_get_devnode(device);
158 fd = open(dnode, O_RDWR);
159 if (fd < 0)
160 continue;
161 if (!is_render_node(fd, &st)) {
162 close(fd);
163 fd = -1;
164 continue;
165 }
166
167 pXglDev = &icd_data.gpu_info[count];
168
169 sscanf(pci_id, "%x:%x", &pXglDev->ven_id, &pXglDev->dev_id);
170 /*
171 * Currently only allowing Ivybridge and Haswell
172 */
173 if (!IS_HASWELL(pXglDev->dev_id) && !IS_IVYBRIDGE(pXglDev->dev_id)) {
174 close(fd);
175 fd = -1;
176 continue;
177 }
178
179 /*
180 * We'll keep the fd open for any subsequent
181 * xglGetGpuInfo calls.
182 */
183 pXglDev->fd = fd;
184 strncpy(pXglDev->device_path, dnode, XGL_MAX_PHYSICAL_GPU_NAME);
185 icd_data.render_node_list[count] = pXglDev;
Chia-I Wu6051cf82014-08-04 10:41:45 +0800186 pXglDev->exec = &intel_normal_dispatch_table;
Courtney Goeltzenleuchtere06e72d2014-08-01 12:44:23 -0600187
188 ret = XGL_SUCCESS;
189 count++;
190 }
191 icd_data.num_gpus = count;
192 udev_enumerate_unref(e);
193 udev_unref(udev);
194
195 if (ret == XGL_SUCCESS) {
196 *pGpuCount = icd_data.num_gpus;
197 memcpy(pGpus, icd_data.render_node_list,
198 (icd_data.num_gpus >
199 maxGpus ? maxGpus : icd_data.num_gpus) *
200 sizeof(XGL_PHYSICAL_GPU));
201 }
202
203 return ret;
204}
205
Chia-I Wu6051cf82014-08-04 10:41:45 +0800206XGL_RESULT XGLAPI intelGetExtensionSupport(
207 XGL_PHYSICAL_GPU gpu,
208 const XGL_CHAR* pExtName)
Courtney Goeltzenleuchtere06e72d2014-08-01 12:44:23 -0600209{
210 // struct _xgl_device *pdev = (struct _xgl_device *) gpu;
211
212 // TODO: Check requested extension
213
214 return XGL_ERROR_INVALID_EXTENSION;
215}