35 #include <linux/module.h>    36 #include <linux/vmalloc.h>    52 static int eccdev_open(
struct inode *, 
struct file *);
    54 static long eccdev_ioctl(
struct file *, 
unsigned int, 
unsigned long);
    55 static int eccdev_mmap(
struct file *, 
struct vm_area_struct *);
    60 #define PAGE_FAULT_VERSION KERNEL_VERSION(2, 6, 23)    62 #if LINUX_VERSION_CODE < KERNEL_VERSION(4, 17, 0)    63 # define FAULT_RETURN_TYPE int    65 # define FAULT_RETURN_TYPE vm_fault_t    68 #if LINUX_VERSION_CODE >= PAGE_FAULT_VERSION    70 #
if LINUX_VERSION_CODE < KERNEL_VERSION(4, 11, 0)
    71         struct vm_area_struct *,
    75 static struct page *eccdev_vma_nopage(
    76         struct vm_area_struct *, 
unsigned long, 
int *);
    94 #if LINUX_VERSION_CODE >= PAGE_FAULT_VERSION    97     .nopage = eccdev_vma_nopage
   127     cdev->
cdev.owner = THIS_MODULE;
   129     ret = cdev_add(&cdev->
cdev,
   130             MKDEV(MAJOR(dev_num), master->
index), 1);
   144     cdev_del(&cdev->
cdev);
   161                 "Failed to allocate memory for private data structure.\n");
   166     priv->
ctx.writable = (filp->f_mode & FMODE_WRITE) != 0;
   167     priv->
ctx.requested = 0;
   168     priv->
ctx.process_data = NULL;
   169     priv->
ctx.process_data_size = 0;
   171     filp->private_data = priv;
   188     if (priv->
ctx.requested) {
   192     if (priv->
ctx.process_data) {
   193         vfree(priv->
ctx.process_data);
   208 long eccdev_ioctl(
struct file *filp, 
unsigned int cmd, 
unsigned long arg)
   214             "ioctl(filp = 0x%p, cmd = 0x%08x (0x%02x), arg = 0x%lx)\n",
   215             filp, cmd, _IOC_NR(cmd), arg);
   218     return ec_ioctl(priv->
cdev->
master, &priv->
ctx, cmd, (
void __user *) arg);
   226 #define VM_DONTDUMP VM_RESERVED   238         struct vm_area_struct *vma
   246 #if LINUX_VERSION_CODE >= KERNEL_VERSION(6, 3, 0)   251     vma->vm_private_data = priv;
   258 #if LINUX_VERSION_CODE >= PAGE_FAULT_VERSION   268 #
if LINUX_VERSION_CODE < KERNEL_VERSION(4, 11, 0)
   269         struct vm_area_struct *vma, 
   274 #if LINUX_VERSION_CODE >= KERNEL_VERSION(4, 11, 0)   275     struct vm_area_struct *vma = vmf->vma;
   277     unsigned long offset = vmf->pgoff << PAGE_SHIFT;
   281     if (offset >= priv->
ctx.process_data_size) {
   282         return VM_FAULT_SIGBUS;
   285     page = vmalloc_to_page(priv->
ctx.process_data + offset);
   287         return VM_FAULT_SIGBUS;
   294             " offset = %lu, page = %p\n", offset, page);
   306 struct page *eccdev_vma_nopage(
   307         struct vm_area_struct *vma, 
   309         unsigned long address, 
   313     unsigned long offset;
   314     struct page *page = NOPAGE_SIGBUS;
   318     offset = (address - vma->vm_start) + (vma->vm_pgoff << PAGE_SHIFT);
   320     if (offset >= priv->
ctx.process_data_size)
   321         return NOPAGE_SIGBUS;
   323     page = vmalloc_to_page(priv->
ctx.process_data + offset);
   326             " offset = %#lx, page = %p\n", address, offset, page);
   330         *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. 
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. 
static FAULT_RETURN_TYPE eccdev_vma_fault(struct vm_fault *)
Page fault callback for a virtual memory area. 
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.