aboutsummaryrefslogtreecommitdiffstats
path: root/tools/xcs/evtchn.c
diff options
context:
space:
mode:
Diffstat (limited to 'tools/xcs/evtchn.c')
-rw-r--r--tools/xcs/evtchn.c108
1 files changed, 108 insertions, 0 deletions
diff --git a/tools/xcs/evtchn.c b/tools/xcs/evtchn.c
new file mode 100644
index 0000000000..a96036db37
--- /dev/null
+++ b/tools/xcs/evtchn.c
@@ -0,0 +1,108 @@
+/* evtchn.c
+ *
+ * Interfaces to event channel driver.
+ *
+ * Most of this is directly based on the original xu interface to python
+ * written by Keir Fraser.
+ *
+ * (c) 2004, Andrew Warfield
+ *
+ */
+
+#include <stdio.h>
+#include <stdlib.h>
+#include <sys/ioctl.h>
+#include <sys/stat.h>
+#include <sys/sysmacros.h> /* XOPEN drops makedev, this gets it back. */
+#include <fcntl.h>
+#include <unistd.h>
+#include <errno.h>
+#include "xcs.h"
+
+static int evtchn_fd = -1;
+
+/* NB. The following should be kept in sync with the kernel's evtchn driver. */
+#define EVTCHN_DEV_NAME "/dev/xen/evtchn"
+#define EVTCHN_DEV_MAJOR 10
+#define EVTCHN_DEV_MINOR 201
+/* /dev/xen/evtchn ioctls: */
+/* EVTCHN_RESET: Clear and reinit the event buffer. Clear error condition. */
+#define EVTCHN_RESET _IO('E', 1)
+/* EVTCHN_BIND: Bind to teh specified event-channel port. */
+#define EVTCHN_BIND _IO('E', 2)
+/* EVTCHN_UNBIND: Unbind from the specified event-channel port. */
+#define EVTCHN_UNBIND _IO('E', 3)
+
+int evtchn_read()
+{
+ u16 v;
+ int bytes;
+
+ while ( (bytes = read(evtchn_fd, &v, sizeof(v))) == -1 )
+ {
+ if ( errno == EINTR )
+ continue;
+ /* EAGAIN was cased to return 'None' in the python version... */
+ return -errno;
+ }
+
+ if ( bytes == sizeof(v) )
+ return v;
+
+ /* bad return */
+ return -1;
+}
+
+void evtchn_unmask(u16 idx)
+{
+ (void)write(evtchn_fd, &idx, sizeof(idx));
+}
+
+int evtchn_bind(int idx)
+{
+ if ( ioctl(evtchn_fd, EVTCHN_BIND, idx) != 0 )
+ return -errno;
+
+ return 0;
+}
+
+int evtchn_unbind(int idx)
+{
+ if ( ioctl(evtchn_fd, EVTCHN_UNBIND, idx) != 0 )
+ return -errno;
+
+ return 0;
+}
+
+int evtchn_open(void)
+{
+ struct stat st;
+
+ /* Make sure any existing device file links to correct device. */
+ if ( (lstat(EVTCHN_DEV_NAME, &st) != 0) ||
+ !S_ISCHR(st.st_mode) ||
+ (st.st_rdev != makedev(EVTCHN_DEV_MAJOR, EVTCHN_DEV_MINOR)) )
+ (void)unlink(EVTCHN_DEV_NAME);
+
+ reopen:
+ evtchn_fd = open(EVTCHN_DEV_NAME, O_NONBLOCK|O_RDWR);
+ if ( evtchn_fd == -1 )
+ {
+ if ( (errno == ENOENT) &&
+ ((mkdir("/dev/xen", 0755) == 0) || (errno == EEXIST)) &&
+ (mknod(EVTCHN_DEV_NAME, S_IFCHR|0600,
+ makedev(EVTCHN_DEV_MAJOR,EVTCHN_DEV_MINOR)) == 0) )
+ goto reopen;
+ return -errno;
+ }
+ /*set_cloexec(evtchn_fd); -- no longer required*/
+printf("Eventchan_fd is %d\n", evtchn_fd);
+ return evtchn_fd;
+}
+
+void evtchn_close()
+{
+ (void)close(evtchn_fd);
+ evtchn_fd = -1;
+}
+