drvlib.c

来自「xenomai 很好的linux实时补丁」· C语言 代码 · 共 1,740 行 · 第 1/3 页

C
1,740
字号
 * * Environments: * * This service can be called from: * * - Kernel-based task * - User-space task (RT, non-RT) * * Rescheduling: possible. */void rtdm_mutex_unlock(rtdm_mutex_t *mutex){    spl_t s;    xnlock_get_irqsave(&nklock, s);    __clear_bit(0, &mutex->locked);    if (likely(xnsynch_wakeup_one_sleeper(&mutex->synch_base) != NULL))        xnpod_schedule();    xnlock_put_irqrestore(&nklock, s);}EXPORT_SYMBOL(rtdm_mutex_unlock);/** @} *//** @} Synchronisation services */#ifdef DOXYGEN_CPP /* Only used for doxygen doc generation *//*! * @ingroup driverapi * @defgroup rtdmirq Interrupt Management Services * @{ *//** * @brief Register an interrupt handler * * @param[in,out] irq_handle IRQ handle * @param[in] irq_no Line number of the addressed IRQ * @param[in] handler Interrupt handler * @param[in] flags Registration flags, see @ref RTDM_IRQTYPE_xxx for details * @param[in] device_name Optional device name to show up in real-time IRQ * lists (not yet implemented) * @param[in] arg Pointer to be passed to the interrupt handler on invocation * * @return 0 on success, otherwise: * * - -EINVAL is returned if an invalid parameter was passed. * * - -EBUSY is returned if the specified IRQ line is already in use. * * @note To receive interrupts on the requested line, you have to call * rtdm_irq_enable() after registering the handler. * * Environments: * * This service can be called from: * * - Kernel module initialization/cleanup code * - Kernel-based task * - User-space task (RT, non-RT) * * Rescheduling: never. */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);/** * @brief Release an interrupt handler * * @param[in,out] irq_handle IRQ handle as returned by rtdm_irq_request() * * @return 0 on success, otherwise negative error code * * Environments: * * This service can be called from: * * - Kernel module initialization/cleanup code * - Kernel-based task * - User-space task (RT, non-RT) * * Rescheduling: never. */int rtdm_irq_free(rtdm_irq_t *irq_handle);/** * @brief Enable interrupt line * * @param[in,out] irq_handle IRQ handle as returned by rtdm_irq_request() * * @return 0 on success, otherwise negative error code * * Environments: * * This service can be called from: * * - Kernel module initialization/cleanup code * - Interrupt service routine * - Kernel-based task * - User-space task (RT, non-RT) * * Rescheduling: possible. */int rtdm_irq_enable(rtdm_irq_t *irq_handle);/** * @brief Disable interrupt line * * @param[in,out] irq_handle IRQ handle as returned by rtdm_irq_request() * * @return 0 on success, otherwise negative error code * * Environments: * * This service can be called from: * * - Kernel module initialization/cleanup code * - Interrupt service routine * - Kernel-based task * - User-space task (RT, non-RT) * * Rescheduling: never. */int rtdm_irq_disable(rtdm_irq_t *irq_handle);/** @} Interrupt Management Services *//*! * @ingroup driverapi * @defgroup nrtsignal Non-Real-Time Signalling Services * * These services provide a mechanism to request the execution of a specified * handler in non-real-time context. The triggering can safely be performed in * real-time context without suffering from unknown delays. The handler * execution will be deferred until the next time the real-time subsystem * releases the CPU to the non-real-time part. * @{ *//** * @brief Register a non-real-time signal handler * * @param[in,out] nrt_sig Signal handle * @param[in] handler Non-real-time signal handler * * @return 0 on success, otherwise: * * - -EAGAIN is returned if no free signal slot is available. * * Environments: * * This service can be called from: * * - Kernel module initialization/cleanup code * - Kernel-based task * - User-space task (RT, non-RT) * * Rescheduling: never. */int rtdm_nrtsig_init(rtdm_nrtsig_t *nrt_sig, rtdm_nrtsig_handler_t handler);/** * @brief Release a non-realtime signal handler * * @param[in,out] nrt_sig Signal handle * * Environments: * * This service can be called from: * * - Kernel module initialization/cleanup code * - Kernel-based task * - User-space task (RT, non-RT) * * Rescheduling: never. */void rtdm_nrtsig_destroy(rtdm_nrtsig_t *nrt_sig);/** * Trigger non-real-time signal * * @param[in,out] nrt_sig Signal handle * * Environments: * * This service can be called from: * * - Kernel module initialization/cleanup code * - Interrupt service routine * - Kernel-based task * - User-space task (RT, non-RT) * * Rescheduling: never in real-time context, possible in non-real-time * environments. */void rtdm_nrtsig_pend(rtdm_nrtsig_t *nrt_sig);/** @} Non-Real-Time Signalling Services */#endif /* DOXYGEN_CPP *//*! * @ingroup driverapi * @defgroup util Utility Services * @{ */struct rtdm_mmap_data {    void *src_addr;    struct vm_operations_struct *vm_ops;    void *vm_private_data;};static int rtdm_mmap_buffer(struct file *filp, struct vm_area_struct *vma){    struct rtdm_mmap_data *mmap_data = filp->private_data;    vma->vm_ops = mmap_data->vm_ops;    vma->vm_private_data = mmap_data->vm_private_data;    return xnarch_remap_page_range(vma, vma->vm_start,                                   virt_to_phys(mmap_data->src_addr),                                   vma->vm_end - vma->vm_start, PAGE_SHARED);}static struct file_operations rtdm_mmap_fops = {    .mmap = rtdm_mmap_buffer,};/** * Map a kernel memory range into the address space of the user. * * @param[in] user_info User information pointer as passed to the invoked * device operation handler * @param[in] src_addr Kernel address to be mapped * @param[in] len Length of the memory range * @param[in] prot Protection flags for the user's memory range, typically * either PROT_READ or PROT_READ|PROT_WRITE * @param[in,out] pptr Address of a pointer containing the desired user * address or NULL on entry and the finally assigned address on return * @param[in] vm_ops vm_operations to be executed on the vma_area of the * user memory range or NULL * @param[in] vm_private_data Private data to be stored in the vma_area, * primarily useful for vm_operation handlers * * @return 0 on success, otherwise (most common values): * * - -EINVAL is returned if an invalid start address, size, or destination * address was passed. * * - -ENOMEM is returned if there is insufficient free memory or the limit of * memory mapping for the user process was reached. * * - -EAGAIN is returned if too much memory has been already locked by the * user process. * * @note RTDM supports two models for unmapping the user memory range again. * One is explicite unmapping via rtdm_munmap(), either performed when the * user requests it via an IOCTL etc. or when the related device is closed. * The other is automatic unmapping, triggered by the user invoking standard * munmap() or by the termination of the related process. To track release of * the mapping and therefore relinquishment of the referenced physical memory, * the caller of rtdm_mmap_to_user() can pass a vm_operations_struct on * invocation, defining a close handler for the vm_area. See Linux * documentaion (e.g. Linux Device Drivers book) on virtual memory management * for details. * * Environments: * * This service can be called from: * * - Kernel module initialization/cleanup code * - User-space task (non-RT) * * Rescheduling: possible. */int rtdm_mmap_to_user(rtdm_user_info_t *user_info, void *src_addr, size_t len,                      int prot, void **pptr,                      struct vm_operations_struct *vm_ops,                      void *vm_private_data){    struct rtdm_mmap_data   mmap_data = {src_addr, vm_ops, vm_private_data};    struct file             *filp;    struct file_operations  *old_fops;    void                    *old_priv_data;    void                    *user_ptr;    filp = filp_open("/dev/zero", O_RDWR, 0);    if (IS_ERR(filp))        return PTR_ERR(filp);    old_fops = filp->f_op;    filp->f_op = &rtdm_mmap_fops;    old_priv_data = filp->private_data;    filp->private_data = &mmap_data;    down_write(&user_info->mm->mmap_sem);    user_ptr = (void *)do_mmap(filp, (unsigned long)*pptr, len, prot,                               MAP_SHARED, 0);    up_write(&user_info->mm->mmap_sem);    filp->f_op = old_fops;    filp->private_data = old_priv_data;    filp_close(filp, user_info->files);    if (IS_ERR(user_ptr))        return PTR_ERR(user_ptr);    *pptr = user_ptr;    return 0;}EXPORT_SYMBOL(rtdm_mmap_to_user);/** * Unmap a user memory range. * * @param[in] user_info User information pointer as passed to * rtdm_mmap_to_user() when requesting to map the memory range * @param[in] ptr User address or the memory range * @param[in] len Length of the memory range * * @return 0 on success, otherwise: * * - -EINVAL is returned if an invalid address or size was passed. * * Environments: * * This service can be called from: * * - Kernel module initialization/cleanup code * - User-space task (non-RT) * * Rescheduling: possible. */int rtdm_munmap(rtdm_user_info_t *user_info, void *ptr, size_t len){    int err;    down_write(&user_info->mm->mmap_sem);    err = do_munmap(user_info->mm, (unsigned long)ptr, len);    up_write(&user_info->mm->mmap_sem);    return err;}EXPORT_SYMBOL(rtdm_munmap);#ifdef DOXYGEN_CPP /* Only used for doxygen doc generation *//** * Real-time safe message printing on kernel console * * @param[in] format Format string (conforming standard @c printf()) * @param ... Arguments referred by @a format * * @return On success, this service returns the number of characters printed. * Otherwise, a negative error code is returned. * * Environments: * * This service can be called from: * * - Kernel module initialization/cleanup code * - Interrupt service routine (consider the overhead!) * - Kernel-based task * - User-space task (RT, non-RT) * * Rescheduling: never in real-time context, possible in non-real-time * environments. */void rtdm_printk(const char *format, ...);/** * Allocate memory block in real-time context * * @param[in] size Requested size of the memory block * * @return The pointer to the allocated block is returned on success, NULL * otherwise. * * Environments: * * This service can be called from: * * - Kernel module initialization/cleanup code * - Interrupt service routine (consider the overhead!) * - Kernel-based task * - User-space task (RT, non-RT) * * Rescheduling: never. */void *rtdm_malloc(size_t size);/** * Release real-time memory block * * @param[in] ptr Pointer to memory block as returned by rtdm_malloc() * * Environments: * * This service can be called from: * * - Kernel module initialization/cleanup code * - Interrupt service routine (consider the overhead!) * - Kernel-based task * - User-space task (RT, non-RT) * * Rescheduling: never. */void rtdm_free(void *ptr);/** * Check if read access to user-space memory block is safe * * @param[in] user_info User information pointer as passed to the invoked * device operation handler * @param[in] ptr Address of the user-provided memory block * @param[in] size Size of the memory block * * @return Non-zero is return when it is safe to read from the specified * memory block, 0 otherwise. * * Environments: * * This service can be called from: * * - Kernel module initialization/cleanup code * - Kernel-based task * - User-space task (RT, non-RT) * * Rescheduling: never. */int rtdm_read_user_ok(rtdm_user_info_t *user_info, const void __user *ptr,                      size_t size);/** * Check if read/write access to user-space memory block is safe * * @param[in] user_info User information pointer as passed to the invoked * device operation handler * @param[in] ptr Address of the user-provided memory block * @param[in] size Size of the memory block * * @return Non-zero is return when it is safe to read from or write to the * specified memory block, 0 otherwise. * * Environments: * * This service can be called from: * * - Kernel module initialization/cleanup code * - Kernel-based task * - User-space task (RT, non-RT) * * Rescheduling: never. */int rtdm_rw_user_ok(rtdm_user_info_t *user_info, const void __user *ptr,                    size_t size);/** * Copy user-space memory block to specified buffer * * @param[in] user_info User information pointer as passed to the invoked * device operation handler * @param[in] dst Destination buffer address * @param[in] src Address of the user-space memory block * @param[in] size Size of the memory block * * @return 0 on success, otherwise: * * - -EFAULT is returned if an invalid memory area was accessed. * * @note Before invoking this service, verify via rtdm_read_user_ok() that the * provided user-space address can securely be accessed. * * Environments: * * This service can be called from: * * - Kernel module initialization/cleanup code * - Kernel-based task * - User-space task (RT, non-RT) * * Rescheduling: never. */int rtdm_copy_from_user(rtdm_user_info_t *user_info, void *dst,                        const void __user *src, size_t size);/** * Copy specified buffer to user-space memory block * * @param[in] user_info User information pointer as passed to the invoked * device operation handler * @param[in] dst Address of the user-space memory block * @param[in] src Source buffer address * @param[in] size Size of the memory block * * @return 0 on success, otherwise: * * - -EFAULT is returned if an invalid memory area was accessed. * * @note Before invoking this service, verify via rtdm_rw_user_ok() that the * provided user-space address can securely be accessed. * * Environments: * * This service can be called from: * * - Kernel module initialization/cleanup code * - Kernel-based task * - User-space task (RT, non-RT) * * Rescheduling: never. */int rtdm_copy_to_user(rtdm_user_info_t *user_info, void __user *dst,                      const void *src, size_t size);/** * Copy user-space string to specified buffer * * @param[in] user_info User information pointer as passed to the invoked * device operation handler * @param[in] dst Destination buffer address * @param[in] src Address of the user-space string * @param[in] count Maximum number of bytes to copy, including the trailing * '0' * * @return 0 on success, otherwise: * * - -EFAULT is returned if an invalid memory area was accessed. * * @note This services already includes a check of the source address, * calling rtdm_read_user_ok() for @a src explicitly is not required. * * Environments: * * This service can be called from: * * - Kernel module initialization/cleanup code * - Kernel-based task * - User-space task (RT, non-RT) * * Rescheduling: never. */int rtdm_strncpy_from_user(rtdm_user_info_t *user_info, char *dst,                           const char __user *src, size_t count);/** * Test if running in a real-time task * * @return Non-zero is returned if the caller resides in real-time context, 0 * otherwise. * * Environments: * * This service can be called from: * * - Kernel module initialization/cleanup code * - Kernel-based task * - User-space task (RT, non-RT) * * Rescheduling: never. */int rtdm_in_rt_context(void);#endif /* DOXYGEN_CPP *//** @} Utility Services */

⌨️ 快捷键说明

复制代码Ctrl + C
搜索代码Ctrl + F
全屏模式F11
增大字号Ctrl + =
减小字号Ctrl + -
显示快捷键?