OSDN Git Service

shutup stupid gcc warning, strtok_r ignores the first parameter
[android-x86/external-libpciaccess.git] / src / common_vgaarb.c
1 /*
2  * Copyright (c) 2007 Paulo R. Zanoni, Tiago Vignatti
3  *               2009 Tiago Vignatti
4  *
5  * Permission is hereby granted, free of charge, to any person
6  * obtaining a copy of this software and associated documentation
7  * files (the "Software"), to deal in the Software without
8  * restriction, including without limitation the rights to use,
9  * copy, modify, merge, publish, distribute, sublicense, and/or sell
10  * copies of the Software, and to permit persons to whom the
11  * Software is furnished to do so, subject to the following
12  * conditions:
13  *
14  * The above copyright notice and this permission notice shall be
15  * included in all copies or substantial portions of the Software.
16  *
17  * THE SOFTWARE IS PROVIDED "AS IS", WITHOUT WARRANTY OF ANY KIND,
18  * EXPRESS OR IMPLIED, INCLUDING BUT NOT LIMITED TO THE WARRANTIES
19  * OF MERCHANTABILITY, FITNESS FOR A PARTICULAR PURPOSE AND
20  * NONINFRINGEMENT. IN NO EVENT SHALL THE AUTHORS OR COPYRIGHT
21  * HOLDERS BE LIABLE FOR ANY CLAIM, DAMAGES OR OTHER LIABILITY,
22  * WHETHER IN AN ACTION OF CONTRACT, TORT OR OTHERWISE, ARISING
23  * FROM, OUT OF OR IN CONNECTION WITH THE SOFTWARE OR THE USE OR
24  * OTHER DEALINGS IN THE SOFTWARE.
25  *
26  */
27
28 #include <stdio.h>
29 #include <string.h>
30 #include <unistd.h>
31 #include <fcntl.h>
32 #include <errno.h>
33 #include <stdlib.h>
34 #include <limits.h>
35
36 #include "pciaccess.h"
37 #include "pciaccess_private.h"
38
39 #define BUFSIZE 64
40
41 static int
42 parse_string_to_decodes_rsrc(char *input, int *vga_count, struct pci_slot_match *match)
43 {
44     char *tok;
45     char *input_sp = NULL, *count_sp, *pci_sp;
46     char tmp[32];
47
48     tok = strtok_r(input,",",&input_sp);
49     if (!tok)
50         goto fail;
51
52     strncpy(tmp, input, 15);
53     tmp[15] = 0;
54
55     tok = strtok_r(tmp,":",&count_sp);
56     if (!tok)
57         goto fail;
58     tok = strtok_r(NULL, ":",&count_sp);
59     if (!tok)
60         goto fail;
61
62     *vga_count = strtoul(tok, NULL, 10);
63     if (*vga_count == LONG_MAX)
64         goto fail;
65
66 #ifdef DEBUG
67     fprintf(stderr,"vga count is %d\n", *vga_count);
68 #endif
69
70     tok = strtok_r(NULL, ",",&input_sp);
71     if (!tok)
72         goto fail;
73
74     if (match) {
75         strncpy(tmp, tok, 32);
76         tmp[31] = 0;
77         tok = strtok_r(tmp, ":", &pci_sp);
78         if (!tok)
79             goto fail;
80         tok = strtok_r(NULL, ":", &pci_sp);
81         if (!tok)
82             goto fail;
83         match->domain = strtoul(tok, NULL, 16);
84
85         tok = strtok_r(NULL, ":", &pci_sp);
86         if (!tok)
87             goto fail;
88         match->bus = strtoul(tok, NULL, 16);
89
90         tok = strtok_r(NULL, ".", &pci_sp);
91         if (!tok)
92             goto fail;
93         match->dev = strtoul(tok, NULL, 16);
94
95         tok = strtok_r(NULL, ".", &pci_sp);
96         if (!tok)
97             goto fail;
98         match->func = strtoul(tok, NULL, 16);
99     }
100
101     tok = strtok_r(NULL, ",",&input_sp);
102     if (!tok)
103         goto fail;
104     tok = strtok_r(tok, "=", &input_sp);
105     if (!tok)
106         goto fail;
107     tok = strtok_r(NULL, "=", &input_sp);
108     if (!tok)
109         goto fail;
110
111     if (!strncmp(tok, "io+mem", 6))
112         return VGA_ARB_RSRC_LEGACY_IO | VGA_ARB_RSRC_LEGACY_MEM;
113     if (!strncmp(tok, "io", 2))
114         return VGA_ARB_RSRC_LEGACY_IO;
115     if (!strncmp(tok, "mem", 3))
116         return VGA_ARB_RSRC_LEGACY_MEM;
117 fail:
118     return VGA_ARB_RSRC_NONE;
119 }
120
121 int
122 pci_device_vgaarb_init(void)
123 {
124     struct pci_slot_match match;
125     char buf[BUFSIZE];
126     int ret, rsrc;
127
128     if (!pci_sys)
129         return -1;
130
131     if ((pci_sys->vgaarb_fd = open ("/dev/vga_arbiter", O_RDWR)) < 0) {
132         return errno;
133     }
134
135     ret = read(pci_sys->vgaarb_fd, buf, BUFSIZE);
136     if (ret <= 0)
137         return -1;
138
139     memset(&match, 0xff, sizeof(match));
140     /* need to find the device to go back to and what it was decoding */
141     rsrc = parse_string_to_decodes_rsrc(buf, &pci_sys->vga_count, &match);
142
143     pci_sys->vga_default_dev = pci_device_find_by_slot(match.domain, match.bus, match.dev, match.func);
144
145     if (pci_sys->vga_default_dev)
146         pci_sys->vga_default_dev->vgaarb_rsrc = rsrc;
147     return 0;
148 }
149
150 void
151 pci_device_vgaarb_fini(void)
152 {
153     if (!pci_sys)
154         return;
155
156     close(pci_sys->vgaarb_fd);
157 }
158
159 /**
160  * Writes message on vga device. The messages are defined by the kernel
161  * implementation.
162  *
163  * \param fd    vga arbiter device.
164  * \param buf   message itself.
165  * \param len   message length.
166  *
167  * \return
168  * Zero on success, 1 if something gets wrong and 2 if fd is busy (only for
169  * 'trylock')
170  */
171 static int
172 vgaarb_write(int fd, char *buf, int len)
173 {
174     int ret;
175
176
177     buf[len] = '\0';
178
179     ret = write(fd, buf, len);
180     if (ret == -1) {
181         /* the user may have called "trylock" and didn't get the lock */
182         if (errno == EBUSY)
183             return 2;
184
185 #ifdef DEBUG
186         fprintf(stderr, "write error");
187 #endif
188         return 1;
189     }
190     else if (ret != len) {
191         /* it's need to receive the exactly amount required. */
192 #ifdef DEBUG
193         fprintf(stderr, "write error: wrote different than expected\n");
194 #endif
195         return 1;
196     }
197
198 #ifdef DEBUG
199     fprintf(stderr, "%s: successfully wrote: '%s'\n", __FUNCTION__, buf);
200 #endif
201
202     return 0;
203 }
204
205
206 static const char *
207 rsrc_to_str(int iostate)
208 {
209     switch (iostate) {
210     case VGA_ARB_RSRC_LEGACY_IO | VGA_ARB_RSRC_LEGACY_MEM:
211         return "io+mem";
212     case VGA_ARB_RSRC_LEGACY_IO:
213         return "io";
214     case VGA_ARB_RSRC_LEGACY_MEM:
215         return "mem";
216     }
217
218     return "none";
219 }
220
221 int
222 pci_device_vgaarb_set_target(struct pci_device *dev)
223 {
224     int len;
225     char buf[BUFSIZE];
226     int ret;
227
228     if (!dev)
229         dev = pci_sys->vga_default_dev;
230     if (!dev)
231         return -1;
232
233     len = snprintf(buf, BUFSIZE, "target PCI:%04x:%02x:%02x.%x",
234                    dev->domain, dev->bus, dev->dev, dev->func);
235
236     ret = vgaarb_write(pci_sys->vgaarb_fd, buf, len);
237     if (ret)
238         return ret;
239
240     ret = read(pci_sys->vgaarb_fd, buf, BUFSIZE);
241     if (ret <= 0)
242         return -1;
243
244     dev->vgaarb_rsrc = parse_string_to_decodes_rsrc(buf, &pci_sys->vga_count, NULL);
245     pci_sys->vga_target = dev;
246     return 0;
247 }
248
249 int
250 pci_device_vgaarb_decodes(int new_vgaarb_rsrc)
251 {
252     int len;
253     char buf[BUFSIZE];
254     int ret;
255     struct pci_device *dev = pci_sys->vga_target;
256
257     if (!dev)
258         return -1;
259     if (dev->vgaarb_rsrc == new_vgaarb_rsrc)
260         return 0;
261
262     len = snprintf(buf, BUFSIZE, "decodes %s", rsrc_to_str(dev->vgaarb_rsrc));
263     ret = vgaarb_write(pci_sys->vgaarb_fd, buf, len);
264     if (ret == 0)
265         dev->vgaarb_rsrc = new_vgaarb_rsrc;
266     return ret;
267 }
268
269 int
270 pci_device_vgaarb_lock(void)
271 {
272     int len;
273     char buf[BUFSIZE];
274     struct pci_device *dev = pci_sys->vga_target;
275
276     if (!dev)
277         return -1;
278
279     if (dev->vgaarb_rsrc == 0 || pci_sys->vga_count == 1)
280         return 0;
281
282     len = snprintf(buf, BUFSIZE, "lock %s", rsrc_to_str(dev->vgaarb_rsrc));
283
284     return vgaarb_write(pci_sys->vgaarb_fd, buf, len);
285 }
286
287 int
288 pci_device_vgaarb_trylock(void)
289 {
290     int len;
291     char buf[BUFSIZE];
292     struct pci_device *dev = pci_sys->vga_target;
293
294     if (!dev)
295         return -1;
296
297     if (dev->vgaarb_rsrc == 0 || pci_sys->vga_count == 1)
298         return 0;
299
300     len = snprintf(buf, BUFSIZE, "trylock %s", rsrc_to_str(dev->vgaarb_rsrc));
301
302     return vgaarb_write(pci_sys->vgaarb_fd, buf, len);
303 }
304
305 int
306 pci_device_vgaarb_unlock(void)
307 {
308     int len;
309     char buf[BUFSIZE];
310     struct pci_device *dev = pci_sys->vga_target;
311
312     if (!dev)
313         return -1;
314
315     if (dev->vgaarb_rsrc == 0 || pci_sys->vga_count == 1)
316         return 0;
317
318     len = snprintf(buf, BUFSIZE, "unlock %s", rsrc_to_str(dev->vgaarb_rsrc));
319
320     return vgaarb_write(pci_sys->vgaarb_fd, buf, len);
321 }
322
323 int pci_device_vgaarb_get_info(struct pci_device *dev, int *vga_count, int *rsrc_decodes)
324 {
325     *vga_count = pci_sys->vga_count;
326     if (!dev)
327         return 0;
328
329     *rsrc_decodes = dev->vgaarb_rsrc;
330         return 0;
331 }