文件operations

在RTDM中
rtdm_open

static inline int rtdm_open(const char *path, int oflag, ...)
{
	return __rtdm_dev_open(path, oflag);
}

__rtdm_dev_open()

int __rtdm_dev_open(const char *path, int oflag)
{
	struct rtdm_dev_context *context;
	struct rtdm_device *dev;
	struct file *filp;
	int ufd, ret;

	secondary_mode_only();

	/*
	 * CAUTION: we do want a lookup into the registry to happen
	 * before any attempt is made to open the devnode, so that we
	 * don't inadvertently open a regular (i.e. non-RTDM) device.
	 * Reason is that opening, then closing a device - because we
	 * don't manage it - may incur side-effects we don't want,
	 * e.g. opening then closing one end of a pipe would cause the
	 * other side to read the EOF condition.  This is basically
	 * why we keep a RTDM registry for named devices, so that we
	 * can figure out whether an open() request is going to be
	 * valid, without having to open the devnode yet.
	 */
	dev = __rtdm_get_namedev(path);
	if (dev == NULL)
		return -ENODEV;

	ufd = get_unused_fd_flags(oflag);
	if (ufd < 0) {
		ret = ufd;
		goto fail_fd;
	}

	filp = open_devnode(dev, path, oflag);
	if (IS_ERR(filp)) {
		ret = PTR_ERR(filp);
		goto fail_fopen;
	}

	ret = create_instance(ufd, dev, &context);
	if (ret < 0)
		goto fail_create;

	context->fd.minor = dev->minor;
	context->fd.oflags = oflag;

	trace_cobalt_fd_open(current, &context->fd, ufd, oflag);

	if (dev->ops.open) {
		ret = dev->ops.open(&context->fd, oflag);
		if (!XENO_ASSERT(COBALT, !spltest()))
			splnone();
		if (ret < 0)
			goto fail_open;
	}

	fd_install(ufd, filp);

	trace_cobalt_fd_created(&context->fd, ufd);

	return ufd;

fail_open:
	cleanup_instance(dev, context);
fail_create:
	filp_close(filp, current->files);
fail_fopen:
	put_unused_fd(ufd);
fail_fd:
	__rtdm_put_device(dev);

	return ret;
}

dev->ops.open

/**
 * @anchor rtdm_fd_ops
 * @brief RTDM file operation descriptor.
 *
 * This structure describes the operations available with a RTDM
 * device, defining handlers for submitting I/O requests. Those
 * handlers are implemented by RTDM device drivers.
 */
struct rtdm_fd_ops {
	/** See rtdm_open_handler(). */
	int (*open)(struct rtdm_fd *fd, int oflags);
	/** See rtdm_socket_handler(). */
	int (*socket)(struct rtdm_fd *fd, int protocol);
	/** See rtdm_close_handler(). */
	void (*close)(struct rtdm_fd *fd);
	/** See rtdm_ioctl_handler(). */
	int (*ioctl_rt)(struct rtdm_fd *fd,
			unsigned int request, void __user *arg);
	/** See rtdm_ioctl_handler(). */
	int (*ioctl_nrt)(struct rtdm_fd *fd,
			 unsigned int request, void __user *arg);
	/** See rtdm_read_handler(). */
	ssize_t (*read_rt)(struct rtdm_fd *fd,
			   void __user *buf, size_t size);
	/** See rtdm_read_handler(). */
	ssize_t (*read_nrt)(struct rtdm_fd *fd,
			    void __user *buf, size_t size);
	/** See rtdm_write_handler(). */
	ssize_t (*write_rt)(struct rtdm_fd *fd,
			    const void __user *buf, size_t size);
	/** See rtdm_write_handler(). */
	ssize_t (*write_nrt)(struct rtdm_fd *fd,
			     const void __user *buf, size_t size);
	/** See rtdm_recvmsg_handler(). */
	ssize_t (*recvmsg_rt)(struct rtdm_fd *fd,
			      struct user_msghdr *msg, int flags);
	/** See rtdm_recvmsg_handler(). */
	ssize_t (*recvmsg_nrt)(struct rtdm_fd *fd,
			       struct user_msghdr *msg, int flags);
	/** See rtdm_sendmsg_handler(). */
	ssize_t (*sendmsg_rt)(struct rtdm_fd *fd,
			      const struct user_msghdr *msg, int flags);
	/** See rtdm_sendmsg_handler(). */
	ssize_t (*sendmsg_nrt)(struct rtdm_fd *fd,
			       const struct user_msghdr *msg, int flags);
	/** See rtdm_select_handler(). */
	int (*select)(struct rtdm_fd *fd,
		      struct xnselector *selector,
		      unsigned int type, unsigned int index);
	/** See rtdm_mmap_handler(). */
	int (*mmap)(struct rtdm_fd *fd,
		    struct vm_area_struct *vma);
	/** See rtdm_get_unmapped_area_handler(). */
	unsigned long (*get_unmapped_area)(struct rtdm_fd *fd,
					   unsigned long len,
					   unsigned long pgoff,
					   unsigned long flags);
};
struct vm_area_struct;
struct rtdm_fd;
struct _rtdm_mmap_request;
struct xnselector;
struct cobalt_ppd;

/**
 * @file
 * @anchor File operation handlers
 * @addtogroup rtdm_device_register
 * @{
 */

```c
/**
 * Open handler for named devices
 *
 * @param[in] fd File descriptor associated with opened device instance
 * @param[in] oflags Open flags as passed by the user
 *
 * The file descriptor carries a device minor information which can be
 * retrieved by a call to rtdm_fd_minor(fd). The minor number can be
 * used for distinguishing devices managed by a driver.
 *
 * @return 0 on success. On failure, a negative error code is returned.
 *
 * @see @c open() in IEEE Std 1003.1,
 * http://www.opengroup.org/onlinepubs/009695399
 */
int rtdm_open_handler(struct rtdm_fd *fd, int oflags);

/*********************************************************sendto ********************************************************/
sendto:
系统调用:

COBALT_IMPL(ssize_t, sendto, (int fd, const void *buf, size_t len, int flags,
			      const struct sockaddr *to, socklen_t tolen))
{
	struct iovec iov = {
		.iov_base = (void *)buf,
		.iov_len = len,
	};
	struct msghdr msg = {
		.msg_name = (struct sockaddr *)to,
		.msg_namelen = tolen,
		.msg_iov = &iov,
		.msg_iovlen = 1,
		.msg_control = NULL,
		.msg_controllen = 0,
	};
	int ret;

	ret = do_sendmsg(fd, &msg, flags);
	if (ret != -EBADF && ret != -ENOSYS)
		return set_errno(ret);

	return __STD(sendto(fd, buf, len, flags, to, tolen));
}

```c
static ssize_t do_sendmsg(int fd, const struct msghdr *msg, int flags)
{
	int ret, oldtype;

	pthread_setcanceltype(PTHREAD_CANCEL_ASYNCHRONOUS, &oldtype);

	ret = XENOMAI_SYSCALL3(sc_cobalt_sendmsg, fd, msg, flags);

	pthread_setcanceltype(oldtype, NULL);

	return ret;
}
#define XENOMAI_SYSCALL3(op,a1,a2,a3)       XENOMAI_DO_SYSCALL(3,op,a1,a2,a3)


#define XENOMAI_DO_SYSCALL(nr, op, args...)		\
    __emit_syscall##nr(__xn_syscode(op), ##args)

CAN控制器设备信息与设备文件操作(硬件发生与接收)

struct rtcan_device {
    unsigned int        version;

    char                name[IFNAMSIZ];

    char                *ctrl_name; /* Name of CAN controller */
    char                *board_name;/* Name of CAN board */

    unsigned long       base_addr;  /* device I/O address   */
    rtdm_irq_t          irq_handle; /* RTDM IRQ handle */

    int                 ifindex;
#ifdef RTCAN_USE_REFCOUNT
    atomic_t            refcount;
#endif

    void                *priv;      /* pointer to chip private data */

    void                *board_priv;/* pointer to board private data*/

    struct semaphore    nrt_lock;   /* non-real-time locking        */

    /* Spinlock for all devices (but not for all attributes) and also for HW
     * access to all CAN controllers
     所有设备(但不是所有属性)和所有控制器的硬件访问的自旋锁 
     */
    rtdm_lock_t         device_lock;

    /* Acts as a mutex allowing only one sender to write to the MSCAN
     * simultaneously. Created when the controller goes into operating mode,
     * destroyed if it goes into reset mode. 
     作为互斥锁,只允许一个发送者同时向MSCAN写入数据。控制器进入工作模式时创建,进入复位模式时销毁。* /*/
    rtdm_sem_t          tx_sem;

    /* Baudrate of this device. Protected by device_lock in all device
     * structures. 
     这个设备的波特率。在所有设备结构中由device_lock保护。*/
    unsigned int        can_sys_clock;


    /* Baudrate of this device. Protected by device_lock in all device
     * structures. */
    can_baudrate_t      baudrate;

    struct can_bittime  bit_time;
    const struct can_bittiming_const *bittiming_const;

    /* State which the controller is in. Protected by device_lock in all
     * device structures. */
    can_state_t state;

    /* State which the controller was before sleeping. Protected by
     * device_lock in all device structures. */
    can_state_t          state_before_sleep;

    /* Controller specific settings. Protected by device_lock in all
     * device structures. */
    can_ctrlmode_t       ctrl_mode;

    /* Device operations 设备操作*/
    int                 (*hard_start_xmit)(struct rtcan_device *dev,
					   struct can_frame *frame);
    int                 (*do_set_mode)(struct rtcan_device *dev,
				       can_mode_t mode,
				       rtdm_lockctx_t *lock_ctx);
    can_state_t         (*do_get_state)(struct rtcan_device *dev);
    int                 (*do_set_bit_time)(struct rtcan_device *dev,
					   struct can_bittime *bit_time,
					   rtdm_lockctx_t *lock_ctx);
#ifdef CONFIG_XENO_DRIVERS_CAN_BUS_ERR
    void                (*do_enable_bus_err)(struct rtcan_device *dev);
#endif

    /* Reception list head. This list contains all filters which have been
     * registered via a bind call. */
    struct rtcan_recv               *recv_list;

    /* Empty list head. This list contains all empty entries not needed
     * by the reception list and therefore is disjunctive with it. */
    struct rtcan_recv               *empty_list;

    /* Preallocated array for the list entries. To increase cache
     * locality all list elements are kept in this array. */
    struct rtcan_recv               receivers[RTCAN_MAX_RECEIVERS];

    /* Indicates the length of the empty list */
    int                             free_entries;

    /* A few statistics counters */
    unsigned int tx_count;
    unsigned int rx_count;
    unsigned int err_count;

#ifdef CONFIG_PROC_FS
    struct proc_dir_entry *proc_root;
#endif
#ifdef CONFIG_XENO_DRIVERS_CAN_LOOPBACK
    struct rtcan_skb tx_skb;
    struct rtcan_socket *tx_socket;
#endif /* CONFIG_XENO_DRIVERS_CAN_LOOPBACK */
};

/*

 *  Start a transmission to a SJA1000 device 
    启动到SJA1000设备的传输 
 */
static int rtcan_sja_start_xmit(struct rtcan_device *dev,
				can_frame_t *frame)
{
    int             i;
    /* "Real" size of the payload 有效载荷的“真实”大小*/
    u8   size;
    /* Content of frame information register 帧信息寄存器的内容*/
    u8   fir;
    struct rtcan_sja1000 *chip = (struct rtcan_sja1000 *)dev->priv;

    /* Get DLC */
    fir  = frame->can_dlc;

    /* If DLC exceeds 8 bytes adjust it to 8 (for the payload) 如果数据链路连接器超过8字节,则将其调整为8(对于有效负载 */
    size = (fir > 8) ? 8 : fir;


    if (frame->can_id & CAN_EFF_FLAG) {
	/* Send extended frame  发送扩展帧 */
	fir |= SJA_FIR_EFF;

	/* Write ID */
	chip->write_reg(dev, SJA_ID1, frame->can_id >> 21);
	chip->write_reg(dev, SJA_ID2, frame->can_id >> 13);
	chip->write_reg(dev, SJA_ID3, frame->can_id >> 5);
	chip->write_reg(dev, SJA_ID4, frame->can_id << 3);

	/* RTR? 远程请求发送位?*/
	if (frame->can_id & CAN_RTR_FLAG)
	    fir |= SJA_FIR_RTR;

	else {
	    /* No RTR, write data bytes */
	    for (i = 0; i < size; i++)
		chip->write_reg(dev, SJA_DATA_EFF(i),
				frame->data[i]);
	}

    } else {
	/* Send standard frame   发送标准帧 */

	/* Write ID */
	chip->write_reg(dev, SJA_ID1, frame->can_id >> 3);
	chip->write_reg(dev, SJA_ID2, frame->can_id << 5);

	/* RTR? */
	if (frame->can_id & CAN_RTR_FLAG)
	    fir |= SJA_FIR_RTR;

	else {
	    /* No RTR, write data bytes */
	    for (i = 0; i < size; i++)
		chip->write_reg(dev, SJA_DATA_SFF(i),
				frame->data[i]);
	}
    }


    /* Write frame information register 写帧信息带寄存器*/
    chip->write_reg(dev, SJA_FIR, fir);

    /* Push the 'send' button 按“发送”按钮 */
    if (dev->ctrl_mode & CAN_CTRLMODE_LOOPBACK)
	chip->write_reg(dev, SJA_CMR, SJA_CMR_SRR);
    else
	chip->write_reg(dev, SJA_CMR, SJA_CMR_TR);

    return 0;
}
上一篇:css3媒体查询中device-width和width的区别


下一篇:各种结构体