2 * Copyright (c) 2007 Paulo R. Zanoni, Tiago Vignatti
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
14 * The above copyright notice and this permission notice shall be
15 * included in all copies or substantial portions of the Software.
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.
37 #include "pciaccess.h"
38 #include "pciaccess_private.h"
43 parse_string_to_decodes_rsrc(char *input, int *vga_count, struct pci_slot_match *match)
46 char *input_sp = NULL, *count_sp, *pci_sp;
49 tok = strtok_r(input,",",&input_sp);
53 strncpy(tmp, input, 15);
56 tok = strtok_r(tmp,":",&count_sp);
59 tok = strtok_r(NULL, ":",&count_sp);
63 *vga_count = strtoul(tok, NULL, 10);
64 if (*vga_count == LONG_MAX)
68 fprintf(stderr,"vga count is %d\n", *vga_count);
71 tok = strtok_r(NULL, ",",&input_sp);
76 strncpy(tmp, tok, 32);
78 tok = strtok_r(tmp, ":", &pci_sp);
81 tok = strtok_r(NULL, ":", &pci_sp);
84 match->domain = strtoul(tok, NULL, 16);
86 tok = strtok_r(NULL, ":", &pci_sp);
89 match->bus = strtoul(tok, NULL, 16);
91 tok = strtok_r(NULL, ".", &pci_sp);
94 match->dev = strtoul(tok, NULL, 16);
96 tok = strtok_r(NULL, ".", &pci_sp);
99 match->func = strtoul(tok, NULL, 16);
102 tok = strtok_r(NULL, ",",&input_sp);
105 tok = strtok_r(tok, "=", &input_sp);
108 tok = strtok_r(NULL, "=", &input_sp);
112 if (!strncmp(tok, "io+mem", 6))
113 return VGA_ARB_RSRC_LEGACY_IO | VGA_ARB_RSRC_LEGACY_MEM;
114 if (!strncmp(tok, "io", 2))
115 return VGA_ARB_RSRC_LEGACY_IO;
116 if (!strncmp(tok, "mem", 3))
117 return VGA_ARB_RSRC_LEGACY_MEM;
119 return VGA_ARB_RSRC_NONE;
123 pci_device_vgaarb_init(void)
125 struct pci_slot_match match;
132 if ((pci_sys->vgaarb_fd = open ("/dev/vga_arbiter", O_RDWR | O_CLOEXEC)) < 0) {
136 ret = read(pci_sys->vgaarb_fd, buf, BUFSIZE);
140 memset(&match, 0xff, sizeof(match));
141 /* need to find the device to go back to and what it was decoding */
142 rsrc = parse_string_to_decodes_rsrc(buf, &pci_sys->vga_count, &match);
144 pci_sys->vga_default_dev = pci_device_find_by_slot(match.domain, match.bus, match.dev, match.func);
146 if (pci_sys->vga_default_dev)
147 pci_sys->vga_default_dev->vgaarb_rsrc = rsrc;
152 pci_device_vgaarb_fini(void)
157 close(pci_sys->vgaarb_fd);
161 * Writes message on vga device. The messages are defined by the kernel
164 * \param fd vga arbiter device.
165 * \param buf message itself.
166 * \param len message length.
169 * Zero on success, 1 if something gets wrong and 2 if fd is busy (only for
173 vgaarb_write(int fd, char *buf, int len)
180 ret = write(fd, buf, len);
182 /* the user may have called "trylock" and didn't get the lock */
187 fprintf(stderr, "write error");
191 else if (ret != len) {
192 /* it's need to receive the exactly amount required. */
194 fprintf(stderr, "write error: wrote different than expected\n");
200 fprintf(stderr, "%s: successfully wrote: '%s'\n", __FUNCTION__, buf);
208 rsrc_to_str(int iostate)
211 case VGA_ARB_RSRC_LEGACY_IO | VGA_ARB_RSRC_LEGACY_MEM:
213 case VGA_ARB_RSRC_LEGACY_IO:
215 case VGA_ARB_RSRC_LEGACY_MEM:
223 pci_device_vgaarb_set_target(struct pci_device *dev)
230 dev = pci_sys->vga_default_dev;
234 len = snprintf(buf, BUFSIZE, "target PCI:%04x:%02x:%02x.%x",
235 dev->domain, dev->bus, dev->dev, dev->func);
237 ret = vgaarb_write(pci_sys->vgaarb_fd, buf, len);
241 ret = read(pci_sys->vgaarb_fd, buf, BUFSIZE);
245 dev->vgaarb_rsrc = parse_string_to_decodes_rsrc(buf, &pci_sys->vga_count, NULL);
246 pci_sys->vga_target = dev;
251 pci_device_vgaarb_decodes(int new_vgaarb_rsrc)
256 struct pci_device *dev = pci_sys->vga_target;
260 if (dev->vgaarb_rsrc == new_vgaarb_rsrc)
263 len = snprintf(buf, BUFSIZE, "decodes %s", rsrc_to_str(new_vgaarb_rsrc));
264 ret = vgaarb_write(pci_sys->vgaarb_fd, buf, len);
266 dev->vgaarb_rsrc = new_vgaarb_rsrc;
268 ret = read(pci_sys->vgaarb_fd, buf, BUFSIZE);
272 parse_string_to_decodes_rsrc(buf, &pci_sys->vga_count, NULL);
278 pci_device_vgaarb_lock(void)
282 struct pci_device *dev = pci_sys->vga_target;
287 if (dev->vgaarb_rsrc == 0 || pci_sys->vga_count == 1)
290 len = snprintf(buf, BUFSIZE, "lock %s", rsrc_to_str(dev->vgaarb_rsrc));
292 return vgaarb_write(pci_sys->vgaarb_fd, buf, len);
296 pci_device_vgaarb_trylock(void)
300 struct pci_device *dev = pci_sys->vga_target;
305 if (dev->vgaarb_rsrc == 0 || pci_sys->vga_count == 1)
308 len = snprintf(buf, BUFSIZE, "trylock %s", rsrc_to_str(dev->vgaarb_rsrc));
310 return vgaarb_write(pci_sys->vgaarb_fd, buf, len);
314 pci_device_vgaarb_unlock(void)
318 struct pci_device *dev = pci_sys->vga_target;
323 if (dev->vgaarb_rsrc == 0 || pci_sys->vga_count == 1)
326 len = snprintf(buf, BUFSIZE, "unlock %s", rsrc_to_str(dev->vgaarb_rsrc));
328 return vgaarb_write(pci_sys->vgaarb_fd, buf, len);
331 int pci_device_vgaarb_get_info(struct pci_device *dev, int *vga_count, int *rsrc_decodes)
333 *vga_count = pci_sys->vga_count;
337 *rsrc_decodes = dev->vgaarb_rsrc;