Xenomai  3.0.2
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/list.h>
31 #include <linux/module.h>
32 #include <linux/cdev.h>
33 #include <linux/wait.h>
34 #include <linux/notifier.h>
35 #include <xenomai/version.h>
36 #include <cobalt/kernel/heap.h>
37 #include <cobalt/kernel/sched.h>
38 #include <cobalt/kernel/intr.h>
39 #include <cobalt/kernel/synch.h>
40 #include <cobalt/kernel/select.h>
41 #include <cobalt/kernel/clock.h>
42 #include <cobalt/kernel/apc.h>
43 #include <cobalt/kernel/init.h>
44 #include <cobalt/kernel/ancillaries.h>
45 #include <cobalt/kernel/tree.h>
46 #include <rtdm/fd.h>
47 #include <rtdm/rtdm.h>
48 
49 /* debug support */
50 #include <cobalt/kernel/assert.h>
51 #include <trace/events/cobalt-rtdm.h>
52 #ifdef CONFIG_PCI
53 #include <asm-generic/xenomai/pci_ids.h>
54 #endif /* CONFIG_PCI */
55 #include <asm/xenomai/syscall.h>
56 
57 struct class;
58 typedef struct xnselector rtdm_selector_t;
59 enum rtdm_selecttype;
60 
73 #define RTDM_EXCLUSIVE 0x0001
74 
80 #define RTDM_FIXED_MINOR 0x0002
81 
83 #define RTDM_NAMED_DEVICE 0x0010
84 
87 #define RTDM_PROTOCOL_DEVICE 0x0020
88 
90 #define RTDM_DEVICE_TYPE_MASK 0x00F0
91 
93 #define RTDM_SECURE_DEVICE 0x80000000
94 
97 #define RTDM_MAX_MINOR 256
98 
113  RTDM_SELECTTYPE_READ = XNSELECT_READ,
114 
116  RTDM_SELECTTYPE_WRITE = XNSELECT_WRITE,
117 
119  RTDM_SELECTTYPE_EXCEPT = XNSELECT_EXCEPT
120 };
137  struct rtdm_fd fd;
138 
142 
144  char dev_private[0];
145 };
146 
147 static inline struct rtdm_dev_context *rtdm_fd_to_context(struct rtdm_fd *fd)
148 {
149  return container_of(fd, struct rtdm_dev_context, fd);
150 }
151 
161 static inline void *rtdm_fd_to_private(struct rtdm_fd *fd)
162 {
163  return &rtdm_fd_to_context(fd)->dev_private[0];
164 }
165 
174 static inline struct rtdm_fd *rtdm_private_to_fd(void *dev_private)
175 {
176  struct rtdm_dev_context *ctx;
177  ctx = container_of(dev_private, struct rtdm_dev_context, dev_private);
178  return &ctx->fd;
179 }
180 
189 static inline bool rtdm_fd_is_user(struct rtdm_fd *fd)
190 {
191  return rtdm_fd_owner(fd) != &cobalt_kernel_ppd;
192 }
193 
202 static inline struct rtdm_device *rtdm_fd_device(struct rtdm_fd *fd)
203 {
204  return rtdm_fd_to_context(fd)->device;
205 }
206 
215 struct rtdm_profile_info {
217  const char *name;
219  int class_id;
222  int subclass_id;
224  int version;
226  unsigned int magic;
227  struct module *owner;
228 };
229 
230 struct rtdm_driver;
231 
235 struct rtdm_sm_ops {
237  int (*start)(struct rtdm_driver *drv);
239  int (*stop)(struct rtdm_driver *drv);
240 };
241 
248 struct rtdm_driver {
254  struct rtdm_profile_info profile_info;
261  size_t context_size;
267  struct rtdm_fd_ops ops;
276  struct {
277  union {
278  struct {
279  struct cdev cdev;
280  int major;
281  } named;
282  };
283  atomic_t refcount;
284  struct notifier_block nb_statechange;
285  DECLARE_BITMAP(minor_map, RTDM_MAX_MINOR);
286  };
287 };
288 
289 #define RTDM_CLASS_MAGIC 0x8284636c
290 
309 #define RTDM_PROFILE_INFO(__name, __id, __subid, __version) \
310 { \
311  .name = ( # __name ), \
312  .class_id = (__id), \
313  .subclass_id = (__subid), \
314  .version = (__version), \
315  .magic = ~RTDM_CLASS_MAGIC, \
316  .owner = THIS_MODULE, \
317 }
318 
325 struct rtdm_device {
329  void *device_data;
341  const char *label;
356  int minor;
358  struct {
359  unsigned int magic;
360  char *name;
361  union {
362  struct {
363  xnhandle_t handle;
364  } named;
365  struct {
366  struct xnid id;
367  } proto;
368  };
369  dev_t rdev;
370  struct device *kdev;
371  atomic_t refcount;
372  struct rtdm_fd_ops ops;
373  wait_queue_head_t putwq;
374  };
375 };
376 
379 /* --- device registration --- */
380 
381 int rtdm_dev_register(struct rtdm_device *device);
382 
383 void rtdm_dev_unregister(struct rtdm_device *device);
384 
385 #ifndef DOXYGEN_CPP /* Avoid static inline tags for RTDM in doxygen */
386 
387 /* --- clock services --- */
388 static inline nanosecs_abs_t rtdm_clock_read(void)
389 {
390  return xnclock_read_realtime(&nkclock);
391 }
392 
393 static inline nanosecs_abs_t rtdm_clock_read_monotonic(void)
394 {
395  return xnclock_read_monotonic(&nkclock);
396 }
397 #endif /* !DOXYGEN_CPP */
398 
399 /* --- timeout sequences */
400 
401 typedef nanosecs_abs_t rtdm_toseq_t;
402 
403 void rtdm_toseq_init(rtdm_toseq_t *timeout_seq, nanosecs_rel_t timeout);
404 
440 #define cobalt_atomic_enter(__context) \
441  do { \
442  xnlock_get_irqsave(&nklock, (__context)); \
443  xnsched_lock(); \
444  } while (0)
445 
458 #define cobalt_atomic_leave(__context) \
459  do { \
460  xnsched_unlock(); \
461  xnlock_put_irqrestore(&nklock, (__context)); \
462  } while (0)
463 
492 #ifdef DOXYGEN_CPP /* Beautify doxygen output */
493 #define RTDM_EXECUTE_ATOMICALLY(code_block) \
494 { \
495  <ENTER_ATOMIC_SECTION> \
496  code_block; \
497  <LEAVE_ATOMIC_SECTION> \
498 }
499 #else /* This is how it really works */
500 static inline __attribute__((deprecated)) void
501 rtdm_execute_atomically(void) { }
502 
503 #define RTDM_EXECUTE_ATOMICALLY(code_block) \
504 { \
505  spl_t __rtdm_s; \
506  \
507  rtdm_execute_atomically(); \
508  xnlock_get_irqsave(&nklock, __rtdm_s); \
509  xnsched_lock(); \
510  code_block; \
511  xnsched_unlock(); \
512  xnlock_put_irqrestore(&nklock, __rtdm_s); \
513 }
514 #endif
515 
526 #define RTDM_LOCK_UNLOCKED(__name) IPIPE_SPIN_LOCK_UNLOCKED
527 
528 #define DEFINE_RTDM_LOCK(__name) \
529  rtdm_lock_t __name = RTDM_LOCK_UNLOCKED(__name)
530 
532 typedef ipipe_spinlock_t rtdm_lock_t;
533 
535 typedef unsigned long rtdm_lockctx_t;
536 
544 static inline void rtdm_lock_init(rtdm_lock_t *lock)
545 {
546  spin_lock_init(lock);
547 }
548 
556 static inline void rtdm_lock_get(rtdm_lock_t *lock)
557 {
558  XENO_BUG_ON(COBALT, !spltest());
559  spin_lock(lock);
560  xnsched_lock();
561 }
562 
570 static inline void rtdm_lock_put(rtdm_lock_t *lock)
571 {
572  spin_unlock(lock);
573  xnsched_unlock();
574 }
575 
584 #define rtdm_lock_get_irqsave(__lock, __context) \
585  ((__context) = __rtdm_lock_get_irqsave(__lock))
586 
587 static inline rtdm_lockctx_t __rtdm_lock_get_irqsave(rtdm_lock_t *lock)
588 {
589  rtdm_lockctx_t context;
590 
591  context = ipipe_test_and_stall_head();
592  spin_lock(lock);
593  xnsched_lock();
594 
595  return context;
596 }
597 
606 static inline
607 void rtdm_lock_put_irqrestore(rtdm_lock_t *lock, rtdm_lockctx_t context)
608 {
609  spin_unlock(lock);
610  xnsched_unlock();
611  ipipe_restore_head(context);
612 }
613 
621 #define rtdm_lock_irqsave(__context) \
622  splhigh(__context)
623 
631 #define rtdm_lock_irqrestore(__context) \
632  splexit(__context)
633 
636 #ifndef DOXYGEN_CPP
637 
638 struct rtdm_waitqueue {
639  struct xnsynch wait;
640 };
641 typedef struct rtdm_waitqueue rtdm_waitqueue_t;
642 
643 #define RTDM_WAITQUEUE_INITIALIZER(__name) { \
644  .wait = XNSYNCH_WAITQUEUE_INITIALIZER((__name).wait), \
645  }
646 
647 #define DEFINE_RTDM_WAITQUEUE(__name) \
648  struct rtdm_waitqueue __name = RTDM_WAITQUEUE_INITIALIZER(__name)
649 
650 #define DEFINE_RTDM_WAITQUEUE_ONSTACK(__name) \
651  DEFINE_RTDM_WAITQUEUE(__name)
652 
653 static inline void rtdm_waitqueue_init(struct rtdm_waitqueue *wq)
654 {
655  *wq = (struct rtdm_waitqueue)RTDM_WAITQUEUE_INITIALIZER(*wq);
656 }
657 
658 static inline void rtdm_waitqueue_destroy(struct rtdm_waitqueue *wq)
659 {
660  xnsynch_destroy(&wq->wait);
661 }
662 
663 static inline int __rtdm_dowait(struct rtdm_waitqueue *wq,
664  nanosecs_rel_t timeout, xntmode_t timeout_mode)
665 {
666  int ret;
667 
668  ret = xnsynch_sleep_on(&wq->wait, timeout, timeout_mode);
669  if (ret & XNBREAK)
670  return -EINTR;
671  if (ret & XNTIMEO)
672  return -ETIMEDOUT;
673  if (ret & XNRMID)
674  return -EIDRM;
675  return 0;
676 }
677 
678 static inline int __rtdm_timedwait(struct rtdm_waitqueue *wq,
679  nanosecs_rel_t timeout, rtdm_toseq_t *toseq)
680 {
681  if (toseq && timeout > 0)
682  return __rtdm_dowait(wq, *toseq, XN_ABSOLUTE);
683 
684  return __rtdm_dowait(wq, timeout, XN_RELATIVE);
685 }
686 
687 #define rtdm_timedwait_condition_locked(__wq, __cond, __timeout, __toseq) \
688  ({ \
689  int __ret = 0; \
690  while (__ret == 0 && !(__cond)) \
691  __ret = __rtdm_timedwait(__wq, __timeout, __toseq); \
692  __ret; \
693  })
694 
695 #define rtdm_wait_condition_locked(__wq, __cond) \
696  ({ \
697  int __ret = 0; \
698  while (__ret == 0 && !(__cond)) \
699  __ret = __rtdm_dowait(__wq, \
700  XN_INFINITE, XN_RELATIVE); \
701  __ret; \
702  })
703 
704 #define rtdm_timedwait_condition(__wq, __cond, __timeout, __toseq) \
705  ({ \
706  spl_t __s; \
707  int __ret; \
708  xnlock_get_irqsave(&nklock, __s); \
709  __ret = rtdm_timedwait_condition_locked(__wq, __cond, \
710  __timeout, __toseq); \
711  xnlock_put_irqrestore(&nklock, __s); \
712  __ret; \
713  })
714 
715 #define rtdm_timedwait(__wq, __timeout, __toseq) \
716  __rtdm_timedwait(__wq, __timeout, __toseq)
717 
718 #define rtdm_timedwait_locked(__wq, __timeout, __toseq) \
719  rtdm_timedwait(__wq, __timeout, __toseq)
720 
721 #define rtdm_wait_condition(__wq, __cond) \
722  ({ \
723  spl_t __s; \
724  int __ret; \
725  xnlock_get_irqsave(&nklock, __s); \
726  __ret = rtdm_wait_condition_locked(__wq, __cond); \
727  xnlock_put_irqrestore(&nklock, __s); \
728  __ret; \
729  })
730 
731 #define rtdm_wait(__wq) \
732  __rtdm_dowait(__wq, XN_INFINITE, XN_RELATIVE)
733 
734 #define rtdm_wait_locked(__wq) rtdm_wait(__wq)
735 
736 #define rtdm_waitqueue_lock(__wq, __context) cobalt_atomic_enter(__context)
737 
738 #define rtdm_waitqueue_unlock(__wq, __context) cobalt_atomic_leave(__context)
739 
740 #define rtdm_waitqueue_signal(__wq) \
741  ({ \
742  struct xnthread *__waiter; \
743  __waiter = xnsynch_wakeup_one_sleeper(&(__wq)->wait); \
744  xnsched_run(); \
745  __waiter != NULL; \
746  })
747 
748 #define __rtdm_waitqueue_flush(__wq, __reason) \
749  ({ \
750  int __ret; \
751  __ret = xnsynch_flush(&(__wq)->wait, __reason); \
752  xnsched_run(); \
753  __ret == XNSYNCH_RESCHED; \
754  })
755 
756 #define rtdm_waitqueue_broadcast(__wq) \
757  __rtdm_waitqueue_flush(__wq, 0)
758 
759 #define rtdm_waitqueue_flush(__wq) \
760  __rtdm_waitqueue_flush(__wq, XNBREAK)
761 
762 #define rtdm_waitqueue_wakeup(__wq, __waiter) \
763  do { \
764  xnsynch_wakeup_this_sleeper(&(__wq)->wait, __waiter); \
765  xnsched_run(); \
766  } while (0)
767 
768 #define rtdm_for_each_waiter(__pos, __wq) \
769  xnsynch_for_each_sleeper(__pos, &(__wq)->wait)
770 
771 #define rtdm_for_each_waiter_safe(__pos, __tmp, __wq) \
772  xnsynch_for_each_sleeper_safe(__pos, __tmp, &(__wq)->wait)
773 
774 #endif /* !DOXYGEN_CPP */
775 
778 /* --- Interrupt management services --- */
784 typedef struct xnintr rtdm_irq_t;
785 
792 #define RTDM_IRQTYPE_SHARED XN_IRQTYPE_SHARED
793 
795 #define RTDM_IRQTYPE_EDGE XN_IRQTYPE_EDGE
796 
805 typedef int (*rtdm_irq_handler_t)(rtdm_irq_t *irq_handle);
806 
813 #define RTDM_IRQ_NONE XN_IRQ_NONE
814 
815 #define RTDM_IRQ_HANDLED XN_IRQ_HANDLED
816 
817 #define RTDM_IRQ_DISABLE XN_IRQ_DISABLE
818 
831 #define rtdm_irq_get_arg(irq_handle, type) ((type *)irq_handle->cookie)
832 
834 int rtdm_irq_request(rtdm_irq_t *irq_handle, unsigned int irq_no,
835  rtdm_irq_handler_t handler, unsigned long flags,
836  const char *device_name, void *arg);
837 
838 #ifndef DOXYGEN_CPP /* Avoid static inline tags for RTDM in doxygen */
839 static inline int rtdm_irq_free(rtdm_irq_t *irq_handle)
840 {
841  if (!XENO_ASSERT(COBALT, xnsched_root_p()))
842  return -EPERM;
843  xnintr_detach(irq_handle);
844  return 0;
845 }
846 
847 static inline int rtdm_irq_enable(rtdm_irq_t *irq_handle)
848 {
849  xnintr_enable(irq_handle);
850  return 0;
851 }
852 
853 static inline int rtdm_irq_disable(rtdm_irq_t *irq_handle)
854 {
855  xnintr_disable(irq_handle);
856  return 0;
857 }
858 #endif /* !DOXYGEN_CPP */
859 
860 /* --- non-real-time signalling services --- */
861 
867 typedef struct rtdm_nrtsig rtdm_nrtsig_t;
878 typedef void (*rtdm_nrtsig_handler_t)(rtdm_nrtsig_t *nrt_sig, void *arg);
879 
880 struct rtdm_nrtsig {
881  rtdm_nrtsig_handler_t handler;
882  void *arg;
883 };
884 
885 void rtdm_schedule_nrt_work(struct work_struct *lostage_work);
888 #ifndef DOXYGEN_CPP /* Avoid static inline tags for RTDM in doxygen */
889 static inline void rtdm_nrtsig_init(rtdm_nrtsig_t *nrt_sig,
890  rtdm_nrtsig_handler_t handler, void *arg)
891 {
892  nrt_sig->handler = handler;
893  nrt_sig->arg = arg;
894 }
895 
896 static inline void rtdm_nrtsig_destroy(rtdm_nrtsig_t *nrt_sig)
897 {
898  nrt_sig->handler = NULL;
899  nrt_sig->arg = NULL;
900 }
901 
902 void rtdm_nrtsig_pend(rtdm_nrtsig_t *nrt_sig);
903 #endif /* !DOXYGEN_CPP */
904 
905 /* --- timer services --- */
906 
912 typedef struct xntimer rtdm_timer_t;
913 
919 typedef void (*rtdm_timer_handler_t)(rtdm_timer_t *timer);
920 
928  RTDM_TIMERMODE_RELATIVE = XN_RELATIVE,
929 
931  RTDM_TIMERMODE_ABSOLUTE = XN_ABSOLUTE,
932 
935 };
940 #ifndef DOXYGEN_CPP /* Avoid broken doxygen output */
941 #define rtdm_timer_init(timer, handler, name) \
942 ({ \
943  xntimer_init((timer), &nkclock, handler, \
944  NULL, XNTIMER_IGRAVITY); \
945  xntimer_set_name((timer), (name)); \
946  0; \
947 })
948 
949 #endif /* !DOXYGEN_CPP */
950 
951 void rtdm_timer_destroy(rtdm_timer_t *timer);
952 
953 int rtdm_timer_start(rtdm_timer_t *timer, nanosecs_abs_t expiry,
954  nanosecs_rel_t interval, enum rtdm_timer_mode mode);
955 
956 void rtdm_timer_stop(rtdm_timer_t *timer);
957 
958 #ifndef DOXYGEN_CPP /* Avoid static inline tags for RTDM in doxygen */
959 static inline int rtdm_timer_start_in_handler(rtdm_timer_t *timer,
960  nanosecs_abs_t expiry,
961  nanosecs_rel_t interval,
962  enum rtdm_timer_mode mode)
963 {
964  return xntimer_start(timer, expiry, interval, (xntmode_t)mode);
965 }
966 
967 static inline void rtdm_timer_stop_in_handler(rtdm_timer_t *timer)
968 {
969  xntimer_stop(timer);
970 }
971 #endif /* !DOXYGEN_CPP */
972 
973 /* --- task services --- */
979 typedef struct xnthread rtdm_task_t;
980 
986 typedef void (*rtdm_task_proc_t)(void *arg);
987 
992 #define RTDM_TASK_LOWEST_PRIORITY 0
993 #define RTDM_TASK_HIGHEST_PRIORITY 99
994 
1000 #define RTDM_TASK_RAISE_PRIORITY (+1)
1001 #define RTDM_TASK_LOWER_PRIORITY (-1)
1002 
1006 int rtdm_task_init(rtdm_task_t *task, const char *name,
1007  rtdm_task_proc_t task_proc, void *arg,
1008  int priority, nanosecs_rel_t period);
1009 int __rtdm_task_sleep(xnticks_t timeout, xntmode_t mode);
1011 
1012 #ifndef DOXYGEN_CPP /* Avoid static inline tags for RTDM in doxygen */
1013 static inline void rtdm_task_destroy(rtdm_task_t *task)
1014 {
1015  xnthread_cancel(task);
1016  xnthread_join(task, true);
1017 }
1018 
1019 static inline int rtdm_task_should_stop(void)
1020 {
1021  return xnthread_test_info(xnthread_current(), XNCANCELD);
1022 }
1023 
1024 void rtdm_task_join(rtdm_task_t *task);
1025 
1026 static inline void __deprecated rtdm_task_join_nrt(rtdm_task_t *task,
1027  unsigned int poll_delay)
1028 {
1029  rtdm_task_join(task);
1030 }
1031 
1032 static inline void rtdm_task_set_priority(rtdm_task_t *task, int priority)
1033 {
1034  union xnsched_policy_param param = { .rt = { .prio = priority } };
1035  xnthread_set_schedparam(task, &xnsched_class_rt, &param);
1036  xnsched_run();
1037 }
1038 
1039 static inline int rtdm_task_set_period(rtdm_task_t *task,
1040  nanosecs_abs_t start_date,
1041  nanosecs_rel_t period)
1042 {
1043  if (period < 0)
1044  period = 0;
1045  if (start_date == 0)
1046  start_date = XN_INFINITE;
1047 
1048  return xnthread_set_periodic(task, start_date, XN_ABSOLUTE, period);
1049 }
1050 
1051 static inline int rtdm_task_unblock(rtdm_task_t *task)
1052 {
1053  int res = xnthread_unblock(task);
1054 
1055  xnsched_run();
1056  return res;
1057 }
1058 
1059 static inline rtdm_task_t *rtdm_task_current(void)
1060 {
1061  return xnthread_current();
1062 }
1063 
1064 static inline int rtdm_task_wait_period(unsigned long *overruns_r)
1065 {
1066  if (!XENO_ASSERT(COBALT, !xnsched_unblockable_p()))
1067  return -EPERM;
1068  return xnthread_wait_period(overruns_r);
1069 }
1070 
1071 static inline int rtdm_task_sleep(nanosecs_rel_t delay)
1072 {
1073  return __rtdm_task_sleep(delay, XN_RELATIVE);
1074 }
1075 
1076 static inline int
1077 rtdm_task_sleep_abs(nanosecs_abs_t wakeup_date, enum rtdm_timer_mode mode)
1078 {
1079  /* For the sake of a consistent API usage... */
1080  if (mode != RTDM_TIMERMODE_ABSOLUTE && mode != RTDM_TIMERMODE_REALTIME)
1081  return -EINVAL;
1082  return __rtdm_task_sleep(wakeup_date, (xntmode_t)mode);
1083 }
1084 
1085 /* rtdm_task_sleep_abs shall be used instead */
1086 static inline int __deprecated rtdm_task_sleep_until(nanosecs_abs_t wakeup_time)
1087 {
1088  return __rtdm_task_sleep(wakeup_time, XN_REALTIME);
1089 }
1090 
1091 #define rtdm_task_busy_wait(__condition, __spin_ns, __sleep_ns) \
1092  ({ \
1093  __label__ done; \
1094  nanosecs_abs_t __end; \
1095  int __ret = 0; \
1096  for (;;) { \
1097  __end = rtdm_clock_read_monotonic() + __spin_ns; \
1098  for (;;) { \
1099  if (__condition) \
1100  goto done; \
1101  if (rtdm_clock_read_monotonic() >= __end) \
1102  break; \
1103  } \
1104  __ret = rtdm_task_sleep(__sleep_ns); \
1105  if (__ret) \
1106  break; \
1107  } \
1108  done: \
1109  __ret; \
1110  })
1111 
1112 #endif /* !DOXYGEN_CPP */
1113 
1114 /* --- event services --- */
1115 
1116 typedef struct rtdm_event {
1117  struct xnsynch synch_base;
1118  DECLARE_XNSELECT(select_block);
1119 } rtdm_event_t;
1120 
1121 #define RTDM_EVENT_PENDING XNSYNCH_SPARE1
1122 
1123 void rtdm_event_init(rtdm_event_t *event, unsigned long pending);
1124 int rtdm_event_select(rtdm_event_t *event, rtdm_selector_t *selector,
1125  enum rtdm_selecttype type, unsigned fd_index);
1126 int rtdm_event_wait(rtdm_event_t *event);
1127 int rtdm_event_timedwait(rtdm_event_t *event, nanosecs_rel_t timeout,
1128  rtdm_toseq_t *timeout_seq);
1129 void rtdm_event_signal(rtdm_event_t *event);
1130 
1131 void rtdm_event_clear(rtdm_event_t *event);
1132 
1133 void rtdm_event_pulse(rtdm_event_t *event);
1134 
1135 void rtdm_event_destroy(rtdm_event_t *event);
1136 
1137 /* --- semaphore services --- */
1138 
1139 typedef struct rtdm_sem {
1140  unsigned long value;
1141  struct xnsynch synch_base;
1142  DECLARE_XNSELECT(select_block);
1143 } rtdm_sem_t;
1144 
1145 void rtdm_sem_init(rtdm_sem_t *sem, unsigned long value);
1146 int rtdm_sem_select(rtdm_sem_t *sem, rtdm_selector_t *selector,
1147  enum rtdm_selecttype type, unsigned fd_index);
1148 int rtdm_sem_down(rtdm_sem_t *sem);
1149 int rtdm_sem_timeddown(rtdm_sem_t *sem, nanosecs_rel_t timeout,
1150  rtdm_toseq_t *timeout_seq);
1151 void rtdm_sem_up(rtdm_sem_t *sem);
1152 
1153 void rtdm_sem_destroy(rtdm_sem_t *sem);
1154 
1155 /* --- mutex services --- */
1156 
1157 typedef struct rtdm_mutex {
1158  struct xnsynch synch_base;
1159  atomic_t fastlock;
1160 } rtdm_mutex_t;
1161 
1162 void rtdm_mutex_init(rtdm_mutex_t *mutex);
1163 int rtdm_mutex_lock(rtdm_mutex_t *mutex);
1164 int rtdm_mutex_timedlock(rtdm_mutex_t *mutex, nanosecs_rel_t timeout,
1165  rtdm_toseq_t *timeout_seq);
1166 void rtdm_mutex_unlock(rtdm_mutex_t *mutex);
1167 void rtdm_mutex_destroy(rtdm_mutex_t *mutex);
1168 
1169 /* --- utility functions --- */
1170 
1171 #define rtdm_printk(format, ...) printk(format, ##__VA_ARGS__)
1172 
1173 struct rtdm_ratelimit_state {
1174  rtdm_lock_t lock; /* protect the state */
1175  nanosecs_abs_t interval;
1176  int burst;
1177  int printed;
1178  int missed;
1179  nanosecs_abs_t begin;
1180 };
1181 
1182 int rtdm_ratelimit(struct rtdm_ratelimit_state *rs, const char *func);
1183 
1184 #define DEFINE_RTDM_RATELIMIT_STATE(name, interval_init, burst_init) \
1185  struct rtdm_ratelimit_state name = { \
1186  .lock = RTDM_LOCK_UNLOCKED((name).lock), \
1187  .interval = interval_init, \
1188  .burst = burst_init, \
1189  }
1190 
1191 /* We use the Linux defaults */
1192 #define DEF_RTDM_RATELIMIT_INTERVAL 5000000000LL
1193 #define DEF_RTDM_RATELIMIT_BURST 10
1194 
1195 #define rtdm_printk_ratelimited(fmt, ...) ({ \
1196  static DEFINE_RTDM_RATELIMIT_STATE(_rs, \
1197  DEF_RTDM_RATELIMIT_INTERVAL, \
1198  DEF_RTDM_RATELIMIT_BURST); \
1199  \
1200  if (rtdm_ratelimit(&_rs, __func__)) \
1201  printk(fmt, ##__VA_ARGS__); \
1202 })
1203 
1204 #ifndef DOXYGEN_CPP /* Avoid static inline tags for RTDM in doxygen */
1205 static inline void *rtdm_malloc(size_t size)
1206 {
1207  return xnmalloc(size);
1208 }
1209 
1210 static inline void rtdm_free(void *ptr)
1211 {
1212  xnfree(ptr);
1213 }
1214 
1215 int rtdm_mmap_to_user(struct rtdm_fd *fd,
1216  void *src_addr, size_t len,
1217  int prot, void **pptr,
1218  struct vm_operations_struct *vm_ops,
1219  void *vm_private_data);
1220 
1221 int rtdm_iomap_to_user(struct rtdm_fd *fd,
1222  phys_addr_t src_addr, size_t len,
1223  int prot, void **pptr,
1224  struct vm_operations_struct *vm_ops,
1225  void *vm_private_data);
1226 
1227 int rtdm_mmap_kmem(struct vm_area_struct *vma, void *va);
1228 
1229 int rtdm_mmap_vmem(struct vm_area_struct *vma, void *va);
1230 
1231 int rtdm_mmap_iomem(struct vm_area_struct *vma, phys_addr_t pa);
1232 
1233 int rtdm_munmap(void *ptr, size_t len);
1234 
1235 static inline int rtdm_read_user_ok(struct rtdm_fd *fd,
1236  const void __user *ptr, size_t size)
1237 {
1238  return access_rok(ptr, size);
1239 }
1240 
1241 static inline int rtdm_rw_user_ok(struct rtdm_fd *fd,
1242  const void __user *ptr, size_t size)
1243 {
1244  return access_wok(ptr, size);
1245 }
1246 
1247 static inline int rtdm_copy_from_user(struct rtdm_fd *fd,
1248  void *dst, const void __user *src,
1249  size_t size)
1250 {
1251  return __xn_copy_from_user(dst, src, size) ? -EFAULT : 0;
1252 }
1253 
1254 static inline int rtdm_safe_copy_from_user(struct rtdm_fd *fd,
1255  void *dst, const void __user *src,
1256  size_t size)
1257 {
1258  return cobalt_copy_from_user(dst, src, size);
1259 }
1260 
1261 static inline int rtdm_copy_to_user(struct rtdm_fd *fd,
1262  void __user *dst, const void *src,
1263  size_t size)
1264 {
1265  return __xn_copy_to_user(dst, src, size) ? -EFAULT : 0;
1266 }
1267 
1268 static inline int rtdm_safe_copy_to_user(struct rtdm_fd *fd,
1269  void __user *dst, const void *src,
1270  size_t size)
1271 {
1272  return cobalt_copy_to_user(dst, src, size);
1273 }
1274 
1275 static inline int rtdm_strncpy_from_user(struct rtdm_fd *fd,
1276  char *dst,
1277  const char __user *src, size_t count)
1278 {
1279  return cobalt_strncpy_from_user(dst, src, count);
1280 }
1281 
1282 static inline int rtdm_rt_capable(struct rtdm_fd *fd)
1283 {
1284  if (!XENO_ASSERT(COBALT, !xnsched_interrupt_p()))
1285  return 0;
1286 
1287  if (!rtdm_fd_is_user(fd))
1288  return !xnsched_root_p();
1289 
1290  return xnthread_current() != NULL;
1291 }
1292 
1293 static inline int rtdm_in_rt_context(void)
1294 {
1295  return (ipipe_current_domain != ipipe_root_domain);
1296 }
1297 
1298 #endif /* !DOXYGEN_CPP */
1299 
1300 #endif /* _COBALT_RTDM_DRIVER_H */
void(* rtdm_task_proc_t)(void *arg)
Real-time task procedure.
Definition: driver.h:986
static void rtdm_lock_put_irqrestore(rtdm_lock_t *lock, rtdm_lockctx_t context)
Release lock and restore preemption state.
Definition: driver.h:607
void rtdm_mutex_destroy(rtdm_mutex_t *mutex)
Destroy a mutex.
Definition: drvlib.c:1177
struct rtdm_fd_ops ops
I/O operation handlers.
Definition: driver.h:267
void rtdm_task_busy_sleep(nanosecs_rel_t delay)
Busy-wait a specified amount of time.
Definition: drvlib.c:400
int rtdm_nrtsig_init(rtdm_nrtsig_t *nrt_sig, rtdm_nrtsig_handler_t handler, void *arg)
Register a non-real-time signal handler.
int socket_type
Protocol device identification: socket type (SOCK_xxx)
Definition: driver.h:265
void xnintr_enable(struct xnintr *intr)
Enable an interrupt line.
Definition: intr.c:892
void rtdm_mutex_unlock(rtdm_mutex_t *mutex)
Release a mutex.
Definition: drvlib.c:1195
void(* rtdm_nrtsig_handler_t)(rtdm_nrtsig_t *nrt_sig, void *arg)
Non-real-time signal handler.
Definition: driver.h:878
void xnintr_detach(struct xnintr *intr)
Detach an interrupt descriptor.
Definition: intr.c:866
Select ouput buffer availability events.
Definition: driver.h:116
ipipe_spinlock_t rtdm_lock_t
Lock variable.
Definition: driver.h:532
void xnthread_cancel(struct xnthread *thread)
Cancel a thread.
Definition: thread.c:1528
#define XNCANCELD
Cancellation request is pending.
Definition: thread.h:72
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_munmap(void *ptr, size_t len)
Unmap a user memory range.
Definition: drvlib.c:2017
int rtdm_task_sleep_abs(nanosecs_abs_t wakeup_time, enum rtdm_timer_mode mode)
Sleep until a specified absolute time.
static void * rtdm_fd_to_private(struct rtdm_fd *fd)
Locate the driver private area associated to a device context structure.
Definition: driver.h:161
static void rtdm_lock_put(rtdm_lock_t *lock)
Release lock without preemption restoration.
Definition: driver.h:570
int64_t nanosecs_rel_t
RTDM type for representing relative intervals.
Definition: rtdm.h:49
struct rtdm_profile_info profile_info
Class profile information.
Definition: driver.h:254
Adjustable timer with absolute timeout.
Definition: driver.h:934
void rtdm_timer_stop_in_handler(rtdm_timer_t *timer)
Stop a timer from inside a timer handler.
RTDM file operation descriptor.
Definition: fd.h:243
int(* rtdm_irq_handler_t)(rtdm_irq_t *irq_handle)
Interrupt handler.
Definition: driver.h:805
char dev_private[0]
Begin of driver defined context data structure.
Definition: driver.h:144
int rtdm_ratelimit(struct rtdm_ratelimit_state *rs, const char *func)
Enforces a rate limit.
Definition: drvlib.c:2039
void xnintr_disable(struct xnintr *intr)
Disable an interrupt line.
Definition: intr.c:923
size_t context_size
Size of driver defined appendix to struct rtdm_dev_context.
Definition: driver.h:261
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:473
int rtdm_dev_register(struct rtdm_device *device)
Register a RTDM device.
Definition: device.c:360
#define XNTIMEO
Woken up due to a timeout condition.
Definition: thread.h:66
void rtdm_task_join(rtdm_task_t *task)
Wait on a real-time task to terminate.
Definition: drvlib.c:377
int(* start)(struct rtdm_driver *drv)
Handler called upon transition to COBALT_STATE_WARMUP.
Definition: driver.h:237
Select exceptional events.
Definition: driver.h:119
int rtdm_sem_select(rtdm_sem_t *sem, rtdm_selector_t *selector, enum rtdm_selecttype type, unsigned int fd_index)
Bind a selector to a semaphore.
Definition: drvlib.c:1115
void * device_data
Driver definable device data.
Definition: driver.h:329
static struct rtdm_device * rtdm_fd_device(struct rtdm_fd *fd)
Locate a device structure from a file descriptor.
Definition: driver.h:202
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.
void * rtdm_malloc(size_t size)
Allocate memory block.
int rtdm_task_sleep(nanosecs_rel_t delay)
Sleep a specified amount of time.
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:1340
void rtdm_timer_destroy(rtdm_timer_t *timer)
Destroy a timer.
Definition: drvlib.c:443
int rtdm_event_wait(rtdm_event_t *event)
Wait on event occurrence.
Definition: drvlib.c:743
int rtdm_mutex_lock(rtdm_mutex_t *mutex)
Request a mutex.
Definition: drvlib.c:1225
void rtdm_event_pulse(rtdm_event_t *event)
Signal an event occurrence to currently listening waiters.
Definition: drvlib.c:683
#define spltest()
Test hard interrupt state on the local processor.
Definition: lock.h:64
Monotonic timer with absolute timeout.
Definition: driver.h:931
void rtdm_toseq_init(rtdm_toseq_t *timeout_seq, nanosecs_rel_t timeout)
Initialise a timeout sequence.
Definition: drvlib.c:613
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:1014
rtdm_task_t * rtdm_task_current(void)
Get current real-time task.
void rtdm_nrtsig_pend(rtdm_nrtsig_t *nrt_sig)
Trigger non-real-time signal.
Definition: drvlib.c:1488
int xnsynch_destroy(struct xnsynch *synch)
Destroy a synchronization object.
Definition: synch.c:117
static struct xnthread * xnthread_current(void)
Retrieve the current Cobalt core TCB.
Definition: thread.h:371
int rtdm_irq_enable(rtdm_irq_t *irq_handle)
Enable interrupt line.
static bool rtdm_fd_is_user(struct rtdm_fd *fd)
Tell whether the passed file descriptor belongs to an application.
Definition: driver.h:189
void rtdm_waitqueue_destroy(struct rtdm_waitqueue *wq)
Deletes a RTDM wait queue.
const char * label
Device label template for composing the device name.
Definition: driver.h:341
RTDM state management handlers.
Definition: driver.h:235
int rtdm_event_select(rtdm_event_t *event, rtdm_selector_t *selector, enum rtdm_selecttype type, unsigned int fd_index)
Bind a selector to an event.
Definition: drvlib.c:882
int xnthread_wait_period(unsigned long *overruns_r)
Wait for the next periodic release point.
Definition: thread.c:1393
uint64_t nanosecs_abs_t
RTDM type for representing absolute dates.
Definition: rtdm.h:43
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.
void rtdm_dev_unregister(struct rtdm_device *device)
Unregister a RTDM device.
Definition: device.c:495
void rtdm_timer_stop(rtdm_timer_t *timer)
Stop a timer.
Definition: drvlib.c:495
int xntimer_start(struct xntimer *timer, xnticks_t value, xnticks_t interval, xntmode_t mode)
Arm a timer.
Definition: timer.c:113
static void rtdm_lock_init(rtdm_lock_t *lock)
Dynamic lock initialisation.
Definition: driver.h:544
int rtdm_irq_disable(rtdm_irq_t *irq_handle)
Disable interrupt line.
rtdm_selecttype
Definition: driver.h:111
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.
void rtdm_event_destroy(rtdm_event_t *event)
Destroy an event.
Definition: drvlib.c:664
int rtdm_task_wait_period(unsigned long *overruns_r)
Wait on next real-time task period.
void rtdm_sem_init(rtdm_sem_t *sem, unsigned long value)
Initialise a semaphore.
Definition: drvlib.c:923
Select input data availability events.
Definition: driver.h:113
nanosecs_abs_t rtdm_clock_read(void)
Get system time.
int xnthread_set_periodic(struct xnthread *thread, xnticks_t idate, xntmode_t timeout_mode, xnticks_t period)
Make a thread periodic.
Definition: thread.c:1299
int device_flags
Device flags, see Device Flags for details.
Definition: driver.h:259
struct rtdm_driver * driver
Device driver.
Definition: driver.h:327
int rtdm_task_unblock(rtdm_task_t *task)
Activate a blocked real-time task.
struct rtdm_device * device
Set of active device operation handlers.
Definition: driver.h:141
void rtdm_event_signal(rtdm_event_t *event)
Signal an event occurrence.
Definition: drvlib.c:701
int xnsynch_sleep_on(struct xnsynch *synch, xnticks_t timeout, xntmode_t timeout_mode)
Sleep on an ownerless synchronization object.
Definition: synch.c:162
void rtdm_mutex_init(rtdm_mutex_t *mutex)
Initialise a mutex.
Definition: drvlib.c:1159
nanosecs_abs_t rtdm_clock_read_monotonic(void)
Get monotonic time.
int rtdm_rt_capable(struct rtdm_fd *fd)
Test if the caller is capable of running in real-time context.
#define XNBREAK
Forcibly awaken from a wait state.
Definition: thread.h:68
Copyright © 2011 Gilles Chanteperdrix gilles.chanteperdrix@xenomai.org.
Definition: atomic.h:24
int rtdm_task_sleep_until(nanosecs_abs_t wakeup_time)
Sleep until a specified absolute time.
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...
static void xntimer_stop(struct xntimer *timer)
Disarm a timer.
Definition: timer.h:465
int rtdm_irq_free(rtdm_irq_t *irq_handle)
Release an interrupt handler.
int xnthread_unblock(struct xnthread *thread)
Unblock a thread.
Definition: thread.c:1208
int device_count
Count of devices this driver manages.
Definition: driver.h:274
void rtdm_event_init(rtdm_event_t *event, unsigned long pending)
Initialise an event.
Definition: drvlib.c:638
void rtdm_free(void *ptr)
Release real-time memory block.
int rtdm_mmap_vmem(struct vm_area_struct *vma, void *va)
Map a virtual memory range to a virtual user area.
Definition: drvlib.c:1968
int xnthread_join(struct xnthread *thread, bool uninterruptible)
Join with a terminated thread.
Definition: thread.c:1657
int rtdm_in_rt_context(void)
Test if running in a real-time task.
int rtdm_task_should_stop(void)
Check for pending termination request.
rtdm_timer_mode
Definition: driver.h:926
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_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_task_set_priority(rtdm_task_t *task, int priority)
Adjust real-time task priority.
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:1519
void rtdm_waitqueue_init(struct rtdm_waitqueue *wq)
Initialize a RTDM wait queue.
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:781
void rtdm_task_destroy(rtdm_task_t *task)
Destroy a real-time task.
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:1259
#define XNRMID
Pending on a removed resource.
Definition: thread.h:67
int protocol_family
Protocol device identification: protocol family (PF_xxx)
Definition: driver.h:263
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:1830
Device context.
Definition: driver.h:136
static int xnsched_run(void)
The rescheduling procedure.
Definition: sched.h:291
void rtdm_sem_destroy(rtdm_sem_t *sem)
Destroy a semaphore.
Definition: drvlib.c:948
void rtdm_sem_up(rtdm_sem_t *sem)
Increment a semaphore.
Definition: drvlib.c:1073
Monotonic timer with relative timeout.
Definition: driver.h:928
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:1899
#define RTDM_MAX_MINOR
Maximum number of named devices per driver.
Definition: driver.h:97
struct rtdm_sm_ops smops
State management handlers.
Definition: driver.h:269
RTDM device.
Definition: driver.h:325
void(* rtdm_timer_handler_t)(rtdm_timer_t *timer)
Timer handler.
Definition: driver.h:919
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:1943
int minor
Minor number of the device.
Definition: driver.h:356
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:1907
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:174
int rtdm_sem_down(rtdm_sem_t *sem)
Decrement a semaphore.
Definition: drvlib.c:976
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:107
unsigned long rtdm_lockctx_t
Variable to save the context while holding a lock.
Definition: driver.h:535
void rtdm_event_clear(rtdm_event_t *event)
Clear event state.
Definition: drvlib.c:844
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.
RTDM driver.
Definition: driver.h:248
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:1996
int(* stop)(struct rtdm_driver *drv)
Handler called upon transition to COBALT_STATE_TEARDOWN.
Definition: driver.h:239
static void rtdm_lock_get(rtdm_lock_t *lock)
Acquire lock from non-preemptible contexts.
Definition: driver.h:556
void rtdm_nrtsig_destroy(rtdm_nrtsig_t *nrt_sig)
Release a non-realtime signal handler.
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.