Subversion Repositories Kolibri OS

Rev

Go to most recent revision | Details | Last modification | View Log | RSS feed

Rev Author Line No. Line
4358 Serge 1
/**************************************************************************
2
 *
3
 * Copyright 2011 Intel Corporation
4
 * Copyright 2012 Francisco Jerez
5
 * All Rights Reserved.
6
 *
7
 * Permission is hereby granted, free of charge, to any person obtaining a
8
 * copy of this software and associated documentation files (the
9
 * "Software"), to deal in the Software without restriction, including
10
 * without limitation the rights to use, copy, modify, merge, publish,
11
 * distribute, sub license, and/or sell copies of the Software, and to
12
 * permit persons to whom the Software is furnished to do so, subject to
13
 * the following conditions:
14
 *
15
 * The above copyright notice and this permission notice (including the
16
 * next paragraph) shall be included in all copies or substantial portions
17
 * of the Software.
18
 *
19
 * THE SOFTWARE IS PROVIDED "AS IS", WITHOUT WARRANTY OF ANY KIND, EXPRESS
20
 * OR IMPLIED, INCLUDING BUT NOT LIMITED TO THE WARRANTIES OF
21
 * MERCHANTABILITY, FITNESS FOR A PARTICULAR PURPOSE AND NON-INFRINGEMENT.
22
 * IN NO EVENT SHALL TUNGSTEN GRAPHICS AND/OR ITS SUPPLIERS BE LIABLE FOR
23
 * ANY CLAIM, DAMAGES OR OTHER LIABILITY, WHETHER IN AN ACTION OF CONTRACT,
24
 * TORT OR OTHERWISE, ARISING FROM, OUT OF OR IN CONNECTION WITH THE
25
 * SOFTWARE OR THE USE OR OTHER DEALINGS IN THE SOFTWARE.
26
 *
27
 * Authors:
28
 *    Kristian Høgsberg 
29
 *    Benjamin Franzke 
30
 *
31
 **************************************************************************/
32
 
33
#include 
34
#include 
35
#include 
36
#include 
37
 
38
#ifdef HAVE_PIPE_LOADER_XCB
39
 
40
#include 
41
 
42
#endif
43
 
44
#include "state_tracker/drm_driver.h"
45
#include "pipe_loader_priv.h"
46
 
47
#include "util/u_memory.h"
48
#include "util/u_dl.h"
49
#include "util/u_debug.h"
50
 
51
#define DRIVER_MAP_GALLIUM_ONLY
52
#include "pci_ids/pci_id_driver_map.h"
53
 
54
struct pipe_loader_drm_device {
55
   struct pipe_loader_device base;
56
   struct util_dl_library *lib;
57
   int fd;
58
};
59
 
60
#define pipe_loader_drm_device(dev) ((struct pipe_loader_drm_device *)dev)
61
 
62
static boolean
63
find_drm_pci_id(struct pipe_loader_drm_device *ddev)
64
{
65
   struct udev *udev = NULL;
66
   struct udev_device *parent, *device = NULL;
67
   struct stat stat;
68
   const char *pci_id;
69
 
70
   if (fstat(ddev->fd, &stat) < 0)
71
      goto fail;
72
 
73
   udev = udev_new();
74
   if (!udev)
75
      goto fail;
76
 
77
   device = udev_device_new_from_devnum(udev, 'c', stat.st_rdev);
78
   if (!device)
79
      goto fail;
80
 
81
   parent = udev_device_get_parent(device);
82
   if (!parent)
83
      goto fail;
84
 
85
   pci_id = udev_device_get_property_value(parent, "PCI_ID");
86
   if (!pci_id ||
87
       sscanf(pci_id, "%x:%x", &ddev->base.u.pci.vendor_id,
88
              &ddev->base.u.pci.chip_id) != 2)
89
      goto fail;
90
 
91
   return TRUE;
92
 
93
  fail:
94
   if (device)
95
      udev_device_unref(device);
96
   if (udev)
97
      udev_unref(udev);
98
 
99
   return FALSE;
100
}
101
 
102
static boolean
103
find_drm_driver_name(struct pipe_loader_drm_device *ddev)
104
{
105
   struct pipe_loader_device *dev = &ddev->base;
106
   int i, j;
107
 
108
   for (i = 0; driver_map[i].driver; i++) {
109
      if (dev->u.pci.vendor_id != driver_map[i].vendor_id)
110
         continue;
111
 
112
      if (driver_map[i].num_chips_ids == -1) {
113
         dev->driver_name = driver_map[i].driver;
114
         goto found;
115
      }
116
 
117
      for (j = 0; j < driver_map[i].num_chips_ids; j++) {
118
         if (dev->u.pci.chip_id == driver_map[i].chip_ids[j]) {
119
            dev->driver_name = driver_map[i].driver;
120
            goto found;
121
         }
122
      }
123
   }
124
 
125
   return FALSE;
126
 
127
  found:
128
   return TRUE;
129
}
130
 
131
static struct pipe_loader_ops pipe_loader_drm_ops;
132
 
133
static void
134
pipe_loader_drm_x_auth(int fd)
135
{
136
#if HAVE_PIPE_LOADER_XCB
137
   /* Try authenticate with the X server to give us access to devices that X
138
    * is running on. */
139
   xcb_connection_t *xcb_conn;
140
   const xcb_setup_t *xcb_setup;
141
   xcb_screen_iterator_t s;
142
   xcb_dri2_connect_cookie_t connect_cookie;
143
   xcb_dri2_connect_reply_t *connect;
144
   drm_magic_t magic;
145
   xcb_dri2_authenticate_cookie_t authenticate_cookie;
146
   xcb_dri2_authenticate_reply_t *authenticate;
147
 
148
   xcb_conn = xcb_connect(NULL,  NULL);
149
 
150
   if(!xcb_conn)
151
      return;
152
 
153
   xcb_setup = xcb_get_setup(xcb_conn);
154
 
155
  if (!xcb_setup)
156
    goto disconnect;
157
 
158
   s = xcb_setup_roots_iterator(xcb_setup);
159
   connect_cookie = xcb_dri2_connect_unchecked(xcb_conn, s.data->root,
160
                                               XCB_DRI2_DRIVER_TYPE_DRI);
161
   connect = xcb_dri2_connect_reply(xcb_conn, connect_cookie, NULL);
162
 
163
   if (!connect || connect->driver_name_length
164
                   + connect->device_name_length == 0) {
165
 
166
      goto disconnect;
167
   }
168
 
169
   if (drmGetMagic(fd, &magic))
170
      goto disconnect;
171
 
172
   authenticate_cookie = xcb_dri2_authenticate_unchecked(xcb_conn,
173
                                                         s.data->root,
174
                                                         magic);
175
   authenticate = xcb_dri2_authenticate_reply(xcb_conn,
176
                                              authenticate_cookie,
177
                                              NULL);
178
   FREE(authenticate);
179
 
180
disconnect:
181
   xcb_disconnect(xcb_conn);
182
 
183
#endif
184
}
185
 
186
boolean
187
pipe_loader_drm_probe_fd(struct pipe_loader_device **dev, int fd)
188
{
189
   struct pipe_loader_drm_device *ddev = CALLOC_STRUCT(pipe_loader_drm_device);
190
 
191
   ddev->base.type = PIPE_LOADER_DEVICE_PCI;
192
   ddev->base.ops = &pipe_loader_drm_ops;
193
   ddev->fd = fd;
194
 
195
   pipe_loader_drm_x_auth(fd);
196
 
197
   if (!find_drm_pci_id(ddev))
198
      goto fail;
199
 
200
   if (!find_drm_driver_name(ddev))
201
      goto fail;
202
 
203
   *dev = &ddev->base;
204
   return TRUE;
205
 
206
  fail:
207
   FREE(ddev);
208
   return FALSE;
209
}
210
 
211
static int
212
open_drm_minor(int minor)
213
{
214
   char path[PATH_MAX];
215
   snprintf(path, sizeof(path), DRM_DEV_NAME, DRM_DIR_NAME, minor);
216
   return open(path, O_RDWR, 0);
217
}
218
 
219
int
220
pipe_loader_drm_probe(struct pipe_loader_device **devs, int ndev)
221
{
222
   int i, j, fd;
223
 
224
   for (i = 0, j = 0; i < DRM_MAX_MINOR; i++) {
225
      fd = open_drm_minor(i);
226
      if (fd < 0)
227
         continue;
228
 
229
      if (j >= ndev || !pipe_loader_drm_probe_fd(&devs[j], fd))
230
         close(fd);
231
 
232
      j++;
233
   }
234
 
235
   return j;
236
}
237
 
238
static void
239
pipe_loader_drm_release(struct pipe_loader_device **dev)
240
{
241
   struct pipe_loader_drm_device *ddev = pipe_loader_drm_device(*dev);
242
 
243
   if (ddev->lib)
244
      util_dl_close(ddev->lib);
245
 
246
   close(ddev->fd);
247
   FREE(ddev);
248
   *dev = NULL;
249
}
250
 
251
static struct pipe_screen *
252
pipe_loader_drm_create_screen(struct pipe_loader_device *dev,
253
                              const char *library_paths)
254
{
255
   struct pipe_loader_drm_device *ddev = pipe_loader_drm_device(dev);
256
   const struct drm_driver_descriptor *dd;
257
 
258
   if (!ddev->lib)
259
      ddev->lib = pipe_loader_find_module(dev, library_paths);
260
   if (!ddev->lib)
261
      return NULL;
262
 
263
   dd = (const struct drm_driver_descriptor *)
264
      util_dl_get_proc_address(ddev->lib, "driver_descriptor");
265
 
266
   /* sanity check on the name */
267
   if (!dd || strcmp(dd->name, ddev->base.driver_name) != 0)
268
      return NULL;
269
 
270
   return dd->create_screen(ddev->fd);
271
}
272
 
273
static struct pipe_loader_ops pipe_loader_drm_ops = {
274
   .create_screen = pipe_loader_drm_create_screen,
275
   .release = pipe_loader_drm_release
276
};