00001
00025 #ifndef _RTDM_DRIVER_H
00026 #define _RTDM_DRIVER_H
00027
00028 #ifndef __KERNEL__
00029 #error This header is for kernel space usage only. \
00030 You are likely looking for rtdm/rtdm.h...
00031 #endif
00032
00033 #include <asm/atomic.h>
00034 #include <linux/list.h>
00035
00036 #include <nucleus/xenomai.h>
00037 #include <nucleus/core.h>
00038 #include <nucleus/heap.h>
00039 #include <nucleus/pod.h>
00040 #include <nucleus/synch.h>
00041 #include <rtdm/rtdm.h>
00042
00043
00044 #include <nucleus/assert.h>
00045
00046 #ifndef CONFIG_XENO_OPT_DEBUG_RTDM
00047 #define CONFIG_XENO_OPT_DEBUG_RTDM 0
00048 #endif
00049
00050
00051 struct rtdm_dev_context;
00052
00053
00066 #define RTDM_EXCLUSIVE 0x0001
00067
00069 #define RTDM_NAMED_DEVICE 0x0010
00070
00073 #define RTDM_PROTOCOL_DEVICE 0x0020
00074
00076 #define RTDM_DEVICE_TYPE_MASK 0x00F0
00077
00087 #define RTDM_CREATED_IN_NRT 0
00088
00090 #define RTDM_CLOSING 1
00091
00094 #define RTDM_FORCED_CLOSING 2
00095
00097 #define RTDM_USER_CONTEXT_FLAG 8
00098
00108 #define RTDM_DEVICE_STRUCT_VER 3
00109
00111 #define RTDM_CONTEXT_STRUCT_VER 3
00112
00114 #define RTDM_SECURE_DEVICE 0x80000000
00115
00117 #define RTDM_DRIVER_VER(major, minor, patch) \
00118 (((major & 0xFF) << 16) | ((minor & 0xFF) << 8) | (patch & 0xFF))
00119
00121 #define RTDM_DRIVER_MAJOR_VER(ver) (((ver) >> 16) & 0xFF)
00122
00124 #define RTDM_DRIVER_MINOR_VER(ver) (((ver) >> 8) & 0xFF)
00125
00127 #define RTDM_DRIVER_PATCH_VER(ver) ((ver) & 0xFF)
00128
00148 typedef
00149 int (*rtdm_open_handler_t) (struct rtdm_dev_context *context,
00150 rtdm_user_info_t *user_info,
00151 int oflag);
00152
00165 typedef
00166 int (*rtdm_socket_handler_t) (struct rtdm_dev_context *context,
00167 rtdm_user_info_t *user_info,
00168 int protocol);
00169
00181 typedef
00182 int (*rtdm_close_handler_t) (struct rtdm_dev_context *context,
00183 rtdm_user_info_t *user_info);
00184
00198 typedef
00199 int (*rtdm_ioctl_handler_t) (struct rtdm_dev_context *context,
00200 rtdm_user_info_t *user_info,
00201 int request,
00202 void *arg);
00203
00217 typedef
00218 ssize_t (*rtdm_read_handler_t) (struct rtdm_dev_context *context,
00219 rtdm_user_info_t *user_info,
00220 void *buf,
00221 size_t nbyte);
00222
00237 typedef
00238 ssize_t (*rtdm_write_handler_t) (struct rtdm_dev_context *context,
00239 rtdm_user_info_t *user_info,
00240 const void *buf,
00241 size_t nbyte);
00242
00258 typedef
00259 ssize_t (*rtdm_recvmsg_handler_t)(struct rtdm_dev_context *context,
00260 rtdm_user_info_t *user_info,
00261 struct msghdr *msg,
00262 int flags);
00263
00279 typedef
00280 ssize_t (*rtdm_sendmsg_handler_t)(struct rtdm_dev_context *context,
00281 rtdm_user_info_t *user_info,
00282 const struct msghdr *msg,
00283 int flags);
00286 typedef
00287 int (*rtdm_rt_handler_t) (struct rtdm_dev_context *context,
00288 rtdm_user_info_t *user_info,
00289 void *arg);
00290
00291
00295 struct rtdm_operations {
00299 rtdm_close_handler_t close_rt;
00301 rtdm_close_handler_t close_nrt;
00303 rtdm_ioctl_handler_t ioctl_rt;
00305 rtdm_ioctl_handler_t ioctl_nrt;
00311 rtdm_read_handler_t read_rt;
00313 rtdm_read_handler_t read_nrt;
00315 rtdm_write_handler_t write_rt;
00317 rtdm_write_handler_t write_nrt;
00323 rtdm_recvmsg_handler_t recvmsg_rt;
00325 rtdm_recvmsg_handler_t recvmsg_nrt;
00327 rtdm_sendmsg_handler_t sendmsg_rt;
00329 rtdm_sendmsg_handler_t sendmsg_nrt;
00331 };
00332
00344 struct rtdm_dev_context {
00346 unsigned long context_flags;
00348 int fd;
00351 atomic_t close_lock_count;
00353 struct rtdm_operations *ops;
00355 struct rtdm_device *device;
00357 char dev_private[0];
00358 };
00359
00360 struct rtdm_dev_reserved {
00361 struct list_head entry;
00362 atomic_t refcount;
00363 struct rtdm_dev_context *exclusive_context;
00364 };
00365
00373 struct rtdm_device {
00376 int struct_version;
00377
00379 int device_flags;
00381 size_t context_size;
00382
00384 char device_name[RTDM_MAX_DEVNAME_LEN+1];
00385
00387 int protocol_family;
00389 int socket_type;
00390
00393 rtdm_open_handler_t open_rt;
00396 rtdm_open_handler_t open_nrt;
00397
00400 rtdm_socket_handler_t socket_rt;
00403 rtdm_socket_handler_t socket_nrt;
00404
00406 struct rtdm_operations ops;
00407
00409 int device_class;
00412 int device_sub_class;
00414 const char *driver_name;
00416 int driver_version;
00419 const char *peripheral_name;
00421 const char *provider_name;
00422
00424 const char *proc_name;
00426 struct proc_dir_entry *proc_entry;
00427
00429 int device_id;
00430
00432 struct rtdm_dev_reserved reserved;
00433 };
00437
00438
00439 int rtdm_dev_register(struct rtdm_device* device);
00440 int rtdm_dev_unregister(struct rtdm_device* device, unsigned int poll_delay);
00441
00442
00443
00444
00445 #define rtdm_open rt_dev_open
00446 #define rtdm_socket rt_dev_socket
00447 #define rtdm_close rt_dev_close
00448 #define rtdm_ioctl rt_dev_ioctl
00449 #define rtdm_read rt_dev_read
00450 #define rtdm_write rt_dev_write
00451 #define rtdm_recvmsg rt_dev_recvmsg
00452 #define rtdm_recv rt_dev_recv
00453 #define rtdm_recvfrom rt_dev_recvfrom
00454 #define rtdm_sendmsg rt_dev_sendmsg
00455 #define rtdm_send rt_dev_send
00456 #define rtdm_sendto rt_dev_sendto
00457 #define rtdm_bind rt_dev_bind
00458 #define rtdm_listen rt_dev_listen
00459 #define rtdm_accept rt_dev_accept
00460 #define rtdm_getsockopt rt_dev_getsockopt
00461 #define rtdm_setsockopt rt_dev_setsockopt
00462 #define rtdm_getsockname rt_dev_getsockname
00463 #define rtdm_getpeername rt_dev_getpeername
00464 #define rtdm_shutdown rt_dev_shutdown
00465
00466 struct rtdm_dev_context *rtdm_context_get(int fd);
00467
00468 #ifndef DOXYGEN_CPP
00469 static inline void rtdm_context_lock(struct rtdm_dev_context *context)
00470 {
00471 atomic_inc(&context->close_lock_count);
00472 }
00473
00474 static inline void rtdm_context_unlock(struct rtdm_dev_context *context)
00475 {
00476 atomic_dec(&context->close_lock_count);
00477 }
00478
00479
00480
00481 static inline nanosecs_abs_t rtdm_clock_read(void)
00482 {
00483 return xnpod_ticks2ns(xnpod_get_time());
00484 }
00485 #endif
00486
00487
00488
00531 #define RTDM_EXECUTE_ATOMICALLY(code_block) \
00532 { \
00533 spl_t s; \
00534 \
00535 xnlock_get_irqsave(&nklock, s); \
00536 code_block; \
00537 xnlock_put_irqrestore(&nklock, s); \
00538 }
00539
00549 #define RTDM_LOCK_UNLOCKED RTHAL_SPIN_LOCK_UNLOCKED
00550
00552 typedef rthal_spinlock_t rtdm_lock_t;
00553
00555 typedef unsigned long rtdm_lockctx_t;
00556
00572 #define rtdm_lock_init(lock) rthal_spin_lock_init(lock)
00573
00590 #define rtdm_lock_get(lock) rthal_spin_lock(lock)
00591
00608 #define rtdm_lock_put(lock) rthal_spin_unlock(lock)
00609
00627 #define rtdm_lock_get_irqsave(lock, context) \
00628 rthal_spin_lock_irqsave(lock, context)
00629
00647 #define rtdm_lock_put_irqrestore(lock, context) \
00648 rthal_spin_unlock_irqrestore(lock, context)
00649
00666 #define rtdm_lock_irqsave(context) \
00667 rthal_local_irq_save(context)
00668
00685 #define rtdm_lock_irqrestore(context) \
00686 rthal_local_irq_restore(context)
00687
00692
00698 typedef xnintr_t rtdm_irq_t;
00699
00706 #define RTDM_IRQTYPE_SHARED XN_ISR_SHARED
00707
00709 #define RTDM_IRQTYPE_EDGE XN_ISR_EDGE
00710
00719 typedef int (*rtdm_irq_handler_t)(rtdm_irq_t *irq_handle);
00720
00727 #define RTDM_IRQ_NONE XN_ISR_NONE
00728
00729 #define RTDM_IRQ_HANDLED XN_ISR_HANDLED
00730
00749 #define rtdm_irq_get_arg(irq_handle, type) ((type *)irq_handle->cookie)
00750
00752 #ifndef DOXYGEN_CPP
00753 static inline int rtdm_irq_request(rtdm_irq_t *irq_handle,
00754 unsigned int irq_no,
00755 rtdm_irq_handler_t handler,
00756 unsigned long flags,
00757 const char *device_name,
00758 void *arg)
00759 {
00760 xnintr_init(irq_handle, device_name, irq_no, handler, NULL, flags);
00761 return xnintr_attach(irq_handle, arg);
00762 }
00763
00764 static inline int rtdm_irq_free(rtdm_irq_t *irq_handle)
00765 {
00766 return xnintr_detach(irq_handle);
00767 }
00768
00769 static inline int rtdm_irq_enable(rtdm_irq_t *irq_handle)
00770 {
00771 return xnintr_enable(irq_handle);
00772 }
00773
00774 static inline int rtdm_irq_disable(rtdm_irq_t *irq_handle)
00775 {
00776 return xnintr_disable(irq_handle);
00777 }
00778 #endif
00779
00780
00781
00782
00788 typedef unsigned rtdm_nrtsig_t;
00789
00799 typedef void (*rtdm_nrtsig_handler_t)(rtdm_nrtsig_t nrt_sig);
00803 #ifndef DOXYGEN_CPP
00804 static inline int rtdm_nrtsig_init(rtdm_nrtsig_t *nrt_sig,
00805 rtdm_nrtsig_handler_t handler)
00806 {
00807 *nrt_sig = rthal_alloc_virq();
00808
00809 if (*nrt_sig == 0)
00810 return -EAGAIN;
00811
00812 rthal_virtualize_irq(rthal_root_domain, *nrt_sig, (rthal_irq_handler_t)handler, NULL, NULL,
00813 IPIPE_HANDLE_MASK);
00814 return 0;
00815 }
00816
00817 static inline void rtdm_nrtsig_destroy(rtdm_nrtsig_t *nrt_sig)
00818 {
00819 rthal_free_virq(*nrt_sig);
00820 }
00821
00822 static inline void rtdm_nrtsig_pend(rtdm_nrtsig_t *nrt_sig)
00823 {
00824 rthal_trigger_irq(*nrt_sig);
00825 }
00826 #endif
00827
00828
00829
00835 typedef xnthread_t rtdm_task_t;
00836
00842 typedef void (*rtdm_task_proc_t)(void *arg);
00843
00844
00849 #define RTDM_TASK_LOWEST_PRIORITY XNCORE_LOW_PRIO
00850 #define RTDM_TASK_HIGHEST_PRIORITY XNCORE_HIGH_PRIO
00851
00857 #define RTDM_TASK_RAISE_PRIORITY (+1)
00858 #define RTDM_TASK_LOWER_PRIORITY (-1)
00859
00863 int rtdm_task_init(rtdm_task_t *task, const char *name,
00864 rtdm_task_proc_t task_proc, void *arg,
00865 int priority, nanosecs_rel_t period);
00866
00867 #ifndef DOXYGEN_CPP
00868 static inline void rtdm_task_destroy(rtdm_task_t *task)
00869 {
00870 xnpod_delete_thread(task);
00871 }
00872
00873 void rtdm_task_join_nrt(rtdm_task_t *task, unsigned int poll_delay);
00874
00875 static inline void rtdm_task_set_priority(rtdm_task_t *task, int priority)
00876 {
00877 xnpod_renice_thread(task, priority);
00878 xnpod_schedule();
00879 }
00880
00881 static inline int rtdm_task_set_period(rtdm_task_t *task,
00882 nanosecs_rel_t period)
00883 {
00884 if (period < 0)
00885 period = 0;
00886 return xnpod_set_thread_periodic(task, XN_INFINITE,
00887 xnpod_ns2ticks(period));
00888 }
00889
00890 static inline int rtdm_task_unblock(rtdm_task_t *task)
00891 {
00892 int res = xnpod_unblock_thread(task);
00893
00894 xnpod_schedule();
00895 return res;
00896 }
00897
00898 static inline rtdm_task_t *rtdm_task_current(void)
00899 {
00900 return xnpod_current_thread();
00901 }
00902
00903 static inline int rtdm_task_wait_period(void)
00904 {
00905 XENO_ASSERT(RTDM, !xnpod_unblockable_p(), return -EPERM;);
00906 return xnpod_wait_thread_period(NULL);
00907 }
00908 #endif
00909
00910 int rtdm_task_sleep(nanosecs_rel_t delay);
00911 int rtdm_task_sleep_until(nanosecs_abs_t wakeup_time);
00912 void rtdm_task_busy_sleep(nanosecs_rel_t delay);
00913
00914
00915
00916
00917 typedef nanosecs_abs_t rtdm_toseq_t;
00918
00919 #ifndef DOXYGEN_CPP
00920 static inline void rtdm_toseq_init(rtdm_toseq_t *timeout_seq,
00921 nanosecs_rel_t timeout)
00922 {
00923 *timeout_seq = xnpod_get_time() + xnpod_ns2ticks(timeout);
00924 }
00925 #endif
00926
00927
00928
00929
00930 typedef struct {
00931 xnsynch_t synch_base;
00932 } rtdm_event_t;
00933
00934 #define RTDM_EVENT_PENDING XNSYNCH_SPARE1
00935
00936 #ifndef DOXYGEN_CPP
00937 static inline void rtdm_event_init(rtdm_event_t *event, unsigned long pending)
00938 {
00939 xnsynch_init(&event->synch_base, XNSYNCH_PRIO);
00940 if (pending)
00941 xnsynch_set_flags(&event->synch_base, RTDM_EVENT_PENDING);
00942 }
00943
00944 void _rtdm_synch_flush(xnsynch_t *synch, unsigned long reason);
00945
00946 static inline void rtdm_event_destroy(rtdm_event_t *event)
00947 {
00948 _rtdm_synch_flush(&event->synch_base, XNRMID);
00949 }
00950
00951 static inline void rtdm_event_pulse(rtdm_event_t *event)
00952 {
00953 _rtdm_synch_flush(&event->synch_base, 0);
00954 }
00955 #endif
00956
00957 int rtdm_event_wait(rtdm_event_t *event);
00958 int rtdm_event_timedwait(rtdm_event_t *event, nanosecs_rel_t timeout,
00959 rtdm_toseq_t *timeout_seq);
00960 void rtdm_event_signal(rtdm_event_t *event);
00961
00962 void rtdm_event_clear(rtdm_event_t *event);
00963
00964
00965
00966
00967 typedef struct {
00968 unsigned long value;
00969 xnsynch_t synch_base;
00970 } rtdm_sem_t;
00971
00972 #ifndef DOXYGEN_CPP
00973 static inline void rtdm_sem_init(rtdm_sem_t *sem, unsigned long value)
00974 {
00975 sem->value = value;
00976 xnsynch_init(&sem->synch_base, XNSYNCH_PRIO);
00977 }
00978
00979 static inline void rtdm_sem_destroy(rtdm_sem_t *sem)
00980 {
00981 _rtdm_synch_flush(&sem->synch_base, XNRMID);
00982 }
00983 #endif
00984
00985 int rtdm_sem_down(rtdm_sem_t *sem);
00986 int rtdm_sem_timeddown(rtdm_sem_t *sem, nanosecs_rel_t timeout,
00987 rtdm_toseq_t *timeout_seq);
00988 void rtdm_sem_up(rtdm_sem_t *sem);
00989
00990
00991
00992
00993 typedef struct {
00994 xnsynch_t synch_base;
00995 } rtdm_mutex_t;
00996
00997 #ifndef DOXYGEN_CPP
00998 static inline void rtdm_mutex_init(rtdm_mutex_t *mutex)
00999 {
01000 xnsynch_init(&mutex->synch_base, XNSYNCH_PRIO|XNSYNCH_PIP);
01001 }
01002
01003 static inline void rtdm_mutex_destroy(rtdm_mutex_t *mutex)
01004 {
01005 _rtdm_synch_flush(&mutex->synch_base, XNRMID);
01006 }
01007
01008 static inline void rtdm_mutex_unlock(rtdm_mutex_t *mutex)
01009 {
01010 XENO_ASSERT(RTDM, !xnpod_asynch_p(), return;);
01011
01012 if (unlikely(xnsynch_wakeup_one_sleeper(&mutex->synch_base) != NULL))
01013 xnpod_schedule();
01014 }
01015 #endif
01016
01017 int rtdm_mutex_lock(rtdm_mutex_t *mutex);
01018 int rtdm_mutex_timedlock(rtdm_mutex_t *mutex, nanosecs_rel_t timeout,
01019 rtdm_toseq_t *timeout_seq);
01020
01021
01022
01023
01024 #define rtdm_printk(format, ...) printk(format, ##__VA_ARGS__)
01025
01026 #ifndef DOXYGEN_CPP
01027 static inline void *rtdm_malloc(size_t size)
01028 {
01029 return xnmalloc(size);
01030 }
01031
01032 static inline void rtdm_free(void *ptr)
01033 {
01034 xnfree(ptr);
01035 }
01036
01037 #ifdef CONFIG_XENO_OPT_PERVASIVE
01038 int rtdm_mmap_to_user(rtdm_user_info_t *user_info,
01039 void *src_addr, size_t len,
01040 int prot, void **pptr,
01041 struct vm_operations_struct *vm_ops,
01042 void *vm_private_data);
01043 int rtdm_iomap_to_user(rtdm_user_info_t *user_info,
01044 unsigned long src_addr, size_t len,
01045 int prot, void **pptr,
01046 struct vm_operations_struct *vm_ops,
01047 void *vm_private_data);
01048 int rtdm_munmap(rtdm_user_info_t *user_info, void *ptr, size_t len);
01049
01050 static inline int rtdm_read_user_ok(rtdm_user_info_t *user_info,
01051 const void __user *ptr, size_t size)
01052 {
01053 return __xn_access_ok(user_info, VERIFY_READ, ptr, size);
01054 }
01055
01056 static inline int rtdm_rw_user_ok(rtdm_user_info_t *user_info,
01057 const void __user *ptr, size_t size)
01058 {
01059 return __xn_access_ok(user_info, VERIFY_WRITE, ptr, size);
01060 }
01061
01062 static inline int rtdm_copy_from_user(rtdm_user_info_t *user_info,
01063 void *dst, const void __user *src,
01064 size_t size)
01065 {
01066 return __xn_copy_from_user(user_info, dst, src, size) ? -EFAULT : 0;
01067 }
01068
01069 static inline int rtdm_safe_copy_from_user(rtdm_user_info_t *user_info,
01070 void *dst, const void __user *src,
01071 size_t size)
01072 {
01073 return (!__xn_access_ok(user_info, VERIFY_READ, src, size) ||
01074 __xn_copy_from_user(user_info, dst, src, size)) ? -EFAULT : 0;
01075 }
01076
01077 static inline int rtdm_copy_to_user(rtdm_user_info_t *user_info,
01078 void __user *dst, const void *src,
01079 size_t size)
01080 {
01081 return __xn_copy_to_user(user_info, dst, src, size) ? -EFAULT : 0;
01082 }
01083
01084 static inline int rtdm_safe_copy_to_user(rtdm_user_info_t *user_info,
01085 void __user *dst, const void *src,
01086 size_t size)
01087 {
01088 return (!__xn_access_ok(user_info, VERIFY_WRITE, dst, size) ||
01089 __xn_copy_to_user(user_info, dst, src, size)) ? -EFAULT : 0;
01090 }
01091
01092 static inline int rtdm_strncpy_from_user(rtdm_user_info_t *user_info,
01093 char *dst,
01094 const char __user *src,
01095 size_t count)
01096 {
01097 if (unlikely(!__xn_access_ok(user_info, VERIFY_READ, src, 1)))
01098 return -EFAULT;
01099 return __xn_strncpy_from_user(user_info, dst, src, count);
01100 }
01101 #else
01102
01103 #define rtdm_mmap_to_user(...) ({ -ENOSYS; })
01104 #define rtdm_munmap(...) ({ -ENOSYS; })
01105 #define rtdm_read_user_ok(...) ({ 0; })
01106 #define rtdm_rw_user_ok(...) ({ 0; })
01107 #define rtdm_copy_from_user(...) ({ -ENOSYS; })
01108 #define rtdm_safe_copy_from_user(...) ({ -ENOSYS; })
01109 #define rtdm_copy_to_user(...) ({ -ENOSYS; })
01110 #define rtdm_safe_copy_to_user(...) ({ -ENOSYS; })
01111 #define rtdm_strncpy_from_user(...) ({ -ENOSYS; })
01112 #endif
01113
01114 static inline int rtdm_in_rt_context(void)
01115 {
01116 return (rthal_current_domain != rthal_root_domain);
01117 }
01118 #endif
01119
01120 int rtdm_exec_in_rt(struct rtdm_dev_context *context,
01121 rtdm_user_info_t *user_info, void *arg,
01122 rtdm_rt_handler_t handler);
01123
01124 #endif