rtdm_driver.h
1 /** 2 * @file 3 * Real-Time Driver Model for RTAI, driver API header 4 * 5 * @note Copyright (C) 2005-2007 Jan Kiszka <jan.kiszka@web.de> 6 * @note Copyright (C) 2005 Joerg Langenberg <joerg.langenberg@gmx.net> 7 * @note Copyright (C) 2008 Gilles Chanteperdrix <gilles.chanteperdrix@gmail.com> 8 * @note Copyright (C) 2005-2010 Paolo Mantegazza <mantegazza@aero.polimi.it> 9 * 10 * RTAI is free software; you can redistribute it and/or modify it 11 * under the terms of the GNU General Public License as published by 12 * the Free Software Foundation; either version 2 of the License, or 13 * (at your option) any later version. 14 * 15 * RTAI is distributed in the hope that it will be useful, but 16 * WITHOUT ANY WARRANTY; without even the implied warranty of 17 * MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the GNU 18 * General Public License for more details. 19 * 20 * You should have received a copy of the GNU General Public License 21 * along with RTAI; if not, write to the Free Software Foundation, 22 * Inc., 59 Temple Place - Suite 330, Boston, MA 02111-1307, USA. 23 * 24 * @ingroup driverapi 25 */ 26 27 #ifndef _RTDM_DRIVER_H 28 #define _RTDM_DRIVER_H 29 30 #ifndef __KERNEL__ 31 #error This header is for kernel space usage only. \ 32 You are likely looking for rtdm/rtdm.h... 33 #endif /* !__KERNEL__ */ 34 35 #include <asm/atomic.h> 36 #include <linux/list.h> 37 38 #include <rtai_schedcore.h> 39 #include <rtai_sched.h> 40 41 #include "xn.h" 42 #include "select.h" 43 #include <rtdm/vfile.h> 44 #include <rtdm/rtdm.h> 45 46 47 struct rtdm_dev_context; 48 typedef struct xnselector rtdm_selector_t; 49 enum rtdm_selecttype; 50 51 /*! 52 * @addtogroup devregister 53 * @{ 54 */ 55 56 /*! 57 * @anchor dev_flags @name Device Flags 58 * Static flags describing a RTDM device 59 * @{ 60 */ 61 /** If set, only a single instance of the device can be requested by an 62 * application. */ 63 #define RTDM_EXCLUSIVE 0x0001 64 65 /** If set, the device is addressed via a clear-text name. */ 66 #define RTDM_NAMED_DEVICE 0x0010 67 68 /** If set, the device is addressed via a combination of protocol ID and 69 * socket type. */ 70 #define RTDM_PROTOCOL_DEVICE 0x0020 71 72 /** Mask selecting the device type. */ 73 #define RTDM_DEVICE_TYPE_MASK 0x00F0 74 /** @} Device Flags */ 75 76 /*! 77 * @anchor ctx_flags @name Context Flags 78 * Dynamic flags describing the state of an open RTDM device (bit numbers) 79 * @{ 80 */ 81 /** Set by RTDM if the device instance was created in non-real-time 82 * context. */ 83 #define RTDM_CREATED_IN_NRT 0 84 85 /** Set by RTDM when the device is being closed. */ 86 #define RTDM_CLOSING 1 87 88 /** Lowest bit number the driver developer can use freely */ 89 #define RTDM_USER_CONTEXT_FLAG 8 /* first user-definable flag */ 90 /** @} Context Flags */ 91 92 /*! 93 * @anchor drv_versioning @name Driver Versioning 94 * Current revisions of RTDM structures, encoding of driver versions. See 95 * @ref api_versioning "API Versioning" for the interface revision. 96 * @{ 97 */ 98 /** Version of struct rtdm_device */ 99 #define RTDM_DEVICE_STRUCT_VER 5 100 101 /** Version of struct rtdm_dev_context */ 102 #define RTDM_CONTEXT_STRUCT_VER 3 103 104 /** Flag indicating a secure variant of RTDM (not supported here) */ 105 #define RTDM_SECURE_DEVICE 0x80000000 106 107 /** Version code constructor for driver revisions */ 108 #define RTDM_DRIVER_VER(major, minor, patch) \ 109 (((major & 0xFF) << 16) | ((minor & 0xFF) << 8) | (patch & 0xFF)) 110 111 /** Get major version number from driver revision code */ 112 #define RTDM_DRIVER_MAJOR_VER(ver) (((ver) >> 16) & 0xFF) 113 114 /** Get minor version number from driver revision code */ 115 #define RTDM_DRIVER_MINOR_VER(ver) (((ver) >> 8) & 0xFF) 116 117 /** Get patch version number from driver revision code */ 118 #define RTDM_DRIVER_PATCH_VER(ver) ((ver) & 0xFF) 119 /** @} Driver Versioning */ 120 121 /*! 122 * @addtogroup rtdmsync 123 * @{ 124 */ 125 126 /*! 127 * @anchor RTDM_SELECTTYPE_xxx @name RTDM_SELECTTYPE_xxx 128 * Event types select can bind to 129 * @{ 130 */ 131 enum rtdm_selecttype { 132 /** Select input data availability events */ 133 RTDM_SELECTTYPE_READ = XNSELECT_READ, 134 135 /** Select ouput buffer availability events */ 136 RTDM_SELECTTYPE_WRITE = XNSELECT_WRITE, 137 138 /** Select exceptional events */ 139 RTDM_SELECTTYPE_EXCEPT = XNSELECT_EXCEPT 140 }; 141 /** @} RTDM_SELECTTYPE_xxx */ 142 143 /** @} rtdmsync */ 144 145 /*! 146 * @name Operation Handler Prototypes 147 * @{ 148 */ 149 150 /** 151 * Named device open handler 152 * 153 * @param[in] context Context structure associated with opened device instance 154 * @param[in] user_info Opaque pointer to information about user mode caller, 155 * NULL if kernel mode call 156 * @param[in] oflag Open flags as passed by the user 157 * 158 * @return 0 on success. On failure return either -ENOSYS, to request that 159 * this handler be called again from the opposite realtime/non-realtime 160 * context, or another negative error code. 161 * 162 * @see @c open() in IEEE Std 1003.1, 163 * http://www.opengroup.org/onlinepubs/009695399 */ 164 typedef int (*rtdm_open_handler_t)(struct rtdm_dev_context *context, 165 rtdm_user_info_t *user_info, int oflag); 166 167 /** 168 * Socket creation handler for protocol devices 169 * 170 * @param[in] context Context structure associated with opened device instance 171 * @param[in] user_info Opaque pointer to information about user mode caller, 172 * NULL if kernel mode call 173 * @param[in] protocol Protocol number as passed by the user 174 * 175 * @return 0 on success. On failure return either -ENOSYS, to request that 176 * this handler be called again from the opposite realtime/non-realtime 177 * context, or another negative error code. 178 * 179 * @see @c socket() in IEEE Std 1003.1, 180 * http://www.opengroup.org/onlinepubs/009695399 */ 181 typedef int (*rtdm_socket_handler_t)(struct rtdm_dev_context *context, 182 rtdm_user_info_t *user_info, int protocol); 183 184 /** 185 * Close handler 186 * 187 * @param[in] context Context structure associated with opened device instance 188 * @param[in] user_info Opaque pointer to information about user mode caller, 189 * NULL if kernel mode or deferred user mode call 190 * 191 * @return 0 on success. On failure return either -ENOSYS, to request that 192 * this handler be called again from the opposite realtime/non-realtime 193 * context, -EAGAIN to request a recall after a grace period, or a valid 194 * negative error code according to IEEE Std 1003.1. 195 * 196 * @note Drivers must be prepared for that case that the close handler is 197 * invoked more than once per open context (even if the handler already 198 * completed an earlier run successfully). The driver has to avoid releasing 199 * resources twice as well as returning false errors on successive close 200 * invocations. 201 * 202 * @see @c close() in IEEE Std 1003.1, 203 * http://www.opengroup.org/onlinepubs/009695399 */ 204 typedef int (*rtdm_close_handler_t)(struct rtdm_dev_context *context, 205 rtdm_user_info_t *user_info); 206 207 /** 208 * IOCTL handler 209 * 210 * @param[in] context Context structure associated with opened device instance 211 * @param[in] user_info Opaque pointer to information about user mode caller, 212 * NULL if kernel mode call 213 * @param[in] request Request number as passed by the user 214 * @param[in,out] arg Request argument as passed by the user 215 * 216 * @return A positive value or 0 on success. On failure return either 217 * -ENOSYS, to request that the function be called again from the opposite 218 * realtime/non-realtime context, or another negative error code. 219 * 220 * @see @c ioctl() in IEEE Std 1003.1, 221 * http://www.opengroup.org/onlinepubs/009695399 */ 222 typedef int (*rtdm_ioctl_handler_t)(struct rtdm_dev_context *context, 223 rtdm_user_info_t *user_info, 224 unsigned int request, void __user *arg); 225 226 /** 227 * Select binding handler 228 * 229 * @param[in] context Context structure associated with opened device instance 230 * @param[in,out] selector Object that shall be bound to the given event 231 * @param[in] type Event type the selector is interested in 232 * @param[in] fd_index Opaque value, to be passed to rtdm_event_select_bind or 233 * rtdm_sem_select_bind unmodfied 234 * 235 * @return 0 on success. On failure return either -ENOSYS, to request that 236 * this handler be called again from the opposite realtime/non-realtime 237 * context, or another negative error code. 238 */ 239 typedef int (*rtdm_select_bind_handler_t)(struct rtdm_dev_context *context, 240 rtdm_selector_t *selector, 241 enum rtdm_selecttype type, 242 unsigned fd_index); 243 244 /** 245 * Read handler 246 * 247 * @param[in] context Context structure associated with opened device instance 248 * @param[in] user_info Opaque pointer to information about user mode caller, 249 * NULL if kernel mode call 250 * @param[out] buf Input buffer as passed by the user 251 * @param[in] nbyte Number of bytes the user requests to read 252 * 253 * @return On success, the number of bytes read. On failure return either 254 * -ENOSYS, to request that this handler be called again from the opposite 255 * realtime/non-realtime context, or another negative error code. 256 * 257 * @see @c read() in IEEE Std 1003.1, 258 * http://www.opengroup.org/onlinepubs/009695399 */ 259 typedef ssize_t (*rtdm_read_handler_t)(struct rtdm_dev_context *context, 260 rtdm_user_info_t *user_info, 261 void *buf, size_t nbyte); 262 263 /** 264 * Write handler 265 * 266 * @param[in] context Context structure associated with opened device instance 267 * @param[in] user_info Opaque pointer to information about user mode caller, 268 * NULL if kernel mode call 269 * @param[in] buf Output buffer as passed by the user 270 * @param[in] nbyte Number of bytes the user requests to write 271 * 272 * @return On success, the number of bytes written. On failure return 273 * either -ENOSYS, to request that this handler be called again from the 274 * opposite realtime/non-realtime context, or another negative error code. 275 * 276 * @see @c write() in IEEE Std 1003.1, 277 * http://www.opengroup.org/onlinepubs/009695399 */ 278 typedef ssize_t (*rtdm_write_handler_t)(struct rtdm_dev_context *context, 279 rtdm_user_info_t *user_info, 280 const void *buf, size_t nbyte); 281 282 /** 283 * Receive message handler 284 * 285 * @param[in] context Context structure associated with opened device instance 286 * @param[in] user_info Opaque pointer to information about user mode caller, 287 * NULL if kernel mode call 288 * @param[in,out] msg Message descriptor as passed by the user, automatically 289 * mirrored to safe kernel memory in case of user mode call 290 * @param[in] flags Message flags as passed by the user 291 * 292 * @return On success, the number of bytes received. On failure return 293 * either -ENOSYS, to request that this handler be called again from the 294 * opposite realtime/non-realtime context, or another negative error code. 295 * 296 * @see @c recvmsg() in IEEE Std 1003.1, 297 * http://www.opengroup.org/onlinepubs/009695399 */ 298 typedef ssize_t (*rtdm_recvmsg_handler_t)(struct rtdm_dev_context *context, 299 rtdm_user_info_t *user_info, 300 struct msghdr *msg, int flags); 301 302 /** 303 * Transmit message handler 304 * 305 * @param[in] context Context structure associated with opened device instance 306 * @param[in] user_info Opaque pointer to information about user mode caller, 307 * NULL if kernel mode call 308 * @param[in] msg Message descriptor as passed by the user, automatically 309 * mirrored to safe kernel memory in case of user mode call 310 * @param[in] flags Message flags as passed by the user 311 * 312 * @return On success, the number of bytes transmitted. On failure return 313 * either -ENOSYS, to request that this handler be called again from the 314 * opposite realtime/non-realtime context, or another negative error code. 315 * 316 * @see @c sendmsg() in IEEE Std 1003.1, 317 * http://www.opengroup.org/onlinepubs/009695399 */ 318 typedef ssize_t (*rtdm_sendmsg_handler_t)(struct rtdm_dev_context *context, 319 rtdm_user_info_t *user_info, 320 const struct msghdr *msg, int flags); 321 /** @} Operation Handler Prototypes */ 322 323 typedef int (*rtdm_rt_handler_t)(struct rtdm_dev_context *context, 324 rtdm_user_info_t *user_info, void *arg); 325 /** 326 * Device operations 327 */ 328 struct rtdm_operations { 329 /*! @name Common Operations 330 * @{ */ 331 /** Close handler for real-time contexts (optional, deprecated) 332 * @deprecated Only use non-real-time close handler in new drivers. */ 333 rtdm_close_handler_t close_rt; 334 /** Close handler for non-real-time contexts (required) */ 335 rtdm_close_handler_t close_nrt; 336 337 /** IOCTL from real-time context (optional) */ 338 rtdm_ioctl_handler_t ioctl_rt; 339 /** IOCTL from non-real-time context (optional) */ 340 rtdm_ioctl_handler_t ioctl_nrt; 341 342 /** Select binding handler for any context (optional) */ 343 rtdm_select_bind_handler_t select_bind; 344 /** @} Common Operations */ 345 346 /*! @name Stream-Oriented Device Operations 347 * @{ */ 348 /** Read handler for real-time context (optional) */ 349 rtdm_read_handler_t read_rt; 350 /** Read handler for non-real-time context (optional) */ 351 rtdm_read_handler_t read_nrt; 352 353 /** Write handler for real-time context (optional) */ 354 rtdm_write_handler_t write_rt; 355 /** Write handler for non-real-time context (optional) */ 356 rtdm_write_handler_t write_nrt; 357 /** @} Stream-Oriented Device Operations */ 358 359 /*! @name Message-Oriented Device Operations 360 * @{ */ 361 /** Receive message handler for real-time context (optional) */ 362 rtdm_recvmsg_handler_t recvmsg_rt; 363 /** Receive message handler for non-real-time context (optional) */ 364 rtdm_recvmsg_handler_t recvmsg_nrt; 365 366 /** Transmit message handler for real-time context (optional) */ 367 rtdm_sendmsg_handler_t sendmsg_rt; 368 /** Transmit message handler for non-real-time context (optional) */ 369 rtdm_sendmsg_handler_t sendmsg_nrt; 370 /** @} Message-Oriented Device Operations */ 371 }; 372 373 struct rtdm_devctx_reserved { 374 void *owner; 375 struct list_head cleanup; 376 }; 377 378 /** 379 * @brief Device context 380 * 381 * A device context structure is associated with every open device instance. 382 * RTDM takes care of its creation and destruction and passes it to the 383 * operation handlers when being invoked. 384 * 385 * Drivers can attach arbitrary data immediately after the official structure. 386 * The size of this data is provided via rtdm_device.context_size during 387 * device registration. 388 */ 389 struct rtdm_dev_context { 390 /** Context flags, see @ref ctx_flags "Context Flags" for details */ 391 unsigned long context_flags; 392 393 /** Associated file descriptor */ 394 int fd; 395 396 /** Lock counter of context, held while structure is referenced by an 397 * operation handler */ 398 atomic_t close_lock_count; 399 400 /** Set of active device operation handlers */ 401 struct rtdm_operations *ops; 402 403 /** Reference to owning device */ 404 struct rtdm_device *device; 405 406 /** Data stored by RTDM inside a device context (internal use only) */ 407 struct rtdm_devctx_reserved reserved; 408 409 /** Begin of driver defined context data structure */ 410 char dev_private[0]; 411 }; 412 413 /** 414 * Locate the driver private area associated to a device context structure 415 * 416 * @param[in] context Context structure associated with opened device instance 417 * 418 * @return The address of the private driver area associated to @a 419 * context. 420 */ 421 static inline void * 422 rtdm_context_to_private(struct rtdm_dev_context *context) 423 { 424 return (void *)context->dev_private; 425 } 426 427 /** 428 * Locate a device context structure from its driver private area 429 * 430 * @param[in] dev_private Address of a private context area 431 * 432 * @return The address of the device context structure defining @a 433 * dev_private. 434 */ 435 static inline struct rtdm_dev_context * 436 rtdm_private_to_context(void *dev_private) 437 { 438 return container_of(dev_private, struct rtdm_dev_context, dev_private); 439 } 440 441 struct rtdm_dev_reserved { 442 struct list_head entry; 443 atomic_t refcount; 444 struct rtdm_dev_context *exclusive_context; 445 }; 446 447 /** 448 * @brief RTDM device 449 * 450 * This structure specifies a RTDM device. As some fields, especially the 451 * reserved area, will be modified by RTDM during runtime, the structure must 452 * not reside in write-protected memory. 453 */ 454 struct rtdm_device { 455 /** Revision number of this structure, see 456 * @ref drv_versioning "Driver Versioning" defines */ 457 int struct_version; 458 459 /** Device flags, see @ref dev_flags "Device Flags" for details */ 460 int device_flags; 461 /** Size of driver defined appendix to struct rtdm_dev_context */ 462 size_t context_size; 463 464 /** Named device identification (orthogonal to Linux device name space) */ 465 char device_name[RTDM_MAX_DEVNAME_LEN + 1]; 466 467 /** Protocol device identification: protocol family (PF_xxx) */ 468 int protocol_family; 469 /** Protocol device identification: socket type (SOCK_xxx) */ 470 int socket_type; 471 472 /** Named device instance creation for real-time contexts, 473 * optional (but deprecated) if open_nrt is non-NULL, ignored for 474 * protocol devices 475 * @deprecated Only use non-real-time open handler in new drivers. */ 476 rtdm_open_handler_t open_rt; 477 /** Named device instance creation for non-real-time contexts, 478 * optional if open_rt is non-NULL, ignored for protocol devices */ 479 rtdm_open_handler_t open_nrt; 480 481 /** Protocol socket creation for real-time contexts, 482 * optional (but deprecated) if socket_nrt is non-NULL, ignored for 483 * named devices 484 * @deprecated Only use non-real-time socket creation handler in new 485 * drivers. */ 486 rtdm_socket_handler_t socket_rt; 487 /** Protocol socket creation for non-real-time contexts, 488 * optional if socket_rt is non-NULL, ignored for named devices */ 489 rtdm_socket_handler_t socket_nrt; 490 491 /** Default operations on newly opened device instance */ 492 struct rtdm_operations ops; 493 494 /** Device class ID, see @ref RTDM_CLASS_xxx */ 495 int device_class; 496 /** Device sub-class, see RTDM_SUBCLASS_xxx definition in the 497 * @ref profiles "Device Profiles" */ 498 int device_sub_class; 499 /** Supported device profile version */ 500 int profile_version; 501 /** Informational driver name (reported via /proc) */ 502 const char *driver_name; 503 /** Driver version, see @ref drv_versioning "Driver Versioning" defines */ 504 int driver_version; 505 /** Informational peripheral name the device is attached to 506 * (reported via /proc) */ 507 const char *peripheral_name; 508 /** Informational driver provider name (reported via /proc) */ 509 const char *provider_name; 510 511 /** Name of /proc entry for the device, must not be NULL */ 512 const char *proc_name; 513 #ifdef CONFIG_PROC_FS 514 /** Set to device's vfile data after registration, do not modify */ 515 struct xnvfile_directory vfroot; 516 struct xnvfile_regular info_vfile; 517 #endif 518 519 /** Set to device's /proc root entry after registration, do not modify */ 520 struct proc_dir_entry *proc_entry; 521 522 /** Driver definable device ID */ 523 int device_id; 524 /** Driver definable device data */ 525 void *device_data; 526 527 /** Data stored by RTDM inside a registered device (internal use only) */ 528 struct rtdm_dev_reserved reserved; 529 }; 530 /** @} devregister */ 531 532 /* --- device registration --- */ 533 534 int rtdm_dev_register(struct rtdm_device *device); 535 int rtdm_dev_unregister(struct rtdm_device *device, unsigned int poll_delay); 536 537 /* --- inter-driver API --- */ 538 539 #define rtdm_open rt_dev_open 540 #define rtdm_socket rt_dev_socket 541 #define rtdm_close rt_dev_close 542 #define rtdm_ioctl rt_dev_ioctl 543 #define rtdm_read rt_dev_read 544 #define rtdm_write rt_dev_write 545 #define rtdm_recvmsg rt_dev_recvmsg 546 #define rtdm_recv rt_dev_recv 547 #define rtdm_recvfrom rt_dev_recvfrom 548 #define rtdm_sendmsg rt_dev_sendmsg 549 #define rtdm_send rt_dev_send 550 #define rtdm_sendto rt_dev_sendto 551 #define rtdm_bind rt_dev_bind 552 #define rtdm_listen rt_dev_listen 553 #define rtdm_accept rt_dev_accept 554 #define rtdm_getsockopt rt_dev_getsockopt 555 #define rtdm_setsockopt rt_dev_setsockopt 556 #define rtdm_getsockname rt_dev_getsockname 557 #define rtdm_getpeername rt_dev_getpeername 558 #define rtdm_shutdown rt_dev_shutdown 559 560 struct rtdm_dev_context *rtdm_context_get(int fd); 561 562 #ifndef DOXYGEN_CPP /* Avoid static inline tags for RTDM in doxygen */ 563 564 #define CONTEXT_IS_LOCKED(context) \ 565 (atomic_read(&(context)->close_lock_count) > 1 || \ 566 (test_bit(RTDM_CLOSING, &(context)->context_flags) && \ 567 atomic_read(&(context)->close_lock_count) > 0)) 568 569 static inline void rtdm_context_lock(struct rtdm_dev_context *context) 570 { 571 RTAI_ASSERT(RTDM, CONTEXT_IS_LOCKED(context), 572 /* just warn if context was a dangling pointer */); 573 atomic_inc(&context->close_lock_count); 574 } 575 576 extern int rtdm_apc; 577 578 static inline void rtdm_context_unlock(struct rtdm_dev_context *context) 579 { 580 RTAI_ASSERT(RTDM, CONTEXT_IS_LOCKED(context), 581 /* just warn if context was a dangling pointer */); 582 smp_mb__before_atomic_dec(); 583 if (unlikely(atomic_dec_and_test(&context->close_lock_count))) 584 rthal_apc_schedule(rtdm_apc); 585 } 586 587 static inline void rtdm_context_put(struct rtdm_dev_context *context) 588 { 589 rtdm_context_unlock(context); 590 } 591 592 /* --- clock services --- */ 593 594 595 596 static inline nanosecs_abs_t rtdm_clock_read(void) 597 { 598 return rt_get_time_ns(); 599 } 600 601 static inline nanosecs_abs_t rtdm_clock_read_monotonic(void) 602 { 603 return rt_get_time_ns(); 604 } 605 #endif /* !DOXYGEN_CPP */ 606 607 /*! 608 * @addtogroup rtdmsync 609 * @{ 610 */ 611 612 int rtdm_select_bind(int fd, rtdm_selector_t *selector, 613 enum rtdm_selecttype type, unsigned fd_index); 614 615 /* --- spin lock services --- */ 616 /*! 617 * @name Global Lock across Scheduler Invocation 618 * @{ 619 */ 620 621 /** 622 * @brief Execute code block atomically 623 * 624 * Generally, it is illegal to suspend the current task by calling 625 * rtdm_task_sleep(), rtdm_event_wait(), etc. while holding a spinlock. In 626 * contrast, this macro allows to combine several operations including 627 * a potentially rescheduling call to an atomic code block with respect to 628 * other RTDM_EXECUTE_ATOMICALLY() blocks. The macro is a light-weight 629 * alternative for protecting code blocks via mutexes, and it can even be used 630 * to synchronise real-time and non-real-time contexts. 631 * 632 * @param code_block Commands to be executed atomically 633 * 634 * @note It is not allowed to leave the code block explicitly by using 635 * @c break, @c return, @c goto, etc. This would leave the global lock held 636 * during the code block execution in an inconsistent state. Moreover, do not 637 * embed complex operations into the code bock. Consider that they will be 638 * executed under preemption lock with interrupts switched-off. Also note that 639 * invocation of rescheduling calls may break the atomicity until the task 640 * gains the CPU again. 641 * 642 * Environments: 643 * 644 * This service can be called from: 645 * 646 * - Kernel module initialization/cleanup code 647 * - Interrupt service routine 648 * - Kernel-based task 649 * - User-space task (RT, non-RT) 650 * 651 * Rescheduling: possible, depends on functions called within @a code_block. 652 */ 653 #ifdef DOXYGEN_CPP /* Beautify doxygen output */ 654 #define RTDM_EXECUTE_ATOMICALLY(code_block) \ 655 { \ 656 <ENTER_ATOMIC_SECTION> \ 657 code_block; \ 658 <LEAVE_ATOMIC_SECTION> \ 659 } 660 #else /* This is how it really works */ 661 #define RTDM_EXECUTE_ATOMICALLY(code_block) \ 662 { \ 663 spl_t s; \ 664 \ 665 s = rt_global_save_flags_and_cli(); \ 666 code_block; \ 667 rt_global_restore_flags(s); \ 668 } 669 #endif 670 /** @} Global Lock across Scheduler Invocation */ 671 672 /*! 673 * @name Spinlock with Preemption Deactivation 674 * @{ 675 */ 676 677 /** 678 * Static lock initialisation 679 */ 680 #define RTDM_LOCK_UNLOCKED SPIN_LOCK_UNLOCKED 681 682 /** Lock variable */ 683 typedef spinlock_t rtdm_lock_t; 684 685 /** Variable to save the context while holding a lock */ 686 typedef unsigned long rtdm_lockctx_t; 687 688 /** 689 * Dynamic lock initialisation 690 * 691 * @param lock Address of lock variable 692 * 693 * Environments: 694 * 695 * This service can be called from: 696 * 697 * - Kernel module initialization/cleanup code 698 * - Kernel-based task 699 * - User-space task (RT, non-RT) 700 * 701 * Rescheduling: never. 702 */ 703 #define rtdm_lock_init(lock) spin_lock_init(lock) 704 705 /** 706 * Acquire lock from non-preemptible contexts 707 * 708 * @param lock Address of lock variable 709 * 710 * Environments: 711 * 712 * This service can be called from: 713 * 714 * - Kernel module initialization/cleanup code 715 * - Interrupt service routine 716 * - Kernel-based task 717 * - User-space task (RT, non-RT) 718 * 719 * Rescheduling: never. 720 */ 721 #ifdef DOXYGEN_CPP /* Beautify doxygen output */ 722 #define rtdm_lock_get(lock) rt_spin_lock(lock) 723 #else /* This is how it really works */ 724 #define rtdm_lock_get(lock) \ 725 do { \ 726 RTAI_BUGON(RTDM, !rthal_local_irq_disabled()); \ 727 rt_spin_lock(lock); \ 728 } while (0) 729 #endif 730 731 /** 732 * Release lock without preemption restoration 733 * 734 * @param lock Address of lock variable 735 * 736 * Environments: 737 * 738 * This service can be called from: 739 * 740 * - Kernel module initialization/cleanup code 741 * - Interrupt service routine 742 * - Kernel-based task 743 * - User-space task (RT, non-RT) 744 * 745 * Rescheduling: never. 746 */ 747 #define rtdm_lock_put(lock) rt_spin_unlock(lock) 748 749 /** 750 * Acquire lock and disable preemption 751 * 752 * @param lock Address of lock variable 753 * @param context name of local variable to store the context in 754 * 755 * Environments: 756 * 757 * This service can be called from: 758 * 759 * - Kernel module initialization/cleanup code 760 * - Interrupt service routine 761 * - Kernel-based task 762 * - User-space task (RT, non-RT) 763 * 764 * Rescheduling: never. 765 */ 766 #define rtdm_lock_get_irqsave(lock, context) \ 767 do { context = rt_spin_lock_irqsave(lock); } while (0) 768 769 /** 770 * Release lock and restore preemption state 771 * 772 * @param lock Address of lock variable 773 * @param context name of local variable which stored the context 774 * 775 * Environments: 776 * 777 * This service can be called from: 778 * 779 * - Kernel module initialization/cleanup code 780 * - Interrupt service routine 781 * - Kernel-based task 782 * - User-space task (RT, non-RT) 783 * 784 * Rescheduling: possible. 785 */ 786 #define rtdm_lock_put_irqrestore(lock, context) \ 787 rt_spin_unlock_irqrestore(context, lock) 788 789 /** 790 * Disable preemption locally 791 * 792 * @param context name of local variable to store the context in 793 * 794 * Environments: 795 * 796 * This service can be called from: 797 * 798 * - Kernel module initialization/cleanup code 799 * - Interrupt service routine 800 * - Kernel-based task 801 * - User-space task (RT, non-RT) 802 * 803 * Rescheduling: never. 804 */ 805 #define rtdm_lock_irqsave(context) \ 806 rtai_save_flags_and_cli(context) 807 808 /** 809 * Restore preemption state 810 * 811 * @param context name of local variable which stored the context 812 * 813 * Environments: 814 * 815 * This service can be called from: 816 * 817 * - Kernel module initialization/cleanup code 818 * - Interrupt service routine 819 * - Kernel-based task 820 * - User-space task (RT, non-RT) 821 * 822 * Rescheduling: possible. 823 */ 824 #define rtdm_lock_irqrestore(context) \ 825 rtai_restore_flags(context) 826 /** @} Spinlock with Preemption Deactivation */ 827 828 /** @} rtdmsync */ 829 830 /* --- Interrupt management services --- */ 831 /*! 832 * @addtogroup rtdmirq 833 * @{ 834 */ 835 836 typedef xnintr_t rtdm_irq_t; 837 838 /*! 839 * @anchor RTDM_IRQTYPE_xxx @name RTDM_IRQTYPE_xxx 840 * Interrupt registrations flags 841 * @{ 842 */ 843 /** Enable IRQ-sharing with other real-time drivers */ 844 #define RTDM_IRQTYPE_SHARED XN_ISR_SHARED 845 /** Mark IRQ as edge-triggered, relevant for correct handling of shared 846 * edge-triggered IRQs */ 847 #define RTDM_IRQTYPE_EDGE XN_ISR_EDGE 848 /** @} RTDM_IRQTYPE_xxx */ 849 850 /** 851 * Interrupt handler 852 * 853 * @param[in] irq_handle IRQ handle as returned by rtdm_irq_request() 854 * 855 * @return 0 or a combination of @ref RTDM_IRQ_xxx flags 856 */ 857 typedef int (*rtdm_irq_handler_t)(rtdm_irq_t *irq_handle); 858 859 /*! 860 * @anchor RTDM_IRQ_xxx @name RTDM_IRQ_xxx 861 * Return flags of interrupt handlers 862 * @{ 863 */ 864 /** Unhandled interrupt */ 865 #define RTDM_IRQ_NONE XN_ISR_NONE 866 /** Denote handled interrupt */ 867 #define RTDM_IRQ_HANDLED XN_ISR_HANDLED 868 /** @} RTDM_IRQ_xxx */ 869 870 /** 871 * Retrieve IRQ handler argument 872 * 873 * @param irq_handle IRQ handle 874 * @param type Type of the pointer to return 875 * 876 * @return The argument pointer registered on rtdm_irq_request() is returned, 877 * type-casted to the specified @a type. 878 * 879 * Environments: 880 * 881 * This service can be called from: 882 * 883 * - Interrupt service routine 884 * 885 * Rescheduling: never. 886 */ 887 #define rtdm_irq_get_arg(irq_handle, type) ((type *)irq_handle->cookie) 888 /** @} rtdmirq */ 889 890 int rtdm_irq_request(rtdm_irq_t *irq_handle, unsigned int irq_no, 891 rtdm_irq_handler_t handler, unsigned long flags, 892 const char *device_name, void *arg); 893 894 #ifndef DOXYGEN_CPP /* Avoid static inline tags for RTDM in doxygen */ 895 static inline int rtdm_irq_free(rtdm_irq_t *irq_handle) 896 { 897 return xnintr_detach(irq_handle); 898 } 899 900 static inline int rtdm_irq_enable(rtdm_irq_t *irq_handle) 901 { 902 return xnintr_enable(irq_handle); 903 } 904 905 static inline int rtdm_irq_disable(rtdm_irq_t *irq_handle) 906 { 907 return xnintr_disable(irq_handle); 908 } 909 #endif /* !DOXYGEN_CPP */ 910 911 /* --- non-real-time signalling services --- */ 912 913 /*! 914 * @addtogroup nrtsignal 915 * @{ 916 */ 917 918 typedef unsigned rtdm_nrtsig_t; 919 920 /** 921 * Non-real-time signal handler 922 * 923 * @param[in] nrt_sig Signal handle as returned by rtdm_nrtsig_init() 924 * @param[in] arg Argument as passed to rtdm_nrtsig_init() 925 * 926 * @note The signal handler will run in soft-IRQ context of the non-real-time 927 * subsystem. Note the implications of this context, e.g. no invocation of 928 * blocking operations. 929 */ 930 typedef void (*rtdm_nrtsig_handler_t)(rtdm_nrtsig_t nrt_sig, void *arg); 931 /** @} nrtsignal */ 932 933 #ifndef DOXYGEN_CPP /* Avoid static inline tags for RTDM in doxygen */ 934 static inline int rtdm_nrtsig_init(rtdm_nrtsig_t *nrt_sig, 935 rtdm_nrtsig_handler_t handler, void *arg) 936 { 937 *nrt_sig = hal_alloc_irq(); 938 939 if (*nrt_sig == 0) 940 return -EAGAIN; 941 942 rthal_virtualize_irq(hal_root_domain, *nrt_sig, handler, arg, NULL, 943 IPIPE_HANDLE_MASK); 944 return 0; 945 } 946 947 static inline void rtdm_nrtsig_destroy(rtdm_nrtsig_t *nrt_sig) 948 { 949 hal_free_irq(*nrt_sig); 950 } 951 952 static inline void rtdm_nrtsig_pend(rtdm_nrtsig_t *nrt_sig) 953 { 954 hal_pend_uncond(*nrt_sig, rtai_cpuid()); 955 } 956 #endif /* !DOXYGEN_CPP */ 957 958 /* --- timer services --- */ 959 960 /*! 961 * @addtogroup rtdmtimer 962 * @{ 963 */ 964 965 typedef xntimer_t rtdm_timer_t; 966 967 /** 968 * Timer handler 969 * 970 * @param[in] timer Timer handle as returned by rtdm_timer_init() 971 */ 972 typedef void (*rtdm_timer_handler_t)(rtdm_timer_t *timer); 973 974 /*! 975 * @anchor RTDM_TIMERMODE_xxx @name RTDM_TIMERMODE_xxx 976 * Timer operation modes 977 * @{ 978 */ 979 enum rtdm_timer_mode { 980 /** Monotonic timer with relative timeout */ 981 RTDM_TIMERMODE_RELATIVE = XN_RELATIVE, 982 983 /** Monotonic timer with absolute timeout */ 984 RTDM_TIMERMODE_ABSOLUTE = XN_ABSOLUTE, 985 986 /** Adjustable timer with absolute timeout */ 987 RTDM_TIMERMODE_REALTIME = XN_REALTIME 988 }; 989 /** @} RTDM_TIMERMODE_xxx */ 990 991 /** @} rtdmtimer */ 992 993 #ifndef DOXYGEN_CPP /* Avoid broken doxygen output */ 994 #define rtdm_timer_init(timer, handler, name) \ 995 ({ \ 996 xntimer_init((timer), handler); \ 997 xntimer_set_name((timer), (name)); \ 998 0; \ 999 }) 1000 #endif /* !DOXYGEN_CPP */ 1001 1002 void rtdm_timer_destroy(rtdm_timer_t *timer); 1003 1004 int rtdm_timer_start(rtdm_timer_t *timer, nanosecs_abs_t expiry, 1005 nanosecs_rel_t interval, enum rtdm_timer_mode mode); 1006 1007 void rtdm_timer_stop(rtdm_timer_t *timer); 1008 1009 #ifndef DOXYGEN_CPP /* Avoid static inline tags for RTDM in doxygen */ 1010 static inline int rtdm_timer_start_in_handler(rtdm_timer_t *timer, 1011 nanosecs_abs_t expiry, 1012 nanosecs_rel_t interval, 1013 enum rtdm_timer_mode mode) 1014 { 1015 return xntimer_start(timer, xntbase_ns2ticks(rtdm_tbase, expiry), 1016 xntbase_ns2ticks(rtdm_tbase, interval), 1017 (xntmode_t)mode); 1018 } 1019 1020 static inline void rtdm_timer_stop_in_handler(rtdm_timer_t *timer) 1021 { 1022 xntimer_stop(timer); 1023 } 1024 #endif /* !DOXYGEN_CPP */ 1025 1026 /* --- task services --- */ 1027 /*! 1028 * @addtogroup rtdmtask 1029 * @{ 1030 */ 1031 1032 typedef struct rt_task_struct rtdm_task_t; 1033 1034 /** 1035 * Real-time task procedure 1036 * 1037 * @param[in,out] arg argument as passed to rtdm_task_init() 1038 */ 1039 typedef void (*rtdm_task_proc_t)(void *arg); 1040 1041 /*! 1042 * @anchor taskprio @name Task Priority Range 1043 * Maximum and minimum task priorities 1044 * @{ */ 1045 #define RTDM_TASK_LOWEST_PRIORITY 999999999 1046 #define RTDM_TASK_HIGHEST_PRIORITY 0 1047 /** @} Task Priority Range */ 1048 1049 /*! 1050 * @anchor changetaskprio @name Task Priority Modification 1051 * Raise or lower task priorities by one level 1052 * @{ */ 1053 #define RTDM_TASK_RAISE_PRIORITY (-1) 1054 #define RTDM_TASK_LOWER_PRIORITY (+1) 1055 /** @} Task Priority Modification */ 1056 1057 /** @} rtdmtask */ 1058 1059 int rtdm_task_init_cpuid(rtdm_task_t *task, const char *name, 1060 rtdm_task_proc_t task_proc, void *arg, 1061 int priority, nanosecs_rel_t period, int cpuid); 1062 1063 extern int get_min_tasks_cpuid(void); 1064 static inline int rtdm_task_init(rtdm_task_t *task, const char *name, 1065 rtdm_task_proc_t task_proc, void *arg, 1066 int priority, nanosecs_rel_t period) 1067 { 1068 return rtdm_task_init_cpuid(task, name, task_proc, arg, priority, period, get_min_tasks_cpuid()); 1069 } 1070 1071 void rtdm_task_busy_sleep(nanosecs_rel_t delay); 1072 1073 #ifndef DOXYGEN_CPP /* Avoid static inline tags for RTDM in doxygen */ 1074 static inline void rtdm_task_destroy(rtdm_task_t *task) 1075 { 1076 rt_drg_on_adr(task); 1077 if (task->magic == RT_TASK_MAGIC) { 1078 rt_task_delete(task); 1079 } 1080 } 1081 1082 void rtdm_task_join_nrt(rtdm_task_t *task, unsigned int poll_delay); 1083 1084 static inline void rtdm_task_set_priority(rtdm_task_t *task, int priority) 1085 { 1086 1087 1088 rt_change_prio(task, priority); 1089 } 1090 1091 static inline int rtdm_task_set_period(rtdm_task_t *task, 1092 nanosecs_rel_t period) 1093 { 1094 if (period < 0) 1095 period = 0; 1096 return rt_task_make_periodic_relative_ns(task, 0, period); 1097 1098 1099 } 1100 1101 static inline int rtdm_task_unblock(rtdm_task_t *task) 1102 { 1103 int res = rt_task_masked_unblock(task, ~RT_SCHED_READY); 1104 1105 1106 return res; 1107 } 1108 1109 static inline rtdm_task_t *rtdm_task_current(void) 1110 { 1111 return _rt_whoami(); 1112 } 1113 1114 static inline int rtdm_task_wait_period(void) 1115 { 1116 if (!_rt_whoami()->period) { 1117 return -EINVAL; 1118 } 1119 if (!rt_task_wait_period()) { 1120 return 0; 1121 } 1122 if (_rt_whoami()->unblocked) { 1123 return -EINTR; 1124 } 1125 return rt_sched_timed ? -ETIMEDOUT : -EIDRM; 1126 } 1127 1128 //RTA_SYSCALL_MODE int rt_sleep(longlong); 1129 static inline int rtdm_task_sleep(nanosecs_rel_t delay) 1130 { 1131 if (delay < 0) { 1132 return 0; 1133 } 1134 if (delay < 0) { 1135 delay = RT_TIME_END; 1136 } 1137 if (rt_sleep(nano2count(delay)) && _rt_whoami()->unblocked) { 1138 return -EINTR; 1139 } 1140 return 0; 1141 } 1142 1143 static inline int 1144 rtdm_task_sleep_abs(nanosecs_abs_t wakeup_date, enum rtdm_timer_mode mode) 1145 { 1146 /* For the sake of a consistent API usage... */ 1147 if (mode != RTDM_TIMERMODE_ABSOLUTE && mode != RTDM_TIMERMODE_REALTIME) 1148 return -EINVAL; 1149 if (rt_sleep_until(nano2count(wakeup_date)) && _rt_whoami()->unblocked) { 1150 return -EINTR; 1151 } 1152 return 0; 1153 } 1154 1155 /* rtdm_task_sleep_abs shall be used instead */ 1156 static inline int __deprecated rtdm_task_sleep_until(nanosecs_abs_t wakeup_time) 1157 { 1158 if (rt_sleep_until(nano2count(wakeup_time)) && _rt_whoami()->unblocked) { 1159 return -EINTR; 1160 } 1161 return 0; 1162 } 1163 #endif /* !DOXYGEN_CPP */ 1164 1165 /* --- timeout sequences */ 1166 1167 typedef nanosecs_abs_t rtdm_toseq_t; 1168 1169 void rtdm_toseq_init(rtdm_toseq_t *timeout_seq, nanosecs_rel_t timeout); 1170 1171 /* --- event services --- */ 1172 1173 typedef struct { 1174 struct rt_semaphore synch_base; unsigned long pending; 1175 DECLARE_XNSELECT(select_block); 1176 } rtdm_event_t; 1177 1178 #define RTDM_EVENT_PENDING XNSYNCH_SPARE1 1179 1180 void rtdm_event_init(rtdm_event_t *event, unsigned long pending); 1181 #ifdef CONFIG_RTAI_RTDM_SELECT 1182 int rtdm_event_select_bind(rtdm_event_t *event, rtdm_selector_t *selector, 1183 enum rtdm_selecttype type, unsigned fd_index); 1184 #else /* !CONFIG_RTAI_RTDM_SELECT */ 1185 #define rtdm_event_select_bind(e, s, t, i) ({ (void)(e); -EBADF; }) 1186 #endif /* !CONFIG_RTAI_RTDM_SELECT */ 1187 int rtdm_event_wait(rtdm_event_t *event); 1188 int rtdm_event_timedwait(rtdm_event_t *event, nanosecs_rel_t timeout, 1189 rtdm_toseq_t *timeout_seq); 1190 void rtdm_event_signal(rtdm_event_t *event); 1191 1192 void rtdm_event_clear(rtdm_event_t *event); 1193 1194 #ifndef DOXYGEN_CPP /* Avoid static inline tags for RTDM in doxygen */ 1195 1196 1197 static inline void rtdm_event_pulse(rtdm_event_t *event) 1198 { 1199 trace_mark(xn_rtdm, event_pulse, "event %p", event); 1200 rt_sem_broadcast(&event->synch_base); 1201 } 1202 1203 static inline void rtdm_event_destroy(rtdm_event_t *event) 1204 { 1205 trace_mark(xn_rtdm, event_destroy, "event %p", event); 1206 rt_sem_delete(&event->synch_base); 1207 xnselect_destroy(&event->select_block); 1208 } 1209 #endif /* !DOXYGEN_CPP */ 1210 1211 /* --- semaphore services --- */ 1212 1213 typedef struct { 1214 struct rt_semaphore sem; 1215 DECLARE_XNSELECT(select_block); 1216 } rtdm_sem_t; 1217 1218 1219 void rtdm_sem_init(rtdm_sem_t *sem, unsigned long value); 1220 #ifdef CONFIG_RTAI_RTDM_SELECT 1221 int rtdm_sem_select_bind(rtdm_sem_t *sem, rtdm_selector_t *selector, 1222 enum rtdm_selecttype type, unsigned fd_index); 1223 #else /* !CONFIG_RTAI_RTDM_SELECT */ 1224 #define rtdm_sem_select_bind(s, se, t, i) ({ -EBADF; }) 1225 #endif /* !CONFIG_RTAI_RTDM_SELECT */ 1226 int rtdm_sem_down(rtdm_sem_t *sem); 1227 int rtdm_sem_timeddown(rtdm_sem_t *sem, nanosecs_rel_t timeout, 1228 rtdm_toseq_t *timeout_seq); 1229 void rtdm_sem_up(rtdm_sem_t *sem); 1230 1231 #ifndef DOXYGEN_CPP /* Avoid static inline tags for RTDM in doxygen */ 1232 static inline void rtdm_sem_destroy(rtdm_sem_t *sem) 1233 { 1234 trace_mark(xn_rtdm, sem_destroy, "sem %p", sem); 1235 rt_sem_delete(&sem->sem); 1236 xnselect_destroy(&sem->select_block); 1237 } 1238 #endif /* !DOXYGEN_CPP */ 1239 1240 /* --- mutex services --- */ 1241 1242 typedef SEM rtdm_mutex_t; 1243 1244 1245 1246 void rtdm_mutex_init(rtdm_mutex_t *mutex); 1247 int rtdm_mutex_lock(rtdm_mutex_t *mutex); 1248 int rtdm_mutex_timedlock(rtdm_mutex_t *mutex, nanosecs_rel_t timeout, 1249 rtdm_toseq_t *timeout_seq); 1250 1251 #ifndef DOXYGEN_CPP /* Avoid static inline tags for RTDM in doxygen */ 1252 static inline void rtdm_mutex_unlock(rtdm_mutex_t *mutex) 1253 { 1254 1255 1256 trace_mark(xn_rtdm, mutex_unlock, "mutex %p", mutex); 1257 1258 1259 rt_sem_signal(mutex); 1260 } 1261 1262 static inline void rtdm_mutex_destroy(rtdm_mutex_t *mutex) 1263 { 1264 trace_mark(xn_rtdm, mutex_destroy, "mutex %p", mutex); 1265 1266 rt_sem_delete(mutex); 1267 } 1268 #endif /* !DOXYGEN_CPP */ 1269 1270 /* --- utility functions --- */ 1271 1272 #define rtdm_printk(format, ...) printk(format, ##__VA_ARGS__) 1273 1274 #ifndef DOXYGEN_CPP /* Avoid static inline tags for RTDM in doxygen */ 1275 static inline void *rtdm_malloc(size_t size) 1276 { 1277 return xnmalloc(size); 1278 } 1279 1280 static inline void rtdm_free(void *ptr) 1281 { 1282 xnfree(ptr); 1283 } 1284 1285 #ifdef CONFIG_RTAI_OPT_PERVASIVE 1286 int rtdm_mmap_to_user(rtdm_user_info_t *user_info, 1287 void *src_addr, size_t len, 1288 int prot, void **pptr, 1289 struct vm_operations_struct *vm_ops, 1290 void *vm_private_data); 1291 int rtdm_iomap_to_user(rtdm_user_info_t *user_info, 1292 phys_addr_t src_addr, size_t len, 1293 int prot, void **pptr, 1294 struct vm_operations_struct *vm_ops, 1295 void *vm_private_data); 1296 int rtdm_munmap(rtdm_user_info_t *user_info, void *ptr, size_t len); 1297 1298 static inline int rtdm_read_user_ok(rtdm_user_info_t *user_info, 1299 const void __user *ptr, size_t size) 1300 { 1301 return __xn_access_ok(user_info, VERIFY_READ, ptr, size); 1302 } 1303 1304 static inline int rtdm_rw_user_ok(rtdm_user_info_t *user_info, 1305 const void __user *ptr, size_t size) 1306 { 1307 return __xn_access_ok(user_info, VERIFY_WRITE, ptr, size); 1308 } 1309 1310 static inline int rtdm_copy_from_user(rtdm_user_info_t *user_info, 1311 void *dst, const void __user *src, 1312 size_t size) 1313 { 1314 return __xn_copy_from_user(user_info, dst, src, size) ? -EFAULT : 0; 1315 } 1316 1317 static inline int rtdm_safe_copy_from_user(rtdm_user_info_t *user_info, 1318 void *dst, const void __user *src, 1319 size_t size) 1320 { 1321 return (!__xn_access_ok(user_info, VERIFY_READ, src, size) || 1322 __xn_copy_from_user(user_info, dst, src, size)) ? -EFAULT : 0; 1323 } 1324 1325 static inline int rtdm_copy_to_user(rtdm_user_info_t *user_info, 1326 void __user *dst, const void *src, 1327 size_t size) 1328 { 1329 return __xn_copy_to_user(user_info, dst, src, size) ? -EFAULT : 0; 1330 } 1331 1332 static inline int rtdm_safe_copy_to_user(rtdm_user_info_t *user_info, 1333 void __user *dst, const void *src, 1334 size_t size) 1335 { 1336 return (!__xn_access_ok(user_info, VERIFY_WRITE, dst, size) || 1337 __xn_copy_to_user(user_info, dst, src, size)) ? -EFAULT : 0; 1338 } 1339 1340 static inline int rtdm_strncpy_from_user(rtdm_user_info_t *user_info, 1341 char *dst, 1342 const char __user *src, size_t count) 1343 { 1344 if (unlikely(!__xn_access_ok(user_info, VERIFY_READ, src, 1))) 1345 return -EFAULT; 1346 return __xn_strncpy_from_user(user_info, dst, src, count); 1347 } 1348 #else /* !CONFIG_RTAI_OPT_PERVASIVE */ 1349 /* Define void user<->kernel services that simply fail */ 1350 #define rtdm_mmap_to_user(...) ({ -ENOSYS; }) 1351 #define rtdm_munmap(...) ({ -ENOSYS; }) 1352 #define rtdm_read_user_ok(...) ({ 0; }) 1353 #define rtdm_rw_user_ok(...) ({ 0; }) 1354 #define rtdm_copy_from_user(...) ({ -ENOSYS; }) 1355 #define rtdm_safe_copy_from_user(...) ({ -ENOSYS; }) 1356 #define rtdm_copy_to_user(...) ({ -ENOSYS; }) 1357 #define rtdm_safe_copy_to_user(...) ({ -ENOSYS; }) 1358 #define rtdm_strncpy_from_user(...) ({ -ENOSYS; }) 1359 #endif /* CONFIG_RTAI_OPT_PERVASIVE */ 1360 1361 static inline int rtdm_in_rt_context(void) 1362 { 1363 return (_rt_whoami()->is_hard > 0); 1364 } 1365 1366 static inline int rtdm_rt_capable(rtdm_user_info_t *user_info) 1367 { 1368 1369 1370 return (user_info ? xnshadow_thread(user_info) != NULL 1371 : !xnpod_root_p()); 1372 } 1373 1374 #endif /* !DOXYGEN_CPP */ 1375 1376 int rtdm_exec_in_rt(struct rtdm_dev_context *context, 1377 rtdm_user_info_t *user_info, void *arg, 1378 rtdm_rt_handler_t handler); 1379 1380 #endif /* _RTDM_DRIVER_H */