diff options
author | Tiago Vignatti <vignatti@freedesktop.org> | 2009-05-13 17:44:46 -0300 |
---|---|---|
committer | Tiago Vignatti <vignatti@freedesktop.org> | 2009-05-13 17:44:46 -0300 |
commit | 67af888bcc5667eadf1e9e9bf15305f742416daf (patch) | |
tree | 36670d627299ff919498ae79a60538f57f7ecca8 | |
parent | 8ba6b02ecfa5b03bbf2807e8262bb1253a026493 (diff) |
Import libvgaaccess (VGA Arbiter) implementation from C3SL repository:
http://git.c3sl.ufpr.br/
-rw-r--r-- | include/pciaccess.h | 75 | ||||
-rw-r--r-- | src/common_vgaarb.c | 273 |
2 files changed, 348 insertions, 0 deletions
diff --git a/include/pciaccess.h b/include/pciaccess.h index 6413ae0..2f0bf9d 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 @@ -449,4 +474,54 @@ struct pci_pcmcia_bridge_info { }; + +/** + * VGA Arbiter definitions, functions and related. + */ + +typedef int VgaArbRsrcType; + +typedef struct { + int fd; + VgaArbRsrcType rsrc; +} vga_arb_rec, *vga_arb_ptr; + +/* This is a mask that can be OR'ed */ +#define VGA_ARB_RSRC_NONE 0 +#define VGA_ARB_RSRC_LEGACY_IO 1 +#define VGA_ARB_RSRC_LEGACY_MEM 2 +#define VGA_ARB_RSRC_NORMAL_IO 4 +#define VGA_ARB_RSRC_NORMAL_MEM 8 + +/* + * All functions, except vga_arb_trylock(), return 1 on success and 0 if + * something went wrong. + * vga_arb_trylock returns 1 on success, 0 if the lock failed and -1 if + * something went wrong. + * + * But I really don't think you should be checking the return values. The lib + * checks for these errors but they should never happen, and when they happen + * it will print error messages at stderr. + * + * To understand the way these functions work see test/test2lib.c. + */ + + +int vga_arb_set_target (vga_arb_ptr vgaDev, unsigned int domain, + unsigned int bus, unsigned int dev, unsigned int fn); + +int vga_arb_read (vga_arb_ptr vgaDev); + +int vga_arb_lock (vga_arb_ptr vgaDev); + +int vga_arb_trylock (vga_arb_ptr vgaDev); + +int vga_arb_unlock (vga_arb_ptr vgaDev); + +int vga_arb_decodes (vga_arb_ptr vgaDev); + +int vga_arb_init (vga_arb_ptr *vgaDev); + +void vga_arb_fini (vga_arb_ptr vgaDev); + #endif /* PCIACCESS_H */ diff --git a/src/common_vgaarb.c b/src/common_vgaarb.c new file mode 100644 index 0000000..729998d --- /dev/null +++ b/src/common_vgaarb.c @@ -0,0 +1,273 @@ +/* + * 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. + * + */ + +/* vgaaccess.c */ + +#ifdef HAVE_CONFIG_H +#include <config.h> +#endif + +#include <string.h> +#include <stdio.h> +#include <stdlib.h> +#include <unistd.h> +#include <sys/types.h> +#include <sys/stat.h> +#include <fcntl.h> +#include <errno.h> + +#include "vgaaccess.h" + +/* ALL messages *should* fit in this buffer */ +#define BUFSIZE 128 + +#define ARBITER_DEVICE "/dev/vga_arbiter" + +/* + * Writes the message on the device. + * + * Returns: 0 if something went wrong + * 1 if everything is ok + * 2 if the device returned EBUSY (used ONLY by trylock) + */ +static int +vga_arb_write(int fd, char *buf, int len) +{ + int ret; + + /* Just to make sure... */ + buf[len] = '\0'; + + ret = write(fd, buf, len); + + if (ret == -1) { + /* Check for EBUSY: the user may have called "trylock" and didn't get + * the lock. */ + if (errno == EBUSY) + return 2; + perror("[libvgaaccess] write error"); + return 0; + } + else if (ret != len) { + /* The VGA arbiter implementation shouldn't recive less than one + * single message. It also shouldn't recive more. */ + fprintf(stderr, "[libvgaaccess] write error: " + "wrote less than expected!\n"); + return 0; + } + +#ifdef DEBUG + fprintf(stderr, "[libvgaaccess] successfully wrote: '%s'.\n", buf); +#endif + + return 1; +} + +/* Convert "integer rsrc" in "string rsrc" */ +static const char * +rsrc_to_str(VgaArbRsrcType 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"; +} + +#ifndef STUB +int +vga_arb_read(vga_arb_ptr vgaDev) +{ + int ret; + char buf[BUFSIZE]; + + + ret = read (vgaDev->fd, buf, BUFSIZE); + + /* Just to make sure... */ + buf[ret]='\0'; + + if (ret == 0) { + /* It always has something to be read. */ + fprintf(stderr, "[libvgaaccess] error: there is nothing to read!\n"); + return 0; + } + else if (ret == -1) { + perror("[libvgaaccess] read error"); + return 0; + } + +#ifdef DEBUG + fprintf(stderr, "[libvgaaccess]: sucessfully read: '%s'.\n", buf); +#endif + return 1; +} + +int +vga_arb_set_target(vga_arb_ptr vgaDev, unsigned int domain, unsigned int bus, + unsigned int dev, unsigned int fn) +{ + int len; + char buf[BUFSIZE]; + + len = snprintf(buf, BUFSIZE, "target PCI:%d:%d:%d.%d", + domain, bus, dev, fn); + + return vga_arb_write(vgaDev->fd, buf, len); +} + +int +vga_arb_lock(vga_arb_ptr vgaDev) +{ + int len; + char buf[BUFSIZE]; + + len = snprintf(buf, BUFSIZE, "lock %s", rsrc_to_str(vgaDev->rsrc)); + + return vga_arb_write(vgaDev->fd, buf, len); +} + +int +vga_arb_trylock(vga_arb_ptr vgaDev) +{ + int len, write_ret; + char buf[BUFSIZE]; + + len = snprintf(buf, BUFSIZE, "trylock %s", rsrc_to_str(vgaDev->rsrc)); + + write_ret = vga_arb_write(vgaDev->fd, buf, len); + + if (write_ret == 0) + return -1; + else if (write_ret == 1) + return 1; + else + /* write_ret == 2 and the lock failed */ + return 0; +} + +int +vga_arb_unlock(vga_arb_ptr vgaDev) +{ + int len; + char buf[BUFSIZE]; + + len = snprintf(buf, BUFSIZE, "unlock %s", rsrc_to_str(vgaDev->rsrc)); + + return vga_arb_write(vgaDev->fd, buf, len); +} + +int +vga_arb_decodes(vga_arb_ptr vgaDev) +{ + int len; + char buf[BUFSIZE]; + + len = snprintf(buf, BUFSIZE, "decodes %s", rsrc_to_str(vgaDev->rsrc)); + + return vga_arb_write(vgaDev->fd, buf, len); +} + +int +vga_arb_init(vga_arb_ptr *vgaDev) +{ + *vgaDev = malloc (sizeof(vga_arb_ptr *)); + if (vgaDev == NULL) { + fprintf(stderr, "[libvgaaccess] malloc: couldn't allocate memory!\n"); + return 0; + } + + (*vgaDev)->rsrc = 0; + + if (((*vgaDev)->fd = open (ARBITER_DEVICE, O_RDWR)) < 0) { + perror("[libvgaaccess] device open failed"); + return 0; + } + + return (*vgaDev)->fd; +} + +void +vga_arb_fini(vga_arb_ptr vgaDev) +{ + if (close(vgaDev->fd) == -1) + perror("[libvgaaccess] device close failed"); +} + +#else /* STUB */ +int +vga_arb_read(vga_arb_ptr vgaDev) +{ + return 1; +} + +int +vga_arb_set_target(vga_arb_ptr vgaDev, unsigned int domain, unsigned int bus, + unsigned int dev, unsigned int fn) +{ + return 1; +} + +int +vga_arb_lock(vga_arb_ptr vgaDev) +{ + return 1; +} + +int +vga_arb_trylock(vga_arb_ptr vgaDev) +{ + return 1; +} + +int +vga_arb_unlock(vga_arb_ptr vgaDev) +{ + return 1; +} + +int +vga_arb_decodes(vga_arb_ptr vgaDev) +{ + return 1; +} + +int +vga_arb_init(vga_arb_ptr *vgaDev) +{ + fprintf(stderr, "[libvgaaccess] YOU'RE USING THE STUB FUNCTIONS!\n"); + return 1; +} + +void +vga_arb_fini(vga_arb_ptr vgaDev) +{ +} +#endif /* END OF STUB */ |