文件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;
}
标签:operations,文件,struct,int,dev,rtdm,fd,device 来源: https://blog.csdn.net/robot1701/article/details/104492552