Xenomai  3.0-rc3
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 
110  RTDM_SELECTTYPE_READ = XNSELECT_READ,
111 
113  RTDM_SELECTTYPE_WRITE = XNSELECT_WRITE,
114 
116  RTDM_SELECTTYPE_EXCEPT = XNSELECT_EXCEPT
117 };
134  struct rtdm_fd fd;
135 
139 
141  char dev_private[0];
142 };
143 
144 static inline struct rtdm_dev_context *rtdm_fd_to_context(struct rtdm_fd *fd)
145 {
146  return container_of(fd, struct rtdm_dev_context, fd);
147 }
148 
158 static inline void *rtdm_fd_to_private(struct rtdm_fd *fd)
159 {
160  return &rtdm_fd_to_context(fd)->dev_private[0];
161 }
162 
171 static inline struct rtdm_fd *rtdm_private_to_fd(void *dev_private)
172 {
173  struct rtdm_dev_context *ctx;
174  ctx = container_of(dev_private, struct rtdm_dev_context, dev_private);
175  return &ctx->fd;
176 }
177 
186 static inline bool rtdm_fd_is_user(struct rtdm_fd *fd)
187 {
188  return rtdm_fd_owner(fd) != &__xnsys_global_ppd;
189 }
190 
199 static inline struct rtdm_device *rtdm_fd_device(struct rtdm_fd *fd)
200 {
201  return rtdm_fd_to_context(fd)->device;
202 }
203 
212 struct rtdm_profile_info {
214  const char *name;
216  int class_id;
219  int subclass_id;
221  int version;
223  unsigned int magic;
224  struct module *owner;
225 };
226 
227 struct rtdm_driver;
228 
232 struct rtdm_sm_ops {
234  int (*start)(struct rtdm_driver *drv);
236  int (*stop)(struct rtdm_driver *drv);
237 };
238 
245 struct rtdm_driver {
251  struct rtdm_profile_info profile_info;
258  size_t context_size;
264  struct rtdm_fd_ops ops;
273  struct {
274  union {
275  struct {
276  struct cdev cdev;
277  int major;
278  } named;
279  };
280  atomic_t refcount;
281  struct notifier_block nb_statechange;
282  };
283 };
284 
285 #define RTDM_CLASS_MAGIC 0x8284636c
286 
305 #define RTDM_PROFILE_INFO(__name, __id, __subid, __version) \
306 { \
307  .name = ( # __name ), \
308  .class_id = (__id), \
309  .subclass_id = (__subid), \
310  .version = (__version), \
311  .magic = ~RTDM_CLASS_MAGIC, \
312  .owner = THIS_MODULE, \
313 }
314 
321 struct rtdm_device {
325  void *device_data;
337  const char *label;
352  int minor;
354  struct {
355  unsigned int magic;
356  char *name;
357  union {
358  struct {
359  xnhandle_t handle;
360  } named;
361  struct {
362  struct xnid id;
363  } proto;
364  };
365  dev_t rdev;
366  struct device *kdev;
367  atomic_t refcount;
368  struct rtdm_fd_ops ops;
369  wait_queue_head_t putwq;
370  };
371 };
372 
375 /* --- device registration --- */
376 
377 int rtdm_dev_register(struct rtdm_device *device);
378 
379 void rtdm_dev_unregister(struct rtdm_device *device);
380 
381 #ifndef DOXYGEN_CPP /* Avoid static inline tags for RTDM in doxygen */
382 
383 /* --- clock services --- */
384 static inline nanosecs_abs_t rtdm_clock_read(void)
385 {
386  return xnclock_read_realtime(&nkclock);
387 }
388 
389 static inline nanosecs_abs_t rtdm_clock_read_monotonic(void)
390 {
391  return xnclock_read_monotonic(&nkclock);
392 }
393 #endif /* !DOXYGEN_CPP */
394 
395 /* --- timeout sequences */
396 
397 typedef nanosecs_abs_t rtdm_toseq_t;
398 
399 void rtdm_toseq_init(rtdm_toseq_t *timeout_seq, nanosecs_rel_t timeout);
400 
436 #define cobalt_atomic_enter(context) \
437  do { \
438  xnlock_get_irqsave(&nklock, (context)); \
439  __xnsched_lock(); \
440  } while (0)
441 
454 #define cobalt_atomic_leave(context) \
455  do { \
456  __xnsched_unlock(); \
457  xnlock_put_irqrestore(&nklock, (context)); \
458  } while (0)
459 
488 #ifdef DOXYGEN_CPP /* Beautify doxygen output */
489 #define RTDM_EXECUTE_ATOMICALLY(code_block) \
490 { \
491  <ENTER_ATOMIC_SECTION> \
492  code_block; \
493  <LEAVE_ATOMIC_SECTION> \
494 }
495 #else /* This is how it really works */
496 static inline __attribute__((deprecated)) void
497 rtdm_execute_atomically(void) { }
498 
499 #define RTDM_EXECUTE_ATOMICALLY(code_block) \
500 { \
501  spl_t __rtdm_s; \
502  \
503  rtdm_execute_atomically(); \
504  xnlock_get_irqsave(&nklock, __rtdm_s); \
505  __xnsched_lock(); \
506  code_block; \
507  __xnsched_unlock(); \
508  xnlock_put_irqrestore(&nklock, __rtdm_s); \
509 }
510 #endif
511 
522 #define RTDM_LOCK_UNLOCKED(__name) IPIPE_SPIN_LOCK_UNLOCKED
523 
524 #define DEFINE_RTDM_LOCK(__name) \
525  rtdm_lock_t __name = RTDM_LOCK_UNLOCKED(__name)
526 
528 typedef ipipe_spinlock_t rtdm_lock_t;
529 
531 typedef unsigned long rtdm_lockctx_t;
532 
540 static inline void rtdm_lock_init(rtdm_lock_t *lock)
541 {
542  spin_lock_init(lock);
543 }
544 
552 static inline void rtdm_lock_get(rtdm_lock_t *lock)
553 {
554  XENO_BUGON(COBALT, !spltest());
555  spin_lock(lock);
556  __xnsched_lock();
557 }
558 
566 static inline void rtdm_lock_put(rtdm_lock_t *lock)
567 {
568  spin_unlock(lock);
569  __xnsched_unlock();
570 }
571 
581 static inline rtdm_lockctx_t __rtdm_lock_get_irqsave(rtdm_lock_t *lock)
582 {
583  rtdm_lockctx_t context;
584 
585  context = ipipe_test_and_stall_head();
586  spin_lock(lock);
587  __xnsched_lock();
588 
589  return context;
590 }
591 #define rtdm_lock_get_irqsave(__lock, __context) \
592  ((__context) = __rtdm_lock_get_irqsave(__lock))
593 
602 static inline
603 void rtdm_lock_put_irqrestore(rtdm_lock_t *lock, rtdm_lockctx_t context)
604 {
605  spin_unlock(lock);
606  __xnsched_unlock();
607  ipipe_restore_head(context);
608 }
609 
617 #define rtdm_lock_irqsave(context) \
618  splhigh(context)
619 
627 #define rtdm_lock_irqrestore(context) \
628  splexit(context)
629 
632 #ifndef DOXYGEN_CPP
633 
634 struct rtdm_waitqueue {
635  struct xnsynch wait;
636 };
637 typedef struct rtdm_waitqueue rtdm_waitqueue_t;
638 
639 #define RTDM_WAITQUEUE_INITIALIZER(__name) { \
640  .wait = XNSYNCH_WAITQUEUE_INITIALIZER((__name).wait), \
641  }
642 
643 #define DEFINE_RTDM_WAITQUEUE(__name) \
644  struct rtdm_waitqueue __name = RTDM_WAITQUEUE_INITIALIZER(__name)
645 
646 #define DEFINE_RTDM_WAITQUEUE_ONSTACK(__name) \
647  DEFINE_RTDM_WAITQUEUE(__name)
648 
649 static inline void rtdm_waitqueue_init(struct rtdm_waitqueue *wq)
650 {
651  *wq = (struct rtdm_waitqueue)RTDM_WAITQUEUE_INITIALIZER(*wq);
652 }
653 
654 static inline void rtdm_waitqueue_destroy(struct rtdm_waitqueue *wq)
655 {
656  xnsynch_destroy(&wq->wait);
657 }
658 
659 static inline int __rtdm_timedwait(struct rtdm_waitqueue *wq,
660  nanosecs_rel_t timeout, rtdm_toseq_t *toseq)
661 {
662  if (toseq && timeout > 0)
663  return xnsynch_sleep_on(&wq->wait, *toseq, XN_ABSOLUTE);
664 
665  return xnsynch_sleep_on(&wq->wait, timeout, XN_RELATIVE);
666 }
667 
668 #define rtdm_timedwait_condition_locked(__wq, __cond, __timeout, __toseq) \
669  ({ \
670  int __ret = 0; \
671  while (__ret == 0 && !(__cond)) \
672  __ret = __rtdm_timedwait(__wq, __timeout, __toseq); \
673  __ret; \
674  })
675 
676 #define rtdm_wait_condition_locked(__wq, __cond) \
677  ({ \
678  int __ret = 0; \
679  while (__ret == 0 && !(__cond)) \
680  __ret = xnsynch_sleep_on(&(__wq)->wait, \
681  XN_INFINITE, XN_RELATIVE); \
682  __ret; \
683  })
684 
685 #define rtdm_timedwait_condition(__wq, __cond, __timeout, __toseq) \
686  ({ \
687  spl_t __s; \
688  int __ret; \
689  xnlock_get_irqsave(&nklock, __s); \
690  __ret = rtdm_timedwait_condition_locked(__wq, __cond, \
691  __timeout, __toseq); \
692  xnlock_put_irqrestore(&nklock, __s); \
693  __ret; \
694  })
695 
696 #define rtdm_timedwait(__wq, __timeout, __toseq) \
697  __rtdm_timedwait(__wq, __timeout, __toseq)
698 
699 #define rtdm_timedwait_locked(__wq, __timeout, __toseq) \
700  rtdm_timedwait(__wq, __timeout, __toseq)
701 
702 #define rtdm_wait_condition(__wq, __cond) \
703  ({ \
704  spl_t __s; \
705  int __ret; \
706  xnlock_get_irqsave(&nklock, __s); \
707  __ret = rtdm_wait_condition_locked(__wq, __cond); \
708  xnlock_put_irqrestore(&nklock, __s); \
709  __ret; \
710  })
711 
712 #define rtdm_wait(__wq) \
713  xnsynch_sleep_on(&(__wq)->wait, XN_INFINITE, XN_RELATIVE)
714 
715 #define rtdm_wait_locked(__wq) rtdm_wait(__wq)
716 
717 #define rtdm_waitqueue_lock(__wq, __context) cobalt_atomic_enter(__context)
718 
719 #define rtdm_waitqueue_unlock(__wq, __context) cobalt_atomic_leave(__context)
720 
721 #define rtdm_waitqueue_signal(__wq) \
722  ({ \
723  struct xnthread *__waiter; \
724  __waiter = xnsynch_wakeup_one_sleeper(&(__wq)->wait); \
725  xnsched_run(); \
726  __waiter != NULL; \
727  })
728 
729 #define __rtdm_waitqueue_flush(__wq, __reason) \
730  ({ \
731  int __ret; \
732  __ret = xnsynch_flush(&(__wq)->wait, __reason); \
733  xnsched_run(); \
734  __ret == XNSYNCH_RESCHED; \
735  })
736 
737 #define rtdm_waitqueue_broadcast(__wq) \
738  __rtdm_waitqueue_flush(__wq, 0)
739 
740 #define rtdm_waitqueue_flush(__wq) \
741  __rtdm_waitqueue_flush(__wq, XNBREAK)
742 
743 #define rtdm_waitqueue_wakeup(__wq, __waiter) \
744  do { \
745  xnsynch_wakeup_this_sleeper(&(__wq)->wait, __waiter); \
746  xnsched_run(); \
747  } while (0)
748 
749 #define rtdm_for_each_waiter(__pos, __wq) \
750  xnsynch_for_each_sleeper(__pos, &(__wq)->wait)
751 
752 #define rtdm_for_each_waiter_safe(__pos, __tmp, __wq) \
753  xnsynch_for_each_sleeper_safe(__pos, __tmp, &(__wq)->wait)
754 
755 #endif /* !DOXYGEN_CPP */
756 
759 /* --- Interrupt management services --- */
765 typedef struct xnintr rtdm_irq_t;
766 
773 #define RTDM_IRQTYPE_SHARED XN_IRQTYPE_SHARED
774 
776 #define RTDM_IRQTYPE_EDGE XN_IRQTYPE_EDGE
777 
786 typedef int (*rtdm_irq_handler_t)(rtdm_irq_t *irq_handle);
787 
794 #define RTDM_IRQ_NONE XN_IRQ_NONE
795 
796 #define RTDM_IRQ_HANDLED XN_IRQ_HANDLED
797 
798 #define RTDM_IRQ_DISABLE XN_IRQ_DISABLE
799 
812 #define rtdm_irq_get_arg(irq_handle, type) ((type *)irq_handle->cookie)
813 
815 int rtdm_irq_request(rtdm_irq_t *irq_handle, unsigned int irq_no,
816  rtdm_irq_handler_t handler, unsigned long flags,
817  const char *device_name, void *arg);
818 
819 #ifndef DOXYGEN_CPP /* Avoid static inline tags for RTDM in doxygen */
820 static inline int rtdm_irq_free(rtdm_irq_t *irq_handle)
821 {
822  if (!XENO_ASSERT(COBALT, xnsched_root_p()))
823  return -EPERM;
824  xnintr_detach(irq_handle);
825  return 0;
826 }
827 
828 static inline int rtdm_irq_enable(rtdm_irq_t *irq_handle)
829 {
830  xnintr_enable(irq_handle);
831  return 0;
832 }
833 
834 static inline int rtdm_irq_disable(rtdm_irq_t *irq_handle)
835 {
836  xnintr_disable(irq_handle);
837  return 0;
838 }
839 #endif /* !DOXYGEN_CPP */
840 
841 /* --- non-real-time signalling services --- */
842 
848 typedef struct rtdm_nrtsig rtdm_nrtsig_t;
859 typedef void (*rtdm_nrtsig_handler_t)(rtdm_nrtsig_t *nrt_sig, void *arg);
860 
861 struct rtdm_nrtsig {
862  rtdm_nrtsig_handler_t handler;
863  void *arg;
864 };
865 
866 void rtdm_schedule_nrt_work(struct work_struct *lostage_work);
869 #ifndef DOXYGEN_CPP /* Avoid static inline tags for RTDM in doxygen */
870 static inline void rtdm_nrtsig_init(rtdm_nrtsig_t *nrt_sig,
871  rtdm_nrtsig_handler_t handler, void *arg)
872 {
873  nrt_sig->handler = handler;
874  nrt_sig->arg = arg;
875 }
876 
877 static inline void rtdm_nrtsig_destroy(rtdm_nrtsig_t *nrt_sig)
878 {
879  nrt_sig->handler = NULL;
880  nrt_sig->arg = NULL;
881 }
882 
883 void rtdm_nrtsig_pend(rtdm_nrtsig_t *nrt_sig);
884 #endif /* !DOXYGEN_CPP */
885 
886 /* --- timer services --- */
887 
893 typedef struct xntimer rtdm_timer_t;
894 
900 typedef void (*rtdm_timer_handler_t)(rtdm_timer_t *timer);
901 
909  RTDM_TIMERMODE_RELATIVE = XN_RELATIVE,
910 
912  RTDM_TIMERMODE_ABSOLUTE = XN_ABSOLUTE,
913 
916 };
921 #ifndef DOXYGEN_CPP /* Avoid broken doxygen output */
922 #define rtdm_timer_init(timer, handler, name) \
923 ({ \
924  xntimer_init((timer), &nkclock, handler, \
925  NULL, XNTIMER_IGRAVITY); \
926  xntimer_set_name((timer), (name)); \
927  0; \
928 })
929 
930 #endif /* !DOXYGEN_CPP */
931 
932 void rtdm_timer_destroy(rtdm_timer_t *timer);
933 
934 int rtdm_timer_start(rtdm_timer_t *timer, nanosecs_abs_t expiry,
935  nanosecs_rel_t interval, enum rtdm_timer_mode mode);
936 
937 void rtdm_timer_stop(rtdm_timer_t *timer);
938 
939 #ifndef DOXYGEN_CPP /* Avoid static inline tags for RTDM in doxygen */
940 static inline int rtdm_timer_start_in_handler(rtdm_timer_t *timer,
941  nanosecs_abs_t expiry,
942  nanosecs_rel_t interval,
943  enum rtdm_timer_mode mode)
944 {
945  return xntimer_start(timer, expiry, interval, (xntmode_t)mode);
946 }
947 
948 static inline void rtdm_timer_stop_in_handler(rtdm_timer_t *timer)
949 {
950  xntimer_stop(timer);
951 }
952 #endif /* !DOXYGEN_CPP */
953 
954 /* --- task services --- */
960 typedef struct xnthread rtdm_task_t;
961 
967 typedef void (*rtdm_task_proc_t)(void *arg);
968 
973 #define RTDM_TASK_LOWEST_PRIORITY 0
974 #define RTDM_TASK_HIGHEST_PRIORITY 99
975 
981 #define RTDM_TASK_RAISE_PRIORITY (+1)
982 #define RTDM_TASK_LOWER_PRIORITY (-1)
983 
987 int rtdm_task_init(rtdm_task_t *task, const char *name,
988  rtdm_task_proc_t task_proc, void *arg,
989  int priority, nanosecs_rel_t period);
990 int __rtdm_task_sleep(xnticks_t timeout, xntmode_t mode);
992 
993 #ifndef DOXYGEN_CPP /* Avoid static inline tags for RTDM in doxygen */
994 static inline void rtdm_task_destroy(rtdm_task_t *task)
995 {
996  xnthread_cancel(task);
997  xnthread_join(task, true);
998 }
999 
1000 static inline int rtdm_task_should_stop(void)
1001 {
1002  return xnthread_test_info(xnthread_current(), XNCANCELD);
1003 }
1004 
1005 void rtdm_task_join(rtdm_task_t *task);
1006 
1007 static inline void __deprecated rtdm_task_join_nrt(rtdm_task_t *task,
1008  unsigned int poll_delay)
1009 {
1010  rtdm_task_join(task);
1011 }
1012 
1013 static inline void rtdm_task_set_priority(rtdm_task_t *task, int priority)
1014 {
1015  union xnsched_policy_param param = { .rt = { .prio = priority } };
1016  xnthread_set_schedparam(task, &xnsched_class_rt, &param);
1017  xnsched_run();
1018 }
1019 
1020 static inline int rtdm_task_set_period(rtdm_task_t *task,
1021  nanosecs_rel_t period)
1022 {
1023  if (period < 0)
1024  period = 0;
1025 
1026  return xnthread_set_periodic(task, XN_INFINITE, XN_RELATIVE, period);
1027 }
1028 
1029 static inline int rtdm_task_unblock(rtdm_task_t *task)
1030 {
1031  int res = xnthread_unblock(task);
1032 
1033  xnsched_run();
1034  return res;
1035 }
1036 
1037 static inline rtdm_task_t *rtdm_task_current(void)
1038 {
1039  return xnthread_current();
1040 }
1041 
1042 static inline int rtdm_task_wait_period(void)
1043 {
1044  if (!XENO_ASSERT(COBALT, !xnsched_unblockable_p()))
1045  return -EPERM;
1046  return xnthread_wait_period(NULL);
1047 }
1048 
1049 static inline int rtdm_task_sleep(nanosecs_rel_t delay)
1050 {
1051  return __rtdm_task_sleep(delay, XN_RELATIVE);
1052 }
1053 
1054 static inline int
1055 rtdm_task_sleep_abs(nanosecs_abs_t wakeup_date, enum rtdm_timer_mode mode)
1056 {
1057  /* For the sake of a consistent API usage... */
1058  if (mode != RTDM_TIMERMODE_ABSOLUTE && mode != RTDM_TIMERMODE_REALTIME)
1059  return -EINVAL;
1060  return __rtdm_task_sleep(wakeup_date, (xntmode_t)mode);
1061 }
1062 
1063 /* rtdm_task_sleep_abs shall be used instead */
1064 static inline int __deprecated rtdm_task_sleep_until(nanosecs_abs_t wakeup_time)
1065 {
1066  return __rtdm_task_sleep(wakeup_time, XN_REALTIME);
1067 }
1068 
1069 #define rtdm_task_busy_wait(__condition, __spin_ns, __sleep_ns) \
1070  ({ \
1071  __label__ done; \
1072  nanosecs_abs_t __end; \
1073  int __ret = 0; \
1074  for (;;) { \
1075  __end = rtdm_clock_read_monotonic() + __spin_ns; \
1076  for (;;) { \
1077  if (__condition) \
1078  goto done; \
1079  if (rtdm_clock_read_monotonic() >= __end) \
1080  break; \
1081  } \
1082  __ret = rtdm_task_sleep(__sleep_ns); \
1083  if (__ret) \
1084  break; \
1085  } \
1086  done: \
1087  __ret; \
1088  })
1089 
1090 #endif /* !DOXYGEN_CPP */
1091 
1092 /* --- event services --- */
1093 
1094 typedef struct rtdm_event {
1095  struct xnsynch synch_base;
1096  DECLARE_XNSELECT(select_block);
1097 } rtdm_event_t;
1098 
1099 #define RTDM_EVENT_PENDING XNSYNCH_SPARE1
1100 
1101 void rtdm_event_init(rtdm_event_t *event, unsigned long pending);
1102 int rtdm_event_select(rtdm_event_t *event, rtdm_selector_t *selector,
1103  enum rtdm_selecttype type, unsigned fd_index);
1104 int rtdm_event_wait(rtdm_event_t *event);
1105 int rtdm_event_timedwait(rtdm_event_t *event, nanosecs_rel_t timeout,
1106  rtdm_toseq_t *timeout_seq);
1107 void rtdm_event_signal(rtdm_event_t *event);
1108 
1109 void rtdm_event_clear(rtdm_event_t *event);
1110 
1111 void rtdm_event_pulse(rtdm_event_t *event);
1112 
1113 void rtdm_event_destroy(rtdm_event_t *event);
1114 
1115 /* --- semaphore services --- */
1116 
1117 typedef struct rtdm_sem {
1118  unsigned long value;
1119  struct xnsynch synch_base;
1120  DECLARE_XNSELECT(select_block);
1121 } rtdm_sem_t;
1122 
1123 void rtdm_sem_init(rtdm_sem_t *sem, unsigned long value);
1124 int rtdm_sem_select(rtdm_sem_t *sem, rtdm_selector_t *selector,
1125  enum rtdm_selecttype type, unsigned fd_index);
1126 int rtdm_sem_down(rtdm_sem_t *sem);
1127 int rtdm_sem_timeddown(rtdm_sem_t *sem, nanosecs_rel_t timeout,
1128  rtdm_toseq_t *timeout_seq);
1129 void rtdm_sem_up(rtdm_sem_t *sem);
1130 
1131 void rtdm_sem_destroy(rtdm_sem_t *sem);
1132 
1133 /* --- mutex services --- */
1134 
1135 typedef struct rtdm_mutex {
1136  struct xnsynch synch_base;
1137  atomic_t fastlock;
1138 } rtdm_mutex_t;
1139 
1140 void rtdm_mutex_init(rtdm_mutex_t *mutex);
1141 int rtdm_mutex_lock(rtdm_mutex_t *mutex);
1142 int rtdm_mutex_timedlock(rtdm_mutex_t *mutex, nanosecs_rel_t timeout,
1143  rtdm_toseq_t *timeout_seq);
1144 void rtdm_mutex_unlock(rtdm_mutex_t *mutex);
1145 void rtdm_mutex_destroy(rtdm_mutex_t *mutex);
1146 
1147 /* --- utility functions --- */
1148 
1149 #define rtdm_printk(format, ...) printk(format, ##__VA_ARGS__)
1150 
1151 struct rtdm_ratelimit_state {
1152  rtdm_lock_t lock; /* protect the state */
1153  nanosecs_abs_t interval;
1154  int burst;
1155  int printed;
1156  int missed;
1157  nanosecs_abs_t begin;
1158 };
1159 
1160 int rtdm_ratelimit(struct rtdm_ratelimit_state *rs, const char *func);
1161 
1162 #define DEFINE_RTDM_RATELIMIT_STATE(name, interval_init, burst_init) \
1163  struct rtdm_ratelimit_state name = { \
1164  .lock = RTDM_LOCK_UNLOCKED((name).lock), \
1165  .interval = interval_init, \
1166  .burst = burst_init, \
1167  }
1168 
1169 /* We use the Linux defaults */
1170 #define DEF_RTDM_RATELIMIT_INTERVAL 5000000000LL
1171 #define DEF_RTDM_RATELIMIT_BURST 10
1172 
1173 #define rtdm_printk_ratelimited(fmt, ...) ({ \
1174  static DEFINE_RTDM_RATELIMIT_STATE(_rs, \
1175  DEF_RTDM_RATELIMIT_INTERVAL, \
1176  DEF_RTDM_RATELIMIT_BURST); \
1177  \
1178  if (rtdm_ratelimit(&_rs, __func__)) \
1179  printk(fmt, ##__VA_ARGS__); \
1180 })
1181 
1182 #ifndef DOXYGEN_CPP /* Avoid static inline tags for RTDM in doxygen */
1183 static inline void *rtdm_malloc(size_t size)
1184 {
1185  return xnmalloc(size);
1186 }
1187 
1188 static inline void rtdm_free(void *ptr)
1189 {
1190  xnfree(ptr);
1191 }
1192 
1193 int rtdm_mmap_to_user(struct rtdm_fd *fd,
1194  void *src_addr, size_t len,
1195  int prot, void **pptr,
1196  struct vm_operations_struct *vm_ops,
1197  void *vm_private_data);
1198 
1199 int rtdm_iomap_to_user(struct rtdm_fd *fd,
1200  phys_addr_t src_addr, size_t len,
1201  int prot, void **pptr,
1202  struct vm_operations_struct *vm_ops,
1203  void *vm_private_data);
1204 
1205 int rtdm_mmap_kmem(struct vm_area_struct *vma, void *va);
1206 
1207 int rtdm_mmap_vmem(struct vm_area_struct *vma, void *va);
1208 
1209 int rtdm_mmap_iomem(struct vm_area_struct *vma, phys_addr_t pa);
1210 
1211 int rtdm_munmap(void *ptr, size_t len);
1212 
1213 static inline int rtdm_read_user_ok(struct rtdm_fd *fd,
1214  const void __user *ptr, size_t size)
1215 {
1216  return access_rok(ptr, size);
1217 }
1218 
1219 static inline int rtdm_rw_user_ok(struct rtdm_fd *fd,
1220  const void __user *ptr, size_t size)
1221 {
1222  return access_wok(ptr, size);
1223 }
1224 
1225 static inline int rtdm_copy_from_user(struct rtdm_fd *fd,
1226  void *dst, const void __user *src,
1227  size_t size)
1228 {
1229  return __xn_copy_from_user(dst, src, size) ? -EFAULT : 0;
1230 }
1231 
1232 static inline int rtdm_safe_copy_from_user(struct rtdm_fd *fd,
1233  void *dst, const void __user *src,
1234  size_t size)
1235 {
1236  return (!access_rok(src, size) ||
1237  __xn_copy_from_user(dst, src, size)) ? -EFAULT : 0;
1238 }
1239 
1240 static inline int rtdm_copy_to_user(struct rtdm_fd *fd,
1241  void __user *dst, const void *src,
1242  size_t size)
1243 {
1244  return __xn_copy_to_user(dst, src, size) ? -EFAULT : 0;
1245 }
1246 
1247 static inline int rtdm_safe_copy_to_user(struct rtdm_fd *fd,
1248  void __user *dst, const void *src,
1249  size_t size)
1250 {
1251  return (!access_wok(dst, size) ||
1252  __xn_copy_to_user(dst, src, size)) ? -EFAULT : 0;
1253 }
1254 
1255 static inline int rtdm_strncpy_from_user(struct rtdm_fd *fd,
1256  char *dst,
1257  const char __user *src, size_t count)
1258 {
1259  if (unlikely(!access_rok(src, 1)))
1260  return -EFAULT;
1261  return __xn_strncpy_from_user(dst, src, count);
1262 }
1263 
1264 static inline int rtdm_rt_capable(struct rtdm_fd *fd)
1265 {
1266  if (!XENO_ASSERT(COBALT, !xnsched_interrupt_p()))
1267  return 0;
1268 
1269  if (!rtdm_fd_is_user(fd))
1270  return !xnsched_root_p();
1271 
1272  return xnthread_current() != NULL;
1273 }
1274 
1275 static inline int rtdm_in_rt_context(void)
1276 {
1277  return (ipipe_current_domain != ipipe_root_domain);
1278 }
1279 
1280 #endif /* !DOXYGEN_CPP */
1281 
1282 #endif /* _COBALT_RTDM_DRIVER_H */
static void rtdm_lock_put_irqrestore(rtdm_lock_t *lock, rtdm_lockctx_t context)
Release lock and restore preemption state.
Definition: driver.h:603
void rtdm_mutex_destroy(rtdm_mutex_t *mutex)
Destroy a mutex.
Definition: drvlib.c:1166
struct rtdm_fd_ops ops
I/O operation handlers.
Definition: driver.h:264
void rtdm_task_busy_sleep(nanosecs_rel_t delay)
Busy-wait a specified amount of time.
Definition: drvlib.c:387
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:262
void xnintr_enable(struct xnintr *intr)
Enable an interrupt line.
Definition: intr.c:889
void rtdm_mutex_unlock(rtdm_mutex_t *mutex)
Release a mutex.
Definition: drvlib.c:1184
void xnintr_detach(struct xnintr *intr)
Detach an interrupt descriptor.
Definition: intr.c:863
Select ouput buffer availability events.
Definition: driver.h:113
void(* rtdm_timer_handler_t)(rtdm_timer_t *timer)
Timer handler.
Definition: driver.h:900
ipipe_spinlock_t rtdm_lock_t
Lock variable.
Definition: driver.h:528
void xnthread_cancel(struct xnthread *thread)
Cancel a thread.
Definition: thread.c:1468
#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:2000
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:158
static void rtdm_lock_put(rtdm_lock_t *lock)
Release lock without preemption restoration.
Definition: driver.h:566
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:251
Adjustable timer with absolute timeout.
Definition: driver.h:915
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(* start)(struct rtdm_driver *drv)
Handler called upon transition to COBALT_STATE_WARMUP.
Definition: driver.h:234
char dev_private[0]
Begin of driver defined context data structure.
Definition: driver.h:141
int rtdm_ratelimit(struct rtdm_ratelimit_state *rs, const char *func)
Enforces a rate limit.
Definition: drvlib.c:2022
void xnintr_disable(struct xnintr *intr)
Disable an interrupt line.
Definition: intr.c:920
size_t context_size
Size of driver defined appendix to struct rtdm_dev_context.
Definition: driver.h:258
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:460
int rtdm_dev_register(struct rtdm_device *device)
Register a RTDM device.
Definition: device.c:357
void rtdm_task_join(rtdm_task_t *task)
Wait on a real-time task to terminate.
Definition: drvlib.c:364
Select exceptional events.
Definition: driver.h:116
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:1104
void * device_data
Driver definable device data.
Definition: driver.h:325
static struct rtdm_device * rtdm_fd_device(struct rtdm_fd *fd)
Locate a device structure from a file descriptor.
Definition: driver.h:199
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:1329
void rtdm_timer_destroy(rtdm_timer_t *timer)
Destroy a timer.
Definition: drvlib.c:430
int rtdm_event_wait(rtdm_event_t *event)
Wait on event occurrence.
Definition: drvlib.c:730
int rtdm_mutex_lock(rtdm_mutex_t *mutex)
Request a mutex.
Definition: drvlib.c:1214
void rtdm_event_pulse(rtdm_event_t *event)
Signal an event occurrence to currently listening waiters.
Definition: drvlib.c:670
Monotonic timer with absolute timeout.
Definition: driver.h:912
void rtdm_toseq_init(rtdm_toseq_t *timeout_seq, nanosecs_rel_t timeout)
Initialise a timeout sequence.
Definition: drvlib.c:600
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:1003
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:1475
static struct xnthread * xnthread_current(void)
Retrieve the current Cobalt core TCB.
Definition: thread.h:352
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:186
#define spltest()
Test hard interrupt state on the local processor.
Definition: lock.h:64
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:337
RTDM state management handlers.
Definition: driver.h:232
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:871
int xnthread_wait_period(unsigned long *overruns_r)
Wait for the next periodic release point.
Definition: thread.c:1335
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:476
void rtdm_timer_stop(rtdm_timer_t *timer)
Stop a timer.
Definition: drvlib.c:482
int xntimer_start(struct xntimer *timer, xnticks_t value, xnticks_t interval, xntmode_t mode)
Arm a timer.
Definition: timer.c:101
static void rtdm_lock_init(rtdm_lock_t *lock)
Dynamic lock initialisation.
Definition: driver.h:540
void(* rtdm_task_proc_t)(void *arg)
Real-time task procedure.
Definition: driver.h:967
int rtdm_irq_disable(rtdm_irq_t *irq_handle)
Disable interrupt line.
rtdm_selecttype
Definition: driver.h:108
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:651
void rtdm_sem_init(rtdm_sem_t *sem, unsigned long value)
Initialise a semaphore.
Definition: drvlib.c:912
int(* stop)(struct rtdm_driver *drv)
Handler called upon transition to COBALT_STATE_TEARDOWN.
Definition: driver.h:236
Select input data availability events.
Definition: driver.h:110
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:1254
int device_flags
Device flags, see Device Flags for details.
Definition: driver.h:256
struct rtdm_driver * driver
Device driver.
Definition: driver.h:323
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:138
void rtdm_event_signal(rtdm_event_t *event)
Signal an event occurrence.
Definition: drvlib.c:688
int(* rtdm_irq_handler_t)(rtdm_irq_t *irq_handle)
Interrupt handler.
Definition: driver.h:786
int xnsynch_sleep_on(struct xnsynch *synch, xnticks_t timeout, xntmode_t timeout_mode)
Sleep on an ownerless synchronization object.
Definition: synch.c:135
int rtdm_task_wait_period(void)
Wait on next real-time task period.
void rtdm_mutex_init(rtdm_mutex_t *mutex)
Initialise a mutex.
Definition: drvlib.c:1148
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.
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:429
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:1167
int device_count
Count of devices this driver manages.
Definition: driver.h:271
void rtdm_event_init(rtdm_event_t *event, unsigned long pending)
Initialise an event.
Definition: drvlib.c:625
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:1951
int xnthread_join(struct xnthread *thread, bool uninterruptible)
Join with a terminated thread.
Definition: thread.c:1554
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:907
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:1506
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:768
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:1248
int protocol_family
Protocol device identification: protocol family (PF_xxx)
Definition: driver.h:260
void(* rtdm_nrtsig_handler_t)(rtdm_nrtsig_t *nrt_sig, void *arg)
Non-real-time signal handler.
Definition: driver.h:859
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:1813
Device context.
Definition: driver.h:133
static int xnsched_run(void)
The rescheduling procedure.
Definition: sched.h:262
void rtdm_sem_destroy(rtdm_sem_t *sem)
Destroy a semaphore.
Definition: drvlib.c:937
void rtdm_sem_up(rtdm_sem_t *sem)
Increment a semaphore.
Definition: drvlib.c:1062
Monotonic timer with relative timeout.
Definition: driver.h:909
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:1882
int rtdm_task_set_period(rtdm_task_t *task, nanosecs_rel_t period)
Adjust real-time task period.
struct rtdm_sm_ops smops
State management handlers.
Definition: driver.h:266
RTDM device.
Definition: driver.h:321
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:1926
int minor
Minor number of the device.
Definition: driver.h:352
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:1764
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:171
int rtdm_sem_down(rtdm_sem_t *sem)
Decrement a semaphore.
Definition: drvlib.c:965
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:531
void rtdm_event_clear(rtdm_event_t *event)
Clear event state.
Definition: drvlib.c:833
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:245
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:1979
static void rtdm_lock_get(rtdm_lock_t *lock)
Acquire lock from non-preemptible contexts.
Definition: driver.h:552
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.