diff --git a/libpciaccess-vga-arbiter.patch b/libpciaccess-vga-arbiter.patch new file mode 100644 index 0000000..88fc0e2 --- /dev/null +++ b/libpciaccess-vga-arbiter.patch @@ -0,0 +1,528 @@ +diff --git a/include/pciaccess.h b/include/pciaccess.h +index 6413ae0..9d68a08 100644 +--- a/include/pciaccess.h ++++ b/include/pciaccess.h +@@ -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 --git a/src/Makefile.am b/src/Makefile.am +index 14f2e48..0de6894 100644 +--- a/src/Makefile.am ++++ b/src/Makefile.am +@@ -45,6 +45,12 @@ if SOLARIS + OS_SUPPORT = solx_devfs.c pci_tools.h + endif + ++if LINUX ++VGA_ARBITER = common_vgaarb.c ++else ++VGA_ARBITER = common_vgaarb_stub.c ++endif ++ + libpciaccess_la_SOURCES = common_bridge.c \ + common_iterator.c \ + common_init.c \ +@@ -53,6 +59,7 @@ libpciaccess_la_SOURCES = common_bridge.c \ + common_device_name.c \ + common_map.c \ + pciaccess_private.h \ ++ $(VGA_ARBITER) \ + $(OS_SUPPORT) + + INCLUDES = -I$(top_srcdir)/include +diff --git a/src/common_interface.c b/src/common_interface.c +index 5dcc707..d46feab 100644 +--- a/src/common_interface.c ++++ b/src/common_interface.c +@@ -124,6 +124,21 @@ pci_device_is_boot_vga( struct pci_device * dev ) + } + + /** ++ * Probe a PCI device to determine if a kernel driver is attached. ++ * ++ * \param dev Device to query ++ * \return ++ * Zero if no driver attached, 1 if attached kernel drviver ++ */ ++int ++pci_device_has_kernel_driver( struct pci_device * dev ) ++{ ++ if (!pci_sys->methods->has_kernel_driver) ++ return 0; ++ return pci_sys->methods->has_kernel_driver( dev ); ++} ++ ++/** + * Probe a PCI device to learn information about the device. + * + * Probes a PCI device to learn various information about the device. Before +diff --git a/src/common_vgaarb.c b/src/common_vgaarb.c +new file mode 100644 +index 0000000..302b89d +--- /dev/null ++++ b/src/common_vgaarb.c +@@ -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 ++#include ++#include ++#include ++#include ++#include ++#include ++ ++#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 --git a/src/common_vgaarb_stub.c b/src/common_vgaarb_stub.c +new file mode 100644 +index 0000000..5fc5dfe +--- /dev/null ++++ b/src/common_vgaarb_stub.c +@@ -0,0 +1,73 @@ ++/* ++ * Copyright (c) 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 ++#include "pciaccess.h" ++ ++int ++pci_device_vgaarb_init(struct pci_device *dev) ++{ ++#ifdef DEBUG ++ fprintf(stderr, "%s: You're using VGA arbiter stub functions!\n", ++ __FUNCTION__); ++#endif ++ return 0; ++} ++ ++void ++pci_device_vgaarb_fini(struct pci_device *dev) ++{ ++} ++ ++int ++pci_device_vgaarb_set_target(struct pci_device *dev) ++{ ++ return 0; ++} ++ ++int ++pci_device_vgaarb_decodes(struct pci_device *dev) ++{ ++ return 0; ++} ++ ++int ++pci_device_vgaarb_lock(struct pci_device *dev) ++{ ++ return 0; ++} ++ ++int ++pci_device_vgaarb_trylock(struct pci_device *dev) ++{ ++ return 0; ++} ++ ++int ++pci_device_vgaarb_unlock(struct pci_device *dev) ++{ ++ return 0; ++} +diff --git a/src/linux_sysfs.c b/src/linux_sysfs.c +index 1ae9e52..65e1cf6 100644 +--- a/src/linux_sysfs.c ++++ b/src/linux_sysfs.c +@@ -76,6 +76,7 @@ static int pci_device_linux_sysfs_write( struct pci_device * dev, + pciaddr_t * bytes_written ); + + static int pci_device_linux_sysfs_boot_vga( struct pci_device * dev ); ++static int pci_device_linux_sysfs_has_kernel_driver(struct pci_device *dev); + + static const struct pci_system_methods linux_sysfs_methods = { + .destroy = NULL, +@@ -91,6 +92,7 @@ static const struct pci_system_methods linux_sysfs_methods = { + .fill_capabilities = pci_fill_capabilities_generic, + .enable = pci_device_linux_sysfs_enable, + .boot_vga = pci_device_linux_sysfs_boot_vga, ++ .has_kernel_driver = pci_device_linux_sysfs_has_kernel_driver, + }; + + #define SYS_BUS_PCI "/sys/bus/pci/devices" +@@ -729,3 +731,22 @@ out: + close(fd); + return ret; + } ++ ++static int pci_device_linux_sysfs_has_kernel_driver(struct pci_device *dev) ++{ ++ char name[256]; ++ struct stat dummy; ++ int ret; ++ ++ snprintf( name, 255, "%s/%04x:%02x:%02x.%1u/driver", ++ SYS_BUS_PCI, ++ dev->domain, ++ dev->bus, ++ dev->dev, ++ dev->func ); ++ ++ ret = stat(name, &dummy); ++ if (ret < 0) ++ return 0; ++ return 1; ++} +diff --git a/src/pciaccess_private.h b/src/pciaccess_private.h +index 769e181..b97d31b 100644 +--- a/src/pciaccess_private.h ++++ b/src/pciaccess_private.h +@@ -61,6 +61,7 @@ struct pci_system_methods { + int (*fill_capabilities)( struct pci_device * dev ); + void (*enable)( struct pci_device *dev ); + int (*boot_vga)( struct pci_device *dev ); ++ int (*has_kernel_driver)( struct pci_device *dev ); + }; + + struct pci_device_mapping { +@@ -131,6 +132,8 @@ struct pci_system { + #ifdef HAVE_MTRR + int mtrr_fd; + #endif ++ int vgaarb_fd; ++ int vga_count; + }; + + extern struct pci_system * pci_sys; diff --git a/libpciaccess.spec b/libpciaccess.spec index 2dae494..92b86c2 100644 --- a/libpciaccess.spec +++ b/libpciaccess.spec @@ -3,7 +3,7 @@ Name: libpciaccess Version: 0.10.6 -Release: 1%{?dist} +Release: 2%{?dist} Summary: PCI access library Group: System Environment/Libraries @@ -20,6 +20,7 @@ BuildRoot: %{_tmppath}/%{name}-%{version}-%{release}-root-%(%{__id_u} -n) Patch0: libpciaccess-fd-cache.patch Patch2: libpciaccess-rom-size.patch Patch3: libpciaccess-boot-vga.patch +Patch4: libpciaccess-vga-arbiter.patch BuildRequires: autoconf automake libtool pkgconfig Requires: hwdata @@ -42,6 +43,7 @@ Development package for libpciaccess. %patch0 -p1 -b .cache %patch2 -p1 -b .rom-size %patch3 -p1 -b .bootvga +%patch4 -p1 -b .vgaarb %build #autoreconf -v --install @@ -72,6 +74,9 @@ rm -rf $RPM_BUILD_ROOT %{_libdir}/pkgconfig/pciaccess.pc %changelog +* Fri Jul 31 2009 Dave Airlie 0.10.6-2 +- libpciaccess-vga-arbiter.patch: add vga arbiter support to libpciaccess + * Mon Jul 27 2009 Dave Airlie 0.10.6-1 - rebase to latest release (will do release with VGA bits later) - libpciaccess-boot-vga.patch: add boot vga patch from upstream