OSDN Git Service

vgaarb: add support for targetting default device
[android-x86/external-libpciaccess.git] / src / common_vgaarb.c
index f75257e..79d3f93 100644 (file)
  */
 
 #include <stdio.h>
+#include <string.h>
 #include <unistd.h>
 #include <fcntl.h>
 #include <errno.h>
+#include <stdlib.h>
+#include <limits.h>
 
 #include "pciaccess.h"
+#include "pciaccess_private.h"
 
-#define BUFSIZE 32
+#define BUFSIZE 64
 
 int
-pci_device_vgaarb_init(struct pci_device *dev)
+pci_device_vgaarb_init(void)
 {
-    dev->vgaarb_rsrc = VGA_ARB_RSRC_NONE;
-
-    if ((dev->vgaarb_fd = open ("/dev/vga_arbiter", O_RDWR)) < 0) {
-        fprintf(stderr, "device open failed");
+    if ((pci_sys->vgaarb_fd = open ("/dev/vga_arbiter", O_RDWR)) < 0) {
         return errno;
     }
 
@@ -48,10 +49,9 @@ pci_device_vgaarb_init(struct pci_device *dev)
 }
 
 void
-pci_device_vgaarb_fini(struct pci_device *dev)
+pci_device_vgaarb_fini(void)
 {
-    if (close(dev->vgaarb_fd) != 0)
-        fprintf(stderr, "device close failed");
+    close(pci_sys->vgaarb_fd);
 }
 
 /**
@@ -80,12 +80,16 @@ vgaarb_write(int fd, char *buf, int len)
         if (errno == EBUSY)
             return 2;
 
+#ifdef DEBUG
         fprintf(stderr, "write error");
+#endif
         return 1;
     }
     else if (ret != len) {
         /* it's need to receive the exactly amount required. */
+#ifdef DEBUG
         fprintf(stderr, "write error: wrote different than expected\n");
+#endif
         return 1;
     }
 
@@ -96,6 +100,54 @@ vgaarb_write(int fd, char *buf, int len)
     return 0;
 }
 
+static int
+parse_string_to_decodes_rsrc(char *input, int *vga_count)
+{
+    char *tok;
+    char count[16];
+
+    strncpy(count, input, 10);
+    count[11] = 0;
+
+    tok = strtok(count,":");
+    if (!tok)
+       goto fail;
+    tok = strtok(NULL, "");
+    if (!tok)
+       goto fail;
+
+    *vga_count = strtoul(tok, NULL, 10);
+    if (*vga_count == LONG_MAX)
+       goto fail;
+
+#ifdef DEBUG
+    fprintf(stderr,"vga count is %d\n", *vga_count);
+#endif
+
+    tok = strtok(input, ",");
+    if (!tok)
+       goto fail;
+
+    tok = strtok(NULL, ",");
+    if (!tok)
+       goto fail;
+    tok = strtok(tok, "=");
+    if (!tok)
+       goto fail;
+    tok = strtok(NULL, "=");
+    if (!tok)
+       goto fail;
+
+    if (!strncmp(tok, "io+mem", 6))
+       return VGA_ARB_RSRC_LEGACY_IO | VGA_ARB_RSRC_LEGACY_MEM;
+    if (!strncmp(tok, "io", 2))
+       return VGA_ARB_RSRC_LEGACY_IO;
+    if (!strncmp(tok, "mem", 3))
+       return VGA_ARB_RSRC_LEGACY_MEM;
+fail:
+    return VGA_ARB_RSRC_NONE;
+}
+
 static const char *
 rsrc_to_str(int iostate)
 {
@@ -116,22 +168,44 @@ pci_device_vgaarb_set_target(struct pci_device *dev)
 {
     int len;
     char buf[BUFSIZE];
+    int ret;
+    int rsrc;
 
-    len = snprintf(buf, BUFSIZE, "target PCI:%d:%d:%d.%d",
-                   dev->domain, dev->bus, dev->dev, dev->func);
+    if (!dev)
+        len = snprintf(buf, BUFSIZE, "default");
+    else
+        len = snprintf(buf, BUFSIZE, "target PCI:%d:%d:%d.%d",
+                       dev->domain, dev->bus, dev->dev, dev->func);
 
-    return vgaarb_write(dev->vgaarb_fd, buf, len);
+    ret = vgaarb_write(pci_sys->vgaarb_fd, buf, len);
+    if (ret)
+       return ret;
+
+    ret = read(pci_sys->vgaarb_fd, buf, BUFSIZE);
+    if (ret <= 0)
+       return -1;
+
+    rsrc = parse_string_to_decodes_rsrc(buf, &pci_sys->vga_count);
+    if (dev)
+        dev->vgaarb_rsrc = rsrc;
+    return 0;
 }
 
 int
-pci_device_vgaarb_decodes(struct pci_device *dev)
+pci_device_vgaarb_decodes(struct pci_device *dev, int new_vgaarb_rsrc)
 {
     int len;
     char buf[BUFSIZE];
+    int ret;
 
-    len = snprintf(buf, BUFSIZE, "decodes %s", rsrc_to_str(dev->vgaarb_rsrc));
+    if (dev->vgaarb_rsrc == new_vgaarb_rsrc)
+       return 0;
 
-    return vgaarb_write(dev->vgaarb_fd, buf, len);
+    len = snprintf(buf, BUFSIZE, "decodes %s", rsrc_to_str(dev->vgaarb_rsrc));
+    ret = vgaarb_write(pci_sys->vgaarb_fd, buf, len);
+    if (ret == 0)
+        dev->vgaarb_rsrc = new_vgaarb_rsrc;
+    return ret;
 }
 
 int
@@ -140,9 +214,12 @@ pci_device_vgaarb_lock(struct pci_device *dev)
     int len;
     char buf[BUFSIZE];
 
+    if (dev->vgaarb_rsrc == 0 || pci_sys->vga_count == 1)
+        return 0;
+
     len = snprintf(buf, BUFSIZE, "lock %s", rsrc_to_str(dev->vgaarb_rsrc));
 
-    return vgaarb_write(dev->vgaarb_fd, buf, len);
+    return vgaarb_write(pci_sys->vgaarb_fd, buf, len);
 }
 
 int
@@ -151,9 +228,12 @@ pci_device_vgaarb_trylock(struct pci_device *dev)
     int len;
     char buf[BUFSIZE];
 
+    if (dev->vgaarb_rsrc == 0 || pci_sys->vga_count == 1)
+        return 0;
+
     len = snprintf(buf, BUFSIZE, "trylock %s", rsrc_to_str(dev->vgaarb_rsrc));
 
-    return vgaarb_write(dev->vgaarb_fd, buf, len);
+    return vgaarb_write(pci_sys->vgaarb_fd, buf, len);
 }
 
 int
@@ -162,7 +242,10 @@ pci_device_vgaarb_unlock(struct pci_device *dev)
     int len;
     char buf[BUFSIZE];
 
+    if (dev->vgaarb_rsrc == 0 || pci_sys->vga_count == 1)
+        return 0;
+
     len = snprintf(buf, BUFSIZE, "unlock %s", rsrc_to_str(dev->vgaarb_rsrc));
 
-    return vgaarb_write(dev->vgaarb_fd, buf, len);
+    return vgaarb_write(pci_sys->vgaarb_fd, buf, len);
 }