37 #include <linux/module.h> 38 #include <linux/vmalloc.h> 54 static int eccdev_open(
struct inode *,
struct file *);
56 static long eccdev_ioctl(
struct file *,
unsigned int,
unsigned long);
57 static int eccdev_mmap(
struct file *,
struct vm_area_struct *);
62 #define PAGE_FAULT_VERSION KERNEL_VERSION(2, 6, 23) 64 #if LINUX_VERSION_CODE >= PAGE_FAULT_VERSION 66 #if LINUX_VERSION_CODE > KERNEL_VERSION(5, 0, 0) 72 #
if LINUX_VERSION_CODE < KERNEL_VERSION(4, 11, 0)
73 struct vm_area_struct *,
77 static struct page *eccdev_vma_nopage(
78 struct vm_area_struct *,
unsigned long,
int *);
96 #if LINUX_VERSION_CODE >= PAGE_FAULT_VERSION 99 .nopage = eccdev_vma_nopage
128 cdev_init(&cdev->
cdev, &eccdev_fops);
129 cdev->
cdev.owner = THIS_MODULE;
131 ret = cdev_add(&cdev->
cdev,
132 MKDEV(MAJOR(dev_num), master->
index), 1);
146 cdev_del(&cdev->
cdev);
163 "Failed to allocate memory for private data structure.\n");
168 priv->
ctx.writable = (filp->f_mode & FMODE_WRITE) != 0;
169 priv->
ctx.requested = 0;
170 priv->
ctx.process_data = NULL;
171 priv->
ctx.process_data_size = 0;
173 filp->private_data = priv;
190 if (priv->
ctx.requested) {
194 if (priv->
ctx.process_data) {
195 vfree(priv->
ctx.process_data);
210 long eccdev_ioctl(
struct file *filp,
unsigned int cmd,
unsigned long arg)
216 "ioctl(filp = 0x%p, cmd = 0x%08x (0x%02x), arg = 0x%lx)\n",
217 filp, cmd, _IOC_NR(cmd), arg);
220 return ec_ioctl(priv->
cdev->
master, &priv->
ctx, cmd, (
void __user *) arg);
228 #define VM_DONTDUMP VM_RESERVED 240 struct vm_area_struct *vma
249 vma->vm_private_data = priv;
256 #if LINUX_VERSION_CODE >= PAGE_FAULT_VERSION 266 #if LINUX_VERSION_CODE > KERNEL_VERSION(5, 0, 0) 272 #
if LINUX_VERSION_CODE < KERNEL_VERSION(4, 11, 0)
273 struct vm_area_struct *vma,
278 #if LINUX_VERSION_CODE >= KERNEL_VERSION(4, 11, 0) 279 struct vm_area_struct *vma = vmf->vma;
281 unsigned long offset = vmf->pgoff << PAGE_SHIFT;
285 if (offset >= priv->
ctx.process_data_size) {
286 return VM_FAULT_SIGBUS;
289 page = vmalloc_to_page(priv->
ctx.process_data + offset);
291 return VM_FAULT_SIGBUS;
298 #if (LINUX_VERSION_CODE >= KERNEL_VERSION(4,10,0))
299 " offset = %lu, page = %p\n", (
void*)vmf->address, offset, page);
301 " offset = %lu, page = %p\n", vmf->virtual_address, offset, page);
314 struct page *eccdev_vma_nopage(
315 struct vm_area_struct *vma,
317 unsigned long address,
321 unsigned long offset;
322 struct page *page = NOPAGE_SIGBUS;
326 offset = (address - vma->vm_start) + (vma->vm_pgoff << PAGE_SHIFT);
328 if (offset >= priv->
ctx.process_data_size)
329 return NOPAGE_SIGBUS;
331 page = vmalloc_to_page(priv->
ctx.process_data + offset);
334 " offset = %#lx, page = %p\n", address, offset, page);
338 *type = VM_FAULT_MINOR;
void ecrt_release_master(ec_master_t *master)
Releases a requested EtherCAT master.
ec_master_t * master
Master owning the device.
#define VM_DONTDUMP
VM_RESERVED disappeared in 3.7.
static int eccdev_vma_fault(struct vm_fault *)
Page fault callback for a virtual memory area.
Private data structure for file handles.
struct cdev cdev
Character device.
ec_cdev_t * cdev
Character device.
EtherCAT master structure.
#define EC_MASTER_DBG(master, level, fmt, args...)
Convenience macro for printing master-specific debug messages to syslog.
Ethernet over EtherCAT (EoE)
static int eccdev_mmap(struct file *, struct vm_area_struct *)
Memory-map callback for the EtherCAT character device.
struct vm_operations_struct eccdev_vm_ops
Callbacks for a virtual memory area retrieved with ecdevc_mmap().
#define EC_MASTER_ERR(master, fmt, args...)
Convenience macro for printing master-specific errors to syslog.
static long eccdev_ioctl(struct file *, unsigned int, unsigned long)
Called when an ioctl() command is issued.
ec_ioctl_context_t ctx
Context.
static int eccdev_open(struct inode *, struct file *)
Called when the cdev is opened.
Vendor specific over EtherCAT protocol handler.
static int eccdev_release(struct inode *, struct file *)
Called when the cdev is closed.
void ec_cdev_clear(ec_cdev_t *cdev)
Destructor.
#define DEBUG
Set to 1 to enable device operations debugging.
EtherCAT master character device.
EtherCAT master character device IOCTL commands.
EtherCAT slave configuration structure.
EtherCAT master character device.
static struct file_operations eccdev_fops
File operation callbacks for the EtherCAT character device.
int ec_cdev_init(ec_cdev_t *cdev, ec_master_t *master, dev_t dev_num)
Constructor.