- Add support for default vga arb device selection
- Update libpciaccess VGA arb code for newer kernel API
This commit is contained in:
		
							parent
							
								
									9d137967fc
								
							
						
					
					
						commit
						dc71c21f80
					
				| @ -1,88 +1,6 @@ | ||||
| diff -up libpciaccess-0.10.6/include/pciaccess.h.da libpciaccess-0.10.6/include/pciaccess.h
 | ||||
| --- libpciaccess-0.10.6/include/pciaccess.h.da	2009-07-31 11:29:24.000000000 +1000
 | ||||
| +++ libpciaccess-0.10.6/include/pciaccess.h	2009-07-31 11:29:36.000000000 +1000
 | ||||
| @@ -21,6 +21,31 @@
 | ||||
|   * FROM, OUT OF OR IN CONNECTION WITH THE SOFTWARE OR THE USE OR OTHER | ||||
|   * DEALINGS IN THE SOFTWARE. | ||||
|   */ | ||||
| +/*
 | ||||
| + * Copyright (c) 2007 Paulo R. Zanoni, Tiago Vignatti
 | ||||
| + *
 | ||||
| + * Permission is hereby granted, free of charge, to any person
 | ||||
| + * obtaining a copy of this software and associated documentation
 | ||||
| + * files (the "Software"), to deal in the Software without
 | ||||
| + * restriction, including without limitation the rights to use,
 | ||||
| + * copy, modify, merge, publish, distribute, sublicense, and/or sell
 | ||||
| + * copies of the Software, and to permit persons to whom the
 | ||||
| + * Software is furnished to do so, subject to the following
 | ||||
| + * conditions:
 | ||||
| + *
 | ||||
| + * The above copyright notice and this permission notice shall be
 | ||||
| + * included in all copies or substantial portions of the Software.
 | ||||
| + *
 | ||||
| + * THE SOFTWARE IS PROVIDED "AS IS", WITHOUT WARRANTY OF ANY KIND,
 | ||||
| + * EXPRESS OR IMPLIED, INCLUDING BUT NOT LIMITED TO THE WARRANTIES
 | ||||
| + * OF MERCHANTABILITY, FITNESS FOR A PARTICULAR PURPOSE AND
 | ||||
| + * NONINFRINGEMENT. IN NO EVENT SHALL THE AUTHORS OR COPYRIGHT
 | ||||
| + * HOLDERS BE LIABLE FOR ANY CLAIM, DAMAGES OR OTHER LIABILITY,
 | ||||
| + * WHETHER IN AN ACTION OF CONTRACT, TORT OR OTHERWISE, ARISING
 | ||||
| + * FROM, OUT OF OR IN CONNECTION WITH THE SOFTWARE OR THE USE OR
 | ||||
| + * OTHER DEALINGS IN THE SOFTWARE.
 | ||||
| + *
 | ||||
| + */
 | ||||
|   | ||||
|  /** | ||||
|   * \file pciaccess.h | ||||
| @@ -50,6 +75,8 @@ struct pci_slot_match;
 | ||||
|  extern "C" { | ||||
|  #endif | ||||
|   | ||||
| +int pci_device_has_kernel_driver(struct pci_device *dev);
 | ||||
| +
 | ||||
|  int pci_device_is_boot_vga(struct pci_device *dev); | ||||
|   | ||||
|  int pci_device_read_rom(struct pci_device *dev, void *buffer); | ||||
| @@ -350,6 +377,11 @@ struct pci_device {
 | ||||
|       * the \c pci_device structure. | ||||
|       */ | ||||
|      intptr_t user_data; | ||||
| +
 | ||||
| +    /**
 | ||||
| +      * Used by the VGA arbiter. Type of resource decoded by the device and
 | ||||
| +      * the file descriptor (/dev/vga_arbiter). */
 | ||||
| +    int vgaarb_rsrc;
 | ||||
|  }; | ||||
|   | ||||
|   | ||||
| @@ -449,4 +481,25 @@ struct pci_pcmcia_bridge_info {
 | ||||
|   | ||||
|  }; | ||||
|   | ||||
| +
 | ||||
| +/**
 | ||||
| + * VGA Arbiter definitions, functions and related.
 | ||||
| + */
 | ||||
| +
 | ||||
| +/* Legacy VGA regions */
 | ||||
| +#define VGA_ARB_RSRC_NONE       0x00
 | ||||
| +#define VGA_ARB_RSRC_LEGACY_IO  0x01
 | ||||
| +#define VGA_ARB_RSRC_LEGACY_MEM 0x02
 | ||||
| +/* Non-legacy access */
 | ||||
| +#define VGA_ARB_RSRC_NORMAL_IO  0x04
 | ||||
| +#define VGA_ARB_RSRC_NORMAL_MEM 0x08
 | ||||
| +
 | ||||
| +int  pci_device_vgaarb_init         (void);
 | ||||
| +void pci_device_vgaarb_fini         (void);
 | ||||
| +int  pci_device_vgaarb_set_target   (struct pci_device *dev);
 | ||||
| +int  pci_device_vgaarb_decodes      (struct pci_device *dev, int new_vga_rsrc);
 | ||||
| +int  pci_device_vgaarb_lock         (struct pci_device *dev);
 | ||||
| +int  pci_device_vgaarb_trylock      (struct pci_device *dev);
 | ||||
| +int  pci_device_vgaarb_unlock       (struct pci_device *dev);
 | ||||
| +
 | ||||
|  #endif /* PCIACCESS_H */ | ||||
| diff -up libpciaccess-0.10.6/src/common_interface.c.da libpciaccess-0.10.6/src/common_interface.c
 | ||||
| --- libpciaccess-0.10.6/src/common_interface.c.da	2009-07-31 11:29:24.000000000 +1000
 | ||||
| +++ libpciaccess-0.10.6/src/common_interface.c	2009-07-31 11:29:36.000000000 +1000
 | ||||
| --- libpciaccess-0.10.6/src/common_interface.c.da	2009-08-03 09:57:13.000000000 +1000
 | ||||
| +++ libpciaccess-0.10.6/src/common_interface.c	2009-08-03 09:57:21.000000000 +1000
 | ||||
| @@ -124,6 +124,21 @@ pci_device_is_boot_vga( struct pci_devic
 | ||||
|  } | ||||
|   | ||||
| @ -105,258 +23,9 @@ diff -up libpciaccess-0.10.6/src/common_interface.c.da libpciaccess-0.10.6/src/c | ||||
|   * Probe a PCI device to learn information about the device. | ||||
|   *  | ||||
|   * Probes a PCI device to learn various information about the device.  Before | ||||
| diff -up /dev/null libpciaccess-0.10.6/src/common_vgaarb.c
 | ||||
| --- /dev/null	2009-07-28 15:36:51.159175345 +1000
 | ||||
| +++ libpciaccess-0.10.6/src/common_vgaarb.c	2009-07-31 11:29:36.000000000 +1000
 | ||||
| @@ -0,0 +1,245 @@
 | ||||
| +/*
 | ||||
| + * Copyright (c) 2007 Paulo R. Zanoni, Tiago Vignatti
 | ||||
| + *               2009 Tiago Vignatti
 | ||||
| + *
 | ||||
| + * Permission is hereby granted, free of charge, to any person
 | ||||
| + * obtaining a copy of this software and associated documentation
 | ||||
| + * files (the "Software"), to deal in the Software without
 | ||||
| + * restriction, including without limitation the rights to use,
 | ||||
| + * copy, modify, merge, publish, distribute, sublicense, and/or sell
 | ||||
| + * copies of the Software, and to permit persons to whom the
 | ||||
| + * Software is furnished to do so, subject to the following
 | ||||
| + * conditions:
 | ||||
| + *
 | ||||
| + * The above copyright notice and this permission notice shall be
 | ||||
| + * included in all copies or substantial portions of the Software.
 | ||||
| + *
 | ||||
| + * THE SOFTWARE IS PROVIDED "AS IS", WITHOUT WARRANTY OF ANY KIND,
 | ||||
| + * EXPRESS OR IMPLIED, INCLUDING BUT NOT LIMITED TO THE WARRANTIES
 | ||||
| + * OF MERCHANTABILITY, FITNESS FOR A PARTICULAR PURPOSE AND
 | ||||
| + * NONINFRINGEMENT. IN NO EVENT SHALL THE AUTHORS OR COPYRIGHT
 | ||||
| + * HOLDERS BE LIABLE FOR ANY CLAIM, DAMAGES OR OTHER LIABILITY,
 | ||||
| + * WHETHER IN AN ACTION OF CONTRACT, TORT OR OTHERWISE, ARISING
 | ||||
| + * FROM, OUT OF OR IN CONNECTION WITH THE SOFTWARE OR THE USE OR
 | ||||
| + * OTHER DEALINGS IN THE SOFTWARE.
 | ||||
| + *
 | ||||
| + */
 | ||||
| +
 | ||||
| +#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 64
 | ||||
| +
 | ||||
| +int
 | ||||
| +pci_device_vgaarb_init(void)
 | ||||
| +{
 | ||||
| +    if ((pci_sys->vgaarb_fd = open ("/dev/vga_arbiter", O_RDWR)) < 0) {
 | ||||
| +        return errno;
 | ||||
| +    }
 | ||||
| +
 | ||||
| +    return 0;
 | ||||
| +}
 | ||||
| +
 | ||||
| +void
 | ||||
| +pci_device_vgaarb_fini(void)
 | ||||
| +{
 | ||||
| +    close(pci_sys->vgaarb_fd);
 | ||||
| +}
 | ||||
| +
 | ||||
| +/**
 | ||||
| + * Writes message on vga device. The messages are defined by the kernel
 | ||||
| + * implementation.
 | ||||
| + *
 | ||||
| + * \param fd    vga arbiter device.
 | ||||
| + * \param buf   message itself.
 | ||||
| + * \param len   message length.
 | ||||
| + *
 | ||||
| + * \return
 | ||||
| + * Zero on success, 1 if something gets wrong and 2 if fd is busy (only for
 | ||||
| + * 'trylock')
 | ||||
| + */
 | ||||
| +static int
 | ||||
| +vgaarb_write(int fd, char *buf, int len)
 | ||||
| +{
 | ||||
| +    int ret;
 | ||||
| +
 | ||||
| +
 | ||||
| +    buf[len] = '\0';
 | ||||
| +
 | ||||
| +    ret = write(fd, buf, len);
 | ||||
| +    if (ret == -1) {
 | ||||
| +        /* the user may have called "trylock" and didn't get the lock */
 | ||||
| +        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;
 | ||||
| +    }
 | ||||
| +
 | ||||
| +#ifdef DEBUG
 | ||||
| +    fprintf(stderr, "%s: successfully wrote: '%s'\n", __FUNCTION__, buf);
 | ||||
| +#endif
 | ||||
| +
 | ||||
| +    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)
 | ||||
| +{
 | ||||
| +    switch (iostate) {
 | ||||
| +    case VGA_ARB_RSRC_LEGACY_IO | VGA_ARB_RSRC_LEGACY_MEM:
 | ||||
| +        return "io+mem";
 | ||||
| +    case VGA_ARB_RSRC_LEGACY_IO:
 | ||||
| +        return "io";
 | ||||
| +    case VGA_ARB_RSRC_LEGACY_MEM:
 | ||||
| +        return "mem";
 | ||||
| +    }
 | ||||
| +
 | ||||
| +    return "none";
 | ||||
| +}
 | ||||
| +
 | ||||
| +int
 | ||||
| +pci_device_vgaarb_set_target(struct pci_device *dev)
 | ||||
| +{
 | ||||
| +    int len;
 | ||||
| +    char buf[BUFSIZE];
 | ||||
| +    int ret;
 | ||||
| +
 | ||||
| +    len = snprintf(buf, BUFSIZE, "target PCI:%d:%d:%d.%d",
 | ||||
| +                   dev->domain, dev->bus, dev->dev, dev->func);
 | ||||
| +
 | ||||
| +    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;
 | ||||
| +
 | ||||
| +    dev->vgaarb_rsrc = parse_string_to_decodes_rsrc(buf, &pci_sys->vga_count);
 | ||||
| +    return 0;
 | ||||
| +}
 | ||||
| +
 | ||||
| +int
 | ||||
| +pci_device_vgaarb_decodes(struct pci_device *dev, int new_vgaarb_rsrc)
 | ||||
| +{
 | ||||
| +    int len;
 | ||||
| +    char buf[BUFSIZE];
 | ||||
| +    int ret;
 | ||||
| +
 | ||||
| +    if (dev->vgaarb_rsrc == new_vgaarb_rsrc)
 | ||||
| +	return 0;
 | ||||
| +
 | ||||
| +    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
 | ||||
| +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(pci_sys->vgaarb_fd, buf, len);
 | ||||
| +}
 | ||||
| +
 | ||||
| +int
 | ||||
| +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(pci_sys->vgaarb_fd, buf, len);
 | ||||
| +}
 | ||||
| +
 | ||||
| +int
 | ||||
| +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(pci_sys->vgaarb_fd, buf, len);
 | ||||
| +}
 | ||||
| diff -up /dev/null libpciaccess-0.10.6/src/common_vgaarb_stub.c
 | ||||
| --- /dev/null	2009-07-28 15:36:51.159175345 +1000
 | ||||
| +++ libpciaccess-0.10.6/src/common_vgaarb_stub.c	2009-07-31 11:29:36.000000000 +1000
 | ||||
| --- /dev/null	2009-08-03 09:43:13.273251881 +1000
 | ||||
| +++ libpciaccess-0.10.6/src/common_vgaarb_stub.c	2009-08-03 09:57:21.000000000 +1000
 | ||||
| @@ -0,0 +1,73 @@
 | ||||
| +/*
 | ||||
| + * Copyright (c) 2009 Tiago Vignatti
 | ||||
| @ -432,8 +101,8 @@ diff -up /dev/null libpciaccess-0.10.6/src/common_vgaarb_stub.c | ||||
| +    return 0;
 | ||||
| +}
 | ||||
| diff -up libpciaccess-0.10.6/src/linux_sysfs.c.da libpciaccess-0.10.6/src/linux_sysfs.c
 | ||||
| --- libpciaccess-0.10.6/src/linux_sysfs.c.da	2009-07-31 11:29:24.000000000 +1000
 | ||||
| +++ libpciaccess-0.10.6/src/linux_sysfs.c	2009-07-31 11:29:36.000000000 +1000
 | ||||
| --- libpciaccess-0.10.6/src/linux_sysfs.c.da	2009-08-03 09:57:13.000000000 +1000
 | ||||
| +++ libpciaccess-0.10.6/src/linux_sysfs.c	2009-08-03 09:57:21.000000000 +1000
 | ||||
| @@ -78,6 +78,7 @@ static int pci_device_linux_sysfs_write(
 | ||||
|      pciaddr_t * bytes_written ); | ||||
|   | ||||
| @ -473,9 +142,327 @@ diff -up libpciaccess-0.10.6/src/linux_sysfs.c.da libpciaccess-0.10.6/src/linux_ | ||||
| +	return 0;
 | ||||
| +    return 1;
 | ||||
| +}
 | ||||
| diff -up /dev/null libpciaccess-0.10.6/src/common_vgaarb.c
 | ||||
| --- /dev/null	2009-08-03 09:43:13.273251881 +1000
 | ||||
| +++ libpciaccess-0.10.6/src/common_vgaarb.c	2009-08-03 09:57:21.000000000 +1000
 | ||||
| @@ -0,0 +1,314 @@
 | ||||
| +/*
 | ||||
| + * Copyright (c) 2007 Paulo R. Zanoni, Tiago Vignatti
 | ||||
| + *               2009 Tiago Vignatti
 | ||||
| + *
 | ||||
| + * Permission is hereby granted, free of charge, to any person
 | ||||
| + * obtaining a copy of this software and associated documentation
 | ||||
| + * files (the "Software"), to deal in the Software without
 | ||||
| + * restriction, including without limitation the rights to use,
 | ||||
| + * copy, modify, merge, publish, distribute, sublicense, and/or sell
 | ||||
| + * copies of the Software, and to permit persons to whom the
 | ||||
| + * Software is furnished to do so, subject to the following
 | ||||
| + * conditions:
 | ||||
| + *
 | ||||
| + * The above copyright notice and this permission notice shall be
 | ||||
| + * included in all copies or substantial portions of the Software.
 | ||||
| + *
 | ||||
| + * THE SOFTWARE IS PROVIDED "AS IS", WITHOUT WARRANTY OF ANY KIND,
 | ||||
| + * EXPRESS OR IMPLIED, INCLUDING BUT NOT LIMITED TO THE WARRANTIES
 | ||||
| + * OF MERCHANTABILITY, FITNESS FOR A PARTICULAR PURPOSE AND
 | ||||
| + * NONINFRINGEMENT. IN NO EVENT SHALL THE AUTHORS OR COPYRIGHT
 | ||||
| + * HOLDERS BE LIABLE FOR ANY CLAIM, DAMAGES OR OTHER LIABILITY,
 | ||||
| + * WHETHER IN AN ACTION OF CONTRACT, TORT OR OTHERWISE, ARISING
 | ||||
| + * FROM, OUT OF OR IN CONNECTION WITH THE SOFTWARE OR THE USE OR
 | ||||
| + * OTHER DEALINGS IN THE SOFTWARE.
 | ||||
| + *
 | ||||
| + */
 | ||||
| +
 | ||||
| +#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 64
 | ||||
| +
 | ||||
| +static int
 | ||||
| +parse_string_to_decodes_rsrc(char *input, int *vga_count, struct pci_slot_match *match)
 | ||||
| +{
 | ||||
| +    char *tok;
 | ||||
| +    char *input_sp, *count_sp, *pci_sp;
 | ||||
| +    char tmp[32];
 | ||||
| +
 | ||||
| +    tok = strtok_r(input,",",&input_sp);
 | ||||
| +    if (!tok)
 | ||||
| +	goto fail;
 | ||||
| +
 | ||||
| +    strncpy(tmp, input, 15);
 | ||||
| +    tmp[15] = 0;
 | ||||
| +
 | ||||
| +    tok = strtok_r(tmp,":",&count_sp);
 | ||||
| +    if (!tok)
 | ||||
| +	goto fail;
 | ||||
| +    tok = strtok_r(NULL, ":",&count_sp);
 | ||||
| +    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_r(NULL, ",",&input_sp);
 | ||||
| +    if (!tok)
 | ||||
| +	goto fail;
 | ||||
| +
 | ||||
| +    if (match) {
 | ||||
| +	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_r(NULL, ",",&input_sp);
 | ||||
| +    if (!tok)
 | ||||
| +	goto fail;
 | ||||
| +    tok = strtok_r(tok, "=", &input_sp);
 | ||||
| +    if (!tok)
 | ||||
| +	goto fail;
 | ||||
| +    tok = strtok_r(NULL, "=", &input_sp);
 | ||||
| +    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;
 | ||||
| +}
 | ||||
| +
 | ||||
| +int
 | ||||
| +pci_device_vgaarb_init(void)
 | ||||
| +{
 | ||||
| +    struct pci_slot_match match;
 | ||||
| +    char buf[BUFSIZE];
 | ||||
| +    int ret, rsrc;
 | ||||
| +    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;
 | ||||
| +
 | ||||
| +    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;
 | ||||
| +}
 | ||||
| +
 | ||||
| +void
 | ||||
| +pci_device_vgaarb_fini(void)
 | ||||
| +{
 | ||||
| +    close(pci_sys->vgaarb_fd);
 | ||||
| +}
 | ||||
| +
 | ||||
| +/**
 | ||||
| + * Writes message on vga device. The messages are defined by the kernel
 | ||||
| + * implementation.
 | ||||
| + *
 | ||||
| + * \param fd    vga arbiter device.
 | ||||
| + * \param buf   message itself.
 | ||||
| + * \param len   message length.
 | ||||
| + *
 | ||||
| + * \return
 | ||||
| + * Zero on success, 1 if something gets wrong and 2 if fd is busy (only for
 | ||||
| + * 'trylock')
 | ||||
| + */
 | ||||
| +static int
 | ||||
| +vgaarb_write(int fd, char *buf, int len)
 | ||||
| +{
 | ||||
| +    int ret;
 | ||||
| +
 | ||||
| +
 | ||||
| +    buf[len] = '\0';
 | ||||
| +
 | ||||
| +    ret = write(fd, buf, len);
 | ||||
| +    if (ret == -1) {
 | ||||
| +        /* the user may have called "trylock" and didn't get the lock */
 | ||||
| +        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;
 | ||||
| +    }
 | ||||
| +
 | ||||
| +#ifdef DEBUG
 | ||||
| +    fprintf(stderr, "%s: successfully wrote: '%s'\n", __FUNCTION__, buf);
 | ||||
| +#endif
 | ||||
| +
 | ||||
| +    return 0;
 | ||||
| +}
 | ||||
| +
 | ||||
| +
 | ||||
| +static const char *
 | ||||
| +rsrc_to_str(int iostate)
 | ||||
| +{
 | ||||
| +    switch (iostate) {
 | ||||
| +    case VGA_ARB_RSRC_LEGACY_IO | VGA_ARB_RSRC_LEGACY_MEM:
 | ||||
| +        return "io+mem";
 | ||||
| +    case VGA_ARB_RSRC_LEGACY_IO:
 | ||||
| +        return "io";
 | ||||
| +    case VGA_ARB_RSRC_LEGACY_MEM:
 | ||||
| +        return "mem";
 | ||||
| +    }
 | ||||
| +
 | ||||
| +    return "none";
 | ||||
| +}
 | ||||
| +
 | ||||
| +int
 | ||||
| +pci_device_vgaarb_set_target(struct pci_device *dev)
 | ||||
| +{
 | ||||
| +    int len;
 | ||||
| +    char buf[BUFSIZE];
 | ||||
| +    int ret;
 | ||||
| +
 | ||||
| +    if (!dev)
 | ||||
| +	dev = pci_sys->vga_default_dev;
 | ||||
| +    if (!dev)
 | ||||
| +	return -1;
 | ||||
| +
 | ||||
| +    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;
 | ||||
| +
 | ||||
| +    ret = read(pci_sys->vgaarb_fd, buf, BUFSIZE);
 | ||||
| +    if (ret <= 0)
 | ||||
| +	return -1;
 | ||||
| +
 | ||||
| +    dev->vgaarb_rsrc = parse_string_to_decodes_rsrc(buf, &pci_sys->vga_count, NULL);
 | ||||
| +    pci_sys->vga_target = dev;
 | ||||
| +    return 0;
 | ||||
| +}
 | ||||
| +
 | ||||
| +int
 | ||||
| +pci_device_vgaarb_decodes(int new_vgaarb_rsrc)
 | ||||
| +{
 | ||||
| +    int len;
 | ||||
| +    char buf[BUFSIZE];
 | ||||
| +    int ret;
 | ||||
| +    struct pci_device *dev = pci_sys->vga_target;
 | ||||
| +
 | ||||
| +    if (!dev)
 | ||||
| +	return -1;
 | ||||
| +    if (dev->vgaarb_rsrc == new_vgaarb_rsrc)
 | ||||
| +	return 0;
 | ||||
| +
 | ||||
| +    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
 | ||||
| +pci_device_vgaarb_lock(void)
 | ||||
| +{
 | ||||
| +    int len;
 | ||||
| +    char buf[BUFSIZE];
 | ||||
| +    struct pci_device *dev = pci_sys->vga_target;
 | ||||
| +
 | ||||
| +    if (!dev)
 | ||||
| +	return -1;
 | ||||
| +
 | ||||
| +    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(pci_sys->vgaarb_fd, buf, len);
 | ||||
| +}
 | ||||
| +
 | ||||
| +int
 | ||||
| +pci_device_vgaarb_trylock(void)
 | ||||
| +{
 | ||||
| +    int len;
 | ||||
| +    char buf[BUFSIZE];
 | ||||
| +    struct pci_device *dev = pci_sys->vga_target;
 | ||||
| +
 | ||||
| +    if (!dev)
 | ||||
| +	return -1;
 | ||||
| +
 | ||||
| +    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(pci_sys->vgaarb_fd, buf, len);
 | ||||
| +}
 | ||||
| +
 | ||||
| +int
 | ||||
| +pci_device_vgaarb_unlock(void)
 | ||||
| +{
 | ||||
| +    int len;
 | ||||
| +    char buf[BUFSIZE];
 | ||||
| +    struct pci_device *dev = pci_sys->vga_target;
 | ||||
| +
 | ||||
| +    if (!dev)
 | ||||
| +	return -1;
 | ||||
| +
 | ||||
| +    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(pci_sys->vgaarb_fd, buf, len);
 | ||||
| +}
 | ||||
| diff -up libpciaccess-0.10.6/src/Makefile.am.da libpciaccess-0.10.6/src/Makefile.am
 | ||||
| --- libpciaccess-0.10.6/src/Makefile.am.da	2009-04-18 15:01:36.000000000 +1000
 | ||||
| +++ libpciaccess-0.10.6/src/Makefile.am	2009-07-31 11:29:36.000000000 +1000
 | ||||
| +++ libpciaccess-0.10.6/src/Makefile.am	2009-08-03 09:57:21.000000000 +1000
 | ||||
| @@ -45,6 +45,12 @@ if SOLARIS
 | ||||
|  OS_SUPPORT = solx_devfs.c pci_tools.h | ||||
|  endif | ||||
| @ -498,8 +485,8 @@ diff -up libpciaccess-0.10.6/src/Makefile.am.da libpciaccess-0.10.6/src/Makefile | ||||
|   | ||||
|  INCLUDES = -I$(top_srcdir)/include | ||||
| diff -up libpciaccess-0.10.6/src/pciaccess_private.h.da libpciaccess-0.10.6/src/pciaccess_private.h
 | ||||
| --- libpciaccess-0.10.6/src/pciaccess_private.h.da	2009-07-31 11:29:24.000000000 +1000
 | ||||
| +++ libpciaccess-0.10.6/src/pciaccess_private.h	2009-07-31 11:29:36.000000000 +1000
 | ||||
| --- libpciaccess-0.10.6/src/pciaccess_private.h.da	2009-08-03 09:57:13.000000000 +1000
 | ||||
| +++ libpciaccess-0.10.6/src/pciaccess_private.h	2009-08-03 09:57:21.000000000 +1000
 | ||||
| @@ -61,6 +61,7 @@ struct pci_system_methods {
 | ||||
|      int (*fill_capabilities)( struct pci_device * dev ); | ||||
|      void (*enable)( struct pci_device *dev ); | ||||
| @ -508,12 +495,97 @@ diff -up libpciaccess-0.10.6/src/pciaccess_private.h.da libpciaccess-0.10.6/src/ | ||||
|  }; | ||||
|   | ||||
|  struct pci_device_mapping { | ||||
| @@ -131,6 +132,8 @@ struct pci_system {
 | ||||
| @@ -131,6 +132,10 @@ struct pci_system {
 | ||||
|  #ifdef HAVE_MTRR | ||||
|      int mtrr_fd; | ||||
|  #endif | ||||
| +    int vgaarb_fd;
 | ||||
| +    int vga_count;
 | ||||
| +    struct pci_device *vga_target;
 | ||||
| +    struct pci_device *vga_default_dev;
 | ||||
|  }; | ||||
|   | ||||
|  extern struct pci_system * pci_sys; | ||||
| diff -up libpciaccess-0.10.6/include/pciaccess.h.da libpciaccess-0.10.6/include/pciaccess.h
 | ||||
| --- libpciaccess-0.10.6/include/pciaccess.h.da	2009-08-03 09:57:13.000000000 +1000
 | ||||
| +++ libpciaccess-0.10.6/include/pciaccess.h	2009-08-03 09:57:21.000000000 +1000
 | ||||
| @@ -21,6 +21,31 @@
 | ||||
|   * FROM, OUT OF OR IN CONNECTION WITH THE SOFTWARE OR THE USE OR OTHER | ||||
|   * DEALINGS IN THE SOFTWARE. | ||||
|   */ | ||||
| +/*
 | ||||
| + * Copyright (c) 2007 Paulo R. Zanoni, Tiago Vignatti
 | ||||
| + *
 | ||||
| + * Permission is hereby granted, free of charge, to any person
 | ||||
| + * obtaining a copy of this software and associated documentation
 | ||||
| + * files (the "Software"), to deal in the Software without
 | ||||
| + * restriction, including without limitation the rights to use,
 | ||||
| + * copy, modify, merge, publish, distribute, sublicense, and/or sell
 | ||||
| + * copies of the Software, and to permit persons to whom the
 | ||||
| + * Software is furnished to do so, subject to the following
 | ||||
| + * conditions:
 | ||||
| + *
 | ||||
| + * The above copyright notice and this permission notice shall be
 | ||||
| + * included in all copies or substantial portions of the Software.
 | ||||
| + *
 | ||||
| + * THE SOFTWARE IS PROVIDED "AS IS", WITHOUT WARRANTY OF ANY KIND,
 | ||||
| + * EXPRESS OR IMPLIED, INCLUDING BUT NOT LIMITED TO THE WARRANTIES
 | ||||
| + * OF MERCHANTABILITY, FITNESS FOR A PARTICULAR PURPOSE AND
 | ||||
| + * NONINFRINGEMENT. IN NO EVENT SHALL THE AUTHORS OR COPYRIGHT
 | ||||
| + * HOLDERS BE LIABLE FOR ANY CLAIM, DAMAGES OR OTHER LIABILITY,
 | ||||
| + * WHETHER IN AN ACTION OF CONTRACT, TORT OR OTHERWISE, ARISING
 | ||||
| + * FROM, OUT OF OR IN CONNECTION WITH THE SOFTWARE OR THE USE OR
 | ||||
| + * OTHER DEALINGS IN THE SOFTWARE.
 | ||||
| + *
 | ||||
| + */
 | ||||
|   | ||||
|  /** | ||||
|   * \file pciaccess.h | ||||
| @@ -50,6 +75,8 @@ struct pci_slot_match;
 | ||||
|  extern "C" { | ||||
|  #endif | ||||
|   | ||||
| +int pci_device_has_kernel_driver(struct pci_device *dev);
 | ||||
| +
 | ||||
|  int pci_device_is_boot_vga(struct pci_device *dev); | ||||
|   | ||||
|  int pci_device_read_rom(struct pci_device *dev, void *buffer); | ||||
| @@ -350,6 +377,11 @@ struct pci_device {
 | ||||
|       * the \c pci_device structure. | ||||
|       */ | ||||
|      intptr_t user_data; | ||||
| +
 | ||||
| +    /**
 | ||||
| +      * Used by the VGA arbiter. Type of resource decoded by the device and
 | ||||
| +      * the file descriptor (/dev/vga_arbiter). */
 | ||||
| +    int vgaarb_rsrc;
 | ||||
|  }; | ||||
|   | ||||
|   | ||||
| @@ -449,4 +481,26 @@ struct pci_pcmcia_bridge_info {
 | ||||
|   | ||||
|  }; | ||||
|   | ||||
| +
 | ||||
| +/**
 | ||||
| + * VGA Arbiter definitions, functions and related.
 | ||||
| + */
 | ||||
| +
 | ||||
| +/* Legacy VGA regions */
 | ||||
| +#define VGA_ARB_RSRC_NONE       0x00
 | ||||
| +#define VGA_ARB_RSRC_LEGACY_IO  0x01
 | ||||
| +#define VGA_ARB_RSRC_LEGACY_MEM 0x02
 | ||||
| +/* Non-legacy access */
 | ||||
| +#define VGA_ARB_RSRC_NORMAL_IO  0x04
 | ||||
| +#define VGA_ARB_RSRC_NORMAL_MEM 0x08
 | ||||
| +
 | ||||
| +int  pci_device_vgaarb_init         (void);
 | ||||
| +void pci_device_vgaarb_fini         (void);
 | ||||
| +int  pci_device_vgaarb_set_target   (struct pci_device *dev);
 | ||||
| +/* use the targetted device */
 | ||||
| +int  pci_device_vgaarb_decodes      (int new_vga_rsrc);
 | ||||
| +int  pci_device_vgaarb_lock         (void);
 | ||||
| +int  pci_device_vgaarb_trylock      (void);
 | ||||
| +int  pci_device_vgaarb_unlock       (void);
 | ||||
| +
 | ||||
|  #endif /* PCIACCESS_H */ | ||||
|  | ||||
| @ -3,7 +3,7 @@ | ||||
| 
 | ||||
| Name:           libpciaccess | ||||
| Version:        0.10.6 | ||||
| Release:        3%{?dist} | ||||
| Release:        4%{?dist} | ||||
| Summary:        PCI access library | ||||
| 
 | ||||
| Group:          System Environment/Libraries | ||||
| @ -74,6 +74,10 @@ rm -rf $RPM_BUILD_ROOT | ||||
| %{_libdir}/pkgconfig/pciaccess.pc | ||||
| 
 | ||||
| %changelog | ||||
| * Mon Aug 03 2009 Dave Airlie <airlied@redhat.com> 0.10.6-4 | ||||
| - Add support for default vga arb device selection | ||||
| - Update libpciaccess VGA arb code for newer kernel API | ||||
| 
 | ||||
| * Fri Jul 31 2009 Dave Airlie <airlied@redhat.com> 0.10.6-3 | ||||
| - enable autoreconf to rebuild configure properly | ||||
| 
 | ||||
|  | ||||
		Loading…
	
		Reference in New Issue
	
	Block a user