hc
2024-11-01 2f529f9b558ca1c1bd74be7437a84e4711743404
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
109
110
111
112
113
114
115
116
117
118
119
120
121
122
123
124
125
126
127
128
129
130
131
132
133
134
135
136
137
138
139
140
141
142
143
144
145
146
147
148
149
150
151
152
153
154
155
156
157
158
159
160
161
162
163
164
165
166
167
168
169
170
171
172
173
174
175
176
177
178
179
180
181
182
183
184
185
186
187
188
189
190
191
192
193
194
195
196
197
198
199
200
201
202
203
204
205
206
207
208
209
210
211
212
213
214
215
216
217
218
219
220
221
222
223
224
225
226
227
228
229
230
231
232
233
234
235
236
237
238
239
240
241
242
243
244
245
246
247
248
249
250
251
252
253
254
255
256
257
258
259
260
261
262
263
264
265
266
267
268
269
270
271
272
273
274
275
276
277
278
279
280
281
282
283
284
285
286
287
288
289
290
291
292
293
294
295
296
297
298
299
300
301
302
303
304
305
306
307
308
309
310
311
312
313
314
315
316
317
318
319
320
321
322
323
324
325
326
327
328
329
330
331
332
333
334
335
336
337
338
339
340
341
342
343
344
345
346
347
348
349
350
351
352
353
354
355
356
357
358
359
360
361
362
363
364
365
366
367
368
369
370
371
372
373
374
375
376
377
378
379
380
381
382
383
384
385
386
387
388
389
390
391
392
393
394
395
396
397
398
399
400
401
402
403
404
405
406
407
408
409
410
411
412
413
414
415
416
417
418
419
420
421
422
423
424
425
426
427
428
429
430
431
/*
 * Copyright (C) 2005-2007 Jan Kiszka <jan.kiszka@web.de>
 * Copyright (C) 2005 Joerg Langenberg <joerg.langenberg@gmx.net>
 * Copyright (C) 2008,2013,2014 Gilles Chanteperdrix <gch@xenomai.org>.
 *
 * This program is free software; you can redistribute it and/or
 * modify it under the terms of the GNU General Public License as
 * published by the Free Software Foundation; either version 2 of the
 * License, or (at your option) any later version.
 *
 * This program is distributed in the hope that it will be useful,
 * but WITHOUT ANY WARRANTY; without even the implied warranty of
 * MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE.  See the
 * GNU General Public License for more details.
 *
 * You should have received a copy of the GNU General Public License
 * along with this program; if not, write to the Free Software
 * Foundation, Inc., 59 Temple Place - Suite 330, Boston, MA 02111-1307, USA.
 */
#ifndef _COBALT_KERNEL_FD_H
#define _COBALT_KERNEL_FD_H
 
#include <linux/types.h>
#include <linux/socket.h>
#include <linux/file.h>
#include <cobalt/kernel/tree.h>
#include <asm-generic/xenomai/syscall.h>
 
struct vm_area_struct;
struct rtdm_fd;
struct _rtdm_mmap_request;
struct _rtdm_setsockaddr_args;
struct _rtdm_setsockopt_args;
struct xnselector;
struct cobalt_ppd;
struct rtdm_device;
 
/**
 * @file
 * @anchor File operation handlers
 * @addtogroup rtdm_device_register
 * @{
 */
 
/**
 * Open handler for named devices
 *
 * @param[in] fd File descriptor associated with opened device instance
 * @param[in] oflags Open flags as passed by the user
 *
 * The file descriptor carries a device minor information which can be
 * retrieved by a call to rtdm_fd_minor(fd). The minor number can be
 * used for distinguishing devices managed by a driver.
 *
 * @return 0 on success. On failure, a negative error code is returned.
 *
 * @see @c open() in IEEE Std 1003.1,
 * http://www.opengroup.org/onlinepubs/009695399
 */
int rtdm_open_handler(struct rtdm_fd *fd, int oflags);
 
/**
 * Socket creation handler for protocol devices
 *
 * @param[in] fd File descriptor associated with opened device instance
 * @param[in] protocol Protocol number as passed by the user
 *
 * @return 0 on success. On failure, a negative error code is returned.
 *
 * @see @c socket() in IEEE Std 1003.1,
 * http://www.opengroup.org/onlinepubs/009695399
 */
int rtdm_socket_handler(struct rtdm_fd *fd, int protocol);
 
/**
 * Close handler
 *
 * @param[in] fd File descriptor associated with opened
 * device instance.
 *
 * @see @c close() in IEEE Std 1003.1,
 * http://www.opengroup.org/onlinepubs/009695399
 */
void rtdm_close_handler(struct rtdm_fd *fd);
 
/**
 * IOCTL handler
 *
 * @param[in] fd File descriptor
 * @param[in] request Request number as passed by the user
 * @param[in,out] arg Request argument as passed by the user
 *
 * @return A positive value or 0 on success. On failure return either
 * -ENOSYS, to request that the function be called again from the opposite
 * realtime/non-realtime context, or another negative error code.
 *
 * @see @c ioctl() in IEEE Std 1003.1,
 * http://www.opengroup.org/onlinepubs/009695399
 */
int rtdm_ioctl_handler(struct rtdm_fd *fd, unsigned int request, void __user *arg);
 
/**
 * Read handler
 *
 * @param[in] fd File descriptor
 * @param[out] buf Input buffer as passed by the user
 * @param[in] size Number of bytes the user requests to read
 *
 * @return On success, the number of bytes read. On failure return either
 * -ENOSYS, to request that this handler be called again from the opposite
 * realtime/non-realtime context, or another negative error code.
 *
 * @see @c read() in IEEE Std 1003.1,
 * http://www.opengroup.org/onlinepubs/009695399
 */
ssize_t rtdm_read_handler(struct rtdm_fd *fd, void __user *buf, size_t size);
 
/**
 * Write handler
 *
 * @param[in] fd File descriptor
 * @param[in] buf Output buffer as passed by the user
 * @param[in] size Number of bytes the user requests to write
 *
 * @return On success, the number of bytes written. On failure return
 * either -ENOSYS, to request that this handler be called again from the
 * opposite realtime/non-realtime context, or another negative error code.
 *
 * @see @c write() in IEEE Std 1003.1,
 * http://www.opengroup.org/onlinepubs/009695399
 */
ssize_t rtdm_write_handler(struct rtdm_fd *fd, const void __user *buf, size_t size);
 
/**
 * Receive message handler
 *
 * @param[in] fd File descriptor
 * @param[in,out] msg Message descriptor as passed by the user, automatically
 * mirrored to safe kernel memory in case of user mode call
 * @param[in] flags Message flags as passed by the user
 *
 * @return On success, the number of bytes received. On failure return
 * either -ENOSYS, to request that this handler be called again from the
 * opposite realtime/non-realtime context, or another negative error code.
 *
 * @see @c recvmsg() in IEEE Std 1003.1,
 * http://www.opengroup.org/onlinepubs/009695399
 */
ssize_t rtdm_recvmsg_handler(struct rtdm_fd *fd, struct user_msghdr *msg, int flags);
 
/**
 * Transmit message handler
 *
 * @param[in] fd File descriptor
 * @param[in] msg Message descriptor as passed by the user, automatically
 * mirrored to safe kernel memory in case of user mode call
 * @param[in] flags Message flags as passed by the user
 *
 * @return On success, the number of bytes transmitted. On failure return
 * either -ENOSYS, to request that this handler be called again from the
 * opposite realtime/non-realtime context, or another negative error code.
 *
 * @see @c sendmsg() in IEEE Std 1003.1,
 * http://www.opengroup.org/onlinepubs/009695399
 */
ssize_t rtdm_sendmsg_handler(struct rtdm_fd *fd, const struct user_msghdr *msg, int flags);
 
/**
 * Select handler
 *
 * @param[in] fd File descriptor
 * @param selector Pointer to the selector structure
 * @param type Type of events (@a XNSELECT_READ, @a XNSELECT_WRITE, or @a
 * XNSELECT_EXCEPT)
 * @param index Index of the file descriptor
 *
 * @return 0 on success. On failure, a negative error code is
 * returned.
 *
 * @see @c select() in POSIX.1-2001,
 * http://pubs.opengroup.org/onlinepubs/007908799/xsh/select.html
 */
int rtdm_select_handler(struct rtdm_fd *fd, struct xnselector *selector,
           unsigned int type, unsigned int index);
 
/**
 * Memory mapping handler
 *
 * @param[in] fd File descriptor
 * @param[in] vma Virtual memory area descriptor
 *
 * @return 0 on success. On failure, a negative error code is
 * returned.
 *
 * @see @c mmap() in POSIX.1-2001,
 * http://pubs.opengroup.org/onlinepubs/7908799/xsh/mmap.html
 *
 * @note The address hint passed to the mmap() request is deliberately
 * ignored by RTDM.
 */
int rtdm_mmap_handler(struct rtdm_fd *fd, struct vm_area_struct *vma);
 
/**
 * Allocate mapping region in address space
 *
 * When present, this optional handler should return the start address
 * of a free region in the process's address space, large enough to
 * cover the ongoing mmap() operation. If unspecified, the default
 * architecture-defined handler is invoked.
 *
 * Most drivers can omit this handler, except on MMU-less platforms
 * (see second note).
 *
 * @param[in] fd File descriptor
 * @param[in] len Length of the requested region
 * @param[in] pgoff Page frame number to map to (see second note).
 * @param[in] flags Requested mapping flags
 *
 * @return The start address of the mapping region on success. On
 * failure, a negative error code should be returned, with -ENOSYS
 * meaning that the driver does not want to provide such information,
 * in which case the ongoing mmap() operation will fail.
 *
 * @note The address hint passed to the mmap() request is deliberately
 * ignored by RTDM, and therefore not passed to this handler.
 *
 * @note On MMU-less platforms, this handler is required because RTDM
 * issues mapping requests over a shareable character device
 * internally. In such context, the RTDM core may pass a null @a pgoff
 * argument to the handler, for probing for the logical start address
 * of the memory region to map to. Otherwise, when @a pgoff is
 * non-zero, pgoff << PAGE_SHIFT is usually returned.
 */
unsigned long
rtdm_get_unmapped_area_handler(struct rtdm_fd *fd,
                  unsigned long len, unsigned long pgoff,
                  unsigned long flags);
/**
 * @anchor rtdm_fd_ops
 * @brief RTDM file operation descriptor.
 *
 * This structure describes the operations available with a RTDM
 * device, defining handlers for submitting I/O requests. Those
 * handlers are implemented by RTDM device drivers.
 */
struct rtdm_fd_ops {
   /** See rtdm_open_handler(). */
   int (*open)(struct rtdm_fd *fd, int oflags);
   /** See rtdm_socket_handler(). */
   int (*socket)(struct rtdm_fd *fd, int protocol);
   /** See rtdm_close_handler(). */
   void (*close)(struct rtdm_fd *fd);
   /** See rtdm_ioctl_handler(). */
   int (*ioctl_rt)(struct rtdm_fd *fd,
           unsigned int request, void __user *arg);
   /** See rtdm_ioctl_handler(). */
   int (*ioctl_nrt)(struct rtdm_fd *fd,
            unsigned int request, void __user *arg);
   /** See rtdm_read_handler(). */
   ssize_t (*read_rt)(struct rtdm_fd *fd,
              void __user *buf, size_t size);
   /** See rtdm_read_handler(). */
   ssize_t (*read_nrt)(struct rtdm_fd *fd,
               void __user *buf, size_t size);
   /** See rtdm_write_handler(). */
   ssize_t (*write_rt)(struct rtdm_fd *fd,
               const void __user *buf, size_t size);
   /** See rtdm_write_handler(). */
   ssize_t (*write_nrt)(struct rtdm_fd *fd,
                const void __user *buf, size_t size);
   /** See rtdm_recvmsg_handler(). */
   ssize_t (*recvmsg_rt)(struct rtdm_fd *fd,
                 struct user_msghdr *msg, int flags);
   /** See rtdm_recvmsg_handler(). */
   ssize_t (*recvmsg_nrt)(struct rtdm_fd *fd,
                  struct user_msghdr *msg, int flags);
   /** See rtdm_sendmsg_handler(). */
   ssize_t (*sendmsg_rt)(struct rtdm_fd *fd,
                 const struct user_msghdr *msg, int flags);
   /** See rtdm_sendmsg_handler(). */
   ssize_t (*sendmsg_nrt)(struct rtdm_fd *fd,
                  const struct user_msghdr *msg, int flags);
   /** See rtdm_select_handler(). */
   int (*select)(struct rtdm_fd *fd,
             struct xnselector *selector,
             unsigned int type, unsigned int index);
   /** See rtdm_mmap_handler(). */
   int (*mmap)(struct rtdm_fd *fd,
           struct vm_area_struct *vma);
   /** See rtdm_get_unmapped_area_handler(). */
   unsigned long (*get_unmapped_area)(struct rtdm_fd *fd,
                      unsigned long len,
                      unsigned long pgoff,
                      unsigned long flags);
};
 
/** @} File operation handlers */
 
struct rtdm_fd {
   unsigned int magic;
   struct rtdm_fd_ops *ops;
   struct cobalt_ppd *owner;
   unsigned int refs;
   int ufd;
   int minor;
   int oflags;
#ifdef CONFIG_XENO_ARCH_SYS3264
   int compat;
#endif
   bool stale;
   struct list_head cleanup;
   struct list_head next;    /* in dev->openfd_list */
};
 
#define RTDM_FD_MAGIC 0x52544446
 
#define RTDM_FD_COMPAT    __COBALT_COMPAT_BIT
#define RTDM_FD_COMPATX    __COBALT_COMPATX_BIT
 
int __rtdm_anon_getfd(const char *name, int flags);
 
void __rtdm_anon_putfd(int ufd);
 
static inline struct cobalt_ppd *rtdm_fd_owner(const struct rtdm_fd *fd)
{
   return fd->owner;
}
 
static inline int rtdm_fd_ufd(const struct rtdm_fd *fd)
{
   return fd->ufd;
}
 
static inline int rtdm_fd_minor(const struct rtdm_fd *fd)
{
   return fd->minor;
}
 
static inline int rtdm_fd_flags(const struct rtdm_fd *fd)
{
   return fd->oflags;
}
 
#ifdef CONFIG_XENO_ARCH_SYS3264
static inline int rtdm_fd_is_compat(const struct rtdm_fd *fd)
{
   return fd->compat;
}
#else
static inline int rtdm_fd_is_compat(const struct rtdm_fd *fd)
{
   return 0;
}
#endif
 
int rtdm_fd_enter(struct rtdm_fd *rtdm_fd, int ufd,
         unsigned int magic, struct rtdm_fd_ops *ops);
 
int rtdm_fd_register(struct rtdm_fd *fd, int ufd);
 
struct rtdm_fd *rtdm_fd_get(int ufd, unsigned int magic);
 
int rtdm_fd_lock(struct rtdm_fd *fd);
 
void rtdm_fd_put(struct rtdm_fd *fd);
 
void rtdm_fd_unlock(struct rtdm_fd *fd);
 
int rtdm_fd_fcntl(int ufd, int cmd, ...);
 
int rtdm_fd_ioctl(int ufd, unsigned int request, ...);
 
ssize_t rtdm_fd_read(int ufd, void __user *buf, size_t size);
 
ssize_t rtdm_fd_write(int ufd, const void __user *buf, size_t size);
 
int rtdm_fd_close(int ufd, unsigned int magic);
 
ssize_t rtdm_fd_recvmsg(int ufd, struct user_msghdr *msg, int flags);
 
int __rtdm_fd_recvmmsg(int ufd, void __user *u_msgvec, unsigned int vlen,
              unsigned int flags, void __user *u_timeout,
              int (*get_mmsg)(struct mmsghdr *mmsg, void __user *u_mmsg),
              int (*put_mmsg)(void __user **u_mmsg_p, const struct mmsghdr *mmsg),
              int (*get_timespec)(struct timespec64 *ts, const void __user *u_ts));
 
int __rtdm_fd_recvmmsg64(int ufd, void __user *u_msgvec, unsigned int vlen,
            unsigned int flags, void __user *u_timeout,
            int (*get_mmsg)(struct mmsghdr *mmsg, void __user *u_mmsg),
            int (*put_mmsg)(void __user **u_mmsg_p, const struct mmsghdr *mmsg));
 
ssize_t rtdm_fd_sendmsg(int ufd, const struct user_msghdr *msg,
           int flags);
 
int __rtdm_fd_sendmmsg(int ufd, void __user *u_msgvec, unsigned int vlen,
              unsigned int flags,
              int (*get_mmsg)(struct mmsghdr *mmsg, void __user *u_mmsg),
              int (*put_mmsg)(void __user **u_mmsg_p, const struct mmsghdr *mmsg));
 
int rtdm_fd_mmap(int ufd, struct _rtdm_mmap_request *rma,
        void **u_addrp);
 
int rtdm_fd_valid_p(int ufd);
 
int rtdm_fd_select(int ufd, struct xnselector *selector,
          unsigned int type);
 
int rtdm_fd_get_setsockaddr_args(struct rtdm_fd *fd,
                struct _rtdm_setsockaddr_args *dst,
                const void *src);
 
int rtdm_fd_get_setsockopt_args(struct rtdm_fd *fd,
               struct _rtdm_setsockopt_args *dst,
               const void *src);
 
int rtdm_fd_get_iovec(struct rtdm_fd *fd, struct iovec *iov,
             const struct user_msghdr *msg, bool rw);
 
int rtdm_fd_put_iovec(struct rtdm_fd *fd, const struct iovec *iov,
             const struct user_msghdr *msg);
 
int rtdm_device_new_fd(struct rtdm_fd *fd, int ufd,
       struct rtdm_device *dev);
 
void rtdm_device_flush_fds(struct rtdm_device *dev);
 
void rtdm_fd_cleanup(struct cobalt_ppd *p);
 
void rtdm_fd_init(void);
 
#endif /* _COBALT_KERNEL_FD_H */