Fix long standing MTRR bug.
[platform/upstream/libpciaccess.git] / src / common_vgaarb.c
index 5d46d70..86eceb5 100644 (file)
@@ -33,6 +33,7 @@
 #include <stdlib.h>
 #include <limits.h>
 
+#include "config.h"
 #include "pciaccess.h"
 #include "pciaccess_private.h"
 
@@ -42,68 +43,78 @@ static int
 parse_string_to_decodes_rsrc(char *input, int *vga_count, struct pci_slot_match *match)
 {
     char *tok;
-    char count[16];
+    char *input_sp = NULL, *count_sp, *pci_sp;
+    char tmp[32];
 
-    strncpy(count, input, 10);
-    count[11] = 0;
+    tok = strtok_r(input,",",&input_sp);
+    if (!tok)
+        goto fail;
+
+    strncpy(tmp, input, 15);
+    tmp[15] = 0;
 
-    tok = strtok(count,":");
+    tok = strtok_r(tmp,":",&count_sp);
     if (!tok)
-       goto fail;
-    tok = strtok(NULL, "");
+        goto fail;
+    tok = strtok_r(NULL, ":",&count_sp);
     if (!tok)
-       goto fail;
+        goto fail;
 
     *vga_count = strtoul(tok, NULL, 10);
     if (*vga_count == LONG_MAX)
-       goto fail;
+        goto fail;
 
 #ifdef DEBUG
     fprintf(stderr,"vga count is %d\n", *vga_count);
 #endif
 
-    tok = strtok(input, ",");
+    tok = strtok_r(NULL, ",",&input_sp);
     if (!tok)
-       goto fail;
+        goto fail;
 
     if (match) {
-       tok = strtok(NULL, ":");
-       if (!tok)
-           goto fail;
-       match->domain = strtoul(tok, NULL, 16);
-
-       tok = strtok(NULL, ":");
-       if (!tok)
-           goto fail;
-       match->bus = strtoul(tok, NULL, 16);
-
-       tok = strtok(NULL, ".");
-       if (!tok)
-           goto fail;
-       match->dev = strtoul(tok, NULL, 16);
-
-       tok = strtok(NULL, ".");
-       if (!tok)
-           goto fail;
-       match->func = strtoul(tok, NULL, 16);
+        strncpy(tmp, tok, 32);
+        tmp[31] = 0;
+        tok = strtok_r(tmp, ":", &pci_sp);
+        if (!tok)
+            goto fail;
+        tok = strtok_r(NULL, ":", &pci_sp);
+        if (!tok)
+            goto fail;
+        match->domain = strtoul(tok, NULL, 16);
+
+        tok = strtok_r(NULL, ":", &pci_sp);
+        if (!tok)
+            goto fail;
+        match->bus = strtoul(tok, NULL, 16);
+
+        tok = strtok_r(NULL, ".", &pci_sp);
+        if (!tok)
+            goto fail;
+        match->dev = strtoul(tok, NULL, 16);
+
+        tok = strtok_r(NULL, ".", &pci_sp);
+        if (!tok)
+            goto fail;
+        match->func = strtoul(tok, NULL, 16);
     }
 
-    tok = strtok(NULL, ",");
+    tok = strtok_r(NULL, ",",&input_sp);
     if (!tok)
-       goto fail;
-    tok = strtok(tok, "=");
+        goto fail;
+    tok = strtok_r(tok, "=", &input_sp);
     if (!tok)
-       goto fail;
-    tok = strtok(NULL, "=");
+        goto fail;
+    tok = strtok_r(NULL, "=", &input_sp);
     if (!tok)
-       goto fail;
+        goto fail;
 
     if (!strncmp(tok, "io+mem", 6))
-       return VGA_ARB_RSRC_LEGACY_IO | VGA_ARB_RSRC_LEGACY_MEM;
+        return VGA_ARB_RSRC_LEGACY_IO | VGA_ARB_RSRC_LEGACY_MEM;
     if (!strncmp(tok, "io", 2))
-       return VGA_ARB_RSRC_LEGACY_IO;
+        return VGA_ARB_RSRC_LEGACY_IO;
     if (!strncmp(tok, "mem", 3))
-       return VGA_ARB_RSRC_LEGACY_MEM;
+        return VGA_ARB_RSRC_LEGACY_MEM;
 fail:
     return VGA_ARB_RSRC_NONE;
 }
@@ -114,20 +125,24 @@ pci_device_vgaarb_init(void)
     struct pci_slot_match match;
     char buf[BUFSIZE];
     int ret, rsrc;
+
+    if (!pci_sys)
+        return -1;
+
     if ((pci_sys->vgaarb_fd = open ("/dev/vga_arbiter", O_RDWR)) < 0) {
         return errno;
     }
 
     ret = read(pci_sys->vgaarb_fd, buf, BUFSIZE);
     if (ret <= 0)
-       return -1;
+        return -1;
 
     memset(&match, 0xff, sizeof(match));
     /* need to find the device to go back to and what it was decoding */
     rsrc = parse_string_to_decodes_rsrc(buf, &pci_sys->vga_count, &match);
-    
+
     pci_sys->vga_default_dev = pci_device_find_by_slot(match.domain, match.bus, match.dev, match.func);
-    
+
     if (pci_sys->vga_default_dev)
         pci_sys->vga_default_dev->vgaarb_rsrc = rsrc;
     return 0;
@@ -136,6 +151,9 @@ pci_device_vgaarb_init(void)
 void
 pci_device_vgaarb_fini(void)
 {
+    if (!pci_sys)
+        return;
+
     close(pci_sys->vgaarb_fd);
 }
 
@@ -209,20 +227,20 @@ pci_device_vgaarb_set_target(struct pci_device *dev)
     int ret;
 
     if (!dev)
-       dev = pci_sys->vga_default_dev;
+        dev = pci_sys->vga_default_dev;
     if (!dev)
-       return -1;
+        return -1;
 
-    len = snprintf(buf, BUFSIZE, "target PCI:%d:%d:%d.%d",
+    len = snprintf(buf, BUFSIZE, "target PCI:%04x:%02x:%02x.%x",
                    dev->domain, dev->bus, dev->dev, dev->func);
 
     ret = vgaarb_write(pci_sys->vgaarb_fd, buf, len);
     if (ret)
-       return ret;
+        return ret;
 
     ret = read(pci_sys->vgaarb_fd, buf, BUFSIZE);
     if (ret <= 0)
-       return -1;
+        return -1;
 
     dev->vgaarb_rsrc = parse_string_to_decodes_rsrc(buf, &pci_sys->vga_count, NULL);
     pci_sys->vga_target = dev;
@@ -238,14 +256,21 @@ pci_device_vgaarb_decodes(int new_vgaarb_rsrc)
     struct pci_device *dev = pci_sys->vga_target;
 
     if (!dev)
-       return -1;
+        return -1;
     if (dev->vgaarb_rsrc == new_vgaarb_rsrc)
-       return 0;
+        return 0;
 
-    len = snprintf(buf, BUFSIZE, "decodes %s", rsrc_to_str(dev->vgaarb_rsrc));
+    len = snprintf(buf, BUFSIZE, "decodes %s", rsrc_to_str(new_vgaarb_rsrc));
     ret = vgaarb_write(pci_sys->vgaarb_fd, buf, len);
     if (ret == 0)
         dev->vgaarb_rsrc = new_vgaarb_rsrc;
+
+    ret = read(pci_sys->vgaarb_fd, buf, BUFSIZE);
+    if (ret <= 0)
+        return -1;
+
+    parse_string_to_decodes_rsrc(buf, &pci_sys->vga_count, NULL);
+
     return ret;
 }
 
@@ -275,7 +300,7 @@ pci_device_vgaarb_trylock(void)
     struct pci_device *dev = pci_sys->vga_target;
 
     if (!dev)
-       return -1;
+        return -1;
 
     if (dev->vgaarb_rsrc == 0 || pci_sys->vga_count == 1)
         return 0;
@@ -293,7 +318,7 @@ pci_device_vgaarb_unlock(void)
     struct pci_device *dev = pci_sys->vga_target;
 
     if (!dev)
-       return -1;
+        return -1;
 
     if (dev->vgaarb_rsrc == 0 || pci_sys->vga_count == 1)
         return 0;
@@ -302,3 +327,13 @@ pci_device_vgaarb_unlock(void)
 
     return vgaarb_write(pci_sys->vgaarb_fd, buf, len);
 }
+
+int pci_device_vgaarb_get_info(struct pci_device *dev, int *vga_count, int *rsrc_decodes)
+{
+    *vga_count = pci_sys->vga_count;
+    if (!dev)
+        return 0;
+
+    *rsrc_decodes = dev->vgaarb_rsrc;
+        return 0;
+}