Xenomai 3.3.2
Loading...
Searching...
No Matches
driver.h
Go to the documentation of this file.
1
26#ifndef _COBALT_RTDM_DRIVER_H
27#define _COBALT_RTDM_DRIVER_H
28
29#include <asm/atomic.h>
30#include <linux/cpumask.h>
31#include <linux/irq_work.h>
32#include <linux/list.h>
33#include <linux/module.h>
34#include <linux/cdev.h>
35#include <linux/wait.h>
36#include <linux/notifier.h>
37#include <pipeline/lock.h>
38#include <xenomai/version.h>
39#include <cobalt/kernel/heap.h>
40#include <cobalt/kernel/sched.h>
41#include <cobalt/kernel/intr.h>
42#include <cobalt/kernel/synch.h>
43#include <cobalt/kernel/select.h>
44#include <cobalt/kernel/clock.h>
45#include <cobalt/kernel/init.h>
46#include <cobalt/kernel/ancillaries.h>
47#include <cobalt/kernel/tree.h>
48#include <rtdm/fd.h>
49#include <rtdm/rtdm.h>
50
51/* debug support */
52#include <cobalt/kernel/assert.h>
53#include <trace/events/cobalt-rtdm.h>
54#ifdef CONFIG_PCI
55#include <asm-generic/xenomai/pci_ids.h>
56#endif /* CONFIG_PCI */
57#include <asm/xenomai/syscall.h>
58
59struct class;
60typedef struct xnselector rtdm_selector_t;
62
75#define RTDM_EXCLUSIVE 0x0001
76
82#define RTDM_FIXED_MINOR 0x0002
83
85#define RTDM_NAMED_DEVICE 0x0010
86
89#define RTDM_PROTOCOL_DEVICE 0x0020
90
92#define RTDM_DEVICE_TYPE_MASK 0x00F0
93
95#define RTDM_SECURE_DEVICE 0x80000000
99#define RTDM_MAX_MINOR 4096
100
115 RTDM_SELECTTYPE_READ = XNSELECT_READ,
116
118 RTDM_SELECTTYPE_WRITE = XNSELECT_WRITE,
119
121 RTDM_SELECTTYPE_EXCEPT = XNSELECT_EXCEPT
139 struct rtdm_fd fd;
140
144
146 char dev_private[0];
147};
148
149static inline struct rtdm_dev_context *rtdm_fd_to_context(struct rtdm_fd *fd)
150{
151 return container_of(fd, struct rtdm_dev_context, fd);
152}
153
163static inline void *rtdm_fd_to_private(struct rtdm_fd *fd)
164{
165 return &rtdm_fd_to_context(fd)->dev_private[0];
166}
167
176static inline struct rtdm_fd *rtdm_private_to_fd(void *dev_private)
177{
178 struct rtdm_dev_context *ctx;
179 ctx = container_of(dev_private, struct rtdm_dev_context, dev_private);
180 return &ctx->fd;
181}
182
191static inline bool rtdm_fd_is_user(struct rtdm_fd *fd)
192{
193 return rtdm_fd_owner(fd) != &cobalt_kernel_ppd;
194}
195
204static inline struct rtdm_device *rtdm_fd_device(struct rtdm_fd *fd)
205{
206 return rtdm_fd_to_context(fd)->device;
207}
208
219 const char *name;
228 unsigned int magic;
229 struct module *owner;
230 struct class *kdev_class;
231};
232
233struct rtdm_driver;
234
240 int (*start)(struct rtdm_driver *drv);
242 int (*stop)(struct rtdm_driver *drv);
243};
244
288 struct {
289 union {
290 struct {
291 struct cdev cdev;
292 int major;
293 } named;
294 };
295 atomic_t refcount;
296 struct notifier_block nb_statechange;
297 DECLARE_BITMAP(minor_map, RTDM_MAX_MINOR);
298 };
299};
300
301#define RTDM_CLASS_MAGIC 0x8284636c
302
321#define RTDM_PROFILE_INFO(__name, __id, __subid, __version) \
322{ \
323 .name = ( # __name ), \
324 .class_id = (__id), \
325 .subclass_id = (__subid), \
326 .version = (__version), \
327 .magic = ~RTDM_CLASS_MAGIC, \
328 .owner = THIS_MODULE, \
329 .kdev_class = NULL, \
330}
331
332int rtdm_drv_set_sysclass(struct rtdm_driver *drv, struct class *cls);
333
356 const char *label;
371 int minor;
373 struct {
374 unsigned int magic;
375 char *name;
376 union {
377 struct {
378 xnhandle_t handle;
379 } named;
380 struct {
381 struct xnid id;
382 } proto;
383 };
384 dev_t rdev;
385 struct device *kdev;
386 struct class *kdev_class;
387 atomic_t refcount;
388 struct rtdm_fd_ops ops;
389 wait_queue_head_t putwq;
390 struct list_head openfd_list;
391 };
392};
393
394/* --- device registration --- */
395
396int rtdm_dev_register(struct rtdm_device *device);
397
398void rtdm_dev_unregister(struct rtdm_device *device);
399
400#ifndef DOXYGEN_CPP /* Avoid static inline tags for RTDM in doxygen */
401
402static inline struct device *rtdm_dev_to_kdev(struct rtdm_device *device)
403{
404 return device->kdev;
405}
406
407/* --- clock services --- */
408static inline nanosecs_abs_t rtdm_clock_read(void)
409{
410 return xnclock_read_realtime(&nkclock);
411}
412
414{
415 return xnclock_read_monotonic(&nkclock);
416}
417#endif /* !DOXYGEN_CPP */
418
419/* --- timeout sequences */
420
421typedef nanosecs_abs_t rtdm_toseq_t;
422
423void rtdm_toseq_init(rtdm_toseq_t *timeout_seq, nanosecs_rel_t timeout);
424
460#define cobalt_atomic_enter(__context) \
461 do { \
462 xnlock_get_irqsave(&nklock, (__context)); \
463 xnsched_lock(); \
464 } while (0)
465
478#define cobalt_atomic_leave(__context) \
479 do { \
480 xnsched_unlock(); \
481 xnlock_put_irqrestore(&nklock, (__context)); \
482 } while (0)
483
512#ifdef DOXYGEN_CPP /* Beautify doxygen output */
513#define RTDM_EXECUTE_ATOMICALLY(code_block) \
514{ \
515 <ENTER_ATOMIC_SECTION> \
516 code_block; \
517 <LEAVE_ATOMIC_SECTION> \
518}
519#else /* This is how it really works */
520static inline __attribute__((deprecated)) void
521rtdm_execute_atomically(void) { }
522
523#define RTDM_EXECUTE_ATOMICALLY(code_block) \
524{ \
525 spl_t __rtdm_s; \
526 \
527 rtdm_execute_atomically(); \
528 xnlock_get_irqsave(&nklock, __rtdm_s); \
529 xnsched_lock(); \
530 code_block; \
531 xnsched_unlock(); \
532 xnlock_put_irqrestore(&nklock, __rtdm_s); \
533}
534#endif
535
546#define RTDM_LOCK_UNLOCKED(__name) PIPELINE_SPIN_LOCK_UNLOCKED(__name)
547
548#define DEFINE_RTDM_LOCK(__name) \
549 rtdm_lock_t __name = RTDM_LOCK_UNLOCKED(__name)
550
552typedef pipeline_spinlock_t rtdm_lock_t;
553
555typedef unsigned long rtdm_lockctx_t;
556
564static inline void rtdm_lock_init(rtdm_lock_t *lock)
565{
566 raw_spin_lock_init(lock);
567}
568
576static inline void rtdm_lock_get(rtdm_lock_t *lock)
577{
578 XENO_BUG_ON(COBALT, !spltest());
579 raw_spin_lock(lock);
580 xnsched_lock();
581}
582
590static inline void rtdm_lock_put(rtdm_lock_t *lock)
591{
592 raw_spin_unlock(lock);
593 xnsched_unlock();
594}
595
604#define rtdm_lock_get_irqsave(__lock, __context) \
605 ((__context) = __rtdm_lock_get_irqsave(__lock))
606
607static inline rtdm_lockctx_t __rtdm_lock_get_irqsave(rtdm_lock_t *lock)
608{
609 rtdm_lockctx_t context;
610
611 splhigh(context);
612 raw_spin_lock(lock);
613 xnsched_lock();
614
615 return context;
616}
617
626static inline
628{
629 raw_spin_unlock(lock);
630 xnsched_unlock();
631 splexit(context);
632}
633
641#define rtdm_lock_irqsave(__context) \
642 splhigh(__context)
643
651#define rtdm_lock_irqrestore(__context) \
652 splexit(__context)
653
656#ifndef DOXYGEN_CPP
657
658struct rtdm_waitqueue {
659 struct xnsynch wait;
660};
661typedef struct rtdm_waitqueue rtdm_waitqueue_t;
662
663#define RTDM_WAITQUEUE_INITIALIZER(__name) { \
664 .wait = XNSYNCH_WAITQUEUE_INITIALIZER((__name).wait), \
665 }
666
667#define DEFINE_RTDM_WAITQUEUE(__name) \
668 struct rtdm_waitqueue __name = RTDM_WAITQUEUE_INITIALIZER(__name)
669
670#define DEFINE_RTDM_WAITQUEUE_ONSTACK(__name) \
671 DEFINE_RTDM_WAITQUEUE(__name)
672
673static inline void rtdm_waitqueue_init(struct rtdm_waitqueue *wq)
674{
675 *wq = (struct rtdm_waitqueue)RTDM_WAITQUEUE_INITIALIZER(*wq);
676}
677
678static inline void rtdm_waitqueue_destroy(struct rtdm_waitqueue *wq)
679{
680 xnsynch_destroy(&wq->wait);
681}
682
683static inline int __rtdm_dowait(struct rtdm_waitqueue *wq,
684 nanosecs_rel_t timeout, xntmode_t timeout_mode)
685{
686 int ret;
687
688 ret = xnsynch_sleep_on(&wq->wait, timeout, timeout_mode);
689 if (ret & XNBREAK)
690 return -EINTR;
691 if (ret & XNTIMEO)
692 return -ETIMEDOUT;
693 if (ret & XNRMID)
694 return -EIDRM;
695 return 0;
696}
697
698static inline int __rtdm_timedwait(struct rtdm_waitqueue *wq,
699 nanosecs_rel_t timeout, rtdm_toseq_t *toseq)
700{
701 if (toseq && timeout > 0)
702 return __rtdm_dowait(wq, *toseq, XN_ABSOLUTE);
703
704 return __rtdm_dowait(wq, timeout, XN_RELATIVE);
705}
706
707#define rtdm_timedwait_condition_locked(__wq, __cond, __timeout, __toseq) \
708 ({ \
709 int __ret = 0; \
710 while (__ret == 0 && !(__cond)) \
711 __ret = __rtdm_timedwait(__wq, __timeout, __toseq); \
712 __ret; \
713 })
714
715#define rtdm_wait_condition_locked(__wq, __cond) \
716 ({ \
717 int __ret = 0; \
718 while (__ret == 0 && !(__cond)) \
719 __ret = __rtdm_dowait(__wq, \
720 XN_INFINITE, XN_RELATIVE); \
721 __ret; \
722 })
723
724#define rtdm_timedwait_condition(__wq, __cond, __timeout, __toseq) \
725 ({ \
726 spl_t __s; \
727 int __ret; \
728 xnlock_get_irqsave(&nklock, __s); \
729 __ret = rtdm_timedwait_condition_locked(__wq, __cond, \
730 __timeout, __toseq); \
731 xnlock_put_irqrestore(&nklock, __s); \
732 __ret; \
733 })
734
735#define rtdm_timedwait(__wq, __timeout, __toseq) \
736 __rtdm_timedwait(__wq, __timeout, __toseq)
737
738#define rtdm_timedwait_locked(__wq, __timeout, __toseq) \
739 rtdm_timedwait(__wq, __timeout, __toseq)
740
741#define rtdm_wait_condition(__wq, __cond) \
742 ({ \
743 spl_t __s; \
744 int __ret; \
745 xnlock_get_irqsave(&nklock, __s); \
746 __ret = rtdm_wait_condition_locked(__wq, __cond); \
747 xnlock_put_irqrestore(&nklock, __s); \
748 __ret; \
749 })
750
751#define rtdm_wait(__wq) \
752 __rtdm_dowait(__wq, XN_INFINITE, XN_RELATIVE)
753
754#define rtdm_wait_locked(__wq) rtdm_wait(__wq)
755
756#define rtdm_waitqueue_lock(__wq, __context) cobalt_atomic_enter(__context)
757
758#define rtdm_waitqueue_unlock(__wq, __context) cobalt_atomic_leave(__context)
759
760#define rtdm_waitqueue_signal(__wq) \
761 ({ \
762 struct xnthread *__waiter; \
763 __waiter = xnsynch_wakeup_one_sleeper(&(__wq)->wait); \
764 xnsched_run(); \
765 __waiter != NULL; \
766 })
767
768#define __rtdm_waitqueue_flush(__wq, __reason) \
769 ({ \
770 int __ret; \
771 __ret = xnsynch_flush(&(__wq)->wait, __reason); \
772 xnsched_run(); \
773 __ret == XNSYNCH_RESCHED; \
774 })
775
776#define rtdm_waitqueue_broadcast(__wq) \
777 __rtdm_waitqueue_flush(__wq, 0)
778
779#define rtdm_waitqueue_flush(__wq) \
780 __rtdm_waitqueue_flush(__wq, XNBREAK)
781
782#define rtdm_waitqueue_wakeup(__wq, __waiter) \
783 do { \
784 xnsynch_wakeup_this_sleeper(&(__wq)->wait, __waiter); \
785 xnsched_run(); \
786 } while (0)
787
788#define rtdm_for_each_waiter(__pos, __wq) \
789 xnsynch_for_each_sleeper(__pos, &(__wq)->wait)
790
791#define rtdm_for_each_waiter_safe(__pos, __tmp, __wq) \
792 xnsynch_for_each_sleeper_safe(__pos, __tmp, &(__wq)->wait)
793
794#endif /* !DOXYGEN_CPP */
795
798/* --- Interrupt management services --- */
804typedef struct xnintr rtdm_irq_t;
805
812#define RTDM_IRQTYPE_SHARED XN_IRQTYPE_SHARED
815#define RTDM_IRQTYPE_EDGE XN_IRQTYPE_EDGE
825typedef int (*rtdm_irq_handler_t)(rtdm_irq_t *irq_handle);
826
833#define RTDM_IRQ_NONE XN_IRQ_NONE
835#define RTDM_IRQ_HANDLED XN_IRQ_HANDLED
837#define RTDM_IRQ_DISABLE XN_IRQ_DISABLE
851#define rtdm_irq_get_arg(irq_handle, type) ((type *)irq_handle->cookie)
854int rtdm_irq_request(rtdm_irq_t *irq_handle, unsigned int irq_no,
855 rtdm_irq_handler_t handler, unsigned long flags,
856 const char *device_name, void *arg);
857
858int rtdm_irq_request_affine(rtdm_irq_t *irq_handle, unsigned int irq_no,
859 rtdm_irq_handler_t handler, unsigned long flags,
860 const char *device_name, void *arg,
861 const cpumask_t *cpumask);
862
863#ifndef DOXYGEN_CPP /* Avoid static inline tags for RTDM in doxygen */
864static inline int rtdm_irq_free(rtdm_irq_t *irq_handle)
865{
866 if (!XENO_ASSERT(COBALT, xnsched_root_p()))
867 return -EPERM;
868 xnintr_destroy(irq_handle);
869 return 0;
870}
871
872static inline int rtdm_irq_enable(rtdm_irq_t *irq_handle)
873{
874 xnintr_enable(irq_handle);
875 return 0;
876}
877
878static inline int rtdm_irq_disable(rtdm_irq_t *irq_handle)
879{
880 xnintr_disable(irq_handle);
881 return 0;
882}
883
884static inline int rtdm_irq_set_affinity(rtdm_irq_t *irq_handle,
885 const cpumask_t *cpumask)
886{
887 return xnintr_affinity(irq_handle, cpumask);
888}
889#endif /* !DOXYGEN_CPP */
890
891/* --- non-real-time signalling services --- */
892
898typedef struct rtdm_nrtsig rtdm_nrtsig_t;
909typedef void (*rtdm_nrtsig_handler_t)(rtdm_nrtsig_t *nrt_sig, void *arg);
910
911struct rtdm_nrtsig {
912 struct irq_work inband_work;
913 rtdm_nrtsig_handler_t handler;
914 void *arg;
915};
916
917void rtdm_schedule_nrt_work(struct work_struct *lostage_work);
920#ifndef DOXYGEN_CPP /* Avoid static inline tags for RTDM in doxygen */
921void __rtdm_nrtsig_execute(struct irq_work *inband_work);
922
923static inline void rtdm_nrtsig_init(rtdm_nrtsig_t *nrt_sig,
924 rtdm_nrtsig_handler_t handler, void *arg)
925{
926 nrt_sig->inband_work = IRQ_WORK_INIT(__rtdm_nrtsig_execute);
927 nrt_sig->handler = handler;
928 nrt_sig->arg = arg;
929}
930
931static inline void rtdm_nrtsig_destroy(rtdm_nrtsig_t *nrt_sig)
932{
933 nrt_sig->handler = NULL;
934 nrt_sig->arg = NULL;
935}
936
937void rtdm_nrtsig_pend(rtdm_nrtsig_t *nrt_sig);
938#endif /* !DOXYGEN_CPP */
939
940/* --- timer services --- */
941
947typedef struct xntimer rtdm_timer_t;
948
954typedef void (*rtdm_timer_handler_t)(rtdm_timer_t *timer);
955
964
967
969 RTDM_TIMERMODE_REALTIME = XN_REALTIME
975int rtdm_timer_init(rtdm_timer_t *timer, rtdm_timer_handler_t handler,
976 const char *name);
977
978void rtdm_timer_destroy(rtdm_timer_t *timer);
979
980int rtdm_timer_start(rtdm_timer_t *timer, nanosecs_abs_t expiry,
981 nanosecs_rel_t interval, enum rtdm_timer_mode mode);
982
983void rtdm_timer_stop(rtdm_timer_t *timer);
984
985#ifndef DOXYGEN_CPP /* Avoid static inline tags for RTDM in doxygen */
986static inline int rtdm_timer_start_in_handler(rtdm_timer_t *timer,
987 nanosecs_abs_t expiry,
988 nanosecs_rel_t interval,
989 enum rtdm_timer_mode mode)
990{
991 return xntimer_start(timer, expiry, interval, (xntmode_t)mode);
992}
993
994static inline void rtdm_timer_stop_in_handler(rtdm_timer_t *timer)
995{
996 xntimer_stop(timer);
997}
998#endif /* !DOXYGEN_CPP */
999
1000/* --- task services --- */
1006typedef struct xnthread rtdm_task_t;
1007
1013typedef void (*rtdm_task_proc_t)(void *arg);
1014
1019#define RTDM_TASK_LOWEST_PRIORITY 0
1020#define RTDM_TASK_HIGHEST_PRIORITY 99
1027#define RTDM_TASK_RAISE_PRIORITY (+1)
1028#define RTDM_TASK_LOWER_PRIORITY (-1)
1033int rtdm_task_init(rtdm_task_t *task, const char *name,
1034 rtdm_task_proc_t task_proc, void *arg,
1035 int priority, nanosecs_rel_t period);
1036int __rtdm_task_sleep(xnticks_t timeout, xntmode_t mode);
1038
1039#ifndef DOXYGEN_CPP /* Avoid static inline tags for RTDM in doxygen */
1040static inline void rtdm_task_destroy(rtdm_task_t *task)
1041{
1042 xnthread_cancel(task);
1043 xnthread_join(task, true);
1044}
1045
1046static inline int rtdm_task_should_stop(void)
1047{
1048 return xnthread_test_info(xnthread_current(), XNCANCELD);
1049}
1050
1051void rtdm_task_join(rtdm_task_t *task);
1052
1053static inline void __deprecated rtdm_task_join_nrt(rtdm_task_t *task,
1054 unsigned int poll_delay)
1055{
1056 rtdm_task_join(task);
1057}
1058
1059static inline void rtdm_task_set_priority(rtdm_task_t *task, int priority)
1060{
1061 union xnsched_policy_param param = { .rt = { .prio = priority } };
1062 spl_t s;
1063
1064 splhigh(s);
1065 xnthread_set_schedparam(task, &xnsched_class_rt, &param);
1066 xnsched_run();
1067 splexit(s);
1068}
1069
1070static inline int rtdm_task_set_period(rtdm_task_t *task,
1071 nanosecs_abs_t start_date,
1072 nanosecs_rel_t period)
1073{
1074 if (period < 0)
1075 period = 0;
1076 if (start_date == 0)
1077 start_date = XN_INFINITE;
1078
1079 return xnthread_set_periodic(task, start_date, XN_ABSOLUTE, period);
1080}
1081
1082static inline int rtdm_task_unblock(rtdm_task_t *task)
1083{
1084 spl_t s;
1085 int res;
1086
1087 splhigh(s);
1088 res = xnthread_unblock(task);
1089 xnsched_run();
1090 splexit(s);
1091
1092 return res;
1093}
1094
1095static inline rtdm_task_t *rtdm_task_current(void)
1096{
1097 return xnthread_current();
1098}
1099
1100static inline int rtdm_task_wait_period(unsigned long *overruns_r)
1101{
1102 if (!XENO_ASSERT(COBALT, !xnsched_unblockable_p()))
1103 return -EPERM;
1104 return xnthread_wait_period(overruns_r);
1105}
1106
1107static inline int rtdm_task_sleep(nanosecs_rel_t delay)
1108{
1109 return __rtdm_task_sleep(delay, XN_RELATIVE);
1110}
1111
1112static inline int
1114{
1115 /* For the sake of a consistent API usage... */
1116 if (mode != RTDM_TIMERMODE_ABSOLUTE && mode != RTDM_TIMERMODE_REALTIME)
1117 return -EINVAL;
1118 return __rtdm_task_sleep(wakeup_date, (xntmode_t)mode);
1119}
1120
1121/* rtdm_task_sleep_abs shall be used instead */
1122static inline int __deprecated rtdm_task_sleep_until(nanosecs_abs_t wakeup_time)
1123{
1124 return __rtdm_task_sleep(wakeup_time, XN_REALTIME);
1125}
1126
1127#define rtdm_task_busy_wait(__condition, __spin_ns, __sleep_ns) \
1128 ({ \
1129 __label__ done; \
1130 nanosecs_abs_t __end; \
1131 int __ret = 0; \
1132 for (;;) { \
1133 __end = rtdm_clock_read_monotonic() + __spin_ns; \
1134 for (;;) { \
1135 if (__condition) \
1136 goto done; \
1137 if (rtdm_clock_read_monotonic() >= __end) \
1138 break; \
1139 } \
1140 __ret = rtdm_task_sleep(__sleep_ns); \
1141 if (__ret) \
1142 break; \
1143 } \
1144 done: \
1145 __ret; \
1146 })
1147
1148#define rtdm_wait_context xnthread_wait_context
1149
1150static inline
1151void rtdm_wait_complete(struct rtdm_wait_context *wc)
1152{
1153 xnthread_complete_wait(wc);
1154}
1155
1156static inline
1157int rtdm_wait_is_completed(struct rtdm_wait_context *wc)
1158{
1159 return xnthread_wait_complete_p(wc);
1160}
1161
1162static inline void rtdm_wait_prepare(struct rtdm_wait_context *wc)
1163{
1164 xnthread_prepare_wait(wc);
1165}
1166
1167static inline
1168struct rtdm_wait_context *rtdm_wait_get_context(rtdm_task_t *task)
1169{
1170 return xnthread_get_wait_context(task);
1171}
1172
1173#endif /* !DOXYGEN_CPP */
1174
1175/* --- event services --- */
1176
1177typedef struct rtdm_event {
1178 struct xnsynch synch_base;
1179 DECLARE_XNSELECT(select_block);
1180} rtdm_event_t;
1181
1182#define RTDM_EVENT_PENDING XNSYNCH_SPARE1
1183
1184void rtdm_event_init(rtdm_event_t *event, unsigned long pending);
1185int rtdm_event_select(rtdm_event_t *event, rtdm_selector_t *selector,
1186 enum rtdm_selecttype type, unsigned fd_index);
1187int rtdm_event_wait(rtdm_event_t *event);
1188int rtdm_event_timedwait(rtdm_event_t *event, nanosecs_rel_t timeout,
1189 rtdm_toseq_t *timeout_seq);
1190void rtdm_event_signal(rtdm_event_t *event);
1191
1192void rtdm_event_clear(rtdm_event_t *event);
1193
1194void rtdm_event_pulse(rtdm_event_t *event);
1195
1196void rtdm_event_destroy(rtdm_event_t *event);
1197
1198/* --- semaphore services --- */
1199
1200typedef struct rtdm_sem {
1201 unsigned long value;
1202 struct xnsynch synch_base;
1203 DECLARE_XNSELECT(select_block);
1204} rtdm_sem_t;
1205
1206void rtdm_sem_init(rtdm_sem_t *sem, unsigned long value);
1207int rtdm_sem_select(rtdm_sem_t *sem, rtdm_selector_t *selector,
1208 enum rtdm_selecttype type, unsigned fd_index);
1209int rtdm_sem_down(rtdm_sem_t *sem);
1210int rtdm_sem_timeddown(rtdm_sem_t *sem, nanosecs_rel_t timeout,
1211 rtdm_toseq_t *timeout_seq);
1212void rtdm_sem_up(rtdm_sem_t *sem);
1213
1214void rtdm_sem_destroy(rtdm_sem_t *sem);
1215
1216/* --- mutex services --- */
1217
1218typedef struct rtdm_mutex {
1219 struct xnsynch synch_base;
1220 atomic_t fastlock;
1221} rtdm_mutex_t;
1222
1223void rtdm_mutex_init(rtdm_mutex_t *mutex);
1224int rtdm_mutex_lock(rtdm_mutex_t *mutex);
1225int rtdm_mutex_timedlock(rtdm_mutex_t *mutex, nanosecs_rel_t timeout,
1226 rtdm_toseq_t *timeout_seq);
1227void rtdm_mutex_unlock(rtdm_mutex_t *mutex);
1228void rtdm_mutex_destroy(rtdm_mutex_t *mutex);
1229
1230/* --- utility functions --- */
1231
1232#define rtdm_printk_ratelimited(fmt, ...) do { \
1233 if (xnclock_ratelimit()) \
1234 printk(fmt, ##__VA_ARGS__); \
1235} while (0)
1236
1237#ifndef DOXYGEN_CPP /* Avoid static inline tags for RTDM in doxygen */
1238static inline void *rtdm_malloc(size_t size)
1239{
1240 return xnmalloc(size);
1241}
1242
1243static inline void rtdm_free(void *ptr)
1244{
1245 xnfree(ptr);
1246}
1247
1248int rtdm_mmap_to_user(struct rtdm_fd *fd,
1249 void *src_addr, size_t len,
1250 int prot, void **pptr,
1251 struct vm_operations_struct *vm_ops,
1252 void *vm_private_data);
1253
1254int rtdm_iomap_to_user(struct rtdm_fd *fd,
1255 phys_addr_t src_addr, size_t len,
1256 int prot, void **pptr,
1257 struct vm_operations_struct *vm_ops,
1258 void *vm_private_data);
1259
1260int rtdm_mmap_kmem(struct vm_area_struct *vma, void *va);
1261
1262int rtdm_mmap_vmem(struct vm_area_struct *vma, void *va);
1263
1264int rtdm_mmap_iomem(struct vm_area_struct *vma, phys_addr_t pa);
1265
1266int rtdm_munmap(void *ptr, size_t len);
1267
1268static inline int rtdm_read_user_ok(struct rtdm_fd *fd,
1269 const void __user *ptr, size_t size)
1270{
1271 return access_ok(ptr, size);
1272}
1273
1274static inline int rtdm_rw_user_ok(struct rtdm_fd *fd,
1275 const void __user *ptr, size_t size)
1276{
1277 return access_ok(ptr, size);
1278}
1279
1280static inline int rtdm_copy_from_user(struct rtdm_fd *fd,
1281 void *dst, const void __user *src,
1282 size_t size)
1283{
1284 return __xn_copy_from_user(dst, src, size) ? -EFAULT : 0;
1285}
1286
1287static inline int rtdm_safe_copy_from_user(struct rtdm_fd *fd,
1288 void *dst, const void __user *src,
1289 size_t size)
1290{
1291 return cobalt_copy_from_user(dst, src, size);
1292}
1293
1294static inline int rtdm_copy_to_user(struct rtdm_fd *fd,
1295 void __user *dst, const void *src,
1296 size_t size)
1297{
1298 return __xn_copy_to_user(dst, src, size) ? -EFAULT : 0;
1299}
1300
1301static inline int rtdm_safe_copy_to_user(struct rtdm_fd *fd,
1302 void __user *dst, const void *src,
1303 size_t size)
1304{
1305 return cobalt_copy_to_user(dst, src, size);
1306}
1307
1308static inline int rtdm_strncpy_from_user(struct rtdm_fd *fd,
1309 char *dst,
1310 const char __user *src, size_t count)
1311{
1312 return cobalt_strncpy_from_user(dst, src, count);
1313}
1314
1315static inline bool rtdm_available(void)
1316{
1317 return realtime_core_enabled();
1318}
1319
1320static inline int rtdm_rt_capable(struct rtdm_fd *fd)
1321{
1322 if (!XENO_ASSERT(COBALT, !xnsched_interrupt_p()))
1323 return 0;
1324
1325 if (!rtdm_fd_is_user(fd))
1326 return !xnsched_root_p();
1327
1328 return xnthread_current() != NULL;
1329}
1330
1331static inline int rtdm_in_rt_context(void)
1332{
1333 return is_primary_domain();
1334}
1335
1336#define RTDM_IOV_FASTMAX 16
1337
1338int rtdm_get_iovec(struct rtdm_fd *fd, struct iovec **iov,
1339 const struct user_msghdr *msg,
1340 struct iovec *iov_fast);
1341
1342int rtdm_put_iovec(struct rtdm_fd *fd, struct iovec *iov,
1343 const struct user_msghdr *msg,
1344 struct iovec *iov_fast);
1345
1346static inline
1347void rtdm_drop_iovec(struct iovec *iov, struct iovec *iov_fast)
1348{
1349 if (iov != iov_fast)
1350 xnfree(iov);
1351}
1352
1353ssize_t rtdm_get_iov_flatlen(struct iovec *iov, int iovlen);
1354
1355#endif /* !DOXYGEN_CPP */
1356
1357#endif /* _COBALT_RTDM_DRIVER_H */
static void * rtdm_fd_to_private(struct rtdm_fd *fd)
Locate the driver private area associated to a device context structure.
Definition driver.h:163
static struct rtdm_fd * rtdm_private_to_fd(void *dev_private)
Locate a device file descriptor structure from its driver private area.
Definition driver.h:176
static bool rtdm_fd_is_user(struct rtdm_fd *fd)
Tell whether the passed file descriptor belongs to an application.
Definition driver.h:191
static struct rtdm_device * rtdm_fd_device(struct rtdm_fd *fd)
Locate a device structure from a file descriptor.
Definition driver.h:204
operation handlers
static int xnsched_run(void)
The rescheduling procedure.
Definition sched.h:312
int __must_check xnsynch_sleep_on(struct xnsynch *synch, xnticks_t timeout, xntmode_t timeout_mode)
Sleep on an ownerless synchronization object.
Definition synch.c:199
int xnsynch_destroy(struct xnsynch *synch)
Destroy a synchronization object.
Definition synch.c:154
#define XNBREAK
Forcibly awaken from a wait state.
Definition thread.h:68
#define XNTIMEO
Woken up due to a timeout condition.
Definition thread.h:66
#define XNRMID
Pending on a removed resource.
Definition thread.h:67
#define XNCANCELD
Cancellation request is pending.
Definition thread.h:72
int xnthread_wait_period(unsigned long *overruns_r)
Wait for the next periodic release point.
Definition thread.c:1394
static struct xnthread * xnthread_current(void)
Retrieve the current Cobalt core TCB.
Definition thread.h:395
int xnthread_unblock(struct xnthread *thread)
Unblock a thread.
Definition thread.c:1212
void xnthread_cancel(struct xnthread *thread)
Cancel a thread.
Definition thread.c:1527
int xnthread_join(struct xnthread *thread, bool uninterruptible)
Join with a terminated thread.
Definition thread.c:1656
int xnthread_set_periodic(struct xnthread *thread, xnticks_t idate, xntmode_t timeout_mode, xnticks_t period)
Make a thread periodic.
Definition thread.c:1304
int xnthread_set_schedparam(struct xnthread *thread, struct xnsched_class *sched_class, const union xnsched_policy_param *sched_param)
Change the base scheduling parameters of a thread.
Definition thread.c:1830
int xntimer_start(struct xntimer *timer, xnticks_t value, xnticks_t interval, xntmode_t mode)
Arm a timer.
Definition timer.c:114
static void xntimer_stop(struct xntimer *timer)
Disarm a timer.
Definition timer.h:471
nanosecs_abs_t rtdm_clock_read(void)
Get system time.
nanosecs_abs_t rtdm_clock_read_monotonic(void)
Get monotonic time.
int rtdm_dev_register(struct rtdm_device *device)
Register a RTDM device.
Definition device.c:393
#define RTDM_MAX_MINOR
Maximum number of named devices per driver.
Definition driver.h:99
void rtdm_dev_unregister(struct rtdm_device *device)
Unregister a RTDM device.
Definition device.c:542
int rtdm_drv_set_sysclass(struct rtdm_driver *drv, struct class *cls)
Set the kernel device class of a RTDM driver.
Definition device.c:615
int rtdm_irq_set_affinity(rtdm_irq_t *irq_handle, const cpumask_t *cpumask)
Set interrupt affinity.
int rtdm_irq_enable(rtdm_irq_t *irq_handle)
Enable interrupt line.
int rtdm_irq_request_affine(rtdm_irq_t *irq_handle, unsigned int irq_no, rtdm_irq_handler_t handler, unsigned long flags, const char *device_name, void *arg, const cpumask_t *cpumask)
Register an interrupt handler.
Definition drvlib.c:1475
int rtdm_irq_request(rtdm_irq_t *irq_handle, unsigned int irq_no, rtdm_irq_handler_t handler, unsigned long flags, const char *device_name, void *arg)
Register an interrupt handler.
Definition drvlib.c:1441
int rtdm_irq_disable(rtdm_irq_t *irq_handle)
Disable interrupt line.
int(* rtdm_irq_handler_t)(rtdm_irq_t *irq_handle)
Interrupt handler.
Definition driver.h:825
int rtdm_irq_free(rtdm_irq_t *irq_handle)
Release an interrupt handler.
int rtdm_nrtsig_init(rtdm_nrtsig_t *nrt_sig, rtdm_nrtsig_handler_t handler, void *arg)
Register a non-real-time signal handler.
void rtdm_nrtsig_destroy(rtdm_nrtsig_t *nrt_sig)
Release a non-realtime signal handler.
void rtdm_nrtsig_pend(rtdm_nrtsig_t *nrt_sig)
Trigger non-real-time signal.
Definition drvlib.c:1634
void rtdm_schedule_nrt_work(struct work_struct *lostage_work)
Put a work task in Linux non real-time global workqueue from primary mode.
Definition drvlib.c:1672
void(* rtdm_nrtsig_handler_t)(rtdm_nrtsig_t *nrt_sig, void *arg)
Non-real-time signal handler.
Definition driver.h:909
void rtdm_event_signal(rtdm_event_t *event)
Signal an event occurrence.
Definition drvlib.c:797
int rtdm_event_wait(rtdm_event_t *event)
Wait on event occurrence.
Definition drvlib.c:839
void rtdm_event_clear(rtdm_event_t *event)
Clear event state.
Definition drvlib.c:940
void rtdm_event_destroy(rtdm_event_t *event)
Destroy an event.
Definition drvlib.c:758
void rtdm_event_pulse(rtdm_event_t *event)
Signal an event occurrence to currently listening waiters.
Definition drvlib.c:779
void rtdm_event_init(rtdm_event_t *event, unsigned long pending)
Initialise an event.
Definition drvlib.c:732
int rtdm_event_timedwait(rtdm_event_t *event, nanosecs_rel_t timeout, rtdm_toseq_t *timeout_seq)
Wait on event occurrence with timeout.
Definition drvlib.c:877
int rtdm_mutex_timedlock(rtdm_mutex_t *mutex, nanosecs_rel_t timeout, rtdm_toseq_t *timeout_seq)
Request a mutex with timeout.
Definition drvlib.c:1358
int rtdm_mutex_lock(rtdm_mutex_t *mutex)
Request a mutex.
Definition drvlib.c:1324
void rtdm_mutex_init(rtdm_mutex_t *mutex)
Initialise a mutex.
Definition drvlib.c:1257
void rtdm_mutex_unlock(rtdm_mutex_t *mutex)
Release a mutex.
Definition drvlib.c:1294
void rtdm_mutex_destroy(rtdm_mutex_t *mutex)
Destroy a mutex.
Definition drvlib.c:1275
int rtdm_sem_down(rtdm_sem_t *sem)
Decrement a semaphore.
Definition drvlib.c:1074
void rtdm_sem_up(rtdm_sem_t *sem)
Increment a semaphore.
Definition drvlib.c:1171
int rtdm_sem_timeddown(rtdm_sem_t *sem, nanosecs_rel_t timeout, rtdm_toseq_t *timeout_seq)
Decrement a semaphore with timeout.
Definition drvlib.c:1112
void rtdm_sem_init(rtdm_sem_t *sem, unsigned long value)
Initialise a semaphore.
Definition drvlib.c:1019
void rtdm_sem_destroy(rtdm_sem_t *sem)
Destroy a semaphore.
Definition drvlib.c:1044
unsigned long rtdm_lockctx_t
Variable to save the context while holding a lock.
Definition driver.h:555
static void rtdm_lock_get(rtdm_lock_t *lock)
Acquire lock from non-preemptible contexts.
Definition driver.h:576
pipeline_spinlock_t rtdm_lock_t
Lock variable.
Definition driver.h:552
static void rtdm_lock_init(rtdm_lock_t *lock)
Dynamic lock initialisation.
Definition driver.h:564
static void rtdm_lock_put(rtdm_lock_t *lock)
Release lock without preemption restoration.
Definition driver.h:590
static void rtdm_lock_put_irqrestore(rtdm_lock_t *lock, rtdm_lockctx_t context)
Release lock and restore preemption state.
Definition driver.h:627
void rtdm_toseq_init(rtdm_toseq_t *timeout_seq, nanosecs_rel_t timeout)
Initialise a timeout sequence.
Definition drvlib.c:707
void rtdm_waitqueue_destroy(struct rtdm_waitqueue *wq)
Deletes a RTDM wait queue.
void rtdm_waitqueue_init(struct rtdm_waitqueue *wq)
Initialize a RTDM wait queue.
rtdm_selecttype
Definition driver.h:113
@ RTDM_SELECTTYPE_EXCEPT
Select exceptional events.
Definition driver.h:121
@ RTDM_SELECTTYPE_WRITE
Select ouput buffer availability events.
Definition driver.h:118
@ RTDM_SELECTTYPE_READ
Select input data availability events.
Definition driver.h:115
int rtdm_task_should_stop(void)
Check for pending termination request.
int rtdm_task_sleep_abs(nanosecs_abs_t wakeup_time, enum rtdm_timer_mode mode)
Sleep until a specified absolute time.
void rtdm_task_set_priority(rtdm_task_t *task, int priority)
Adjust real-time task priority.
void rtdm_task_join(rtdm_task_t *task)
Wait on a real-time task to terminate.
Definition drvlib.c:465
rtdm_task_t * rtdm_task_current(void)
Get current real-time task.
void(* rtdm_task_proc_t)(void *arg)
Real-time task procedure.
Definition driver.h:1013
int rtdm_task_init(rtdm_task_t *task, const char *name, rtdm_task_proc_t task_proc, void *arg, int priority, nanosecs_rel_t period)
Initialise and start a real-time task.
Definition drvlib.c:108
int rtdm_task_set_period(rtdm_task_t *task, nanosecs_abs_t start_date, nanosecs_rel_t period)
Adjust real-time task period.
int rtdm_task_sleep_until(nanosecs_abs_t wakeup_time)
Sleep until a specified absolute time.
void rtdm_task_destroy(rtdm_task_t *task)
Destroy a real-time task.
void rtdm_wait_prepare(struct rtdm_wait_context *wc)
Register wait context.
void rtdm_wait_complete(struct rtdm_wait_context *wc)
Mark completion for a wait context.
int rtdm_task_wait_period(unsigned long *overruns_r)
Wait on next real-time task period.
void rtdm_task_busy_sleep(nanosecs_rel_t delay)
Busy-wait a specified amount of time.
Definition drvlib.c:488
int rtdm_task_sleep(nanosecs_rel_t delay)
Sleep a specified amount of time.
int rtdm_wait_is_completed(struct rtdm_wait_context *wc)
Test completion of a wait context.
int rtdm_task_unblock(rtdm_task_t *task)
Activate a blocked real-time task.
void(* rtdm_timer_handler_t)(rtdm_timer_t *timer)
Timer handler.
Definition driver.h:954
int rtdm_timer_start(rtdm_timer_t *timer, nanosecs_abs_t expiry, nanosecs_rel_t interval, enum rtdm_timer_mode mode)
Start a timer.
Definition drvlib.c:569
void rtdm_timer_stop(rtdm_timer_t *timer)
Stop a timer.
Definition drvlib.c:591
int rtdm_timer_init(rtdm_timer_t *timer, rtdm_timer_handler_t handler, const char *name)
Initialise a timer.
Definition drvlib.c:519
void rtdm_timer_destroy(rtdm_timer_t *timer)
Destroy a timer.
Definition drvlib.c:539
rtdm_timer_mode
Definition driver.h:961
int rtdm_timer_start_in_handler(rtdm_timer_t *timer, nanosecs_abs_t expiry, nanosecs_rel_t interval, enum rtdm_timer_mode mode)
Start a timer from inside a timer handler.
void rtdm_timer_stop_in_handler(rtdm_timer_t *timer)
Stop a timer from inside a timer handler.
@ RTDM_TIMERMODE_ABSOLUTE
Monotonic timer with absolute timeout.
Definition driver.h:966
@ RTDM_TIMERMODE_REALTIME
Adjustable timer with absolute timeout.
Definition driver.h:969
@ RTDM_TIMERMODE_RELATIVE
Monotonic timer with relative timeout.
Definition driver.h:963
int rtdm_munmap(void *ptr, size_t len)
Unmap a user memory range.
Definition drvlib.c:2186
int rtdm_read_user_ok(struct rtdm_fd *fd, const void __user *ptr, size_t size)
Check if read access to user-space memory block is safe.
int rtdm_rw_user_ok(struct rtdm_fd *fd, const void __user *ptr, size_t size)
Check if read/write access to user-space memory block is safe.
int rtdm_copy_from_user(struct rtdm_fd *fd, void *dst, const void __user *src, size_t size)
Copy user-space memory block to specified buffer.
int rtdm_iomap_to_user(struct rtdm_fd *fd, phys_addr_t src_addr, size_t len, int prot, void **pptr, struct vm_operations_struct *vm_ops, void *vm_private_data)
Map an I/O memory range into the address space of the user.
Definition drvlib.c:2068
int rtdm_mmap_kmem(struct vm_area_struct *vma, void *va)
Map a kernel logical memory range to a virtual user area.
Definition drvlib.c:2112
int rtdm_safe_copy_to_user(struct rtdm_fd *fd, void __user *dst, const void *src, size_t size)
Check if read/write access to user-space memory block is safe and copy specified buffer to it.
int rtdm_copy_to_user(struct rtdm_fd *fd, void __user *dst, const void *src, size_t size)
Copy specified buffer to user-space memory block.
int rtdm_mmap_to_user(struct rtdm_fd *fd, void *src_addr, size_t len, int prot, void **pptr, struct vm_operations_struct *vm_ops, void *vm_private_data)
Map a kernel memory range into the address space of the user.
Definition drvlib.c:1999
void * rtdm_malloc(size_t size)
Allocate memory block.
void rtdm_free(void *ptr)
Release real-time memory block.
int rtdm_in_rt_context(void)
Test if running in a real-time task.
int rtdm_rt_capable(struct rtdm_fd *fd)
Test if the caller is capable of running in real-time context.
int rtdm_mmap_iomem(struct vm_area_struct *vma, phys_addr_t pa)
Map an I/O memory range to a virtual user area.
Definition drvlib.c:2165
bool rtdm_available(void)
Test if the real-time core is available.
int rtdm_mmap_vmem(struct vm_area_struct *vma, void *va)
Map a kernel virtual memory range to a virtual user area.
Definition drvlib.c:2137
int rtdm_strncpy_from_user(struct rtdm_fd *fd, char *dst, const char __user *src, size_t count)
Copy user-space string to specified buffer.
int rtdm_safe_copy_from_user(struct rtdm_fd *fd, void *dst, const void __user *src, size_t size)
Check if read access to user-space memory block and copy it to specified buffer.
uint64_t nanosecs_abs_t
RTDM type for representing absolute dates.
Definition rtdm.h:43
int64_t nanosecs_rel_t
RTDM type for representing relative intervals.
Definition rtdm.h:49
Copyright © 2011 Gilles Chanteperdrix gilles.chanteperdrix@xenomai.org.
Definition atomic.h:24
Device context.
Definition driver.h:138
char dev_private[0]
Begin of driver defined context data structure.
Definition driver.h:146
struct rtdm_device * device
Set of active device operation handlers.
Definition driver.h:143
RTDM device.
Definition driver.h:340
int minor
Minor number of the device.
Definition driver.h:371
void * device_data
Driver definable device data.
Definition driver.h:344
struct rtdm_driver * driver
Device driver.
Definition driver.h:342
const char * label
Device label template for composing the device name.
Definition driver.h:356
RTDM driver.
Definition driver.h:251
struct rtdm_fd_ops ops
I/O operation handlers.
Definition driver.h:277
int socket_type
Protocol device identification: socket type (SOCK_xxx)
Definition driver.h:275
int device_flags
Device flags, see Device Flags for details .
Definition driver.h:262
int base_minor
Base minor for named devices.
Definition driver.h:286
size_t context_size
Size of the private memory area the core should automatically allocate for each open file descriptor,...
Definition driver.h:271
int device_count
Count of devices this driver manages.
Definition driver.h:284
struct rtdm_sm_ops smops
State management handlers.
Definition driver.h:279
int protocol_family
Protocol device identification: protocol family (PF_xxx)
Definition driver.h:273
struct rtdm_profile_info profile_info
Class profile information.
Definition driver.h:257
Definition fd.h:246
RTDM profile information.
Definition driver.h:217
int version
Supported device profile version.
Definition driver.h:226
unsigned int magic
Reserved.
Definition driver.h:228
int subclass_id
Device sub-class, see RTDM_SUBCLASS_xxx definition in the Device Profiles.
Definition driver.h:224
const char * name
Device class name.
Definition driver.h:219
int class_id
Device class ID, see RTDM_CLASS_xxx.
Definition driver.h:221
RTDM state management handlers.
Definition driver.h:238
int(* stop)(struct rtdm_driver *drv)
Handler called upon transition to COBALT_STATE_TEARDOWN.
Definition driver.h:242
int(* start)(struct rtdm_driver *drv)
Handler called upon transition to COBALT_STATE_WARMUP.
Definition driver.h:240