Xenomai API
2.5.6.1
|
00001 00026 #ifndef _RTDM_DRIVER_H 00027 #define _RTDM_DRIVER_H 00028 00029 #ifndef __KERNEL__ 00030 #error This header is for kernel space usage only. \ 00031 You are likely looking for rtdm/rtdm.h... 00032 #endif /* !__KERNEL__ */ 00033 00034 #include <asm/atomic.h> 00035 #include <linux/list.h> 00036 00037 #include <nucleus/xenomai.h> 00038 #include <nucleus/heap.h> 00039 #include <nucleus/pod.h> 00040 #include <nucleus/synch.h> 00041 #include <nucleus/select.h> 00042 #include <rtdm/rtdm.h> 00043 00044 /* debug support */ 00045 #include <nucleus/assert.h> 00046 #ifdef CONFIG_PCI 00047 #include <asm-generic/xenomai/pci_ids.h> 00048 #endif /* CONFIG_PCI */ 00049 00050 #ifndef CONFIG_XENO_OPT_DEBUG_RTDM 00051 #define CONFIG_XENO_OPT_DEBUG_RTDM 0 00052 #endif 00053 00054 struct rtdm_dev_context; 00055 typedef struct xnselector rtdm_selector_t; 00056 enum rtdm_selecttype; 00057 00070 #define RTDM_EXCLUSIVE 0x0001 00071 00073 #define RTDM_NAMED_DEVICE 0x0010 00074 00077 #define RTDM_PROTOCOL_DEVICE 0x0020 00078 00080 #define RTDM_DEVICE_TYPE_MASK 0x00F0 00081 00090 #define RTDM_CREATED_IN_NRT 0 00091 00093 #define RTDM_CLOSING 1 00094 00096 #define RTDM_USER_CONTEXT_FLAG 8 /* first user-definable flag */ 00097 00106 #define RTDM_DEVICE_STRUCT_VER 5 00107 00109 #define RTDM_CONTEXT_STRUCT_VER 3 00110 00112 #define RTDM_SECURE_DEVICE 0x80000000 00113 00115 #define RTDM_DRIVER_VER(major, minor, patch) \ 00116 (((major & 0xFF) << 16) | ((minor & 0xFF) << 8) | (patch & 0xFF)) 00117 00119 #define RTDM_DRIVER_MAJOR_VER(ver) (((ver) >> 16) & 0xFF) 00120 00122 #define RTDM_DRIVER_MINOR_VER(ver) (((ver) >> 8) & 0xFF) 00123 00125 #define RTDM_DRIVER_PATCH_VER(ver) ((ver) & 0xFF) 00126 00138 enum rtdm_selecttype { 00140 RTDM_SELECTTYPE_READ = XNSELECT_READ, 00141 00143 RTDM_SELECTTYPE_WRITE = XNSELECT_WRITE, 00144 00146 RTDM_SELECTTYPE_EXCEPT = XNSELECT_EXCEPT 00147 }; 00171 typedef int (*rtdm_open_handler_t)(struct rtdm_dev_context *context, 00172 rtdm_user_info_t *user_info, int oflag); 00173 00188 typedef int (*rtdm_socket_handler_t)(struct rtdm_dev_context *context, 00189 rtdm_user_info_t *user_info, int protocol); 00190 00211 typedef int (*rtdm_close_handler_t)(struct rtdm_dev_context *context, 00212 rtdm_user_info_t *user_info); 00213 00229 typedef int (*rtdm_ioctl_handler_t)(struct rtdm_dev_context *context, 00230 rtdm_user_info_t *user_info, 00231 unsigned int request, void __user *arg); 00232 00246 typedef int (*rtdm_select_bind_handler_t)(struct rtdm_dev_context *context, 00247 rtdm_selector_t *selector, 00248 enum rtdm_selecttype type, 00249 unsigned fd_index); 00250 00266 typedef ssize_t (*rtdm_read_handler_t)(struct rtdm_dev_context *context, 00267 rtdm_user_info_t *user_info, 00268 void *buf, size_t nbyte); 00269 00285 typedef ssize_t (*rtdm_write_handler_t)(struct rtdm_dev_context *context, 00286 rtdm_user_info_t *user_info, 00287 const void *buf, size_t nbyte); 00288 00305 typedef ssize_t (*rtdm_recvmsg_handler_t)(struct rtdm_dev_context *context, 00306 rtdm_user_info_t *user_info, 00307 struct msghdr *msg, int flags); 00308 00325 typedef ssize_t (*rtdm_sendmsg_handler_t)(struct rtdm_dev_context *context, 00326 rtdm_user_info_t *user_info, 00327 const struct msghdr *msg, int flags); 00330 typedef int (*rtdm_rt_handler_t)(struct rtdm_dev_context *context, 00331 rtdm_user_info_t *user_info, void *arg); 00335 struct rtdm_operations { 00340 rtdm_close_handler_t close_rt; 00342 rtdm_close_handler_t close_nrt; 00343 00345 rtdm_ioctl_handler_t ioctl_rt; 00347 rtdm_ioctl_handler_t ioctl_nrt; 00348 00350 rtdm_select_bind_handler_t select_bind; 00356 rtdm_read_handler_t read_rt; 00358 rtdm_read_handler_t read_nrt; 00359 00361 rtdm_write_handler_t write_rt; 00363 rtdm_write_handler_t write_nrt; 00369 rtdm_recvmsg_handler_t recvmsg_rt; 00371 rtdm_recvmsg_handler_t recvmsg_nrt; 00372 00374 rtdm_sendmsg_handler_t sendmsg_rt; 00376 rtdm_sendmsg_handler_t sendmsg_nrt; 00378 }; 00379 00380 struct rtdm_devctx_reserved { 00381 void *owner; 00382 struct list_head cleanup; 00383 }; 00384 00396 struct rtdm_dev_context { 00398 unsigned long context_flags; 00399 00401 int fd; 00402 00405 atomic_t close_lock_count; 00406 00408 struct rtdm_operations *ops; 00409 00411 struct rtdm_device *device; 00412 00414 struct rtdm_devctx_reserved reserved; 00415 00417 char dev_private[0]; 00418 }; 00419 00428 static inline void * 00429 rtdm_context_to_private(struct rtdm_dev_context *context) 00430 { 00431 return (void *)context->dev_private; 00432 } 00433 00442 static inline struct rtdm_dev_context * 00443 rtdm_private_to_context(void *dev_private) 00444 { 00445 return container_of(dev_private, struct rtdm_dev_context, dev_private); 00446 } 00447 00448 struct rtdm_dev_reserved { 00449 struct list_head entry; 00450 atomic_t refcount; 00451 struct rtdm_dev_context *exclusive_context; 00452 }; 00453 00461 struct rtdm_device { 00464 int struct_version; 00465 00467 int device_flags; 00469 size_t context_size; 00470 00472 char device_name[RTDM_MAX_DEVNAME_LEN + 1]; 00473 00475 int protocol_family; 00477 int socket_type; 00478 00483 rtdm_open_handler_t open_rt; 00486 rtdm_open_handler_t open_nrt; 00487 00493 rtdm_socket_handler_t socket_rt; 00496 rtdm_socket_handler_t socket_nrt; 00497 00499 struct rtdm_operations ops; 00500 00502 int device_class; 00505 int device_sub_class; 00507 int profile_version; 00509 const char *driver_name; 00511 int driver_version; 00514 const char *peripheral_name; 00516 const char *provider_name; 00517 00519 const char *proc_name; 00521 struct proc_dir_entry *proc_entry; 00522 00524 int device_id; 00526 void *device_data; 00527 00529 struct rtdm_dev_reserved reserved; 00530 }; 00533 /* --- device registration --- */ 00534 00535 int rtdm_dev_register(struct rtdm_device *device); 00536 int rtdm_dev_unregister(struct rtdm_device *device, unsigned int poll_delay); 00537 00538 /* --- inter-driver API --- */ 00539 00540 #define rtdm_open rt_dev_open 00541 #define rtdm_socket rt_dev_socket 00542 #define rtdm_close rt_dev_close 00543 #define rtdm_ioctl rt_dev_ioctl 00544 #define rtdm_read rt_dev_read 00545 #define rtdm_write rt_dev_write 00546 #define rtdm_recvmsg rt_dev_recvmsg 00547 #define rtdm_recv rt_dev_recv 00548 #define rtdm_recvfrom rt_dev_recvfrom 00549 #define rtdm_sendmsg rt_dev_sendmsg 00550 #define rtdm_send rt_dev_send 00551 #define rtdm_sendto rt_dev_sendto 00552 #define rtdm_bind rt_dev_bind 00553 #define rtdm_listen rt_dev_listen 00554 #define rtdm_accept rt_dev_accept 00555 #define rtdm_getsockopt rt_dev_getsockopt 00556 #define rtdm_setsockopt rt_dev_setsockopt 00557 #define rtdm_getsockname rt_dev_getsockname 00558 #define rtdm_getpeername rt_dev_getpeername 00559 #define rtdm_shutdown rt_dev_shutdown 00560 00561 struct rtdm_dev_context *rtdm_context_get(int fd); 00562 00563 #ifndef DOXYGEN_CPP /* Avoid static inline tags for RTDM in doxygen */ 00564 00565 #define CONTEXT_IS_LOCKED(context) \ 00566 (atomic_read(&(context)->close_lock_count) > 1 || \ 00567 (test_bit(RTDM_CLOSING, &(context)->context_flags) && \ 00568 atomic_read(&(context)->close_lock_count) > 0)) 00569 00570 static inline void rtdm_context_lock(struct rtdm_dev_context *context) 00571 { 00572 XENO_ASSERT(RTDM, CONTEXT_IS_LOCKED(context), 00573 /* just warn if context was a dangling pointer */); 00574 atomic_inc(&context->close_lock_count); 00575 } 00576 00577 extern int rtdm_apc; 00578 00579 static inline void rtdm_context_unlock(struct rtdm_dev_context *context) 00580 { 00581 XENO_ASSERT(RTDM, CONTEXT_IS_LOCKED(context), 00582 /* just warn if context was a dangling pointer */); 00583 smp_mb__before_atomic_dec(); 00584 if (unlikely(atomic_dec_and_test(&context->close_lock_count))) 00585 rthal_apc_schedule(rtdm_apc); 00586 } 00587 00588 static inline void rtdm_context_put(struct rtdm_dev_context *context) 00589 { 00590 rtdm_context_unlock(context); 00591 } 00592 00593 /* --- clock services --- */ 00594 struct xntbase; 00595 extern struct xntbase *rtdm_tbase; 00596 00597 static inline nanosecs_abs_t rtdm_clock_read(void) 00598 { 00599 return xntbase_ticks2ns(rtdm_tbase, xntbase_get_time(rtdm_tbase)); 00600 } 00601 00602 static inline nanosecs_abs_t rtdm_clock_read_monotonic(void) 00603 { 00604 return xntbase_ticks2ns(rtdm_tbase, xntbase_get_jiffies(rtdm_tbase)); 00605 } 00606 #endif /* !DOXYGEN_CPP */ 00607 00613 int rtdm_select_bind(int fd, rtdm_selector_t *selector, 00614 enum rtdm_selecttype type, unsigned fd_index); 00615 00616 /* --- spin lock services --- */ 00654 #ifdef DOXYGEN_CPP /* Beautify doxygen output */ 00655 #define RTDM_EXECUTE_ATOMICALLY(code_block) \ 00656 { \ 00657 <ENTER_ATOMIC_SECTION> \ 00658 code_block; \ 00659 <LEAVE_ATOMIC_SECTION> \ 00660 } 00661 #else /* This is how it really works */ 00662 #define RTDM_EXECUTE_ATOMICALLY(code_block) \ 00663 { \ 00664 spl_t __rtdm_s; \ 00665 \ 00666 xnlock_get_irqsave(&nklock, __rtdm_s); \ 00667 code_block; \ 00668 xnlock_put_irqrestore(&nklock, __rtdm_s); \ 00669 } 00670 #endif 00671 00681 #define RTDM_LOCK_UNLOCKED RTHAL_SPIN_LOCK_UNLOCKED 00682 00684 typedef rthal_spinlock_t rtdm_lock_t; 00685 00687 typedef unsigned long rtdm_lockctx_t; 00688 00704 #define rtdm_lock_init(lock) rthal_spin_lock_init(lock) 00705 00722 #ifdef DOXYGEN_CPP /* Beautify doxygen output */ 00723 #define rtdm_lock_get(lock) rthal_spin_lock(lock) 00724 #else /* This is how it really works */ 00725 #define rtdm_lock_get(lock) \ 00726 do { \ 00727 XENO_BUGON(RTDM, !rthal_local_irq_disabled()); \ 00728 rthal_spin_lock(lock); \ 00729 } while (0) 00730 #endif 00731 00748 #define rtdm_lock_put(lock) rthal_spin_unlock(lock) 00749 00767 #define rtdm_lock_get_irqsave(lock, context) \ 00768 rthal_spin_lock_irqsave(lock, context) 00769 00787 #define rtdm_lock_put_irqrestore(lock, context) \ 00788 rthal_spin_unlock_irqrestore(lock, context) 00789 00806 #define rtdm_lock_irqsave(context) \ 00807 rthal_local_irq_save(context) 00808 00825 #define rtdm_lock_irqrestore(context) \ 00826 rthal_local_irq_restore(context) 00827 00831 /* --- Interrupt management services --- */ 00837 typedef xnintr_t rtdm_irq_t; 00838 00845 #define RTDM_IRQTYPE_SHARED XN_ISR_SHARED 00846 00848 #define RTDM_IRQTYPE_EDGE XN_ISR_EDGE 00849 00858 typedef int (*rtdm_irq_handler_t)(rtdm_irq_t *irq_handle); 00859 00866 #define RTDM_IRQ_NONE XN_ISR_NONE 00867 00868 #define RTDM_IRQ_HANDLED XN_ISR_HANDLED 00869 00888 #define rtdm_irq_get_arg(irq_handle, type) ((type *)irq_handle->cookie) 00889 00891 int rtdm_irq_request(rtdm_irq_t *irq_handle, unsigned int irq_no, 00892 rtdm_irq_handler_t handler, unsigned long flags, 00893 const char *device_name, void *arg); 00894 00895 #ifndef DOXYGEN_CPP /* Avoid static inline tags for RTDM in doxygen */ 00896 static inline int rtdm_irq_free(rtdm_irq_t *irq_handle) 00897 { 00898 return xnintr_detach(irq_handle); 00899 } 00900 00901 static inline int rtdm_irq_enable(rtdm_irq_t *irq_handle) 00902 { 00903 return xnintr_enable(irq_handle); 00904 } 00905 00906 static inline int rtdm_irq_disable(rtdm_irq_t *irq_handle) 00907 { 00908 return xnintr_disable(irq_handle); 00909 } 00910 #endif /* !DOXYGEN_CPP */ 00911 00912 /* --- non-real-time signalling services --- */ 00913 00919 typedef unsigned rtdm_nrtsig_t; 00920 00931 typedef void (*rtdm_nrtsig_handler_t)(rtdm_nrtsig_t nrt_sig, void *arg); 00934 #ifndef DOXYGEN_CPP /* Avoid static inline tags for RTDM in doxygen */ 00935 static inline int rtdm_nrtsig_init(rtdm_nrtsig_t *nrt_sig, 00936 rtdm_nrtsig_handler_t handler, void *arg) 00937 { 00938 *nrt_sig = rthal_alloc_virq(); 00939 00940 if (*nrt_sig == 0) 00941 return -EAGAIN; 00942 00943 rthal_virtualize_irq(rthal_root_domain, *nrt_sig, handler, arg, NULL, 00944 IPIPE_HANDLE_MASK); 00945 return 0; 00946 } 00947 00948 static inline void rtdm_nrtsig_destroy(rtdm_nrtsig_t *nrt_sig) 00949 { 00950 rthal_free_virq(*nrt_sig); 00951 } 00952 00953 static inline void rtdm_nrtsig_pend(rtdm_nrtsig_t *nrt_sig) 00954 { 00955 rthal_trigger_irq(*nrt_sig); 00956 } 00957 #endif /* !DOXYGEN_CPP */ 00958 00959 /* --- timer services --- */ 00960 00966 typedef xntimer_t rtdm_timer_t; 00967 00973 typedef void (*rtdm_timer_handler_t)(rtdm_timer_t *timer); 00974 00980 enum rtdm_timer_mode { 00982 RTDM_TIMERMODE_RELATIVE = XN_RELATIVE, 00983 00985 RTDM_TIMERMODE_ABSOLUTE = XN_ABSOLUTE, 00986 00988 RTDM_TIMERMODE_REALTIME = XN_REALTIME 00989 }; 00994 #ifndef DOXYGEN_CPP /* Avoid broken doxygen output */ 00995 #define rtdm_timer_init(timer, handler, name) \ 00996 ({ \ 00997 xntimer_init((timer), rtdm_tbase, handler); \ 00998 xntimer_set_name((timer), (name)); \ 00999 0; \ 01000 }) 01001 #endif /* !DOXYGEN_CPP */ 01002 01003 void rtdm_timer_destroy(rtdm_timer_t *timer); 01004 01005 int rtdm_timer_start(rtdm_timer_t *timer, nanosecs_abs_t expiry, 01006 nanosecs_rel_t interval, enum rtdm_timer_mode mode); 01007 01008 void rtdm_timer_stop(rtdm_timer_t *timer); 01009 01010 #ifndef DOXYGEN_CPP /* Avoid static inline tags for RTDM in doxygen */ 01011 static inline int rtdm_timer_start_in_handler(rtdm_timer_t *timer, 01012 nanosecs_abs_t expiry, 01013 nanosecs_rel_t interval, 01014 enum rtdm_timer_mode mode) 01015 { 01016 return xntimer_start(timer, xntbase_ns2ticks_ceil(rtdm_tbase, expiry), 01017 xntbase_ns2ticks_ceil(rtdm_tbase, interval), 01018 (xntmode_t)mode); 01019 } 01020 01021 static inline void rtdm_timer_stop_in_handler(rtdm_timer_t *timer) 01022 { 01023 xntimer_stop(timer); 01024 } 01025 #endif /* !DOXYGEN_CPP */ 01026 01027 /* --- task services --- */ 01033 typedef xnthread_t rtdm_task_t; 01034 01040 typedef void (*rtdm_task_proc_t)(void *arg); 01041 01046 #define RTDM_TASK_LOWEST_PRIORITY XNSCHED_LOW_PRIO 01047 #define RTDM_TASK_HIGHEST_PRIORITY XNSCHED_HIGH_PRIO 01048 01054 #define RTDM_TASK_RAISE_PRIORITY (+1) 01055 #define RTDM_TASK_LOWER_PRIORITY (-1) 01056 01060 int rtdm_task_init(rtdm_task_t *task, const char *name, 01061 rtdm_task_proc_t task_proc, void *arg, 01062 int priority, nanosecs_rel_t period); 01063 int __rtdm_task_sleep(xnticks_t timeout, xntmode_t mode); 01064 void rtdm_task_busy_sleep(nanosecs_rel_t delay); 01065 01066 #ifndef DOXYGEN_CPP /* Avoid static inline tags for RTDM in doxygen */ 01067 static inline void rtdm_task_destroy(rtdm_task_t *task) 01068 { 01069 xnpod_delete_thread(task); 01070 } 01071 01072 void rtdm_task_join_nrt(rtdm_task_t *task, unsigned int poll_delay); 01073 01074 static inline void rtdm_task_set_priority(rtdm_task_t *task, int priority) 01075 { 01076 union xnsched_policy_param param = { .rt = { .prio = priority } }; 01077 xnpod_set_thread_schedparam(task, &xnsched_class_rt, ¶m); 01078 xnpod_schedule(); 01079 } 01080 01081 static inline int rtdm_task_set_period(rtdm_task_t *task, 01082 nanosecs_rel_t period) 01083 { 01084 if (period < 0) 01085 period = 0; 01086 return xnpod_set_thread_periodic(task, XN_INFINITE, 01087 xntbase_ns2ticks_ceil 01088 (xnthread_time_base(task), period)); 01089 } 01090 01091 static inline int rtdm_task_unblock(rtdm_task_t *task) 01092 { 01093 int res = xnpod_unblock_thread(task); 01094 01095 xnpod_schedule(); 01096 return res; 01097 } 01098 01099 static inline rtdm_task_t *rtdm_task_current(void) 01100 { 01101 return xnpod_current_thread(); 01102 } 01103 01104 static inline int rtdm_task_wait_period(void) 01105 { 01106 XENO_ASSERT(RTDM, !xnpod_unblockable_p(), return -EPERM;); 01107 return xnpod_wait_thread_period(NULL); 01108 } 01109 01110 static inline int rtdm_task_sleep(nanosecs_rel_t delay) 01111 { 01112 return __rtdm_task_sleep(delay, XN_RELATIVE); 01113 } 01114 01115 static inline int 01116 rtdm_task_sleep_abs(nanosecs_abs_t wakeup_date, enum rtdm_timer_mode mode) 01117 { 01118 /* For the sake of a consistent API usage... */ 01119 if (mode != RTDM_TIMERMODE_ABSOLUTE && mode != RTDM_TIMERMODE_REALTIME) 01120 return -EINVAL; 01121 return __rtdm_task_sleep(wakeup_date, (xntmode_t)mode); 01122 } 01123 01124 /* rtdm_task_sleep_abs shall be used instead */ 01125 static inline int __deprecated rtdm_task_sleep_until(nanosecs_abs_t wakeup_time) 01126 { 01127 return __rtdm_task_sleep(wakeup_time, XN_REALTIME); 01128 } 01129 #endif /* !DOXYGEN_CPP */ 01130 01131 /* --- timeout sequences */ 01132 01133 typedef nanosecs_abs_t rtdm_toseq_t; 01134 01135 void rtdm_toseq_init(rtdm_toseq_t *timeout_seq, nanosecs_rel_t timeout); 01136 01137 /* --- event services --- */ 01138 01139 typedef struct { 01140 xnsynch_t synch_base; 01141 DECLARE_XNSELECT(select_block); 01142 } rtdm_event_t; 01143 01144 #define RTDM_EVENT_PENDING XNSYNCH_SPARE1 01145 01146 void rtdm_event_init(rtdm_event_t *event, unsigned long pending); 01147 #ifdef CONFIG_XENO_OPT_RTDM_SELECT 01148 int rtdm_event_select_bind(rtdm_event_t *event, rtdm_selector_t *selector, 01149 enum rtdm_selecttype type, unsigned fd_index); 01150 #else /* !CONFIG_XENO_OPT_RTDM_SELECT */ 01151 #define rtdm_event_select_bind(e, s, t, i) ({ (void)(e); -EBADF; }) 01152 #endif /* !CONFIG_XENO_OPT_RTDM_SELECT */ 01153 int rtdm_event_wait(rtdm_event_t *event); 01154 int rtdm_event_timedwait(rtdm_event_t *event, nanosecs_rel_t timeout, 01155 rtdm_toseq_t *timeout_seq); 01156 void rtdm_event_signal(rtdm_event_t *event); 01157 01158 void rtdm_event_clear(rtdm_event_t *event); 01159 01160 #ifndef DOXYGEN_CPP /* Avoid static inline tags for RTDM in doxygen */ 01161 void __rtdm_synch_flush(xnsynch_t *synch, unsigned long reason); 01162 01163 static inline void rtdm_event_pulse(rtdm_event_t *event) 01164 { 01165 trace_mark(xn_rtdm, event_pulse, "event %p", event); 01166 __rtdm_synch_flush(&event->synch_base, 0); 01167 } 01168 01169 static inline void rtdm_event_destroy(rtdm_event_t *event) 01170 { 01171 trace_mark(xn_rtdm, event_destroy, "event %p", event); 01172 __rtdm_synch_flush(&event->synch_base, XNRMID); 01173 xnselect_destroy(&event->select_block); 01174 } 01175 #endif /* !DOXYGEN_CPP */ 01176 01177 /* --- semaphore services --- */ 01178 01179 typedef struct { 01180 unsigned long value; 01181 xnsynch_t synch_base; 01182 DECLARE_XNSELECT(select_block); 01183 } rtdm_sem_t; 01184 01185 void rtdm_sem_init(rtdm_sem_t *sem, unsigned long value); 01186 #ifdef CONFIG_XENO_OPT_RTDM_SELECT 01187 int rtdm_sem_select_bind(rtdm_sem_t *sem, rtdm_selector_t *selector, 01188 enum rtdm_selecttype type, unsigned fd_index); 01189 #else /* !CONFIG_XENO_OPT_RTDM_SELECT */ 01190 #define rtdm_sem_select_bind(s, se, t, i) ({ (void)(s); -EBADF; }) 01191 #endif /* !CONFIG_XENO_OPT_RTDM_SELECT */ 01192 int rtdm_sem_down(rtdm_sem_t *sem); 01193 int rtdm_sem_timeddown(rtdm_sem_t *sem, nanosecs_rel_t timeout, 01194 rtdm_toseq_t *timeout_seq); 01195 void rtdm_sem_up(rtdm_sem_t *sem); 01196 01197 #ifndef DOXYGEN_CPP /* Avoid static inline tags for RTDM in doxygen */ 01198 static inline void rtdm_sem_destroy(rtdm_sem_t *sem) 01199 { 01200 trace_mark(xn_rtdm, sem_destroy, "sem %p", sem); 01201 __rtdm_synch_flush(&sem->synch_base, XNRMID); 01202 xnselect_destroy(&sem->select_block); 01203 } 01204 #endif /* !DOXYGEN_CPP */ 01205 01206 /* --- mutex services --- */ 01207 01208 typedef struct { 01209 xnsynch_t synch_base; 01210 } rtdm_mutex_t; 01211 01212 void rtdm_mutex_init(rtdm_mutex_t *mutex); 01213 int rtdm_mutex_lock(rtdm_mutex_t *mutex); 01214 int rtdm_mutex_timedlock(rtdm_mutex_t *mutex, nanosecs_rel_t timeout, 01215 rtdm_toseq_t *timeout_seq); 01216 01217 #ifndef DOXYGEN_CPP /* Avoid static inline tags for RTDM in doxygen */ 01218 static inline void rtdm_mutex_unlock(rtdm_mutex_t *mutex) 01219 { 01220 XENO_ASSERT(RTDM, !xnpod_asynch_p(), return;); 01221 01222 trace_mark(xn_rtdm, mutex_unlock, "mutex %p", mutex); 01223 01224 if (unlikely(xnsynch_release(&mutex->synch_base) != NULL)) 01225 xnpod_schedule(); 01226 } 01227 01228 static inline void rtdm_mutex_destroy(rtdm_mutex_t *mutex) 01229 { 01230 trace_mark(xn_rtdm, mutex_destroy, "mutex %p", mutex); 01231 01232 __rtdm_synch_flush(&mutex->synch_base, XNRMID); 01233 } 01234 #endif /* !DOXYGEN_CPP */ 01235 01236 /* --- utility functions --- */ 01237 01238 #define rtdm_printk(format, ...) printk(format, ##__VA_ARGS__) 01239 01240 #ifndef DOXYGEN_CPP /* Avoid static inline tags for RTDM in doxygen */ 01241 static inline void *rtdm_malloc(size_t size) 01242 { 01243 return xnmalloc(size); 01244 } 01245 01246 static inline void rtdm_free(void *ptr) 01247 { 01248 xnfree(ptr); 01249 } 01250 01251 #ifdef CONFIG_XENO_OPT_PERVASIVE 01252 int rtdm_mmap_to_user(rtdm_user_info_t *user_info, 01253 void *src_addr, size_t len, 01254 int prot, void **pptr, 01255 struct vm_operations_struct *vm_ops, 01256 void *vm_private_data); 01257 int rtdm_iomap_to_user(rtdm_user_info_t *user_info, 01258 phys_addr_t src_addr, size_t len, 01259 int prot, void **pptr, 01260 struct vm_operations_struct *vm_ops, 01261 void *vm_private_data); 01262 int rtdm_munmap(rtdm_user_info_t *user_info, void *ptr, size_t len); 01263 01264 static inline int rtdm_read_user_ok(rtdm_user_info_t *user_info, 01265 const void __user *ptr, size_t size) 01266 { 01267 return access_rok(ptr, size); 01268 } 01269 01270 static inline int rtdm_rw_user_ok(rtdm_user_info_t *user_info, 01271 const void __user *ptr, size_t size) 01272 { 01273 return access_wok(ptr, size); 01274 } 01275 01276 static inline int rtdm_copy_from_user(rtdm_user_info_t *user_info, 01277 void *dst, const void __user *src, 01278 size_t size) 01279 { 01280 return __xn_copy_from_user(dst, src, size) ? -EFAULT : 0; 01281 } 01282 01283 static inline int rtdm_safe_copy_from_user(rtdm_user_info_t *user_info, 01284 void *dst, const void __user *src, 01285 size_t size) 01286 { 01287 return (!access_rok(src, size) || 01288 __xn_copy_from_user(dst, src, size)) ? -EFAULT : 0; 01289 } 01290 01291 static inline int rtdm_copy_to_user(rtdm_user_info_t *user_info, 01292 void __user *dst, const void *src, 01293 size_t size) 01294 { 01295 return __xn_copy_to_user(dst, src, size) ? -EFAULT : 0; 01296 } 01297 01298 static inline int rtdm_safe_copy_to_user(rtdm_user_info_t *user_info, 01299 void __user *dst, const void *src, 01300 size_t size) 01301 { 01302 return (!access_wok(dst, size) || 01303 __xn_copy_to_user(dst, src, size)) ? -EFAULT : 0; 01304 } 01305 01306 static inline int rtdm_strncpy_from_user(rtdm_user_info_t *user_info, 01307 char *dst, 01308 const char __user *src, size_t count) 01309 { 01310 if (unlikely(!access_rok(src, 1))) 01311 return -EFAULT; 01312 return __xn_strncpy_from_user(dst, src, count); 01313 } 01314 01315 static inline int rtdm_rt_capable(rtdm_user_info_t *user_info) 01316 { 01317 XENO_ASSERT(RTDM, !xnpod_asynch_p(), return 0;); 01318 01319 return (user_info ? xnshadow_thread(user_info) != NULL 01320 : !xnpod_root_p()); 01321 } 01322 01323 #else /* !CONFIG_XENO_OPT_PERVASIVE */ 01324 /* Define void user<->kernel services that simply fail */ 01325 #define rtdm_mmap_to_user(...) ({ -ENOSYS; }) 01326 #define rtdm_munmap(...) ({ -ENOSYS; }) 01327 #define rtdm_read_user_ok(...) ({ 0; }) 01328 #define rtdm_rw_user_ok(...) ({ 0; }) 01329 #define rtdm_copy_from_user(...) ({ -ENOSYS; }) 01330 #define rtdm_safe_copy_from_user(...) ({ -ENOSYS; }) 01331 #define rtdm_copy_to_user(...) ({ -ENOSYS; }) 01332 #define rtdm_safe_copy_to_user(...) ({ -ENOSYS; }) 01333 #define rtdm_strncpy_from_user(...) ({ -ENOSYS; }) 01334 01335 static inline int rtdm_rt_capable(rtdm_user_info_t *user_info) 01336 { 01337 XENO_ASSERT(RTDM, !xnpod_asynch_p(), return 0;); 01338 01339 return !xnpod_root_p(); 01340 } 01341 01342 #endif /* CONFIG_XENO_OPT_PERVASIVE */ 01343 01344 static inline int rtdm_in_rt_context(void) 01345 { 01346 return (rthal_current_domain != rthal_root_domain); 01347 } 01348 01349 #endif /* !DOXYGEN_CPP */ 01350 01351 int rtdm_exec_in_rt(struct rtdm_dev_context *context, 01352 rtdm_user_info_t *user_info, void *arg, 01353 rtdm_rt_handler_t handler); 01354 01355 #endif /* _RTDM_DRIVER_H */