/ addons / rtdm / rtdm_driver.h
rtdm_driver.h
   1  /**
   2   * @file
   3   * Real-Time Driver Model for RTAI, driver API header
   4   *
   5   * @note Copyright (C) 2005-2007 Jan Kiszka <jan.kiszka@web.de>
   6   * @note Copyright (C) 2005 Joerg Langenberg <joerg.langenberg@gmx.net>
   7   * @note Copyright (C) 2008 Gilles Chanteperdrix <gilles.chanteperdrix@gmail.com>
   8   * @note Copyright (C) 2005-2010 Paolo Mantegazza <mantegazza@aero.polimi.it>
   9   *
  10   * RTAI is free software; you can redistribute it and/or modify it
  11   * under the terms of the GNU General Public License as published by
  12   * the Free Software Foundation; either version 2 of the License, or
  13   * (at your option) any later version.
  14   *
  15   * RTAI is distributed in the hope that it will be useful, but
  16   * WITHOUT ANY WARRANTY; without even the implied warranty of
  17   * MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE.  See the GNU
  18   * General Public License for more details.
  19   *
  20   * You should have received a copy of the GNU General Public License
  21   * along with RTAI; if not, write to the Free Software Foundation,
  22   * Inc., 59 Temple Place - Suite 330, Boston, MA 02111-1307, USA.
  23   *
  24   * @ingroup driverapi
  25   */
  26  
  27  #ifndef _RTDM_DRIVER_H
  28  #define _RTDM_DRIVER_H
  29  
  30  #ifndef __KERNEL__
  31  #error This header is for kernel space usage only. \
  32         You are likely looking for rtdm/rtdm.h...
  33  #endif /* !__KERNEL__ */
  34  
  35  #include <asm/atomic.h>
  36  #include <linux/list.h>
  37  
  38  #include <rtai_schedcore.h>
  39  #include <rtai_sched.h>
  40  
  41  #include "xn.h"
  42  #include "select.h"
  43  #include <rtdm/vfile.h>
  44  #include <rtdm/rtdm.h>
  45  
  46  
  47  struct rtdm_dev_context;
  48  typedef struct xnselector rtdm_selector_t;
  49  enum rtdm_selecttype;
  50  
  51  /*!
  52   * @addtogroup devregister
  53   * @{
  54   */
  55  
  56  /*!
  57   * @anchor dev_flags @name Device Flags
  58   * Static flags describing a RTDM device
  59   * @{
  60   */
  61  /** If set, only a single instance of the device can be requested by an
  62   *  application. */
  63  #define RTDM_EXCLUSIVE			0x0001
  64  
  65  /** If set, the device is addressed via a clear-text name. */
  66  #define RTDM_NAMED_DEVICE		0x0010
  67  
  68  /** If set, the device is addressed via a combination of protocol ID and
  69   *  socket type. */
  70  #define RTDM_PROTOCOL_DEVICE		0x0020
  71  
  72  /** Mask selecting the device type. */
  73  #define RTDM_DEVICE_TYPE_MASK		0x00F0
  74  /** @} Device Flags */
  75  
  76  /*!
  77   * @anchor ctx_flags @name Context Flags
  78   * Dynamic flags describing the state of an open RTDM device (bit numbers)
  79   * @{
  80   */
  81  /** Set by RTDM if the device instance was created in non-real-time
  82   *  context. */
  83  #define RTDM_CREATED_IN_NRT		0
  84  
  85  /** Set by RTDM when the device is being closed. */
  86  #define RTDM_CLOSING			1
  87  
  88  /** Lowest bit number the driver developer can use freely */
  89  #define RTDM_USER_CONTEXT_FLAG		8  /* first user-definable flag */
  90  /** @} Context Flags */
  91  
  92  /*!
  93   * @anchor drv_versioning @name Driver Versioning
  94   * Current revisions of RTDM structures, encoding of driver versions. See
  95   * @ref api_versioning "API Versioning" for the interface revision.
  96   * @{
  97   */
  98  /** Version of struct rtdm_device */
  99  #define RTDM_DEVICE_STRUCT_VER		5
 100  
 101  /** Version of struct rtdm_dev_context */
 102  #define RTDM_CONTEXT_STRUCT_VER		3
 103  
 104  /** Flag indicating a secure variant of RTDM (not supported here) */
 105  #define RTDM_SECURE_DEVICE		0x80000000
 106  
 107  /** Version code constructor for driver revisions */
 108  #define RTDM_DRIVER_VER(major, minor, patch) \
 109  	(((major & 0xFF) << 16) | ((minor & 0xFF) << 8) | (patch & 0xFF))
 110  
 111  /** Get major version number from driver revision code */
 112  #define RTDM_DRIVER_MAJOR_VER(ver)	(((ver) >> 16) & 0xFF)
 113  
 114  /** Get minor version number from driver revision code */
 115  #define RTDM_DRIVER_MINOR_VER(ver)	(((ver) >> 8) & 0xFF)
 116  
 117  /** Get patch version number from driver revision code */
 118  #define RTDM_DRIVER_PATCH_VER(ver)	((ver) & 0xFF)
 119  /** @} Driver Versioning */
 120  
 121  /*!
 122   * @addtogroup rtdmsync
 123   * @{
 124   */
 125  
 126  /*!
 127   * @anchor RTDM_SELECTTYPE_xxx   @name RTDM_SELECTTYPE_xxx
 128   * Event types select can bind to
 129   * @{
 130   */
 131  enum rtdm_selecttype {
 132  	/** Select input data availability events */
 133  	RTDM_SELECTTYPE_READ = XNSELECT_READ,
 134  
 135  	/** Select ouput buffer availability events */
 136  	RTDM_SELECTTYPE_WRITE = XNSELECT_WRITE,
 137  
 138  	/** Select exceptional events */
 139  	RTDM_SELECTTYPE_EXCEPT = XNSELECT_EXCEPT
 140  };
 141  /** @} RTDM_SELECTTYPE_xxx */
 142  
 143  /** @} rtdmsync */
 144  
 145  /*!
 146   * @name Operation Handler Prototypes
 147   * @{
 148   */
 149  
 150  /**
 151   * Named device open handler
 152   *
 153   * @param[in] context Context structure associated with opened device instance
 154   * @param[in] user_info Opaque pointer to information about user mode caller,
 155   * NULL if kernel mode call
 156   * @param[in] oflag Open flags as passed by the user
 157   *
 158   * @return 0 on success. On failure return either -ENOSYS, to request that
 159   * this handler be called again from the opposite realtime/non-realtime
 160   * context, or another negative error code.
 161   *
 162   * @see @c open() in IEEE Std 1003.1,
 163   * http://www.opengroup.org/onlinepubs/009695399 */
 164  typedef int (*rtdm_open_handler_t)(struct rtdm_dev_context *context,
 165  				   rtdm_user_info_t *user_info, int oflag);
 166  
 167  /**
 168   * Socket creation handler for protocol devices
 169   *
 170   * @param[in] context Context structure associated with opened device instance
 171   * @param[in] user_info Opaque pointer to information about user mode caller,
 172   * NULL if kernel mode call
 173   * @param[in] protocol Protocol number as passed by the user
 174   *
 175   * @return 0 on success. On failure return either -ENOSYS, to request that
 176   * this handler be called again from the opposite realtime/non-realtime
 177   * context, or another negative error code.
 178   *
 179   * @see @c socket() in IEEE Std 1003.1,
 180   * http://www.opengroup.org/onlinepubs/009695399 */
 181  typedef int (*rtdm_socket_handler_t)(struct rtdm_dev_context *context,
 182  				     rtdm_user_info_t *user_info, int protocol);
 183  
 184  /**
 185   * Close handler
 186   *
 187   * @param[in] context Context structure associated with opened device instance
 188   * @param[in] user_info Opaque pointer to information about user mode caller,
 189   * NULL if kernel mode or deferred user mode call
 190   *
 191   * @return 0 on success. On failure return either -ENOSYS, to request that
 192   * this handler be called again from the opposite realtime/non-realtime
 193   * context, -EAGAIN to request a recall after a grace period, or a valid
 194   * negative error code according to IEEE Std 1003.1.
 195   *
 196   * @note Drivers must be prepared for that case that the close handler is
 197   * invoked more than once per open context (even if the handler already
 198   * completed an earlier run successfully). The driver has to avoid releasing
 199   * resources twice as well as returning false errors on successive close
 200   * invocations.
 201   *
 202   * @see @c close() in IEEE Std 1003.1,
 203   * http://www.opengroup.org/onlinepubs/009695399 */
 204  typedef int (*rtdm_close_handler_t)(struct rtdm_dev_context *context,
 205  				    rtdm_user_info_t *user_info);
 206  
 207  /**
 208   * IOCTL handler
 209   *
 210   * @param[in] context Context structure associated with opened device instance
 211   * @param[in] user_info Opaque pointer to information about user mode caller,
 212   * NULL if kernel mode call
 213   * @param[in] request Request number as passed by the user
 214   * @param[in,out] arg Request argument as passed by the user
 215   *
 216   * @return A positive value or 0 on success. On failure return either
 217   * -ENOSYS, to request that the function be called again from the opposite
 218   * realtime/non-realtime context, or another negative error code.
 219   *
 220   * @see @c ioctl() in IEEE Std 1003.1,
 221   * http://www.opengroup.org/onlinepubs/009695399 */
 222  typedef int (*rtdm_ioctl_handler_t)(struct rtdm_dev_context *context,
 223  				    rtdm_user_info_t *user_info,
 224  				    unsigned int request, void __user *arg);
 225  
 226  /**
 227   * Select binding handler
 228   *
 229   * @param[in] context Context structure associated with opened device instance
 230   * @param[in,out] selector Object that shall be bound to the given event
 231   * @param[in] type Event type the selector is interested in
 232   * @param[in] fd_index Opaque value, to be passed to rtdm_event_select_bind or
 233   * rtdm_sem_select_bind unmodfied
 234   *
 235   * @return 0 on success. On failure return either -ENOSYS, to request that
 236   * this handler be called again from the opposite realtime/non-realtime
 237   * context, or another negative error code.
 238   */
 239  typedef int (*rtdm_select_bind_handler_t)(struct rtdm_dev_context *context,
 240  					  rtdm_selector_t *selector,
 241  					  enum rtdm_selecttype type,
 242  					  unsigned fd_index);
 243  
 244  /**
 245   * Read handler
 246   *
 247   * @param[in] context Context structure associated with opened device instance
 248   * @param[in] user_info Opaque pointer to information about user mode caller,
 249   * NULL if kernel mode call
 250   * @param[out] buf Input buffer as passed by the user
 251   * @param[in] nbyte Number of bytes the user requests to read
 252   *
 253   * @return On success, the number of bytes read. On failure return either
 254   * -ENOSYS, to request that this handler be called again from the opposite
 255   * realtime/non-realtime context, or another negative error code.
 256   *
 257   * @see @c read() in IEEE Std 1003.1,
 258   * http://www.opengroup.org/onlinepubs/009695399 */
 259  typedef ssize_t (*rtdm_read_handler_t)(struct rtdm_dev_context *context,
 260  				       rtdm_user_info_t *user_info,
 261  				       void *buf, size_t nbyte);
 262  
 263  /**
 264   * Write handler
 265   *
 266   * @param[in] context Context structure associated with opened device instance
 267   * @param[in] user_info Opaque pointer to information about user mode caller,
 268   * NULL if kernel mode call
 269   * @param[in] buf Output buffer as passed by the user
 270   * @param[in] nbyte Number of bytes the user requests to write
 271   *
 272   * @return On success, the number of bytes written. On failure return
 273   * either -ENOSYS, to request that this handler be called again from the
 274   * opposite realtime/non-realtime context, or another negative error code.
 275   *
 276   * @see @c write() in IEEE Std 1003.1,
 277   * http://www.opengroup.org/onlinepubs/009695399 */
 278  typedef ssize_t (*rtdm_write_handler_t)(struct rtdm_dev_context *context,
 279  					rtdm_user_info_t *user_info,
 280  					const void *buf, size_t nbyte);
 281  
 282  /**
 283   * Receive message handler
 284   *
 285   * @param[in] context Context structure associated with opened device instance
 286   * @param[in] user_info Opaque pointer to information about user mode caller,
 287   * NULL if kernel mode call
 288   * @param[in,out] msg Message descriptor as passed by the user, automatically
 289   * mirrored to safe kernel memory in case of user mode call
 290   * @param[in] flags Message flags as passed by the user
 291   *
 292   * @return On success, the number of bytes received. On failure return
 293   * either -ENOSYS, to request that this handler be called again from the
 294   * opposite realtime/non-realtime context, or another negative error code.
 295   *
 296   * @see @c recvmsg() in IEEE Std 1003.1,
 297   * http://www.opengroup.org/onlinepubs/009695399 */
 298  typedef ssize_t (*rtdm_recvmsg_handler_t)(struct rtdm_dev_context *context,
 299  					  rtdm_user_info_t *user_info,
 300  					  struct msghdr *msg, int flags);
 301  
 302  /**
 303   * Transmit message handler
 304   *
 305   * @param[in] context Context structure associated with opened device instance
 306   * @param[in] user_info Opaque pointer to information about user mode caller,
 307   * NULL if kernel mode call
 308   * @param[in] msg Message descriptor as passed by the user, automatically
 309   * mirrored to safe kernel memory in case of user mode call
 310   * @param[in] flags Message flags as passed by the user
 311   *
 312   * @return On success, the number of bytes transmitted. On failure return
 313   * either -ENOSYS, to request that this handler be called again from the
 314   * opposite realtime/non-realtime context, or another negative error code.
 315   *
 316   * @see @c sendmsg() in IEEE Std 1003.1,
 317   * http://www.opengroup.org/onlinepubs/009695399 */
 318  typedef ssize_t (*rtdm_sendmsg_handler_t)(struct rtdm_dev_context *context,
 319  					  rtdm_user_info_t *user_info,
 320  					  const struct msghdr *msg, int flags);
 321  /** @} Operation Handler Prototypes */
 322  
 323  typedef int (*rtdm_rt_handler_t)(struct rtdm_dev_context *context,
 324  				 rtdm_user_info_t *user_info, void *arg);
 325  /**
 326   * Device operations
 327   */
 328  struct rtdm_operations {
 329  	/*! @name Common Operations
 330  	 * @{ */
 331  	/** Close handler for real-time contexts (optional, deprecated)
 332  	 *  @deprecated Only use non-real-time close handler in new drivers. */
 333  	rtdm_close_handler_t close_rt;
 334  	/** Close handler for non-real-time contexts (required) */
 335  	rtdm_close_handler_t close_nrt;
 336  
 337  	/** IOCTL from real-time context (optional) */
 338  	rtdm_ioctl_handler_t ioctl_rt;
 339  	/** IOCTL from non-real-time context (optional) */
 340  	rtdm_ioctl_handler_t ioctl_nrt;
 341  
 342  	/** Select binding handler for any context (optional) */
 343  	rtdm_select_bind_handler_t select_bind;
 344  	/** @} Common Operations */
 345  
 346  	/*! @name Stream-Oriented Device Operations
 347  	 * @{ */
 348  	/** Read handler for real-time context (optional) */
 349  	rtdm_read_handler_t read_rt;
 350  	/** Read handler for non-real-time context (optional) */
 351  	rtdm_read_handler_t read_nrt;
 352  
 353  	/** Write handler for real-time context (optional) */
 354  	rtdm_write_handler_t write_rt;
 355  	/** Write handler for non-real-time context (optional) */
 356  	rtdm_write_handler_t write_nrt;
 357  	/** @} Stream-Oriented Device Operations */
 358  
 359  	/*! @name Message-Oriented Device Operations
 360  	 * @{ */
 361  	/** Receive message handler for real-time context (optional) */
 362  	rtdm_recvmsg_handler_t recvmsg_rt;
 363  	/** Receive message handler for non-real-time context (optional) */
 364  	rtdm_recvmsg_handler_t recvmsg_nrt;
 365  
 366  	/** Transmit message handler for real-time context (optional) */
 367  	rtdm_sendmsg_handler_t sendmsg_rt;
 368  	/** Transmit message handler for non-real-time context (optional) */
 369  	rtdm_sendmsg_handler_t sendmsg_nrt;
 370  	/** @} Message-Oriented Device Operations */
 371  };
 372  
 373  struct rtdm_devctx_reserved {
 374  	void *owner;
 375  	struct list_head cleanup;
 376  };
 377  
 378  /**
 379   * @brief Device context
 380   *
 381   * A device context structure is associated with every open device instance.
 382   * RTDM takes care of its creation and destruction and passes it to the
 383   * operation handlers when being invoked.
 384   *
 385   * Drivers can attach arbitrary data immediately after the official structure.
 386   * The size of this data is provided via rtdm_device.context_size during
 387   * device registration.
 388   */
 389  struct rtdm_dev_context {
 390  	/** Context flags, see @ref ctx_flags "Context Flags" for details */
 391  	unsigned long context_flags;
 392  
 393  	/** Associated file descriptor */
 394  	int fd;
 395  
 396  	/** Lock counter of context, held while structure is referenced by an
 397  	 *  operation handler */
 398  	atomic_t close_lock_count;
 399  
 400  	/** Set of active device operation handlers */
 401  	struct rtdm_operations *ops;
 402  
 403  	/** Reference to owning device */
 404  	struct rtdm_device *device;
 405  
 406  	/** Data stored by RTDM inside a device context (internal use only) */
 407  	struct rtdm_devctx_reserved reserved;
 408  
 409  	/** Begin of driver defined context data structure */
 410  	char dev_private[0];
 411  };
 412  
 413  /**
 414   * Locate the driver private area associated to a device context structure
 415   *
 416   * @param[in] context Context structure associated with opened device instance
 417   *
 418   * @return The address of the private driver area associated to @a
 419   * context.
 420   */
 421  static inline void *
 422  rtdm_context_to_private(struct rtdm_dev_context *context)
 423  {
 424  	return (void *)context->dev_private;
 425  }
 426  
 427  /**
 428   * Locate a device context structure from its driver private area
 429   *
 430   * @param[in] dev_private Address of a private context area
 431   *
 432   * @return The address of the device context structure defining @a
 433   * dev_private.
 434   */
 435  static inline struct rtdm_dev_context *
 436  rtdm_private_to_context(void *dev_private)
 437  {
 438  	return container_of(dev_private, struct rtdm_dev_context, dev_private);
 439  }
 440  
 441  struct rtdm_dev_reserved {
 442  	struct list_head entry;
 443  	atomic_t refcount;
 444  	struct rtdm_dev_context *exclusive_context;
 445  };
 446  
 447  /**
 448   * @brief RTDM device
 449   *
 450   * This structure specifies a RTDM device. As some fields, especially the
 451   * reserved area, will be modified by RTDM during runtime, the structure must
 452   * not reside in write-protected memory.
 453   */
 454  struct rtdm_device {
 455  	/** Revision number of this structure, see
 456  	 *  @ref drv_versioning "Driver Versioning" defines */
 457  	int struct_version;
 458  
 459  	/** Device flags, see @ref dev_flags "Device Flags" for details */
 460  	int device_flags;
 461  	/** Size of driver defined appendix to struct rtdm_dev_context */
 462  	size_t context_size;
 463  
 464  	/** Named device identification (orthogonal to Linux device name space) */
 465  	char device_name[RTDM_MAX_DEVNAME_LEN + 1];
 466  
 467  	/** Protocol device identification: protocol family (PF_xxx) */
 468  	int protocol_family;
 469  	/** Protocol device identification: socket type (SOCK_xxx) */
 470  	int socket_type;
 471  
 472  	/** Named device instance creation for real-time contexts,
 473  	 *  optional (but deprecated) if open_nrt is non-NULL, ignored for
 474  	 *  protocol devices
 475  	 *  @deprecated Only use non-real-time open handler in new drivers. */
 476  	rtdm_open_handler_t open_rt;
 477  	/** Named device instance creation for non-real-time contexts,
 478  	 *  optional if open_rt is non-NULL, ignored for protocol devices */
 479  	rtdm_open_handler_t open_nrt;
 480  
 481  	/** Protocol socket creation for real-time contexts,
 482  	 *  optional (but deprecated) if socket_nrt is non-NULL, ignored for
 483  	 *  named devices
 484  	 *  @deprecated Only use non-real-time socket creation handler in new
 485  	 *  drivers. */
 486  	rtdm_socket_handler_t socket_rt;
 487  	/** Protocol socket creation for non-real-time contexts,
 488  	 *  optional if socket_rt is non-NULL, ignored for named devices */
 489  	rtdm_socket_handler_t socket_nrt;
 490  
 491  	/** Default operations on newly opened device instance */
 492  	struct rtdm_operations ops;
 493  
 494  	/** Device class ID, see @ref RTDM_CLASS_xxx */
 495  	int device_class;
 496  	/** Device sub-class, see RTDM_SUBCLASS_xxx definition in the
 497  	 *  @ref profiles "Device Profiles" */
 498  	int device_sub_class;
 499  	/** Supported device profile version */
 500  	int profile_version;
 501  	/** Informational driver name (reported via /proc) */
 502  	const char *driver_name;
 503  	/** Driver version, see @ref drv_versioning "Driver Versioning" defines */
 504  	int driver_version;
 505  	/** Informational peripheral name the device is attached to
 506  	 *  (reported via /proc) */
 507  	const char *peripheral_name;
 508  	/** Informational driver provider name (reported via /proc) */
 509  	const char *provider_name;
 510  
 511  	/** Name of /proc entry for the device, must not be NULL */
 512  	const char *proc_name;
 513  #ifdef CONFIG_PROC_FS
 514          /** Set to device's vfile data after registration, do not modify */
 515          struct xnvfile_directory vfroot;
 516          struct xnvfile_regular info_vfile;
 517  #endif
 518  
 519  	/** Set to device's /proc root entry after registration, do not modify */
 520  	struct proc_dir_entry *proc_entry;
 521  
 522  	/** Driver definable device ID */
 523  	int device_id;
 524  	/** Driver definable device data */
 525  	void *device_data;
 526  
 527  	/** Data stored by RTDM inside a registered device (internal use only) */
 528  	struct rtdm_dev_reserved reserved;
 529  };
 530  /** @} devregister */
 531  
 532  /* --- device registration --- */
 533  
 534  int rtdm_dev_register(struct rtdm_device *device);
 535  int rtdm_dev_unregister(struct rtdm_device *device, unsigned int poll_delay);
 536  
 537  /* --- inter-driver API --- */
 538  
 539  #define rtdm_open		rt_dev_open
 540  #define rtdm_socket		rt_dev_socket
 541  #define rtdm_close		rt_dev_close
 542  #define rtdm_ioctl		rt_dev_ioctl
 543  #define rtdm_read		rt_dev_read
 544  #define rtdm_write		rt_dev_write
 545  #define rtdm_recvmsg		rt_dev_recvmsg
 546  #define rtdm_recv		rt_dev_recv
 547  #define rtdm_recvfrom		rt_dev_recvfrom
 548  #define rtdm_sendmsg		rt_dev_sendmsg
 549  #define rtdm_send		rt_dev_send
 550  #define rtdm_sendto		rt_dev_sendto
 551  #define rtdm_bind		rt_dev_bind
 552  #define rtdm_listen		rt_dev_listen
 553  #define rtdm_accept		rt_dev_accept
 554  #define rtdm_getsockopt		rt_dev_getsockopt
 555  #define rtdm_setsockopt		rt_dev_setsockopt
 556  #define rtdm_getsockname	rt_dev_getsockname
 557  #define rtdm_getpeername	rt_dev_getpeername
 558  #define rtdm_shutdown		rt_dev_shutdown
 559  
 560  struct rtdm_dev_context *rtdm_context_get(int fd);
 561  
 562  #ifndef DOXYGEN_CPP /* Avoid static inline tags for RTDM in doxygen */
 563  
 564  #define CONTEXT_IS_LOCKED(context) \
 565  	(atomic_read(&(context)->close_lock_count) > 1 || \
 566  	 (test_bit(RTDM_CLOSING, &(context)->context_flags) && \
 567  	  atomic_read(&(context)->close_lock_count) > 0))
 568  
 569  static inline void rtdm_context_lock(struct rtdm_dev_context *context)
 570  {
 571  	RTAI_ASSERT(RTDM, CONTEXT_IS_LOCKED(context),
 572  		    /* just warn if context was a dangling pointer */);
 573  	atomic_inc(&context->close_lock_count);
 574  }
 575  
 576  extern int rtdm_apc;
 577  
 578  static inline void rtdm_context_unlock(struct rtdm_dev_context *context)
 579  {
 580  	RTAI_ASSERT(RTDM, CONTEXT_IS_LOCKED(context),
 581  		    /* just warn if context was a dangling pointer */);
 582  	smp_mb__before_atomic_dec();
 583  	if (unlikely(atomic_dec_and_test(&context->close_lock_count)))
 584  		rthal_apc_schedule(rtdm_apc);
 585  }
 586  
 587  static inline void rtdm_context_put(struct rtdm_dev_context *context)
 588  {
 589  	rtdm_context_unlock(context);
 590  }
 591  
 592  /* --- clock services --- */
 593  
 594  
 595  
 596  static inline nanosecs_abs_t rtdm_clock_read(void)
 597  {
 598  	return rt_get_time_ns();
 599  }
 600  
 601  static inline nanosecs_abs_t rtdm_clock_read_monotonic(void)
 602  {
 603  	return rt_get_time_ns();
 604  }
 605  #endif /* !DOXYGEN_CPP */
 606  
 607  /*!
 608   * @addtogroup rtdmsync
 609   * @{
 610   */
 611  
 612  int rtdm_select_bind(int fd, rtdm_selector_t *selector,
 613  		     enum rtdm_selecttype type, unsigned fd_index);
 614  
 615  /* --- spin lock services --- */
 616  /*!
 617   * @name Global Lock across Scheduler Invocation
 618   * @{
 619   */
 620  
 621  /**
 622   * @brief Execute code block atomically
 623   *
 624   * Generally, it is illegal to suspend the current task by calling
 625   * rtdm_task_sleep(), rtdm_event_wait(), etc. while holding a spinlock. In
 626   * contrast, this macro allows to combine several operations including
 627   * a potentially rescheduling call to an atomic code block with respect to
 628   * other RTDM_EXECUTE_ATOMICALLY() blocks. The macro is a light-weight
 629   * alternative for protecting code blocks via mutexes, and it can even be used
 630   * to synchronise real-time and non-real-time contexts.
 631   *
 632   * @param code_block Commands to be executed atomically
 633   *
 634   * @note It is not allowed to leave the code block explicitly by using
 635   * @c break, @c return, @c goto, etc. This would leave the global lock held
 636   * during the code block execution in an inconsistent state. Moreover, do not
 637   * embed complex operations into the code bock. Consider that they will be
 638   * executed under preemption lock with interrupts switched-off. Also note that
 639   * invocation of rescheduling calls may break the atomicity until the task
 640   * gains the CPU again.
 641   *
 642   * Environments:
 643   *
 644   * This service can be called from:
 645   *
 646   * - Kernel module initialization/cleanup code
 647   * - Interrupt service routine
 648   * - Kernel-based task
 649   * - User-space task (RT, non-RT)
 650   *
 651   * Rescheduling: possible, depends on functions called within @a code_block.
 652   */
 653  #ifdef DOXYGEN_CPP /* Beautify doxygen output */
 654  #define RTDM_EXECUTE_ATOMICALLY(code_block)	\
 655  {						\
 656  	<ENTER_ATOMIC_SECTION>			\
 657  	code_block;				\
 658  	<LEAVE_ATOMIC_SECTION>			\
 659  }
 660  #else /* This is how it really works */
 661  #define RTDM_EXECUTE_ATOMICALLY(code_block)	\
 662  {						\
 663  	spl_t s;				\
 664  						\
 665  	s = rt_global_save_flags_and_cli();	\
 666  	code_block;				\
 667  	rt_global_restore_flags(s);		\
 668  }
 669  #endif
 670  /** @} Global Lock across Scheduler Invocation */
 671  
 672  /*!
 673   * @name Spinlock with Preemption Deactivation
 674   * @{
 675   */
 676  
 677  /**
 678   * Static lock initialisation
 679   */
 680  #define RTDM_LOCK_UNLOCKED	SPIN_LOCK_UNLOCKED
 681  
 682  /** Lock variable */
 683  typedef spinlock_t rtdm_lock_t;
 684  
 685  /** Variable to save the context while holding a lock */
 686  typedef unsigned long rtdm_lockctx_t;
 687  
 688  /**
 689   * Dynamic lock initialisation
 690   *
 691   * @param lock Address of lock variable
 692   *
 693   * Environments:
 694   *
 695   * This service can be called from:
 696   *
 697   * - Kernel module initialization/cleanup code
 698   * - Kernel-based task
 699   * - User-space task (RT, non-RT)
 700   *
 701   * Rescheduling: never.
 702   */
 703  #define rtdm_lock_init(lock)	spin_lock_init(lock)
 704  
 705  /**
 706   * Acquire lock from non-preemptible contexts
 707   *
 708   * @param lock Address of lock variable
 709   *
 710   * Environments:
 711   *
 712   * This service can be called from:
 713   *
 714   * - Kernel module initialization/cleanup code
 715   * - Interrupt service routine
 716   * - Kernel-based task
 717   * - User-space task (RT, non-RT)
 718   *
 719   * Rescheduling: never.
 720   */
 721  #ifdef DOXYGEN_CPP /* Beautify doxygen output */
 722  #define rtdm_lock_get(lock)	rt_spin_lock(lock)
 723  #else /* This is how it really works */
 724  #define rtdm_lock_get(lock)					\
 725  	do {							\
 726  		RTAI_BUGON(RTDM, !rthal_local_irq_disabled());	\
 727  		rt_spin_lock(lock);				\
 728  	} while (0)
 729  #endif
 730  
 731  /**
 732   * Release lock without preemption restoration
 733   *
 734   * @param lock Address of lock variable
 735   *
 736   * Environments:
 737   *
 738   * This service can be called from:
 739   *
 740   * - Kernel module initialization/cleanup code
 741   * - Interrupt service routine
 742   * - Kernel-based task
 743   * - User-space task (RT, non-RT)
 744   *
 745   * Rescheduling: never.
 746   */
 747  #define rtdm_lock_put(lock)	rt_spin_unlock(lock)
 748  
 749  /**
 750   * Acquire lock and disable preemption
 751   *
 752   * @param lock Address of lock variable
 753   * @param context name of local variable to store the context in
 754   *
 755   * Environments:
 756   *
 757   * This service can be called from:
 758   *
 759   * - Kernel module initialization/cleanup code
 760   * - Interrupt service routine
 761   * - Kernel-based task
 762   * - User-space task (RT, non-RT)
 763   *
 764   * Rescheduling: never.
 765   */
 766  #define rtdm_lock_get_irqsave(lock, context)    \
 767  	do { context = rt_spin_lock_irqsave(lock); } while (0)
 768  
 769  /**
 770   * Release lock and restore preemption state
 771   *
 772   * @param lock Address of lock variable
 773   * @param context name of local variable which stored the context
 774   *
 775   * Environments:
 776   *
 777   * This service can be called from:
 778   *
 779   * - Kernel module initialization/cleanup code
 780   * - Interrupt service routine
 781   * - Kernel-based task
 782   * - User-space task (RT, non-RT)
 783   *
 784   * Rescheduling: possible.
 785   */
 786  #define rtdm_lock_put_irqrestore(lock, context) \
 787  	rt_spin_unlock_irqrestore(context, lock)
 788  
 789  /**
 790   * Disable preemption locally
 791   *
 792   * @param context name of local variable to store the context in
 793   *
 794   * Environments:
 795   *
 796   * This service can be called from:
 797   *
 798   * - Kernel module initialization/cleanup code
 799   * - Interrupt service routine
 800   * - Kernel-based task
 801   * - User-space task (RT, non-RT)
 802   *
 803   * Rescheduling: never.
 804   */
 805  #define rtdm_lock_irqsave(context)	\
 806  	rtai_save_flags_and_cli(context)
 807  
 808  /**
 809   * Restore preemption state
 810   *
 811   * @param context name of local variable which stored the context
 812   *
 813   * Environments:
 814   *
 815   * This service can be called from:
 816   *
 817   * - Kernel module initialization/cleanup code
 818   * - Interrupt service routine
 819   * - Kernel-based task
 820   * - User-space task (RT, non-RT)
 821   *
 822   * Rescheduling: possible.
 823   */
 824  #define rtdm_lock_irqrestore(context)	\
 825  	rtai_restore_flags(context)
 826  /** @} Spinlock with Preemption Deactivation */
 827  
 828  /** @} rtdmsync */
 829  
 830  /* --- Interrupt management services --- */
 831  /*!
 832   * @addtogroup rtdmirq
 833   * @{
 834   */
 835  
 836  typedef xnintr_t rtdm_irq_t;
 837  
 838  /*!
 839   * @anchor RTDM_IRQTYPE_xxx   @name RTDM_IRQTYPE_xxx
 840   * Interrupt registrations flags
 841   * @{
 842   */
 843  /** Enable IRQ-sharing with other real-time drivers */
 844  #define RTDM_IRQTYPE_SHARED		XN_ISR_SHARED
 845  /** Mark IRQ as edge-triggered, relevant for correct handling of shared
 846   *  edge-triggered IRQs */
 847  #define RTDM_IRQTYPE_EDGE		XN_ISR_EDGE
 848  /** @} RTDM_IRQTYPE_xxx */
 849  
 850  /**
 851   * Interrupt handler
 852   *
 853   * @param[in] irq_handle IRQ handle as returned by rtdm_irq_request()
 854   *
 855   * @return 0 or a combination of @ref RTDM_IRQ_xxx flags
 856   */
 857  typedef int (*rtdm_irq_handler_t)(rtdm_irq_t *irq_handle);
 858  
 859  /*!
 860   * @anchor RTDM_IRQ_xxx   @name RTDM_IRQ_xxx
 861   * Return flags of interrupt handlers
 862   * @{
 863   */
 864  /** Unhandled interrupt */
 865  #define RTDM_IRQ_NONE			XN_ISR_NONE
 866  /** Denote handled interrupt */
 867  #define RTDM_IRQ_HANDLED		XN_ISR_HANDLED
 868  /** @} RTDM_IRQ_xxx */
 869  
 870  /**
 871   * Retrieve IRQ handler argument
 872   *
 873   * @param irq_handle IRQ handle
 874   * @param type Type of the pointer to return
 875   *
 876   * @return The argument pointer registered on rtdm_irq_request() is returned,
 877   * type-casted to the specified @a type.
 878   *
 879   * Environments:
 880   *
 881   * This service can be called from:
 882   *
 883   * - Interrupt service routine
 884   *
 885   * Rescheduling: never.
 886   */
 887  #define rtdm_irq_get_arg(irq_handle, type)	((type *)irq_handle->cookie)
 888  /** @} rtdmirq */
 889  
 890  int rtdm_irq_request(rtdm_irq_t *irq_handle, unsigned int irq_no,
 891  		     rtdm_irq_handler_t handler, unsigned long flags,
 892  		     const char *device_name, void *arg);
 893  
 894  #ifndef DOXYGEN_CPP /* Avoid static inline tags for RTDM in doxygen */
 895  static inline int rtdm_irq_free(rtdm_irq_t *irq_handle)
 896  {
 897  	return xnintr_detach(irq_handle);
 898  }
 899  
 900  static inline int rtdm_irq_enable(rtdm_irq_t *irq_handle)
 901  {
 902  	return xnintr_enable(irq_handle);
 903  }
 904  
 905  static inline int rtdm_irq_disable(rtdm_irq_t *irq_handle)
 906  {
 907  	return xnintr_disable(irq_handle);
 908  }
 909  #endif /* !DOXYGEN_CPP */
 910  
 911  /* --- non-real-time signalling services --- */
 912  
 913  /*!
 914   * @addtogroup nrtsignal
 915   * @{
 916   */
 917  
 918  typedef unsigned rtdm_nrtsig_t;
 919  
 920  /**
 921   * Non-real-time signal handler
 922   *
 923   * @param[in] nrt_sig Signal handle as returned by rtdm_nrtsig_init()
 924   * @param[in] arg Argument as passed to rtdm_nrtsig_init()
 925   *
 926   * @note The signal handler will run in soft-IRQ context of the non-real-time
 927   * subsystem. Note the implications of this context, e.g. no invocation of
 928   * blocking operations.
 929   */
 930  typedef void (*rtdm_nrtsig_handler_t)(rtdm_nrtsig_t nrt_sig, void *arg);
 931  /** @} nrtsignal */
 932  
 933  #ifndef DOXYGEN_CPP /* Avoid static inline tags for RTDM in doxygen */
 934  static inline int rtdm_nrtsig_init(rtdm_nrtsig_t *nrt_sig,
 935  				   rtdm_nrtsig_handler_t handler, void *arg)
 936  {
 937  	*nrt_sig = hal_alloc_irq();
 938  
 939  	if (*nrt_sig == 0)
 940  		return -EAGAIN;
 941  
 942  	rthal_virtualize_irq(hal_root_domain, *nrt_sig, handler, arg, NULL,
 943  			     IPIPE_HANDLE_MASK);
 944  	return 0;
 945  }
 946  
 947  static inline void rtdm_nrtsig_destroy(rtdm_nrtsig_t *nrt_sig)
 948  {
 949  	hal_free_irq(*nrt_sig);
 950  }
 951  
 952  static inline void rtdm_nrtsig_pend(rtdm_nrtsig_t *nrt_sig)
 953  {
 954  	hal_pend_uncond(*nrt_sig, rtai_cpuid());
 955  }
 956  #endif /* !DOXYGEN_CPP */
 957  
 958  /* --- timer services --- */
 959  
 960  /*!
 961   * @addtogroup rtdmtimer
 962   * @{
 963   */
 964  
 965  typedef xntimer_t rtdm_timer_t;
 966  
 967  /**
 968   * Timer handler
 969   *
 970   * @param[in] timer Timer handle as returned by rtdm_timer_init()
 971   */
 972  typedef void (*rtdm_timer_handler_t)(rtdm_timer_t *timer);
 973  
 974  /*!
 975   * @anchor RTDM_TIMERMODE_xxx   @name RTDM_TIMERMODE_xxx
 976   * Timer operation modes
 977   * @{
 978   */
 979  enum rtdm_timer_mode {
 980  	/** Monotonic timer with relative timeout */
 981  	RTDM_TIMERMODE_RELATIVE = XN_RELATIVE,
 982  
 983  	/** Monotonic timer with absolute timeout */
 984  	RTDM_TIMERMODE_ABSOLUTE = XN_ABSOLUTE,
 985  
 986  	/** Adjustable timer with absolute timeout */
 987  	RTDM_TIMERMODE_REALTIME = XN_REALTIME
 988  };
 989  /** @} RTDM_TIMERMODE_xxx */
 990  
 991  /** @} rtdmtimer */
 992  
 993  #ifndef DOXYGEN_CPP /* Avoid broken doxygen output */
 994  #define rtdm_timer_init(timer, handler, name)		\
 995  ({							\
 996  	xntimer_init((timer), handler);			\
 997  	xntimer_set_name((timer), (name));		\
 998  	0;						\
 999  })
1000  #endif /* !DOXYGEN_CPP */
1001  
1002  void rtdm_timer_destroy(rtdm_timer_t *timer);
1003  
1004  int rtdm_timer_start(rtdm_timer_t *timer, nanosecs_abs_t expiry,
1005  		     nanosecs_rel_t interval, enum rtdm_timer_mode mode);
1006  
1007  void rtdm_timer_stop(rtdm_timer_t *timer);
1008  
1009  #ifndef DOXYGEN_CPP /* Avoid static inline tags for RTDM in doxygen */
1010  static inline int rtdm_timer_start_in_handler(rtdm_timer_t *timer,
1011  					      nanosecs_abs_t expiry,
1012  					      nanosecs_rel_t interval,
1013  					      enum rtdm_timer_mode mode)
1014  {
1015  	return xntimer_start(timer, xntbase_ns2ticks(rtdm_tbase, expiry),
1016  			     xntbase_ns2ticks(rtdm_tbase, interval),
1017  			     (xntmode_t)mode);
1018  }
1019  
1020  static inline void rtdm_timer_stop_in_handler(rtdm_timer_t *timer)
1021  {
1022  	xntimer_stop(timer);
1023  }
1024  #endif /* !DOXYGEN_CPP */
1025  
1026  /* --- task services --- */
1027  /*!
1028   * @addtogroup rtdmtask
1029   * @{
1030   */
1031  
1032  typedef struct rt_task_struct rtdm_task_t;
1033  
1034  /**
1035   * Real-time task procedure
1036   *
1037   * @param[in,out] arg argument as passed to rtdm_task_init()
1038   */
1039  typedef void (*rtdm_task_proc_t)(void *arg);
1040  
1041  /*!
1042   * @anchor taskprio @name Task Priority Range
1043   * Maximum and minimum task priorities
1044   * @{ */
1045  #define RTDM_TASK_LOWEST_PRIORITY	999999999
1046  #define RTDM_TASK_HIGHEST_PRIORITY	0
1047  /** @} Task Priority Range */
1048  
1049  /*!
1050   * @anchor changetaskprio @name Task Priority Modification
1051   * Raise or lower task priorities by one level
1052   * @{ */
1053  #define RTDM_TASK_RAISE_PRIORITY	(-1)
1054  #define RTDM_TASK_LOWER_PRIORITY	(+1)
1055  /** @} Task Priority Modification */
1056  
1057  /** @} rtdmtask */
1058  
1059  int rtdm_task_init_cpuid(rtdm_task_t *task, const char *name,
1060  			 rtdm_task_proc_t task_proc, void *arg,
1061  			 int priority, nanosecs_rel_t period, int cpuid);
1062  
1063  extern int get_min_tasks_cpuid(void);
1064  static inline int rtdm_task_init(rtdm_task_t *task, const char *name,
1065  				 rtdm_task_proc_t task_proc, void *arg,
1066  				 int priority, nanosecs_rel_t period)
1067  {
1068  	return rtdm_task_init_cpuid(task, name, task_proc, arg, priority, period, get_min_tasks_cpuid());
1069  }
1070  
1071  void rtdm_task_busy_sleep(nanosecs_rel_t delay);
1072  
1073  #ifndef DOXYGEN_CPP /* Avoid static inline tags for RTDM in doxygen */
1074  static inline void rtdm_task_destroy(rtdm_task_t *task)
1075  {
1076  	rt_drg_on_adr(task);
1077  	if (task->magic == RT_TASK_MAGIC) {
1078  		rt_task_delete(task);
1079  	}
1080  }
1081  
1082  void rtdm_task_join_nrt(rtdm_task_t *task, unsigned int poll_delay);
1083  
1084  static inline void rtdm_task_set_priority(rtdm_task_t *task, int priority)
1085  {
1086  
1087  
1088  	rt_change_prio(task, priority);
1089  }
1090  
1091  static inline int rtdm_task_set_period(rtdm_task_t *task,
1092  				       nanosecs_rel_t period)
1093  {
1094  	if (period < 0)
1095  		period = 0;
1096  	return rt_task_make_periodic_relative_ns(task, 0, period);
1097  
1098  
1099  }
1100  
1101  static inline int rtdm_task_unblock(rtdm_task_t *task)
1102  {
1103  	int res = rt_task_masked_unblock(task, ~RT_SCHED_READY);
1104  
1105  
1106  	return res;
1107  }
1108  
1109  static inline rtdm_task_t *rtdm_task_current(void)
1110  {
1111  	return _rt_whoami();
1112  }
1113  
1114  static inline int rtdm_task_wait_period(void)
1115  {
1116  	if (!_rt_whoami()->period) {
1117  		return -EINVAL;
1118  	}
1119  	if (!rt_task_wait_period()) {
1120  		return 0;
1121  	}
1122  	if (_rt_whoami()->unblocked) {
1123  		return -EINTR;
1124  	}
1125  	return rt_sched_timed ? -ETIMEDOUT : -EIDRM;
1126  }
1127  
1128  //RTA_SYSCALL_MODE int rt_sleep(longlong);
1129  static inline int rtdm_task_sleep(nanosecs_rel_t delay)
1130  {
1131          if (delay < 0) {
1132                  return 0;
1133          }
1134          if (delay < 0) {
1135                  delay = RT_TIME_END;
1136          }
1137          if (rt_sleep(nano2count(delay)) && _rt_whoami()->unblocked) {
1138                  return -EINTR;
1139          }
1140          return 0;
1141  }
1142  
1143  static inline int
1144  rtdm_task_sleep_abs(nanosecs_abs_t wakeup_date, enum rtdm_timer_mode mode)
1145  {
1146  	/* For the sake of a consistent API usage... */
1147  	if (mode != RTDM_TIMERMODE_ABSOLUTE && mode != RTDM_TIMERMODE_REALTIME)
1148  		return -EINVAL;
1149  	if (rt_sleep_until(nano2count(wakeup_date)) && _rt_whoami()->unblocked) {
1150  		return -EINTR;
1151  	}
1152  	return 0;
1153  }
1154  
1155  /* rtdm_task_sleep_abs shall be used instead */
1156  static inline int __deprecated rtdm_task_sleep_until(nanosecs_abs_t wakeup_time)
1157  {
1158  	if (rt_sleep_until(nano2count(wakeup_time)) && _rt_whoami()->unblocked) {
1159  		return -EINTR;
1160  	}
1161  	return 0;
1162  }
1163  #endif /* !DOXYGEN_CPP */
1164  
1165  /* --- timeout sequences */
1166  
1167  typedef nanosecs_abs_t rtdm_toseq_t;
1168  
1169  void rtdm_toseq_init(rtdm_toseq_t *timeout_seq, nanosecs_rel_t timeout);
1170  
1171  /* --- event services --- */
1172  
1173  typedef struct {
1174  	struct rt_semaphore synch_base; unsigned long pending;
1175  	DECLARE_XNSELECT(select_block);
1176  } rtdm_event_t;
1177  
1178  #define RTDM_EVENT_PENDING		XNSYNCH_SPARE1
1179  
1180  void rtdm_event_init(rtdm_event_t *event, unsigned long pending);
1181  #ifdef CONFIG_RTAI_RTDM_SELECT
1182  int rtdm_event_select_bind(rtdm_event_t *event, rtdm_selector_t *selector,
1183  			   enum rtdm_selecttype type, unsigned fd_index);
1184  #else /* !CONFIG_RTAI_RTDM_SELECT */
1185  #define rtdm_event_select_bind(e, s, t, i) ({ (void)(e); -EBADF; })
1186  #endif /* !CONFIG_RTAI_RTDM_SELECT */
1187  int rtdm_event_wait(rtdm_event_t *event);
1188  int rtdm_event_timedwait(rtdm_event_t *event, nanosecs_rel_t timeout,
1189  			 rtdm_toseq_t *timeout_seq);
1190  void rtdm_event_signal(rtdm_event_t *event);
1191  
1192  void rtdm_event_clear(rtdm_event_t *event);
1193  
1194  #ifndef DOXYGEN_CPP /* Avoid static inline tags for RTDM in doxygen */
1195  
1196  
1197  static inline void rtdm_event_pulse(rtdm_event_t *event)
1198  {
1199  	trace_mark(xn_rtdm, event_pulse, "event %p", event);
1200  	rt_sem_broadcast(&event->synch_base);
1201  }
1202  
1203  static inline void rtdm_event_destroy(rtdm_event_t *event)
1204  {
1205  	trace_mark(xn_rtdm, event_destroy, "event %p", event);
1206  	rt_sem_delete(&event->synch_base);
1207  	xnselect_destroy(&event->select_block);
1208  }
1209  #endif /* !DOXYGEN_CPP */
1210  
1211  /* --- semaphore services --- */
1212  
1213  typedef struct {
1214  	struct rt_semaphore sem;
1215  	DECLARE_XNSELECT(select_block);
1216  } rtdm_sem_t;
1217  
1218  
1219  void rtdm_sem_init(rtdm_sem_t *sem, unsigned long value);
1220  #ifdef CONFIG_RTAI_RTDM_SELECT
1221  int rtdm_sem_select_bind(rtdm_sem_t *sem, rtdm_selector_t *selector,
1222  			 enum rtdm_selecttype type, unsigned fd_index);
1223  #else /* !CONFIG_RTAI_RTDM_SELECT */
1224  #define rtdm_sem_select_bind(s, se, t, i) ({ -EBADF; })
1225  #endif /* !CONFIG_RTAI_RTDM_SELECT */
1226  int rtdm_sem_down(rtdm_sem_t *sem);
1227  int rtdm_sem_timeddown(rtdm_sem_t *sem, nanosecs_rel_t timeout,
1228  		       rtdm_toseq_t *timeout_seq);
1229  void rtdm_sem_up(rtdm_sem_t *sem);
1230  
1231  #ifndef DOXYGEN_CPP /* Avoid static inline tags for RTDM in doxygen */
1232  static inline void rtdm_sem_destroy(rtdm_sem_t *sem)
1233  {
1234  	trace_mark(xn_rtdm, sem_destroy, "sem %p", sem);
1235  	rt_sem_delete(&sem->sem);
1236  	xnselect_destroy(&sem->select_block);
1237  }
1238  #endif /* !DOXYGEN_CPP */
1239  
1240  /* --- mutex services --- */
1241  
1242  typedef SEM rtdm_mutex_t;
1243  
1244  
1245  
1246  void rtdm_mutex_init(rtdm_mutex_t *mutex);
1247  int rtdm_mutex_lock(rtdm_mutex_t *mutex);
1248  int rtdm_mutex_timedlock(rtdm_mutex_t *mutex, nanosecs_rel_t timeout,
1249  			 rtdm_toseq_t *timeout_seq);
1250  
1251  #ifndef DOXYGEN_CPP /* Avoid static inline tags for RTDM in doxygen */
1252  static inline void rtdm_mutex_unlock(rtdm_mutex_t *mutex)
1253  {
1254  
1255  
1256  	trace_mark(xn_rtdm, mutex_unlock, "mutex %p", mutex);
1257  
1258  
1259  	rt_sem_signal(mutex);
1260  }
1261  
1262  static inline void rtdm_mutex_destroy(rtdm_mutex_t *mutex)
1263  {
1264  	trace_mark(xn_rtdm, mutex_destroy, "mutex %p", mutex);
1265  
1266  	rt_sem_delete(mutex);
1267  }
1268  #endif /* !DOXYGEN_CPP */
1269  
1270  /* --- utility functions --- */
1271  
1272  #define rtdm_printk(format, ...)	printk(format, ##__VA_ARGS__)
1273  
1274  #ifndef DOXYGEN_CPP /* Avoid static inline tags for RTDM in doxygen */
1275  static inline void *rtdm_malloc(size_t size)
1276  {
1277  	return xnmalloc(size);
1278  }
1279  
1280  static inline void rtdm_free(void *ptr)
1281  {
1282  	xnfree(ptr);
1283  }
1284  
1285  #ifdef CONFIG_RTAI_OPT_PERVASIVE
1286  int rtdm_mmap_to_user(rtdm_user_info_t *user_info,
1287  		      void *src_addr, size_t len,
1288  		      int prot, void **pptr,
1289  		      struct vm_operations_struct *vm_ops,
1290  		      void *vm_private_data);
1291  int rtdm_iomap_to_user(rtdm_user_info_t *user_info,
1292  		       phys_addr_t src_addr, size_t len,
1293  		       int prot, void **pptr,
1294  		       struct vm_operations_struct *vm_ops,
1295  		       void *vm_private_data);
1296  int rtdm_munmap(rtdm_user_info_t *user_info, void *ptr, size_t len);
1297  
1298  static inline int rtdm_read_user_ok(rtdm_user_info_t *user_info,
1299  				    const void __user *ptr, size_t size)
1300  {
1301  	return __xn_access_ok(user_info, VERIFY_READ, ptr, size);
1302  }
1303  
1304  static inline int rtdm_rw_user_ok(rtdm_user_info_t *user_info,
1305  				  const void __user *ptr, size_t size)
1306  {
1307  	return __xn_access_ok(user_info, VERIFY_WRITE, ptr, size);
1308  }
1309  
1310  static inline int rtdm_copy_from_user(rtdm_user_info_t *user_info,
1311  				      void *dst, const void __user *src,
1312  				      size_t size)
1313  {
1314  	return __xn_copy_from_user(user_info, dst, src, size) ? -EFAULT : 0;
1315  }
1316  
1317  static inline int rtdm_safe_copy_from_user(rtdm_user_info_t *user_info,
1318  					   void *dst, const void __user *src,
1319  					   size_t size)
1320  {
1321  	return (!__xn_access_ok(user_info, VERIFY_READ, src, size) ||
1322  		__xn_copy_from_user(user_info, dst, src, size)) ? -EFAULT : 0;
1323  }
1324  
1325  static inline int rtdm_copy_to_user(rtdm_user_info_t *user_info,
1326  				    void __user *dst, const void *src,
1327  				    size_t size)
1328  {
1329  	return __xn_copy_to_user(user_info, dst, src, size) ? -EFAULT : 0;
1330  }
1331  
1332  static inline int rtdm_safe_copy_to_user(rtdm_user_info_t *user_info,
1333  					 void __user *dst, const void *src,
1334  					 size_t size)
1335  {
1336  	return (!__xn_access_ok(user_info, VERIFY_WRITE, dst, size) ||
1337  		__xn_copy_to_user(user_info, dst, src, size)) ? -EFAULT : 0;
1338  }
1339  
1340  static inline int rtdm_strncpy_from_user(rtdm_user_info_t *user_info,
1341  					 char *dst,
1342  					 const char __user *src, size_t count)
1343  {
1344  	if (unlikely(!__xn_access_ok(user_info, VERIFY_READ, src, 1)))
1345  		return -EFAULT;
1346  	return __xn_strncpy_from_user(user_info, dst, src, count);
1347  }
1348  #else /* !CONFIG_RTAI_OPT_PERVASIVE */
1349  /* Define void user<->kernel services that simply fail */
1350  #define rtdm_mmap_to_user(...)		({ -ENOSYS; })
1351  #define rtdm_munmap(...)		({ -ENOSYS; })
1352  #define rtdm_read_user_ok(...)		({ 0; })
1353  #define rtdm_rw_user_ok(...)		({ 0; })
1354  #define rtdm_copy_from_user(...)	({ -ENOSYS; })
1355  #define rtdm_safe_copy_from_user(...)	({ -ENOSYS; })
1356  #define rtdm_copy_to_user(...)		({ -ENOSYS; })
1357  #define rtdm_safe_copy_to_user(...)	({ -ENOSYS; })
1358  #define rtdm_strncpy_from_user(...)	({ -ENOSYS; })
1359  #endif /* CONFIG_RTAI_OPT_PERVASIVE */
1360  
1361  static inline int rtdm_in_rt_context(void)
1362  {
1363  	return (_rt_whoami()->is_hard > 0);
1364  }
1365  
1366  static inline int rtdm_rt_capable(rtdm_user_info_t *user_info)
1367  {
1368  
1369  
1370          return (user_info ? xnshadow_thread(user_info) != NULL
1371                            : !xnpod_root_p());
1372  }
1373  
1374  #endif /* !DOXYGEN_CPP */
1375  
1376  int rtdm_exec_in_rt(struct rtdm_dev_context *context,
1377  		    rtdm_user_info_t *user_info, void *arg,
1378  		    rtdm_rt_handler_t handler);
1379  
1380  #endif /* _RTDM_DRIVER_H */