1
2
3
4
5
6
7
8
9
10
11
12
13
14
15
16
17
18
19
20
21
22
23
24
25
26
27
28
29
30
31
32
33
34
35
36
37
38
39
40
41
42
43
44
45
46
47
48
49
50
51
52
53
54
55
56
57
58
59
60
61
62
63
64
65
66
67
68
69
70
71
72
73
74
75
76
77
78
79
80
81
82
83
84
85
86
87
88
89
90
91
92
93
94
95
96
97
98
99
100
101
102
103
104
105
106
107
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;
}
|