Fix python install
[archipelago] / xseg / drivers / user / xseg_segdev.c
1 /*
2  * Copyright 2012 GRNET S.A. All rights reserved.
3  *
4  * Redistribution and use in source and binary forms, with or
5  * without modification, are permitted provided that the following
6  * conditions are met:
7  *
8  *   1. Redistributions of source code must retain the above
9  *      copyright notice, this list of conditions and the following
10  *      disclaimer.
11  *   2. Redistributions in binary form must reproduce the above
12  *      copyright notice, this list of conditions and the following
13  *      disclaimer in the documentation and/or other materials
14  *      provided with the distribution.
15  *
16  * THIS SOFTWARE IS PROVIDED BY GRNET S.A. ``AS IS'' AND ANY EXPRESS
17  * OR IMPLIED WARRANTIES, INCLUDING, BUT NOT LIMITED TO, THE IMPLIED
18  * WARRANTIES OF MERCHANTABILITY AND FITNESS FOR A PARTICULAR
19  * PURPOSE ARE DISCLAIMED. IN NO EVENT SHALL GRNET S.A OR
20  * CONTRIBUTORS BE LIABLE FOR ANY DIRECT, INDIRECT, INCIDENTAL,
21  * SPECIAL, EXEMPLARY, OR CONSEQUENTIAL DAMAGES (INCLUDING, BUT NOT
22  * LIMITED TO, PROCUREMENT OF SUBSTITUTE GOODS OR SERVICES; LOSS OF
23  * USE, DATA, OR PROFITS; OR BUSINESS INTERRUPTION) HOWEVER CAUSED
24  * AND ON ANY THEORY OF LIABILITY, WHETHER IN CONTRACT, STRICT
25  * LIABILITY, OR TORT (INCLUDING NEGLIGENCE OR OTHERWISE) ARISING IN
26  * ANY WAY OUT OF THE USE OF THIS SOFTWARE, EVEN IF ADVISED OF THE
27  * POSSIBILITY OF SUCH DAMAGE.
28  *
29  * The views and conclusions contained in the software and
30  * documentation are those of the authors and should not be
31  * interpreted as representing official policies, either expressed
32  * or implied, of GRNET S.A.
33  */
34
35 #define _GNU_SOURCE
36 #include <stdio.h>
37 #include <stdlib.h>
38 #include <unistd.h>
39 #include <sys/types.h>
40 #include <sys/stat.h>
41 #include <sys/ioctl.h>
42 #include <sys/mman.h>
43 #include <sys/syscall.h>
44 #include <fcntl.h>
45 #include <errno.h>
46 #include <string.h>
47 #include <signal.h>
48 #include <xseg/xseg.h>
49 #include <sys/util.h>
50 #include <sys/kernel/segdev.h>
51 #include <drivers/xseg_segdev.h>
52
53 #define ERRSIZE 512
54 static char errbuf[ERRSIZE];
55
56 #define SEGDEV_DEVICE "/dev/segdev"
57 static int fdev = -1;
58
59 static int opendev(void)
60 {
61         if (fdev >= 0)
62                 return fdev;
63
64         fdev = open(SEGDEV_DEVICE, O_RDWR);
65         if (fdev < 0) {
66                 XSEGLOG("Cannot open %s: %s\n", SEGDEV_DEVICE,
67                         strerror_r(errno, errbuf, ERRSIZE));
68                 fdev = -1;
69         }
70         return fdev;
71 }
72
73 static int closedev(void)
74 {
75         int r;
76         if (fdev < 0)
77                 return 0;
78
79         r = close(fdev);
80         if (r < 0) {
81                 XSEGLOG("Cannot close %s: %s\n", SEGDEV_DEVICE,
82                         strerror_r(errno, errbuf, ERRSIZE));
83                 return -1;
84         } else
85                 fdev = -1;
86
87         return 0;
88 }
89
90 static long segdev_allocate(const char *name, uint64_t size)
91 {
92         int fd;
93         long oldsize;
94
95         fd = opendev();
96         if (fd < 0)
97                 return fd;
98
99         oldsize = ioctl(fd, SEGDEV_IOC_SEGSIZE, 0);
100         if (oldsize >= 0) {
101                 XSEGLOG("Destroying old segment\n");
102                 if (ioctl(fd, SEGDEV_IOC_DESTROYSEG, 0)) {
103                         XSEGLOG("Failed to destroy old segment");
104                         closedev();
105                         return -2;
106                 }
107         }
108
109         XSEGLOG("creating segment of size %llu\n", size);
110
111         if (ioctl(fd, SEGDEV_IOC_CREATESEG, size)) {
112                 XSEGLOG("Failed to create segment");
113                 closedev();
114                 return -3;
115         }
116
117         return 0;
118 }
119
120 static long segdev_deallocate(const char *name)
121 {
122         int fd;
123         fd = open(SEGDEV_DEVICE, O_RDWR);
124         if (fd < 0) {
125                 XSEGLOG("Cannot open %s: %s\n", SEGDEV_DEVICE,
126                         strerror_r(errno, errbuf, ERRSIZE));
127                 return -1;
128         }
129
130         if (ioctl(fd, SEGDEV_IOC_DESTROYSEG, 0)) {
131                 XSEGLOG("Failed to destroy old segment");
132                 return -2;
133         }
134
135         closedev();
136         return 0;
137 }
138
139 static void *segdev_map(const char *name, uint64_t size, struct xseg *seg)
140 {
141         struct xseg *xseg;
142         int fd;
143
144         if (seg)
145                 XSEGLOG("struct xseg * not NULL. Ignoring...\n");
146
147         fd = opendev();
148         if (fd < 0)
149                 return NULL;
150
151         xseg = mmap (   XSEG_BASE_AS_PTR,
152                         size,
153                         PROT_READ | PROT_WRITE,
154                         MAP_SHARED | MAP_FIXED /* | MAP_LOCKED */,
155                         fd, 0   );
156
157         if (xseg == MAP_FAILED) {
158                 XSEGLOG("Could not map segment: %s\n",
159                         strerror_r(errno, errbuf, ERRSIZE));
160                 closedev();
161                 return NULL;
162         }
163
164         return xseg;
165 }
166
167 static void segdev_unmap(void *ptr, uint64_t size)
168 {
169         struct xseg *xseg = ptr;
170         (void)munmap(xseg, xseg->segment_size);
171 }
172
173
174 static struct xseg_type xseg_segdev = {
175         /* xseg_operations */
176         {
177                 .allocate       = segdev_allocate,
178                 .deallocate     = segdev_deallocate,
179                 .map            = segdev_map,
180                 .unmap          = segdev_unmap
181         },
182         /* name */
183         "segdev"
184 };
185
186 static int segdev_local_signal_init(struct xseg *xseg, xport portno)
187 {
188         return -1;
189 }
190
191 static void segdev_local_signal_quit(struct xseg *xseg, xport portno)
192 {
193         return;
194 }
195
196 static int segdev_remote_signal_init(void)
197 {
198         return 0;
199 }
200
201 static void segdev_remote_signal_quit(void)
202 {
203         return;
204 }
205
206 static int segdev_prepare_wait(struct xseg *xseg, uint32_t portno)
207 {
208         return -1;
209 }
210
211 static int segdev_cancel_wait(struct xseg *xseg, uint32_t portno)
212 {
213         return -1;
214 }
215
216 static int segdev_wait_signal(struct xseg *xseg, uint32_t timeout)
217 {
218         return -1;
219 }
220
221 static int segdev_signal(struct xseg *xseg, uint32_t portno)
222 {
223         struct xseg_port *port = xseg_get_port(xseg, portno);
224         if (!port)
225                 return -1;
226         struct segdev_signal_desc *ssd = xseg_get_signal_desc(xseg, port);
227         if (!ssd)
228                 return -1;
229
230         if (!ssd->waitcue){
231                 return 0;
232         }
233         else
234                 return write(opendev(), &portno, sizeof(portno));
235 }
236
237 static void *segdev_malloc(uint64_t size)
238 {
239         return NULL;
240 }
241
242 static void *segdev_realloc(void *mem, uint64_t size)
243 {
244         return NULL;
245 }
246
247 static void segdev_mfree(void *mem) { }
248
249 static int segdev_init_signal_desc(struct xseg *xseg, void *sd)
250 {
251         return -1;
252 }
253
254 static void segdev_quit_signal_desc(struct xseg *xseg, void *sd)
255 {
256         return;
257 }
258
259 static void *segdev_alloc_data(struct xseg *xseg)
260 {
261         return NULL;
262 }
263
264 static void segdev_free_data(struct xseg *xseg, void *data)
265 {
266         return;
267 }
268
269 static void *segdev_alloc_signal_desc(struct xseg *xseg, void *data)
270 {
271         return NULL;
272 }
273
274 static void segdev_free_signal_desc(struct xseg *xseg, void *data, void *sd)
275 {
276         return;
277 }
278
279 static struct xseg_peer xseg_peer_segdev = {
280         /* xseg signal operations */
281         {
282                 .init_signal_desc   = segdev_init_signal_desc,
283                 .quit_signal_desc   = segdev_quit_signal_desc,
284                 .alloc_data         = segdev_alloc_data,
285                 .free_data          = segdev_free_data,
286                 .alloc_signal_desc  = segdev_alloc_signal_desc,
287                 .free_signal_desc   = segdev_free_signal_desc,
288                 .local_signal_init  = segdev_local_signal_init,
289                 .local_signal_quit  = segdev_local_signal_quit,
290                 .remote_signal_init = segdev_remote_signal_init,
291                 .remote_signal_quit = segdev_remote_signal_quit,
292                 .prepare_wait = segdev_prepare_wait,
293                 .cancel_wait = segdev_cancel_wait,
294                 .wait_signal = segdev_wait_signal,
295                 .signal = segdev_signal,
296                 .malloc = segdev_malloc,
297                 .realloc = segdev_realloc,
298                 .mfree = segdev_mfree
299         },
300         /* name */
301         "segdev"
302 };
303
304 void xseg_segdev_init(void)
305 {
306         xseg_register_type(&xseg_segdev);
307         xseg_register_peer(&xseg_peer_segdev);
308 }
309