master/cdev.c
branchstable-1.5
changeset 2433 3bdd7a747fae
parent 2421 bc2d4bf9cbe5
child 2516 3680924f6f87
equal deleted inserted replaced
2432:f4313f5aba88 2433:3bdd7a747fae
     1 /******************************************************************************
     1 /******************************************************************************
     2  *
     2  *
     3  *  $Id$
     3  *  $Id$
     4  *
     4  *
     5  *  Copyright (C) 2006-2008  Florian Pose, Ingenieurgemeinschaft IgH
     5  *  Copyright (C) 2006-2012  Florian Pose, Ingenieurgemeinschaft IgH
     6  *
     6  *
     7  *  This file is part of the IgH EtherCAT Master.
     7  *  This file is part of the IgH EtherCAT Master.
     8  *
     8  *
     9  *  The IgH EtherCAT Master is free software; you can redistribute it and/or
     9  *  The IgH EtherCAT Master is free software; you can redistribute it and/or
    10  *  modify it under the terms of the GNU General Public License version 2, as
    10  *  modify it under the terms of the GNU General Public License version 2, as
    43 #include "slave_config.h"
    43 #include "slave_config.h"
    44 #include "voe_handler.h"
    44 #include "voe_handler.h"
    45 #include "ethernet.h"
    45 #include "ethernet.h"
    46 #include "ioctl.h"
    46 #include "ioctl.h"
    47 
    47 
    48 /** Set to 1 to enable ioctl() command debugging.
    48 /** Set to 1 to enable device operations debugging.
    49  */
    49  */
    50 #define DEBUG_IOCTL 0
    50 #define DEBUG 0
    51 
       
    52 /** Set to 1 to enable ioctl() latency warnings.
       
    53  *
       
    54  * Requires CPU timestamp counter!
       
    55  */
       
    56 #define DEBUG_LATENCY 0
       
    57 
    51 
    58 /*****************************************************************************/
    52 /*****************************************************************************/
    59 
    53 
    60 static int eccdev_open(struct inode *, struct file *);
    54 static int eccdev_open(struct inode *, struct file *);
    61 static int eccdev_release(struct inode *, struct file *);
    55 static int eccdev_release(struct inode *, struct file *);
   100 
    94 
   101 /** Private data structure for file handles.
    95 /** Private data structure for file handles.
   102  */
    96  */
   103 typedef struct {
    97 typedef struct {
   104     ec_cdev_t *cdev; /**< Character device. */
    98     ec_cdev_t *cdev; /**< Character device. */
   105     unsigned int requested; /**< Master wac requested via this file handle. */
    99     ec_ioctl_context_t ctx; /**< Context. */
   106     uint8_t *process_data; /**< Total process data area. */
       
   107     size_t process_data_size; /**< Size of the \a process_data. */
       
   108 } ec_cdev_priv_t;
   100 } ec_cdev_priv_t;
   109 
   101 
   110 /*****************************************************************************/
   102 /*****************************************************************************/
   111 
   103 
   112 /** Constructor.
   104 /** Constructor.
   140 /** Destructor.
   132 /** Destructor.
   141  */
   133  */
   142 void ec_cdev_clear(ec_cdev_t *cdev /**< EtherCAT XML device */)
   134 void ec_cdev_clear(ec_cdev_t *cdev /**< EtherCAT XML device */)
   143 {
   135 {
   144     cdev_del(&cdev->cdev);
   136     cdev_del(&cdev->cdev);
   145 }
       
   146 
       
   147 /*****************************************************************************/
       
   148 
       
   149 /** Copies a string to an ioctl structure.
       
   150  */
       
   151 void ec_cdev_strcpy(
       
   152         char *target, /**< Target. */
       
   153         const char *source /**< Source. */
       
   154         )
       
   155 {
       
   156     if (source) {
       
   157         strncpy(target, source, EC_IOCTL_STRING_SIZE);
       
   158         target[EC_IOCTL_STRING_SIZE - 1] = 0;
       
   159     } else {
       
   160         target[0] = 0;
       
   161     }
       
   162 }
       
   163 
       
   164 /*****************************************************************************/
       
   165 
       
   166 /** Get module information.
       
   167  */
       
   168 int ec_cdev_ioctl_module(
       
   169         unsigned long arg /**< Userspace address to store the results. */
       
   170         )
       
   171 {
       
   172     ec_ioctl_module_t data;
       
   173 
       
   174     data.ioctl_version_magic = EC_IOCTL_VERSION_MAGIC;
       
   175     data.master_count = ec_master_count();
       
   176 
       
   177     if (copy_to_user((void __user *) arg, &data, sizeof(data)))
       
   178         return -EFAULT;
       
   179 
       
   180     return 0;
       
   181 }
       
   182 
       
   183 /*****************************************************************************/
       
   184 
       
   185 /** Get master information.
       
   186  */
       
   187 int ec_cdev_ioctl_master(
       
   188         ec_master_t *master, /**< EtherCAT master. */
       
   189         unsigned long arg /**< Userspace address to store the results. */
       
   190         )
       
   191 {
       
   192     ec_ioctl_master_t data;
       
   193     unsigned int i, j;
       
   194 
       
   195     if (down_interruptible(&master->master_sem))
       
   196         return -EINTR;
       
   197 
       
   198     data.slave_count = master->slave_count;
       
   199     data.config_count = ec_master_config_count(master);
       
   200     data.domain_count = ec_master_domain_count(master);
       
   201 #ifdef EC_EOE
       
   202     data.eoe_handler_count = ec_master_eoe_handler_count(master);
       
   203 #endif
       
   204     data.phase = (uint8_t) master->phase;
       
   205     data.active = (uint8_t) master->active;
       
   206     data.scan_busy = master->scan_busy;
       
   207 
       
   208     up(&master->master_sem);
       
   209 
       
   210     if (down_interruptible(&master->device_sem))
       
   211         return -EINTR;
       
   212 
       
   213     for (i = 0; i < EC_NUM_DEVICES; i++) {
       
   214         ec_device_t *device = &master->devices[i];
       
   215 
       
   216         if (device->dev) {
       
   217             memcpy(data.devices[i].address,
       
   218                     device->dev->dev_addr, ETH_ALEN);
       
   219         } else {
       
   220             memcpy(data.devices[i].address, master->macs[i], ETH_ALEN);
       
   221         }
       
   222         data.devices[i].attached = device->dev ? 1 : 0;
       
   223         data.devices[i].link_state = device->link_state ? 1 : 0;
       
   224         data.devices[i].tx_count = device->tx_count;
       
   225         data.devices[i].rx_count = device->rx_count;
       
   226         data.devices[i].tx_bytes = device->tx_bytes;
       
   227         data.devices[i].rx_bytes = device->rx_bytes;
       
   228         data.devices[i].tx_errors = device->tx_errors;
       
   229         for (j = 0; j < EC_RATE_COUNT; j++) {
       
   230             data.devices[i].tx_frame_rates[j] =
       
   231                 device->tx_frame_rates[j];
       
   232             data.devices[i].rx_frame_rates[j] =
       
   233                 device->rx_frame_rates[j];
       
   234             data.devices[i].tx_byte_rates[j] =
       
   235                 device->tx_byte_rates[j];
       
   236             data.devices[i].rx_byte_rates[j] =
       
   237                 device->rx_byte_rates[j];
       
   238         }
       
   239     }
       
   240 
       
   241     data.tx_count = master->device_stats.tx_count;
       
   242     data.rx_count = master->device_stats.rx_count;
       
   243     data.tx_bytes = master->device_stats.tx_bytes;
       
   244     data.rx_bytes = master->device_stats.rx_bytes;
       
   245     for (i = 0; i < EC_RATE_COUNT; i++) {
       
   246         data.tx_frame_rates[i] =
       
   247             master->device_stats.tx_frame_rates[i];
       
   248         data.rx_frame_rates[i] =
       
   249             master->device_stats.rx_frame_rates[i];
       
   250         data.tx_byte_rates[i] =
       
   251             master->device_stats.tx_byte_rates[i];
       
   252         data.rx_byte_rates[i] =
       
   253             master->device_stats.rx_byte_rates[i];
       
   254         data.loss_rates[i] =
       
   255             master->device_stats.loss_rates[i];
       
   256     }
       
   257 
       
   258     up(&master->device_sem);
       
   259 
       
   260     data.app_time = master->app_time;
       
   261     data.ref_clock =
       
   262         master->dc_ref_clock ? master->dc_ref_clock->ring_position : 0xffff;
       
   263 
       
   264     if (copy_to_user((void __user *) arg, &data, sizeof(data)))
       
   265         return -EFAULT;
       
   266 
       
   267     return 0;
       
   268 }
       
   269 
       
   270 /*****************************************************************************/
       
   271 
       
   272 /** Get slave information.
       
   273  */
       
   274 int ec_cdev_ioctl_slave(
       
   275         ec_master_t *master, /**< EtherCAT master. */
       
   276         unsigned long arg /**< Userspace address to store the results. */
       
   277         )
       
   278 {
       
   279     ec_ioctl_slave_t data;
       
   280     const ec_slave_t *slave;
       
   281     int i;
       
   282 
       
   283     if (copy_from_user(&data, (void __user *) arg, sizeof(data))) {
       
   284         return -EFAULT;
       
   285     }
       
   286 
       
   287     if (down_interruptible(&master->master_sem))
       
   288         return -EINTR;
       
   289 
       
   290     if (!(slave = ec_master_find_slave_const(
       
   291                     master, 0, data.position))) {
       
   292         up(&master->master_sem);
       
   293         EC_MASTER_ERR(master, "Slave %u does not exist!\n", data.position);
       
   294         return -EINVAL;
       
   295     }
       
   296 
       
   297     data.device_index = slave->device_index;
       
   298     data.vendor_id = slave->sii.vendor_id;
       
   299     data.product_code = slave->sii.product_code;
       
   300     data.revision_number = slave->sii.revision_number;
       
   301     data.serial_number = slave->sii.serial_number;
       
   302     data.alias = slave->effective_alias;
       
   303     data.boot_rx_mailbox_offset = slave->sii.boot_rx_mailbox_offset;
       
   304     data.boot_rx_mailbox_size = slave->sii.boot_rx_mailbox_size;
       
   305     data.boot_tx_mailbox_offset = slave->sii.boot_tx_mailbox_offset;
       
   306     data.boot_tx_mailbox_size = slave->sii.boot_tx_mailbox_size;
       
   307     data.std_rx_mailbox_offset = slave->sii.std_rx_mailbox_offset;
       
   308     data.std_rx_mailbox_size = slave->sii.std_rx_mailbox_size;
       
   309     data.std_tx_mailbox_offset = slave->sii.std_tx_mailbox_offset;
       
   310     data.std_tx_mailbox_size = slave->sii.std_tx_mailbox_size;
       
   311     data.mailbox_protocols = slave->sii.mailbox_protocols;
       
   312     data.has_general_category = slave->sii.has_general;
       
   313     data.coe_details = slave->sii.coe_details;
       
   314     data.general_flags = slave->sii.general_flags;
       
   315     data.current_on_ebus = slave->sii.current_on_ebus;
       
   316     for (i = 0; i < EC_MAX_PORTS; i++) {
       
   317         data.ports[i].desc = slave->ports[i].desc;
       
   318         data.ports[i].link.link_up = slave->ports[i].link.link_up;
       
   319         data.ports[i].link.loop_closed = slave->ports[i].link.loop_closed;
       
   320         data.ports[i].link.signal_detected =
       
   321             slave->ports[i].link.signal_detected;
       
   322         data.ports[i].receive_time = slave->ports[i].receive_time;
       
   323         if (slave->ports[i].next_slave) {
       
   324             data.ports[i].next_slave =
       
   325                 slave->ports[i].next_slave->ring_position;
       
   326         } else {
       
   327             data.ports[i].next_slave = 0xffff;
       
   328         }
       
   329         data.ports[i].delay_to_next_dc = slave->ports[i].delay_to_next_dc;
       
   330     }
       
   331     data.fmmu_bit = slave->base_fmmu_bit_operation;
       
   332     data.dc_supported = slave->base_dc_supported;
       
   333     data.dc_range = slave->base_dc_range;
       
   334     data.has_dc_system_time = slave->has_dc_system_time;
       
   335     data.transmission_delay = slave->transmission_delay;
       
   336     data.al_state = slave->current_state;
       
   337     data.error_flag = slave->error_flag;
       
   338 
       
   339     data.sync_count = slave->sii.sync_count;
       
   340     data.sdo_count = ec_slave_sdo_count(slave);
       
   341     data.sii_nwords = slave->sii_nwords;
       
   342     ec_cdev_strcpy(data.group, slave->sii.group);
       
   343     ec_cdev_strcpy(data.image, slave->sii.image);
       
   344     ec_cdev_strcpy(data.order, slave->sii.order);
       
   345     ec_cdev_strcpy(data.name, slave->sii.name);
       
   346 
       
   347     up(&master->master_sem);
       
   348 
       
   349     if (copy_to_user((void __user *) arg, &data, sizeof(data)))
       
   350         return -EFAULT;
       
   351 
       
   352     return 0;
       
   353 }
       
   354 
       
   355 /*****************************************************************************/
       
   356 
       
   357 /** Get slave sync manager information.
       
   358  */
       
   359 int ec_cdev_ioctl_slave_sync(
       
   360         ec_master_t *master, /**< EtherCAT master. */
       
   361         unsigned long arg /**< Userspace address to store the results. */
       
   362         )
       
   363 {
       
   364     ec_ioctl_slave_sync_t data;
       
   365     const ec_slave_t *slave;
       
   366     const ec_sync_t *sync;
       
   367 
       
   368     if (copy_from_user(&data, (void __user *) arg, sizeof(data))) {
       
   369         return -EFAULT;
       
   370     }
       
   371 
       
   372     if (down_interruptible(&master->master_sem))
       
   373         return -EINTR;
       
   374 
       
   375     if (!(slave = ec_master_find_slave_const(
       
   376                     master, 0, data.slave_position))) {
       
   377         up(&master->master_sem);
       
   378         EC_MASTER_ERR(master, "Slave %u does not exist!\n",
       
   379                 data.slave_position);
       
   380         return -EINVAL;
       
   381     }
       
   382 
       
   383     if (data.sync_index >= slave->sii.sync_count) {
       
   384         up(&master->master_sem);
       
   385         EC_SLAVE_ERR(slave, "Sync manager %u does not exist!\n",
       
   386                 data.sync_index);
       
   387         return -EINVAL;
       
   388     }
       
   389 
       
   390     sync = &slave->sii.syncs[data.sync_index];
       
   391 
       
   392     data.physical_start_address = sync->physical_start_address;
       
   393     data.default_size = sync->default_length;
       
   394     data.control_register = sync->control_register;
       
   395     data.enable = sync->enable;
       
   396     data.pdo_count = ec_pdo_list_count(&sync->pdos);
       
   397 
       
   398     up(&master->master_sem);
       
   399 
       
   400     if (copy_to_user((void __user *) arg, &data, sizeof(data)))
       
   401         return -EFAULT;
       
   402 
       
   403     return 0;
       
   404 }
       
   405 
       
   406 /*****************************************************************************/
       
   407 
       
   408 /** Get slave sync manager PDO information.
       
   409  */
       
   410 int ec_cdev_ioctl_slave_sync_pdo(
       
   411         ec_master_t *master, /**< EtherCAT master. */
       
   412         unsigned long arg /**< Userspace address to store the results. */
       
   413         )
       
   414 {
       
   415     ec_ioctl_slave_sync_pdo_t data;
       
   416     const ec_slave_t *slave;
       
   417     const ec_sync_t *sync;
       
   418     const ec_pdo_t *pdo;
       
   419 
       
   420     if (copy_from_user(&data, (void __user *) arg, sizeof(data))) {
       
   421         return -EFAULT;
       
   422     }
       
   423 
       
   424     if (down_interruptible(&master->master_sem))
       
   425         return -EINTR;
       
   426 
       
   427     if (!(slave = ec_master_find_slave_const(
       
   428                     master, 0, data.slave_position))) {
       
   429         up(&master->master_sem);
       
   430         EC_MASTER_ERR(master, "Slave %u does not exist!\n",
       
   431                 data.slave_position);
       
   432         return -EINVAL;
       
   433     }
       
   434 
       
   435     if (data.sync_index >= slave->sii.sync_count) {
       
   436         up(&master->master_sem);
       
   437         EC_SLAVE_ERR(slave, "Sync manager %u does not exist!\n",
       
   438                 data.sync_index);
       
   439         return -EINVAL;
       
   440     }
       
   441 
       
   442     sync = &slave->sii.syncs[data.sync_index];
       
   443     if (!(pdo = ec_pdo_list_find_pdo_by_pos_const(
       
   444                     &sync->pdos, data.pdo_pos))) {
       
   445         up(&master->master_sem);
       
   446         EC_SLAVE_ERR(slave, "Sync manager %u does not contain a PDO with "
       
   447                 "position %u!\n", data.sync_index, data.pdo_pos);
       
   448         return -EINVAL;
       
   449     }
       
   450 
       
   451     data.index = pdo->index;
       
   452     data.entry_count = ec_pdo_entry_count(pdo);
       
   453     ec_cdev_strcpy(data.name, pdo->name);
       
   454 
       
   455     up(&master->master_sem);
       
   456 
       
   457     if (copy_to_user((void __user *) arg, &data, sizeof(data)))
       
   458         return -EFAULT;
       
   459 
       
   460     return 0;
       
   461 }
       
   462 
       
   463 /*****************************************************************************/
       
   464 
       
   465 /** Get slave sync manager PDO entry information.
       
   466  */
       
   467 int ec_cdev_ioctl_slave_sync_pdo_entry(
       
   468         ec_master_t *master, /**< EtherCAT master. */
       
   469         unsigned long arg /**< Userspace address to store the results. */
       
   470         )
       
   471 {
       
   472     ec_ioctl_slave_sync_pdo_entry_t data;
       
   473     const ec_slave_t *slave;
       
   474     const ec_sync_t *sync;
       
   475     const ec_pdo_t *pdo;
       
   476     const ec_pdo_entry_t *entry;
       
   477 
       
   478     if (copy_from_user(&data, (void __user *) arg, sizeof(data))) {
       
   479         return -EFAULT;
       
   480     }
       
   481 
       
   482     if (down_interruptible(&master->master_sem))
       
   483         return -EINTR;
       
   484 
       
   485     if (!(slave = ec_master_find_slave_const(
       
   486                     master, 0, data.slave_position))) {
       
   487         up(&master->master_sem);
       
   488         EC_MASTER_ERR(master, "Slave %u does not exist!\n",
       
   489                 data.slave_position);
       
   490         return -EINVAL;
       
   491     }
       
   492 
       
   493     if (data.sync_index >= slave->sii.sync_count) {
       
   494         up(&master->master_sem);
       
   495         EC_SLAVE_ERR(slave, "Sync manager %u does not exist!\n",
       
   496                 data.sync_index);
       
   497         return -EINVAL;
       
   498     }
       
   499 
       
   500     sync = &slave->sii.syncs[data.sync_index];
       
   501     if (!(pdo = ec_pdo_list_find_pdo_by_pos_const(
       
   502                     &sync->pdos, data.pdo_pos))) {
       
   503         up(&master->master_sem);
       
   504         EC_SLAVE_ERR(slave, "Sync manager %u does not contain a PDO with "
       
   505                 "position %u!\n", data.sync_index, data.pdo_pos);
       
   506         return -EINVAL;
       
   507     }
       
   508 
       
   509     if (!(entry = ec_pdo_find_entry_by_pos_const(
       
   510                     pdo, data.entry_pos))) {
       
   511         up(&master->master_sem);
       
   512         EC_SLAVE_ERR(slave, "PDO 0x%04X does not contain an entry with "
       
   513                 "position %u!\n", data.pdo_pos, data.entry_pos);
       
   514         return -EINVAL;
       
   515     }
       
   516 
       
   517     data.index = entry->index;
       
   518     data.subindex = entry->subindex;
       
   519     data.bit_length = entry->bit_length;
       
   520     ec_cdev_strcpy(data.name, entry->name);
       
   521 
       
   522     up(&master->master_sem);
       
   523 
       
   524     if (copy_to_user((void __user *) arg, &data, sizeof(data)))
       
   525         return -EFAULT;
       
   526 
       
   527     return 0;
       
   528 }
       
   529 
       
   530 /*****************************************************************************/
       
   531 
       
   532 /** Get domain information.
       
   533  */
       
   534 int ec_cdev_ioctl_domain(
       
   535         ec_master_t *master, /**< EtherCAT master. */
       
   536         unsigned long arg /**< Userspace address to store the results. */
       
   537         )
       
   538 {
       
   539     ec_ioctl_domain_t data;
       
   540     const ec_domain_t *domain;
       
   541     unsigned int dev_idx;
       
   542 
       
   543     if (copy_from_user(&data, (void __user *) arg, sizeof(data))) {
       
   544         return -EFAULT;
       
   545     }
       
   546 
       
   547     if (down_interruptible(&master->master_sem))
       
   548         return -EINTR;
       
   549 
       
   550     if (!(domain = ec_master_find_domain_const(master, data.index))) {
       
   551         up(&master->master_sem);
       
   552         EC_MASTER_ERR(master, "Domain %u does not exist!\n", data.index);
       
   553         return -EINVAL;
       
   554     }
       
   555 
       
   556     data.data_size = domain->data_size;
       
   557     data.logical_base_address = domain->logical_base_address;
       
   558     for (dev_idx = 0; dev_idx < EC_NUM_DEVICES; dev_idx++) {
       
   559         data.working_counter[dev_idx] = domain->working_counter[dev_idx];
       
   560     }
       
   561     data.expected_working_counter = domain->expected_working_counter;
       
   562     data.fmmu_count = ec_domain_fmmu_count(domain);
       
   563 
       
   564     up(&master->master_sem);
       
   565 
       
   566     if (copy_to_user((void __user *) arg, &data, sizeof(data)))
       
   567         return -EFAULT;
       
   568 
       
   569     return 0;
       
   570 }
       
   571 
       
   572 /*****************************************************************************/
       
   573 
       
   574 /** Get domain FMMU information.
       
   575  */
       
   576 int ec_cdev_ioctl_domain_fmmu(
       
   577         ec_master_t *master, /**< EtherCAT master. */
       
   578         unsigned long arg /**< Userspace address to store the results. */
       
   579         )
       
   580 {
       
   581     ec_ioctl_domain_fmmu_t data;
       
   582     const ec_domain_t *domain;
       
   583     const ec_fmmu_config_t *fmmu;
       
   584 
       
   585     if (copy_from_user(&data, (void __user *) arg, sizeof(data))) {
       
   586         return -EFAULT;
       
   587     }
       
   588 
       
   589     if (down_interruptible(&master->master_sem))
       
   590         return -EINTR;
       
   591 
       
   592     if (!(domain = ec_master_find_domain_const(master, data.domain_index))) {
       
   593         up(&master->master_sem);
       
   594         EC_MASTER_ERR(master, "Domain %u does not exist!\n",
       
   595                 data.domain_index);
       
   596         return -EINVAL;
       
   597     }
       
   598 
       
   599     if (!(fmmu = ec_domain_find_fmmu(domain, data.fmmu_index))) {
       
   600         up(&master->master_sem);
       
   601         EC_MASTER_ERR(master, "Domain %u has less than %u"
       
   602                 " fmmu configurations.\n",
       
   603                 data.domain_index, data.fmmu_index + 1);
       
   604         return -EINVAL;
       
   605     }
       
   606 
       
   607     data.slave_config_alias = fmmu->sc->alias;
       
   608     data.slave_config_position = fmmu->sc->position;
       
   609     data.sync_index = fmmu->sync_index;
       
   610     data.dir = fmmu->dir;
       
   611     data.logical_address = fmmu->logical_start_address;
       
   612     data.data_size = fmmu->data_size;
       
   613 
       
   614     up(&master->master_sem);
       
   615 
       
   616     if (copy_to_user((void __user *) arg, &data, sizeof(data)))
       
   617         return -EFAULT;
       
   618 
       
   619     return 0;
       
   620 }
       
   621 
       
   622 /*****************************************************************************/
       
   623 
       
   624 /** Get domain data.
       
   625  */
       
   626 int ec_cdev_ioctl_domain_data(
       
   627         ec_master_t *master, /**< EtherCAT master. */
       
   628         unsigned long arg /**< Userspace address to store the results. */
       
   629         )
       
   630 {
       
   631     ec_ioctl_domain_data_t data;
       
   632     const ec_domain_t *domain;
       
   633 
       
   634     if (copy_from_user(&data, (void __user *) arg, sizeof(data))) {
       
   635         return -EFAULT;
       
   636     }
       
   637 
       
   638     if (down_interruptible(&master->master_sem))
       
   639         return -EINTR;
       
   640 
       
   641     if (!(domain = ec_master_find_domain_const(master, data.domain_index))) {
       
   642         up(&master->master_sem);
       
   643         EC_MASTER_ERR(master, "Domain %u does not exist!\n",
       
   644                 data.domain_index);
       
   645         return -EINVAL;
       
   646     }
       
   647 
       
   648     if (domain->data_size != data.data_size) {
       
   649         up(&master->master_sem);
       
   650         EC_MASTER_ERR(master, "Data size mismatch %u/%zu!\n",
       
   651                 data.data_size, domain->data_size);
       
   652         return -EFAULT;
       
   653     }
       
   654 
       
   655     if (copy_to_user((void __user *) data.target, domain->data,
       
   656                 domain->data_size)) {
       
   657         up(&master->master_sem);
       
   658         return -EFAULT;
       
   659     }
       
   660 
       
   661     up(&master->master_sem);
       
   662     return 0;
       
   663 }
       
   664 
       
   665 /*****************************************************************************/
       
   666 
       
   667 /** Set master debug level.
       
   668  */
       
   669 int ec_cdev_ioctl_master_debug(
       
   670         ec_master_t *master, /**< EtherCAT master. */
       
   671         unsigned long arg /**< ioctl() argument. */
       
   672         )
       
   673 {
       
   674     return ec_master_debug_level(master, (unsigned int) arg);
       
   675 }
       
   676 
       
   677 /*****************************************************************************/
       
   678 
       
   679 /** Issue a bus scan.
       
   680  */
       
   681 int ec_cdev_ioctl_master_rescan(
       
   682         ec_master_t *master, /**< EtherCAT master. */
       
   683         unsigned long arg /**< ioctl() argument. */
       
   684         )
       
   685 {
       
   686     master->fsm.rescan_required = 1;
       
   687     return 0;
       
   688 }
       
   689 
       
   690 /*****************************************************************************/
       
   691 
       
   692 /** Set slave state.
       
   693  */
       
   694 int ec_cdev_ioctl_slave_state(
       
   695         ec_master_t *master, /**< EtherCAT master. */
       
   696         unsigned long arg /**< ioctl() argument. */
       
   697         )
       
   698 {
       
   699     ec_ioctl_slave_state_t data;
       
   700     ec_slave_t *slave;
       
   701 
       
   702     if (copy_from_user(&data, (void __user *) arg, sizeof(data))) {
       
   703         return -EFAULT;
       
   704     }
       
   705 
       
   706     if (down_interruptible(&master->master_sem))
       
   707         return -EINTR;
       
   708 
       
   709     if (!(slave = ec_master_find_slave(
       
   710                     master, 0, data.slave_position))) {
       
   711         up(&master->master_sem);
       
   712         EC_MASTER_ERR(master, "Slave %u does not exist!\n",
       
   713                 data.slave_position);
       
   714         return -EINVAL;
       
   715     }
       
   716 
       
   717     ec_slave_request_state(slave, data.al_state);
       
   718 
       
   719     up(&master->master_sem);
       
   720     return 0;
       
   721 }
       
   722 
       
   723 /*****************************************************************************/
       
   724 
       
   725 /** Get slave SDO information.
       
   726  */
       
   727 int ec_cdev_ioctl_slave_sdo(
       
   728         ec_master_t *master, /**< EtherCAT master. */
       
   729         unsigned long arg /**< ioctl() argument. */
       
   730         )
       
   731 {
       
   732     ec_ioctl_slave_sdo_t data;
       
   733     const ec_slave_t *slave;
       
   734     const ec_sdo_t *sdo;
       
   735 
       
   736     if (copy_from_user(&data, (void __user *) arg, sizeof(data))) {
       
   737         return -EFAULT;
       
   738     }
       
   739 
       
   740     if (down_interruptible(&master->master_sem))
       
   741         return -EINTR;
       
   742 
       
   743     if (!(slave = ec_master_find_slave_const(
       
   744                     master, 0, data.slave_position))) {
       
   745         up(&master->master_sem);
       
   746         EC_MASTER_ERR(master, "Slave %u does not exist!\n",
       
   747                 data.slave_position);
       
   748         return -EINVAL;
       
   749     }
       
   750 
       
   751     if (!(sdo = ec_slave_get_sdo_by_pos_const(
       
   752                     slave, data.sdo_position))) {
       
   753         up(&master->master_sem);
       
   754         EC_SLAVE_ERR(slave, "SDO %u does not exist!\n", data.sdo_position);
       
   755         return -EINVAL;
       
   756     }
       
   757 
       
   758     data.sdo_index = sdo->index;
       
   759     data.max_subindex = sdo->max_subindex;
       
   760     ec_cdev_strcpy(data.name, sdo->name);
       
   761 
       
   762     up(&master->master_sem);
       
   763 
       
   764     if (copy_to_user((void __user *) arg, &data, sizeof(data)))
       
   765         return -EFAULT;
       
   766 
       
   767     return 0;
       
   768 }
       
   769 
       
   770 /*****************************************************************************/
       
   771 
       
   772 /** Get slave SDO entry information.
       
   773  */
       
   774 int ec_cdev_ioctl_slave_sdo_entry(
       
   775         ec_master_t *master, /**< EtherCAT master. */
       
   776         unsigned long arg /**< ioctl() argument. */
       
   777         )
       
   778 {
       
   779     ec_ioctl_slave_sdo_entry_t data;
       
   780     const ec_slave_t *slave;
       
   781     const ec_sdo_t *sdo;
       
   782     const ec_sdo_entry_t *entry;
       
   783 
       
   784     if (copy_from_user(&data, (void __user *) arg, sizeof(data))) {
       
   785         return -EFAULT;
       
   786     }
       
   787 
       
   788     if (down_interruptible(&master->master_sem))
       
   789         return -EINTR;
       
   790 
       
   791     if (!(slave = ec_master_find_slave_const(
       
   792                     master, 0, data.slave_position))) {
       
   793         up(&master->master_sem);
       
   794         EC_MASTER_ERR(master, "Slave %u does not exist!\n",
       
   795                 data.slave_position);
       
   796         return -EINVAL;
       
   797     }
       
   798 
       
   799     if (data.sdo_spec <= 0) {
       
   800         if (!(sdo = ec_slave_get_sdo_by_pos_const(
       
   801                         slave, -data.sdo_spec))) {
       
   802             up(&master->master_sem);
       
   803             EC_SLAVE_ERR(slave, "SDO %u does not exist!\n", -data.sdo_spec);
       
   804             return -EINVAL;
       
   805         }
       
   806     } else {
       
   807         if (!(sdo = ec_slave_get_sdo_const(
       
   808                         slave, data.sdo_spec))) {
       
   809             up(&master->master_sem);
       
   810             EC_SLAVE_ERR(slave, "SDO 0x%04X does not exist!\n",
       
   811                     data.sdo_spec);
       
   812             return -EINVAL;
       
   813         }
       
   814     }
       
   815 
       
   816     if (!(entry = ec_sdo_get_entry_const(
       
   817                     sdo, data.sdo_entry_subindex))) {
       
   818         up(&master->master_sem);
       
   819         EC_SLAVE_ERR(slave, "SDO entry 0x%04X:%02X does not exist!\n",
       
   820                 sdo->index, data.sdo_entry_subindex);
       
   821         return -EINVAL;
       
   822     }
       
   823 
       
   824     data.data_type = entry->data_type;
       
   825     data.bit_length = entry->bit_length;
       
   826     data.read_access[EC_SDO_ENTRY_ACCESS_PREOP] =
       
   827         entry->read_access[EC_SDO_ENTRY_ACCESS_PREOP];
       
   828     data.read_access[EC_SDO_ENTRY_ACCESS_SAFEOP] =
       
   829         entry->read_access[EC_SDO_ENTRY_ACCESS_SAFEOP];
       
   830     data.read_access[EC_SDO_ENTRY_ACCESS_OP] =
       
   831         entry->read_access[EC_SDO_ENTRY_ACCESS_OP];
       
   832     data.write_access[EC_SDO_ENTRY_ACCESS_PREOP] =
       
   833         entry->write_access[EC_SDO_ENTRY_ACCESS_PREOP];
       
   834     data.write_access[EC_SDO_ENTRY_ACCESS_SAFEOP] =
       
   835         entry->write_access[EC_SDO_ENTRY_ACCESS_SAFEOP];
       
   836     data.write_access[EC_SDO_ENTRY_ACCESS_OP] =
       
   837         entry->write_access[EC_SDO_ENTRY_ACCESS_OP];
       
   838     ec_cdev_strcpy(data.description, entry->description);
       
   839 
       
   840     up(&master->master_sem);
       
   841 
       
   842     if (copy_to_user((void __user *) arg, &data, sizeof(data)))
       
   843         return -EFAULT;
       
   844 
       
   845     return 0;
       
   846 }
       
   847 
       
   848 /*****************************************************************************/
       
   849 
       
   850 /** Upload SDO.
       
   851  */
       
   852 int ec_cdev_ioctl_slave_sdo_upload(
       
   853         ec_master_t *master, /**< EtherCAT master. */
       
   854         unsigned long arg /**< ioctl() argument. */
       
   855         )
       
   856 {
       
   857     ec_ioctl_slave_sdo_upload_t data;
       
   858     uint8_t *target;
       
   859     int ret;
       
   860 
       
   861     if (copy_from_user(&data, (void __user *) arg, sizeof(data))) {
       
   862         return -EFAULT;
       
   863     }
       
   864 
       
   865     if (!(target = kmalloc(data.target_size, GFP_KERNEL))) {
       
   866         EC_MASTER_ERR(master, "Failed to allocate %u bytes"
       
   867                 " for SDO upload.\n", data.target_size);
       
   868         return -ENOMEM;
       
   869     }
       
   870 
       
   871     ret = ecrt_master_sdo_upload(master, data.slave_position,
       
   872             data.sdo_index, data.sdo_entry_subindex, target,
       
   873             data.target_size, &data.data_size, &data.abort_code);
       
   874 
       
   875     if (!ret) {
       
   876         if (copy_to_user((void __user *) data.target,
       
   877                     target, data.data_size)) {
       
   878             kfree(target);
       
   879             return -EFAULT;
       
   880         }
       
   881     }
       
   882 
       
   883     kfree(target);
       
   884 
       
   885     if (__copy_to_user((void __user *) arg, &data, sizeof(data))) {
       
   886         return -EFAULT;
       
   887     }
       
   888 
       
   889     return 0;
       
   890 }
       
   891 
       
   892 /*****************************************************************************/
       
   893 
       
   894 /** Download SDO.
       
   895  */
       
   896 int ec_cdev_ioctl_slave_sdo_download(
       
   897         ec_master_t *master, /**< EtherCAT master. */
       
   898         unsigned long arg /**< ioctl() argument. */
       
   899         )
       
   900 {
       
   901     ec_ioctl_slave_sdo_download_t data;
       
   902     uint8_t *sdo_data;
       
   903     int retval;
       
   904 
       
   905     if (copy_from_user(&data, (void __user *) arg, sizeof(data))) {
       
   906         return -EFAULT;
       
   907     }
       
   908 
       
   909     if (!(sdo_data = kmalloc(data.data_size, GFP_KERNEL))) {
       
   910         EC_MASTER_ERR(master, "Failed to allocate %u bytes"
       
   911                 " for SDO download.\n", data.data_size);
       
   912         return -ENOMEM;
       
   913     }
       
   914 
       
   915     if (copy_from_user(sdo_data, (void __user *) data.data, data.data_size)) {
       
   916         kfree(sdo_data);
       
   917         return -EFAULT;
       
   918     }
       
   919 
       
   920     if (data.complete_access) {
       
   921         retval = ecrt_master_sdo_download_complete(master, data.slave_position,
       
   922                 data.sdo_index, sdo_data, data.data_size, &data.abort_code);
       
   923     } else {
       
   924         retval = ecrt_master_sdo_download(master, data.slave_position,
       
   925                 data.sdo_index, data.sdo_entry_subindex, sdo_data,
       
   926                 data.data_size, &data.abort_code);
       
   927     }
       
   928 
       
   929     kfree(sdo_data);
       
   930 
       
   931     if (__copy_to_user((void __user *) arg, &data, sizeof(data))) {
       
   932         retval = -EFAULT;
       
   933     }
       
   934 
       
   935     return retval;
       
   936 }
       
   937 
       
   938 /*****************************************************************************/
       
   939 
       
   940 /** Read a slave's SII.
       
   941  */
       
   942 int ec_cdev_ioctl_slave_sii_read(
       
   943         ec_master_t *master, /**< EtherCAT master. */
       
   944         unsigned long arg /**< ioctl() argument. */
       
   945         )
       
   946 {
       
   947     ec_ioctl_slave_sii_t data;
       
   948     const ec_slave_t *slave;
       
   949     int retval;
       
   950 
       
   951     if (copy_from_user(&data, (void __user *) arg, sizeof(data))) {
       
   952         return -EFAULT;
       
   953     }
       
   954 
       
   955     if (down_interruptible(&master->master_sem))
       
   956         return -EINTR;
       
   957 
       
   958     if (!(slave = ec_master_find_slave_const(
       
   959                     master, 0, data.slave_position))) {
       
   960         up(&master->master_sem);
       
   961         EC_MASTER_ERR(master, "Slave %u does not exist!\n",
       
   962                 data.slave_position);
       
   963         return -EINVAL;
       
   964     }
       
   965 
       
   966     if (!data.nwords
       
   967             || data.offset + data.nwords > slave->sii_nwords) {
       
   968         up(&master->master_sem);
       
   969         EC_SLAVE_ERR(slave, "Invalid SII read offset/size %u/%u for slave SII"
       
   970                 " size %zu!\n", data.offset, data.nwords, slave->sii_nwords);
       
   971         return -EINVAL;
       
   972     }
       
   973 
       
   974     if (copy_to_user((void __user *) data.words,
       
   975                 slave->sii_words + data.offset, data.nwords * 2))
       
   976         retval = -EFAULT;
       
   977     else
       
   978         retval = 0;
       
   979 
       
   980     up(&master->master_sem);
       
   981     return retval;
       
   982 }
       
   983 
       
   984 /*****************************************************************************/
       
   985 
       
   986 /** Write a slave's SII.
       
   987  */
       
   988 int ec_cdev_ioctl_slave_sii_write(
       
   989         ec_master_t *master, /**< EtherCAT master. */
       
   990         unsigned long arg /**< ioctl() argument. */
       
   991         )
       
   992 {
       
   993     ec_ioctl_slave_sii_t data;
       
   994     ec_slave_t *slave;
       
   995     unsigned int byte_size;
       
   996     uint16_t *words;
       
   997     ec_sii_write_request_t request;
       
   998 
       
   999     if (copy_from_user(&data, (void __user *) arg, sizeof(data))) {
       
  1000         return -EFAULT;
       
  1001     }
       
  1002 
       
  1003     if (!data.nwords)
       
  1004         return 0;
       
  1005 
       
  1006     byte_size = sizeof(uint16_t) * data.nwords;
       
  1007     if (!(words = kmalloc(byte_size, GFP_KERNEL))) {
       
  1008         EC_MASTER_ERR(master, "Failed to allocate %u bytes"
       
  1009                 " for SII contents.\n", byte_size);
       
  1010         return -ENOMEM;
       
  1011     }
       
  1012 
       
  1013     if (copy_from_user(words,
       
  1014                 (void __user *) data.words, byte_size)) {
       
  1015         kfree(words);
       
  1016         return -EFAULT;
       
  1017     }
       
  1018 
       
  1019     if (down_interruptible(&master->master_sem))
       
  1020         return -EINTR;
       
  1021 
       
  1022     if (!(slave = ec_master_find_slave(
       
  1023                     master, 0, data.slave_position))) {
       
  1024         up(&master->master_sem);
       
  1025         EC_MASTER_ERR(master, "Slave %u does not exist!\n",
       
  1026                 data.slave_position);
       
  1027         kfree(words);
       
  1028         return -EINVAL;
       
  1029     }
       
  1030 
       
  1031     // init SII write request
       
  1032     INIT_LIST_HEAD(&request.list);
       
  1033     request.slave = slave;
       
  1034     request.words = words;
       
  1035     request.offset = data.offset;
       
  1036     request.nwords = data.nwords;
       
  1037     request.state = EC_INT_REQUEST_QUEUED;
       
  1038 
       
  1039     // schedule SII write request.
       
  1040     list_add_tail(&request.list, &master->sii_requests);
       
  1041 
       
  1042     up(&master->master_sem);
       
  1043 
       
  1044     // wait for processing through FSM
       
  1045     if (wait_event_interruptible(master->sii_queue,
       
  1046                 request.state != EC_INT_REQUEST_QUEUED)) {
       
  1047         // interrupted by signal
       
  1048         down(&master->master_sem);
       
  1049         if (request.state == EC_INT_REQUEST_QUEUED) {
       
  1050             // abort request
       
  1051             list_del(&request.list);
       
  1052             up(&master->master_sem);
       
  1053             kfree(words);
       
  1054             return -EINTR;
       
  1055         }
       
  1056         up(&master->master_sem);
       
  1057     }
       
  1058 
       
  1059     // wait until master FSM has finished processing
       
  1060     wait_event(master->sii_queue, request.state != EC_INT_REQUEST_BUSY);
       
  1061 
       
  1062     kfree(words);
       
  1063 
       
  1064     return request.state == EC_INT_REQUEST_SUCCESS ? 0 : -EIO;
       
  1065 }
       
  1066 
       
  1067 /*****************************************************************************/
       
  1068 
       
  1069 /** Read a slave's registers.
       
  1070  */
       
  1071 int ec_cdev_ioctl_slave_reg_read(
       
  1072         ec_master_t *master, /**< EtherCAT master. */
       
  1073         unsigned long arg /**< ioctl() argument. */
       
  1074         )
       
  1075 {
       
  1076     ec_ioctl_slave_reg_t data;
       
  1077     ec_slave_t *slave;
       
  1078     uint8_t *contents;
       
  1079     ec_reg_request_t request;
       
  1080 
       
  1081     if (copy_from_user(&data, (void __user *) arg, sizeof(data))) {
       
  1082         return -EFAULT;
       
  1083     }
       
  1084 
       
  1085     if (!data.length)
       
  1086         return 0;
       
  1087 
       
  1088     if (!(contents = kmalloc(data.length, GFP_KERNEL))) {
       
  1089         EC_MASTER_ERR(master, "Failed to allocate %u bytes"
       
  1090                 " for register data.\n", data.length);
       
  1091         return -ENOMEM;
       
  1092     }
       
  1093 
       
  1094     if (down_interruptible(&master->master_sem))
       
  1095         return -EINTR;
       
  1096 
       
  1097     if (!(slave = ec_master_find_slave(
       
  1098                     master, 0, data.slave_position))) {
       
  1099         up(&master->master_sem);
       
  1100         EC_MASTER_ERR(master, "Slave %u does not exist!\n",
       
  1101                 data.slave_position);
       
  1102         return -EINVAL;
       
  1103     }
       
  1104 
       
  1105     // init register request
       
  1106     INIT_LIST_HEAD(&request.list);
       
  1107     request.slave = slave;
       
  1108     request.dir = EC_DIR_INPUT;
       
  1109     request.data = contents;
       
  1110     request.offset = data.offset;
       
  1111     request.length = data.length;
       
  1112     request.state = EC_INT_REQUEST_QUEUED;
       
  1113 
       
  1114     // schedule request.
       
  1115     list_add_tail(&request.list, &master->reg_requests);
       
  1116 
       
  1117     up(&master->master_sem);
       
  1118 
       
  1119     // wait for processing through FSM
       
  1120     if (wait_event_interruptible(master->reg_queue,
       
  1121                 request.state != EC_INT_REQUEST_QUEUED)) {
       
  1122         // interrupted by signal
       
  1123         down(&master->master_sem);
       
  1124         if (request.state == EC_INT_REQUEST_QUEUED) {
       
  1125             // abort request
       
  1126             list_del(&request.list);
       
  1127             up(&master->master_sem);
       
  1128             kfree(contents);
       
  1129             return -EINTR;
       
  1130         }
       
  1131         up(&master->master_sem);
       
  1132     }
       
  1133 
       
  1134     // wait until master FSM has finished processing
       
  1135     wait_event(master->reg_queue, request.state != EC_INT_REQUEST_BUSY);
       
  1136 
       
  1137     if (request.state == EC_INT_REQUEST_SUCCESS) {
       
  1138         if (copy_to_user((void __user *) data.data, contents, data.length))
       
  1139             return -EFAULT;
       
  1140     }
       
  1141     kfree(contents);
       
  1142 
       
  1143     return request.state == EC_INT_REQUEST_SUCCESS ? 0 : -EIO;
       
  1144 }
       
  1145 
       
  1146 /*****************************************************************************/
       
  1147 
       
  1148 /** Write a slave's registers.
       
  1149  */
       
  1150 int ec_cdev_ioctl_slave_reg_write(
       
  1151         ec_master_t *master, /**< EtherCAT master. */
       
  1152         unsigned long arg /**< ioctl() argument. */
       
  1153         )
       
  1154 {
       
  1155     ec_ioctl_slave_reg_t data;
       
  1156     ec_slave_t *slave;
       
  1157     uint8_t *contents;
       
  1158     ec_reg_request_t request;
       
  1159 
       
  1160     if (copy_from_user(&data, (void __user *) arg, sizeof(data))) {
       
  1161         return -EFAULT;
       
  1162     }
       
  1163 
       
  1164     if (!data.length)
       
  1165         return 0;
       
  1166 
       
  1167     if (!(contents = kmalloc(data.length, GFP_KERNEL))) {
       
  1168         EC_MASTER_ERR(master, "Failed to allocate %u bytes"
       
  1169                 " for register data.\n", data.length);
       
  1170         return -ENOMEM;
       
  1171     }
       
  1172 
       
  1173     if (copy_from_user(contents, (void __user *) data.data, data.length)) {
       
  1174         kfree(contents);
       
  1175         return -EFAULT;
       
  1176     }
       
  1177 
       
  1178     if (down_interruptible(&master->master_sem))
       
  1179         return -EINTR;
       
  1180 
       
  1181     if (!(slave = ec_master_find_slave(
       
  1182                     master, 0, data.slave_position))) {
       
  1183         up(&master->master_sem);
       
  1184         EC_MASTER_ERR(master, "Slave %u does not exist!\n",
       
  1185                 data.slave_position);
       
  1186         kfree(contents);
       
  1187         return -EINVAL;
       
  1188     }
       
  1189 
       
  1190     // init register request
       
  1191     INIT_LIST_HEAD(&request.list);
       
  1192     request.slave = slave;
       
  1193     request.dir = EC_DIR_OUTPUT;
       
  1194     request.data = contents;
       
  1195     request.offset = data.offset;
       
  1196     request.length = data.length;
       
  1197     request.state = EC_INT_REQUEST_QUEUED;
       
  1198 
       
  1199     // schedule request.
       
  1200     list_add_tail(&request.list, &master->reg_requests);
       
  1201 
       
  1202     up(&master->master_sem);
       
  1203 
       
  1204     // wait for processing through FSM
       
  1205     if (wait_event_interruptible(master->reg_queue,
       
  1206                 request.state != EC_INT_REQUEST_QUEUED)) {
       
  1207         // interrupted by signal
       
  1208         down(&master->master_sem);
       
  1209         if (request.state == EC_INT_REQUEST_QUEUED) {
       
  1210             // abort request
       
  1211             list_del(&request.list);
       
  1212             up(&master->master_sem);
       
  1213             kfree(contents);
       
  1214             return -EINTR;
       
  1215         }
       
  1216         up(&master->master_sem);
       
  1217     }
       
  1218 
       
  1219     // wait until master FSM has finished processing
       
  1220     wait_event(master->reg_queue, request.state != EC_INT_REQUEST_BUSY);
       
  1221 
       
  1222     kfree(contents);
       
  1223 
       
  1224     return request.state == EC_INT_REQUEST_SUCCESS ? 0 : -EIO;
       
  1225 }
       
  1226 
       
  1227 /*****************************************************************************/
       
  1228 
       
  1229 /** Get slave configuration information.
       
  1230  */
       
  1231 int ec_cdev_ioctl_config(
       
  1232         ec_master_t *master, /**< EtherCAT master. */
       
  1233         unsigned long arg /**< ioctl() argument. */
       
  1234         )
       
  1235 {
       
  1236     ec_ioctl_config_t data;
       
  1237     const ec_slave_config_t *sc;
       
  1238     uint8_t i;
       
  1239 
       
  1240     if (copy_from_user(&data, (void __user *) arg, sizeof(data))) {
       
  1241         return -EFAULT;
       
  1242     }
       
  1243 
       
  1244     if (down_interruptible(&master->master_sem))
       
  1245         return -EINTR;
       
  1246 
       
  1247     if (!(sc = ec_master_get_config_const(
       
  1248                     master, data.config_index))) {
       
  1249         up(&master->master_sem);
       
  1250         EC_MASTER_ERR(master, "Slave config %u does not exist!\n",
       
  1251                 data.config_index);
       
  1252         return -EINVAL;
       
  1253     }
       
  1254 
       
  1255     data.alias = sc->alias;
       
  1256     data.position = sc->position;
       
  1257     data.vendor_id = sc->vendor_id;
       
  1258     data.product_code = sc->product_code;
       
  1259     for (i = 0; i < EC_MAX_SYNC_MANAGERS; i++) {
       
  1260         data.syncs[i].dir = sc->sync_configs[i].dir;
       
  1261         data.syncs[i].watchdog_mode = sc->sync_configs[i].watchdog_mode;
       
  1262         data.syncs[i].pdo_count =
       
  1263             ec_pdo_list_count(&sc->sync_configs[i].pdos);
       
  1264     }
       
  1265     data.watchdog_divider = sc->watchdog_divider;
       
  1266     data.watchdog_intervals = sc->watchdog_intervals;
       
  1267     data.sdo_count = ec_slave_config_sdo_count(sc);
       
  1268     data.idn_count = ec_slave_config_idn_count(sc);
       
  1269     data.slave_position = sc->slave ? sc->slave->ring_position : -1;
       
  1270     data.dc_assign_activate = sc->dc_assign_activate;
       
  1271     for (i = 0; i < EC_SYNC_SIGNAL_COUNT; i++) {
       
  1272         data.dc_sync[i] = sc->dc_sync[i];
       
  1273     }
       
  1274 
       
  1275     up(&master->master_sem);
       
  1276 
       
  1277     if (copy_to_user((void __user *) arg, &data, sizeof(data)))
       
  1278         return -EFAULT;
       
  1279 
       
  1280     return 0;
       
  1281 }
       
  1282 
       
  1283 /*****************************************************************************/
       
  1284 
       
  1285 /** Get slave configuration PDO information.
       
  1286  */
       
  1287 int ec_cdev_ioctl_config_pdo(
       
  1288         ec_master_t *master, /**< EtherCAT master. */
       
  1289         unsigned long arg /**< ioctl() argument. */
       
  1290         )
       
  1291 {
       
  1292     ec_ioctl_config_pdo_t data;
       
  1293     const ec_slave_config_t *sc;
       
  1294     const ec_pdo_t *pdo;
       
  1295 
       
  1296     if (copy_from_user(&data, (void __user *) arg, sizeof(data))) {
       
  1297         return -EFAULT;
       
  1298     }
       
  1299 
       
  1300     if (data.sync_index >= EC_MAX_SYNC_MANAGERS) {
       
  1301         EC_MASTER_ERR(master, "Invalid sync manager index %u!\n",
       
  1302                 data.sync_index);
       
  1303         return -EINVAL;
       
  1304     }
       
  1305 
       
  1306     if (down_interruptible(&master->master_sem))
       
  1307         return -EINTR;
       
  1308 
       
  1309     if (!(sc = ec_master_get_config_const(
       
  1310                     master, data.config_index))) {
       
  1311         up(&master->master_sem);
       
  1312         EC_MASTER_ERR(master, "Slave config %u does not exist!\n",
       
  1313                 data.config_index);
       
  1314         return -EINVAL;
       
  1315     }
       
  1316 
       
  1317     if (!(pdo = ec_pdo_list_find_pdo_by_pos_const(
       
  1318                     &sc->sync_configs[data.sync_index].pdos,
       
  1319                     data.pdo_pos))) {
       
  1320         up(&master->master_sem);
       
  1321         EC_MASTER_ERR(master, "Invalid PDO position!\n");
       
  1322         return -EINVAL;
       
  1323     }
       
  1324 
       
  1325     data.index = pdo->index;
       
  1326     data.entry_count = ec_pdo_entry_count(pdo);
       
  1327     ec_cdev_strcpy(data.name, pdo->name);
       
  1328 
       
  1329     up(&master->master_sem);
       
  1330 
       
  1331     if (copy_to_user((void __user *) arg, &data, sizeof(data)))
       
  1332         return -EFAULT;
       
  1333 
       
  1334     return 0;
       
  1335 }
       
  1336 
       
  1337 /*****************************************************************************/
       
  1338 
       
  1339 /** Get slave configuration PDO entry information.
       
  1340  */
       
  1341 int ec_cdev_ioctl_config_pdo_entry(
       
  1342         ec_master_t *master, /**< EtherCAT master. */
       
  1343         unsigned long arg /**< ioctl() argument. */
       
  1344         )
       
  1345 {
       
  1346     ec_ioctl_config_pdo_entry_t data;
       
  1347     const ec_slave_config_t *sc;
       
  1348     const ec_pdo_t *pdo;
       
  1349     const ec_pdo_entry_t *entry;
       
  1350 
       
  1351     if (copy_from_user(&data, (void __user *) arg, sizeof(data))) {
       
  1352         return -EFAULT;
       
  1353     }
       
  1354 
       
  1355     if (data.sync_index >= EC_MAX_SYNC_MANAGERS) {
       
  1356         EC_MASTER_ERR(master, "Invalid sync manager index %u!\n",
       
  1357                 data.sync_index);
       
  1358         return -EINVAL;
       
  1359     }
       
  1360 
       
  1361     if (down_interruptible(&master->master_sem))
       
  1362         return -EINTR;
       
  1363 
       
  1364     if (!(sc = ec_master_get_config_const(
       
  1365                     master, data.config_index))) {
       
  1366         up(&master->master_sem);
       
  1367         EC_MASTER_ERR(master, "Slave config %u does not exist!\n",
       
  1368                 data.config_index);
       
  1369         return -EINVAL;
       
  1370     }
       
  1371 
       
  1372     if (!(pdo = ec_pdo_list_find_pdo_by_pos_const(
       
  1373                     &sc->sync_configs[data.sync_index].pdos,
       
  1374                     data.pdo_pos))) {
       
  1375         up(&master->master_sem);
       
  1376         EC_MASTER_ERR(master, "Invalid PDO position!\n");
       
  1377         return -EINVAL;
       
  1378     }
       
  1379 
       
  1380     if (!(entry = ec_pdo_find_entry_by_pos_const(
       
  1381                     pdo, data.entry_pos))) {
       
  1382         up(&master->master_sem);
       
  1383         EC_MASTER_ERR(master, "Entry not found!\n");
       
  1384         return -EINVAL;
       
  1385     }
       
  1386 
       
  1387     data.index = entry->index;
       
  1388     data.subindex = entry->subindex;
       
  1389     data.bit_length = entry->bit_length;
       
  1390     ec_cdev_strcpy(data.name, entry->name);
       
  1391 
       
  1392     up(&master->master_sem);
       
  1393 
       
  1394     if (copy_to_user((void __user *) arg, &data, sizeof(data)))
       
  1395         return -EFAULT;
       
  1396 
       
  1397     return 0;
       
  1398 }
       
  1399 
       
  1400 /*****************************************************************************/
       
  1401 
       
  1402 /** Get slave configuration SDO information.
       
  1403  */
       
  1404 int ec_cdev_ioctl_config_sdo(
       
  1405         ec_master_t *master, /**< EtherCAT master. */
       
  1406         unsigned long arg /**< ioctl() argument. */
       
  1407         )
       
  1408 {
       
  1409     ec_ioctl_config_sdo_t *ioctl;
       
  1410     const ec_slave_config_t *sc;
       
  1411     const ec_sdo_request_t *req;
       
  1412 
       
  1413     if (!(ioctl = kmalloc(sizeof(*ioctl), GFP_KERNEL))) {
       
  1414         return -ENOMEM;
       
  1415     }
       
  1416 
       
  1417     if (copy_from_user(ioctl, (void __user *) arg, sizeof(*ioctl))) {
       
  1418         kfree(ioctl);
       
  1419         return -EFAULT;
       
  1420     }
       
  1421 
       
  1422     if (down_interruptible(&master->master_sem)) {
       
  1423         kfree(ioctl);
       
  1424         return -EINTR;
       
  1425     }
       
  1426 
       
  1427     if (!(sc = ec_master_get_config_const(
       
  1428                     master, ioctl->config_index))) {
       
  1429         up(&master->master_sem);
       
  1430         EC_MASTER_ERR(master, "Slave config %u does not exist!\n",
       
  1431                 ioctl->config_index);
       
  1432         kfree(ioctl);
       
  1433         return -EINVAL;
       
  1434     }
       
  1435 
       
  1436     if (!(req = ec_slave_config_get_sdo_by_pos_const(
       
  1437                     sc, ioctl->sdo_pos))) {
       
  1438         up(&master->master_sem);
       
  1439         EC_MASTER_ERR(master, "Invalid SDO position!\n");
       
  1440         kfree(ioctl);
       
  1441         return -EINVAL;
       
  1442     }
       
  1443 
       
  1444     ioctl->index = req->index;
       
  1445     ioctl->subindex = req->subindex;
       
  1446     ioctl->size = req->data_size;
       
  1447     memcpy(ioctl->data, req->data,
       
  1448             min((u32) ioctl->size, (u32) EC_MAX_SDO_DATA_SIZE));
       
  1449 
       
  1450     up(&master->master_sem);
       
  1451 
       
  1452     if (copy_to_user((void __user *) arg, ioctl, sizeof(*ioctl))) {
       
  1453         kfree(ioctl);
       
  1454         return -EFAULT;
       
  1455     }
       
  1456 
       
  1457     kfree(ioctl);
       
  1458     return 0;
       
  1459 }
       
  1460 
       
  1461 /*****************************************************************************/
       
  1462 
       
  1463 /** Get slave configuration IDN information.
       
  1464  */
       
  1465 int ec_cdev_ioctl_config_idn(
       
  1466         ec_master_t *master, /**< EtherCAT master. */
       
  1467         unsigned long arg /**< ioctl() argument. */
       
  1468         )
       
  1469 {
       
  1470     ec_ioctl_config_idn_t *ioctl;
       
  1471     const ec_slave_config_t *sc;
       
  1472     const ec_soe_request_t *req;
       
  1473 
       
  1474     if (!(ioctl = kmalloc(sizeof(*ioctl), GFP_KERNEL))) {
       
  1475         return -ENOMEM;
       
  1476     }
       
  1477 
       
  1478     if (copy_from_user(ioctl, (void __user *) arg, sizeof(*ioctl))) {
       
  1479         kfree(ioctl);
       
  1480         return -EFAULT;
       
  1481     }
       
  1482 
       
  1483     if (down_interruptible(&master->master_sem)) {
       
  1484         kfree(ioctl);
       
  1485         return -EINTR;
       
  1486     }
       
  1487 
       
  1488     if (!(sc = ec_master_get_config_const(
       
  1489                     master, ioctl->config_index))) {
       
  1490         up(&master->master_sem);
       
  1491         EC_MASTER_ERR(master, "Slave config %u does not exist!\n",
       
  1492                 ioctl->config_index);
       
  1493         kfree(ioctl);
       
  1494         return -EINVAL;
       
  1495     }
       
  1496 
       
  1497     if (!(req = ec_slave_config_get_idn_by_pos_const(
       
  1498                     sc, ioctl->idn_pos))) {
       
  1499         up(&master->master_sem);
       
  1500         EC_MASTER_ERR(master, "Invalid IDN position!\n");
       
  1501         kfree(ioctl);
       
  1502         return -EINVAL;
       
  1503     }
       
  1504 
       
  1505     ioctl->drive_no = req->drive_no;
       
  1506     ioctl->idn = req->idn;
       
  1507     ioctl->state = req->state;
       
  1508     ioctl->size = req->data_size;
       
  1509     memcpy(ioctl->data, req->data,
       
  1510             min((u32) ioctl->size, (u32) EC_MAX_IDN_DATA_SIZE));
       
  1511 
       
  1512     up(&master->master_sem);
       
  1513 
       
  1514     if (copy_to_user((void __user *) arg, ioctl, sizeof(*ioctl))) {
       
  1515         kfree(ioctl);
       
  1516         return -EFAULT;
       
  1517     }
       
  1518 
       
  1519     kfree(ioctl);
       
  1520     return 0;
       
  1521 }
       
  1522 
       
  1523 /*****************************************************************************/
       
  1524 
       
  1525 #ifdef EC_EOE
       
  1526 
       
  1527 /** Get EoE handler information.
       
  1528  */
       
  1529 int ec_cdev_ioctl_eoe_handler(
       
  1530         ec_master_t *master, /**< EtherCAT master. */
       
  1531         unsigned long arg /**< ioctl() argument. */
       
  1532         )
       
  1533 {
       
  1534     ec_ioctl_eoe_handler_t data;
       
  1535     const ec_eoe_t *eoe;
       
  1536 
       
  1537     if (copy_from_user(&data, (void __user *) arg, sizeof(data))) {
       
  1538         return -EFAULT;
       
  1539     }
       
  1540 
       
  1541     if (down_interruptible(&master->master_sem))
       
  1542         return -EINTR;
       
  1543 
       
  1544     if (!(eoe = ec_master_get_eoe_handler_const(master, data.eoe_index))) {
       
  1545         up(&master->master_sem);
       
  1546         EC_MASTER_ERR(master, "EoE handler %u does not exist!\n",
       
  1547                 data.eoe_index);
       
  1548         return -EINVAL;
       
  1549     }
       
  1550 
       
  1551     if (eoe->slave) {
       
  1552         data.slave_position = eoe->slave->ring_position;
       
  1553     } else {
       
  1554         data.slave_position = 0xffff;
       
  1555     }
       
  1556     snprintf(data.name, EC_DATAGRAM_NAME_SIZE, eoe->dev->name);
       
  1557     data.open = eoe->opened;
       
  1558     data.rx_bytes = eoe->stats.tx_bytes;
       
  1559     data.rx_rate = eoe->tx_rate;
       
  1560     data.tx_bytes = eoe->stats.rx_bytes;
       
  1561     data.tx_rate = eoe->tx_rate;
       
  1562     data.tx_queued_frames = eoe->tx_queued_frames;
       
  1563     data.tx_queue_size = eoe->tx_queue_size;
       
  1564 
       
  1565     up(&master->master_sem);
       
  1566 
       
  1567     if (copy_to_user((void __user *) arg, &data, sizeof(data)))
       
  1568         return -EFAULT;
       
  1569 
       
  1570     return 0;
       
  1571 }
       
  1572 
       
  1573 #endif
       
  1574 
       
  1575 /*****************************************************************************/
       
  1576 
       
  1577 /** Request the master from userspace.
       
  1578  */
       
  1579 int ec_cdev_ioctl_request(
       
  1580         ec_master_t *master, /**< EtherCAT master. */
       
  1581         unsigned long arg, /**< ioctl() argument. */
       
  1582         ec_cdev_priv_t *priv /**< Private data structure of file handle. */
       
  1583         )
       
  1584 {
       
  1585     ec_master_t *m;
       
  1586     int ret = 0;
       
  1587 
       
  1588     m = ecrt_request_master_err(master->index);
       
  1589     if (IS_ERR(m)) {
       
  1590         ret = PTR_ERR(m);
       
  1591     } else {
       
  1592         priv->requested = 1;
       
  1593     }
       
  1594 
       
  1595     return ret;
       
  1596 }
       
  1597 
       
  1598 /*****************************************************************************/
       
  1599 
       
  1600 /** Create a domain.
       
  1601  */
       
  1602 int ec_cdev_ioctl_create_domain(
       
  1603         ec_master_t *master, /**< EtherCAT master. */
       
  1604         unsigned long arg, /**< ioctl() argument. */
       
  1605         ec_cdev_priv_t *priv /**< Private data structure of file handle. */
       
  1606         )
       
  1607 {
       
  1608     ec_domain_t *domain;
       
  1609 
       
  1610     if (unlikely(!priv->requested))
       
  1611         return -EPERM;
       
  1612 
       
  1613     domain = ecrt_master_create_domain_err(master);
       
  1614     if (IS_ERR(domain))
       
  1615         return PTR_ERR(domain);
       
  1616 
       
  1617     return domain->index;
       
  1618 }
       
  1619 
       
  1620 /*****************************************************************************/
       
  1621 
       
  1622 /** Create a slave configuration.
       
  1623  */
       
  1624 int ec_cdev_ioctl_create_slave_config(
       
  1625         ec_master_t *master, /**< EtherCAT master. */
       
  1626         unsigned long arg, /**< ioctl() argument. */
       
  1627         ec_cdev_priv_t *priv /**< Private data structure of file handle. */
       
  1628         )
       
  1629 {
       
  1630     ec_ioctl_config_t data;
       
  1631     ec_slave_config_t *sc, *entry;
       
  1632 
       
  1633     if (unlikely(!priv->requested))
       
  1634         return -EPERM;
       
  1635 
       
  1636     if (copy_from_user(&data, (void __user *) arg, sizeof(data))) {
       
  1637         return -EFAULT;
       
  1638     }
       
  1639 
       
  1640     sc = ecrt_master_slave_config_err(master, data.alias, data.position,
       
  1641             data.vendor_id, data.product_code);
       
  1642     if (IS_ERR(sc))
       
  1643         return PTR_ERR(sc);
       
  1644 
       
  1645     data.config_index = 0;
       
  1646 
       
  1647     if (down_interruptible(&master->master_sem))
       
  1648         return -EINTR;
       
  1649 
       
  1650     list_for_each_entry(entry, &master->configs, list) {
       
  1651         if (entry == sc)
       
  1652             break;
       
  1653         data.config_index++;
       
  1654     }
       
  1655 
       
  1656     up(&master->master_sem);
       
  1657 
       
  1658     if (copy_to_user((void __user *) arg, &data, sizeof(data)))
       
  1659         return -EFAULT;
       
  1660 
       
  1661     return 0;
       
  1662 }
       
  1663 
       
  1664 /*****************************************************************************/
       
  1665 
       
  1666 /** Activates the master.
       
  1667  */
       
  1668 int ec_cdev_ioctl_activate(
       
  1669         ec_master_t *master, /**< EtherCAT master. */
       
  1670         unsigned long arg, /**< ioctl() argument. */
       
  1671         ec_cdev_priv_t *priv /**< Private data structure of file handle. */
       
  1672         )
       
  1673 {
       
  1674     ec_domain_t *domain;
       
  1675     off_t offset;
       
  1676     int ret;
       
  1677 
       
  1678     if (unlikely(!priv->requested))
       
  1679         return -EPERM;
       
  1680 
       
  1681     /* Get the sum of the domains' process data sizes. */
       
  1682 
       
  1683     priv->process_data_size = 0;
       
  1684 
       
  1685     if (down_interruptible(&master->master_sem))
       
  1686         return -EINTR;
       
  1687 
       
  1688     list_for_each_entry(domain, &master->domains, list) {
       
  1689         priv->process_data_size += ecrt_domain_size(domain);
       
  1690     }
       
  1691 
       
  1692     up(&master->master_sem);
       
  1693 
       
  1694     if (priv->process_data_size) {
       
  1695         priv->process_data = vmalloc(priv->process_data_size);
       
  1696         if (!priv->process_data) {
       
  1697             priv->process_data_size = 0;
       
  1698             return -ENOMEM;
       
  1699         }
       
  1700 
       
  1701         /* Set the memory as external process data memory for the domains. */
       
  1702 
       
  1703         offset = 0;
       
  1704         list_for_each_entry(domain, &master->domains, list) {
       
  1705             ecrt_domain_external_memory(domain, priv->process_data + offset);
       
  1706             offset += ecrt_domain_size(domain);
       
  1707         }
       
  1708     }
       
  1709 
       
  1710     ecrt_master_callbacks(master, ec_master_internal_send_cb,
       
  1711             ec_master_internal_receive_cb, master);
       
  1712 
       
  1713     ret = ecrt_master_activate(master);
       
  1714     if (ret < 0)
       
  1715         return ret;
       
  1716 
       
  1717     if (copy_to_user((void __user *) arg,
       
  1718                 &priv->process_data_size, sizeof(size_t)))
       
  1719         return -EFAULT;
       
  1720 
       
  1721     return 0;
       
  1722 }
       
  1723 
       
  1724 /*****************************************************************************/
       
  1725 
       
  1726 /** Deactivates the master.
       
  1727  */
       
  1728 int ec_cdev_ioctl_deactivate(
       
  1729         ec_master_t *master, /**< EtherCAT master. */
       
  1730         unsigned long arg, /**< ioctl() argument. */
       
  1731         ec_cdev_priv_t *priv /**< Private data structure of file handle. */
       
  1732         )
       
  1733 {
       
  1734     if (unlikely(!priv->requested))
       
  1735         return -EPERM;
       
  1736 
       
  1737     ecrt_master_deactivate(master);
       
  1738     return 0;
       
  1739 }
       
  1740 
       
  1741 /*****************************************************************************/
       
  1742 
       
  1743 /** Set max. number of databytes in a cycle
       
  1744  */
       
  1745 int ec_cdev_ioctl_set_send_interval(
       
  1746         ec_master_t *master, /**< EtherCAT master. */
       
  1747         unsigned long arg, /**< ioctl() argument. */
       
  1748         ec_cdev_priv_t *priv /**< Private data structure of file handle. */
       
  1749         )
       
  1750 {
       
  1751     size_t send_interval;
       
  1752 
       
  1753     if (copy_from_user(&send_interval, (void __user *) arg,
       
  1754                 sizeof(send_interval))) {
       
  1755         return -EFAULT;
       
  1756     }
       
  1757 
       
  1758     if (down_interruptible(&master->master_sem))
       
  1759         return -EINTR;
       
  1760 
       
  1761     ec_master_set_send_interval(master, send_interval);
       
  1762 
       
  1763     up(&master->master_sem);
       
  1764     return 0;
       
  1765 }
       
  1766 
       
  1767 /*****************************************************************************/
       
  1768 
       
  1769 /** Send frames.
       
  1770  */
       
  1771 int ec_cdev_ioctl_send(
       
  1772         ec_master_t *master, /**< EtherCAT master. */
       
  1773         unsigned long arg, /**< ioctl() argument. */
       
  1774         ec_cdev_priv_t *priv /**< Private data structure of file handle. */
       
  1775         )
       
  1776 {
       
  1777     if (unlikely(!priv->requested))
       
  1778         return -EPERM;
       
  1779 
       
  1780     down(&master->io_sem);
       
  1781     ecrt_master_send(master);
       
  1782     up(&master->io_sem);
       
  1783     return 0;
       
  1784 }
       
  1785 
       
  1786 /*****************************************************************************/
       
  1787 
       
  1788 /** Receive frames.
       
  1789  */
       
  1790 int ec_cdev_ioctl_receive(
       
  1791         ec_master_t *master, /**< EtherCAT master. */
       
  1792         unsigned long arg, /**< ioctl() argument. */
       
  1793         ec_cdev_priv_t *priv /**< Private data structure of file handle. */
       
  1794         )
       
  1795 {
       
  1796     if (unlikely(!priv->requested))
       
  1797         return -EPERM;
       
  1798 
       
  1799     down(&master->io_sem);
       
  1800     ecrt_master_receive(master);
       
  1801     up(&master->io_sem);
       
  1802     return 0;
       
  1803 }
       
  1804 
       
  1805 /*****************************************************************************/
       
  1806 
       
  1807 /** Get the master state.
       
  1808  */
       
  1809 int ec_cdev_ioctl_master_state(
       
  1810         ec_master_t *master, /**< EtherCAT master. */
       
  1811         unsigned long arg, /**< ioctl() argument. */
       
  1812         ec_cdev_priv_t *priv /**< Private data structure of file handle. */
       
  1813         )
       
  1814 {
       
  1815     ec_master_state_t data;
       
  1816 
       
  1817     if (unlikely(!priv->requested))
       
  1818         return -EPERM;
       
  1819 
       
  1820     ecrt_master_state(master, &data);
       
  1821 
       
  1822     if (copy_to_user((void __user *) arg, &data, sizeof(data)))
       
  1823         return -EFAULT;
       
  1824 
       
  1825     return 0;
       
  1826 }
       
  1827 
       
  1828 /*****************************************************************************/
       
  1829 
       
  1830 /** Get the master state.
       
  1831  */
       
  1832 int ec_cdev_ioctl_master_link_state(
       
  1833         ec_master_t *master, /**< EtherCAT master. */
       
  1834         unsigned long arg, /**< ioctl() argument. */
       
  1835         ec_cdev_priv_t *priv /**< Private data structure of file handle. */
       
  1836         )
       
  1837 {
       
  1838     ec_ioctl_link_state_t ioctl;
       
  1839     ec_master_link_state_t state;
       
  1840     int ret;
       
  1841 
       
  1842     if (unlikely(!priv->requested)) {
       
  1843         return -EPERM;
       
  1844     }
       
  1845 
       
  1846     if (copy_from_user(&ioctl, (void __user *) arg, sizeof(ioctl))) {
       
  1847         return -EFAULT;
       
  1848     }
       
  1849 
       
  1850     ret = ecrt_master_link_state(master, ioctl.dev_idx, &state);
       
  1851     if (ret < 0) {
       
  1852         return ret;
       
  1853     }
       
  1854 
       
  1855     if (copy_to_user((void __user *) ioctl.state, &state, sizeof(state))) {
       
  1856         return -EFAULT;
       
  1857     }
       
  1858 
       
  1859     return 0;
       
  1860 }
       
  1861 
       
  1862 /*****************************************************************************/
       
  1863 
       
  1864 /** Get the master state.
       
  1865  */
       
  1866 int ec_cdev_ioctl_app_time(
       
  1867         ec_master_t *master, /**< EtherCAT master. */
       
  1868         unsigned long arg, /**< ioctl() argument. */
       
  1869         ec_cdev_priv_t *priv /**< Private data structure of file handle. */
       
  1870         )
       
  1871 {
       
  1872     ec_ioctl_app_time_t data;
       
  1873 
       
  1874     if (unlikely(!priv->requested))
       
  1875         return -EPERM;
       
  1876 
       
  1877     if (copy_from_user(&data, (void __user *) arg, sizeof(data))) {
       
  1878         return -EFAULT;
       
  1879     }
       
  1880 
       
  1881     ecrt_master_application_time(master, data.app_time);
       
  1882     return 0;
       
  1883 }
       
  1884 
       
  1885 /*****************************************************************************/
       
  1886 
       
  1887 /** Sync the reference clock.
       
  1888  */
       
  1889 int ec_cdev_ioctl_sync_ref(
       
  1890         ec_master_t *master, /**< EtherCAT master. */
       
  1891         unsigned long arg, /**< ioctl() argument. */
       
  1892         ec_cdev_priv_t *priv /**< Private data structure of file handle. */
       
  1893         )
       
  1894 {
       
  1895     if (unlikely(!priv->requested))
       
  1896         return -EPERM;
       
  1897 
       
  1898     down(&master->io_sem);
       
  1899     ecrt_master_sync_reference_clock(master);
       
  1900     up(&master->io_sem);
       
  1901     return 0;
       
  1902 }
       
  1903 
       
  1904 /*****************************************************************************/
       
  1905 
       
  1906 /** Sync the slave clocks.
       
  1907  */
       
  1908 int ec_cdev_ioctl_sync_slaves(
       
  1909         ec_master_t *master, /**< EtherCAT master. */
       
  1910         unsigned long arg, /**< ioctl() argument. */
       
  1911         ec_cdev_priv_t *priv /**< Private data structure of file handle. */
       
  1912         )
       
  1913 {
       
  1914     if (unlikely(!priv->requested))
       
  1915         return -EPERM;
       
  1916 
       
  1917     down(&master->io_sem);
       
  1918     ecrt_master_sync_slave_clocks(master);
       
  1919     up(&master->io_sem);
       
  1920     return 0;
       
  1921 }
       
  1922 
       
  1923 /*****************************************************************************/
       
  1924 
       
  1925 /** Queue the sync monitoring datagram.
       
  1926  */
       
  1927 int ec_cdev_ioctl_sync_mon_queue(
       
  1928         ec_master_t *master, /**< EtherCAT master. */
       
  1929         unsigned long arg, /**< ioctl() argument. */
       
  1930         ec_cdev_priv_t *priv /**< Private data structure of file handle. */
       
  1931         )
       
  1932 {
       
  1933     if (unlikely(!priv->requested))
       
  1934         return -EPERM;
       
  1935 
       
  1936     down(&master->io_sem);
       
  1937     ecrt_master_sync_monitor_queue(master);
       
  1938     up(&master->io_sem);
       
  1939     return 0;
       
  1940 }
       
  1941 
       
  1942 /*****************************************************************************/
       
  1943 
       
  1944 /** Processes the sync monitoring datagram.
       
  1945  */
       
  1946 int ec_cdev_ioctl_sync_mon_process(
       
  1947         ec_master_t *master, /**< EtherCAT master. */
       
  1948         unsigned long arg, /**< ioctl() argument. */
       
  1949         ec_cdev_priv_t *priv /**< Private data structure of file handle. */
       
  1950         )
       
  1951 {
       
  1952     uint32_t time_diff;
       
  1953 
       
  1954     if (unlikely(!priv->requested))
       
  1955         return -EPERM;
       
  1956 
       
  1957     down(&master->io_sem);
       
  1958     time_diff = ecrt_master_sync_monitor_process(master);
       
  1959     up(&master->io_sem);
       
  1960 
       
  1961     if (copy_to_user((void __user *) arg, &time_diff, sizeof(time_diff)))
       
  1962         return -EFAULT;
       
  1963 
       
  1964     return 0;
       
  1965 }
       
  1966 
       
  1967 /*****************************************************************************/
       
  1968 
       
  1969 /** Reset configuration.
       
  1970  */
       
  1971 int ec_cdev_ioctl_reset(
       
  1972         ec_master_t *master, /**< EtherCAT master. */
       
  1973         unsigned long arg, /**< ioctl() argument. */
       
  1974         ec_cdev_priv_t *priv /**< Private data structure of file handle. */
       
  1975         )
       
  1976 {
       
  1977     if (unlikely(!priv->requested))
       
  1978         return -EPERM;
       
  1979 
       
  1980     down(&master->master_sem);
       
  1981     ecrt_master_reset(master);
       
  1982     up(&master->master_sem);
       
  1983     return 0;
       
  1984 }
       
  1985 
       
  1986 /*****************************************************************************/
       
  1987 
       
  1988 /** Configure a sync manager.
       
  1989  */
       
  1990 int ec_cdev_ioctl_sc_sync(
       
  1991         ec_master_t *master, /**< EtherCAT master. */
       
  1992         unsigned long arg, /**< ioctl() argument. */
       
  1993         ec_cdev_priv_t *priv /**< Private data structure of file handle. */
       
  1994         )
       
  1995 {
       
  1996     ec_ioctl_config_t data;
       
  1997     ec_slave_config_t *sc;
       
  1998     unsigned int i;
       
  1999     int ret = 0;
       
  2000 
       
  2001     if (unlikely(!priv->requested)) {
       
  2002         ret = -EPERM;
       
  2003         goto out_return;
       
  2004     }
       
  2005 
       
  2006     if (copy_from_user(&data, (void __user *) arg, sizeof(data))) {
       
  2007         ret = -EFAULT;
       
  2008         goto out_return;
       
  2009     }
       
  2010 
       
  2011     if (down_interruptible(&master->master_sem)) {
       
  2012         ret = -EINTR;
       
  2013         goto out_return;
       
  2014     }
       
  2015 
       
  2016     if (!(sc = ec_master_get_config(master, data.config_index))) {
       
  2017         ret = -ENOENT;
       
  2018         goto out_up;
       
  2019     }
       
  2020 
       
  2021     for (i = 0; i < EC_MAX_SYNC_MANAGERS; i++) {
       
  2022         if (data.syncs[i].config_this) {
       
  2023             if (ecrt_slave_config_sync_manager(sc, i, data.syncs[i].dir,
       
  2024                         data.syncs[i].watchdog_mode)) {
       
  2025                 ret = -EINVAL;
       
  2026                 goto out_up;
       
  2027             }
       
  2028         }
       
  2029     }
       
  2030 
       
  2031 out_up:
       
  2032     up(&master->master_sem);
       
  2033 out_return:
       
  2034     return ret;
       
  2035 }
       
  2036 
       
  2037 /*****************************************************************************/
       
  2038 
       
  2039 /** Configure a slave's watchdogs.
       
  2040  */
       
  2041 int ec_cdev_ioctl_sc_watchdog(
       
  2042         ec_master_t *master, /**< EtherCAT master. */
       
  2043         unsigned long arg, /**< ioctl() argument. */
       
  2044         ec_cdev_priv_t *priv /**< Private data structure of file handle. */
       
  2045         )
       
  2046 {
       
  2047     ec_ioctl_config_t data;
       
  2048     ec_slave_config_t *sc;
       
  2049     int ret = 0;
       
  2050 
       
  2051     if (unlikely(!priv->requested)) {
       
  2052         ret = -EPERM;
       
  2053         goto out_return;
       
  2054     }
       
  2055 
       
  2056     if (copy_from_user(&data, (void __user *) arg, sizeof(data))) {
       
  2057         ret = -EFAULT;
       
  2058         goto out_return;
       
  2059     }
       
  2060 
       
  2061     if (down_interruptible(&master->master_sem)) {
       
  2062         ret = -EINTR;
       
  2063         goto out_return;
       
  2064     }
       
  2065 
       
  2066     if (!(sc = ec_master_get_config(master, data.config_index))) {
       
  2067         ret = -ENOENT;
       
  2068         goto out_up;
       
  2069     }
       
  2070 
       
  2071     ecrt_slave_config_watchdog(sc,
       
  2072             data.watchdog_divider, data.watchdog_intervals);
       
  2073 
       
  2074 out_up:
       
  2075     up(&master->master_sem);
       
  2076 out_return:
       
  2077     return ret;
       
  2078 }
       
  2079 
       
  2080 /*****************************************************************************/
       
  2081 
       
  2082 /** Add a PDO to the assignment.
       
  2083  */
       
  2084 int ec_cdev_ioctl_sc_add_pdo(
       
  2085         ec_master_t *master, /**< EtherCAT master. */
       
  2086         unsigned long arg, /**< ioctl() argument. */
       
  2087         ec_cdev_priv_t *priv /**< Private data structure of file handle. */
       
  2088         )
       
  2089 {
       
  2090     ec_ioctl_config_pdo_t data;
       
  2091     ec_slave_config_t *sc;
       
  2092 
       
  2093     if (unlikely(!priv->requested))
       
  2094         return -EPERM;
       
  2095 
       
  2096     if (copy_from_user(&data, (void __user *) arg, sizeof(data)))
       
  2097         return -EFAULT;
       
  2098 
       
  2099     if (down_interruptible(&master->master_sem))
       
  2100         return -EINTR;
       
  2101 
       
  2102     if (!(sc = ec_master_get_config(master, data.config_index))) {
       
  2103         up(&master->master_sem);
       
  2104         return -ENOENT;
       
  2105     }
       
  2106 
       
  2107     up(&master->master_sem); /** \fixme sc could be invalidated */
       
  2108 
       
  2109     return ecrt_slave_config_pdo_assign_add(sc, data.sync_index, data.index);
       
  2110 }
       
  2111 
       
  2112 /*****************************************************************************/
       
  2113 
       
  2114 /** Clears the PDO assignment.
       
  2115  */
       
  2116 int ec_cdev_ioctl_sc_clear_pdos(
       
  2117         ec_master_t *master, /**< EtherCAT master. */
       
  2118         unsigned long arg, /**< ioctl() argument. */
       
  2119         ec_cdev_priv_t *priv /**< Private data structure of file handle. */
       
  2120         )
       
  2121 {
       
  2122     ec_ioctl_config_pdo_t data;
       
  2123     ec_slave_config_t *sc;
       
  2124 
       
  2125     if (unlikely(!priv->requested))
       
  2126         return -EPERM;
       
  2127 
       
  2128     if (copy_from_user(&data, (void __user *) arg, sizeof(data)))
       
  2129         return -EFAULT;
       
  2130 
       
  2131     if (down_interruptible(&master->master_sem))
       
  2132         return -EINTR;
       
  2133 
       
  2134     if (!(sc = ec_master_get_config(master, data.config_index))) {
       
  2135         up(&master->master_sem);
       
  2136         return -ENOENT;
       
  2137     }
       
  2138 
       
  2139     up(&master->master_sem); /** \fixme sc could be invalidated */
       
  2140 
       
  2141     ecrt_slave_config_pdo_assign_clear(sc, data.sync_index);
       
  2142     return 0;
       
  2143 }
       
  2144 
       
  2145 /*****************************************************************************/
       
  2146 
       
  2147 /** Add an entry to a PDO's mapping.
       
  2148  */
       
  2149 int ec_cdev_ioctl_sc_add_entry(
       
  2150         ec_master_t *master, /**< EtherCAT master. */
       
  2151         unsigned long arg, /**< ioctl() argument. */
       
  2152         ec_cdev_priv_t *priv /**< Private data structure of file handle. */
       
  2153         )
       
  2154 {
       
  2155     ec_ioctl_add_pdo_entry_t data;
       
  2156     ec_slave_config_t *sc;
       
  2157 
       
  2158     if (unlikely(!priv->requested))
       
  2159         return -EPERM;
       
  2160 
       
  2161     if (copy_from_user(&data, (void __user *) arg, sizeof(data)))
       
  2162         return -EFAULT;
       
  2163 
       
  2164     if (down_interruptible(&master->master_sem))
       
  2165         return -EINTR;
       
  2166 
       
  2167     if (!(sc = ec_master_get_config(master, data.config_index))) {
       
  2168         up(&master->master_sem);
       
  2169         return -ENOENT;
       
  2170     }
       
  2171 
       
  2172     up(&master->master_sem); /** \fixme sc could be invalidated */
       
  2173 
       
  2174     return ecrt_slave_config_pdo_mapping_add(sc, data.pdo_index,
       
  2175             data.entry_index, data.entry_subindex, data.entry_bit_length);
       
  2176 }
       
  2177 
       
  2178 /*****************************************************************************/
       
  2179 
       
  2180 /** Clears the mapping of a PDO.
       
  2181  */
       
  2182 int ec_cdev_ioctl_sc_clear_entries(
       
  2183         ec_master_t *master, /**< EtherCAT master. */
       
  2184         unsigned long arg, /**< ioctl() argument. */
       
  2185         ec_cdev_priv_t *priv /**< Private data structure of file handle. */
       
  2186         )
       
  2187 {
       
  2188     ec_ioctl_config_pdo_t data;
       
  2189     ec_slave_config_t *sc;
       
  2190 
       
  2191     if (unlikely(!priv->requested))
       
  2192         return -EPERM;
       
  2193 
       
  2194     if (copy_from_user(&data, (void __user *) arg, sizeof(data)))
       
  2195         return -EFAULT;
       
  2196 
       
  2197     if (down_interruptible(&master->master_sem))
       
  2198         return -EINTR;
       
  2199 
       
  2200     if (!(sc = ec_master_get_config(master, data.config_index))) {
       
  2201         up(&master->master_sem);
       
  2202         return -ENOENT;
       
  2203     }
       
  2204 
       
  2205     up(&master->master_sem); /** \fixme sc could be invalidated */
       
  2206 
       
  2207     ecrt_slave_config_pdo_mapping_clear(sc, data.index);
       
  2208     return 0;
       
  2209 }
       
  2210 
       
  2211 /*****************************************************************************/
       
  2212 
       
  2213 /** Registers a PDO entry.
       
  2214  */
       
  2215 int ec_cdev_ioctl_sc_reg_pdo_entry(
       
  2216         ec_master_t *master, /**< EtherCAT master. */
       
  2217         unsigned long arg, /**< ioctl() argument. */
       
  2218         ec_cdev_priv_t *priv /**< Private data structure of file handle. */
       
  2219         )
       
  2220 {
       
  2221     ec_ioctl_reg_pdo_entry_t data;
       
  2222     ec_slave_config_t *sc;
       
  2223     ec_domain_t *domain;
       
  2224     int ret;
       
  2225 
       
  2226     if (unlikely(!priv->requested))
       
  2227         return -EPERM;
       
  2228 
       
  2229     if (copy_from_user(&data, (void __user *) arg, sizeof(data)))
       
  2230         return -EFAULT;
       
  2231 
       
  2232     if (down_interruptible(&master->master_sem))
       
  2233         return -EINTR;
       
  2234 
       
  2235     if (!(sc = ec_master_get_config(master, data.config_index))) {
       
  2236         up(&master->master_sem);
       
  2237         return -ENOENT;
       
  2238     }
       
  2239 
       
  2240     if (!(domain = ec_master_find_domain(master, data.domain_index))) {
       
  2241         up(&master->master_sem);
       
  2242         return -ENOENT;
       
  2243     }
       
  2244 
       
  2245     up(&master->master_sem); /** \fixme sc or domain could be invalidated */
       
  2246 
       
  2247     ret = ecrt_slave_config_reg_pdo_entry(sc, data.entry_index,
       
  2248             data.entry_subindex, domain, &data.bit_position);
       
  2249 
       
  2250     if (copy_to_user((void __user *) arg, &data, sizeof(data)))
       
  2251         return -EFAULT;
       
  2252 
       
  2253     return ret;
       
  2254 }
       
  2255 
       
  2256 /*****************************************************************************/
       
  2257 
       
  2258 /** Sets the DC AssignActivate word and the sync signal times.
       
  2259  */
       
  2260 int ec_cdev_ioctl_sc_dc(
       
  2261         ec_master_t *master, /**< EtherCAT master. */
       
  2262         unsigned long arg, /**< ioctl() argument. */
       
  2263         ec_cdev_priv_t *priv /**< Private data structure of file handle. */
       
  2264         )
       
  2265 {
       
  2266     ec_ioctl_config_t data;
       
  2267     ec_slave_config_t *sc;
       
  2268 
       
  2269     if (unlikely(!priv->requested))
       
  2270         return -EPERM;
       
  2271 
       
  2272     if (copy_from_user(&data, (void __user *) arg, sizeof(data)))
       
  2273         return -EFAULT;
       
  2274 
       
  2275     if (down_interruptible(&master->master_sem))
       
  2276         return -EINTR;
       
  2277 
       
  2278     if (!(sc = ec_master_get_config(master, data.config_index))) {
       
  2279         up(&master->master_sem);
       
  2280         return -ENOENT;
       
  2281     }
       
  2282 
       
  2283     ecrt_slave_config_dc(sc, data.dc_assign_activate,
       
  2284             data.dc_sync[0].cycle_time,
       
  2285             data.dc_sync[0].shift_time,
       
  2286             data.dc_sync[1].cycle_time,
       
  2287             data.dc_sync[1].shift_time);
       
  2288 
       
  2289     up(&master->master_sem);
       
  2290 
       
  2291     return 0;
       
  2292 }
       
  2293 
       
  2294 /*****************************************************************************/
       
  2295 
       
  2296 /** Configures an SDO.
       
  2297  */
       
  2298 int ec_cdev_ioctl_sc_sdo(
       
  2299         ec_master_t *master, /**< EtherCAT master. */
       
  2300         unsigned long arg, /**< ioctl() argument. */
       
  2301         ec_cdev_priv_t *priv /**< Private data structure of file handle. */
       
  2302         )
       
  2303 {
       
  2304     ec_ioctl_sc_sdo_t data;
       
  2305     ec_slave_config_t *sc;
       
  2306     uint8_t *sdo_data = NULL;
       
  2307     int ret;
       
  2308 
       
  2309     if (unlikely(!priv->requested))
       
  2310         return -EPERM;
       
  2311 
       
  2312     if (copy_from_user(&data, (void __user *) arg, sizeof(data)))
       
  2313         return -EFAULT;
       
  2314 
       
  2315     if (!data.size)
       
  2316         return -EINVAL;
       
  2317 
       
  2318     if (!(sdo_data = kmalloc(data.size, GFP_KERNEL))) {
       
  2319         return -ENOMEM;
       
  2320     }
       
  2321 
       
  2322     if (copy_from_user(sdo_data, (void __user *) data.data, data.size)) {
       
  2323         kfree(sdo_data);
       
  2324         return -EFAULT;
       
  2325     }
       
  2326 
       
  2327     if (down_interruptible(&master->master_sem)) {
       
  2328         kfree(sdo_data);
       
  2329         return -EINTR;
       
  2330     }
       
  2331 
       
  2332     if (!(sc = ec_master_get_config(master, data.config_index))) {
       
  2333         up(&master->master_sem);
       
  2334         kfree(sdo_data);
       
  2335         return -ENOENT;
       
  2336     }
       
  2337 
       
  2338     up(&master->master_sem); /** \fixme sc could be invalidated */
       
  2339 
       
  2340     if (data.complete_access) {
       
  2341         ret = ecrt_slave_config_complete_sdo(sc,
       
  2342                 data.index, sdo_data, data.size);
       
  2343     } else {
       
  2344         ret = ecrt_slave_config_sdo(sc, data.index, data.subindex, sdo_data,
       
  2345                 data.size);
       
  2346     }
       
  2347     kfree(sdo_data);
       
  2348     return ret;
       
  2349 }
       
  2350 
       
  2351 /*****************************************************************************/
       
  2352 
       
  2353 /** Create an SDO request.
       
  2354  */
       
  2355 int ec_cdev_ioctl_sc_create_sdo_request(
       
  2356         ec_master_t *master, /**< EtherCAT master. */
       
  2357         unsigned long arg, /**< ioctl() argument. */
       
  2358         ec_cdev_priv_t *priv /**< Private data structure of file handle. */
       
  2359         )
       
  2360 {
       
  2361     ec_ioctl_sdo_request_t data;
       
  2362     ec_slave_config_t *sc;
       
  2363     ec_sdo_request_t *req;
       
  2364 
       
  2365     if (unlikely(!priv->requested))
       
  2366         return -EPERM;
       
  2367 
       
  2368     if (copy_from_user(&data, (void __user *) arg, sizeof(data))) {
       
  2369         return -EFAULT;
       
  2370     }
       
  2371 
       
  2372     data.request_index = 0;
       
  2373 
       
  2374     if (down_interruptible(&master->master_sem))
       
  2375         return -EINTR;
       
  2376 
       
  2377     sc = ec_master_get_config(master, data.config_index);
       
  2378     if (!sc) {
       
  2379         up(&master->master_sem);
       
  2380         return -ENOENT;
       
  2381     }
       
  2382 
       
  2383     list_for_each_entry(req, &sc->sdo_requests, list) {
       
  2384         data.request_index++;
       
  2385     }
       
  2386 
       
  2387     up(&master->master_sem); /** \fixme sc could be invalidated */
       
  2388 
       
  2389     req = ecrt_slave_config_create_sdo_request_err(sc, data.sdo_index,
       
  2390             data.sdo_subindex, data.size);
       
  2391     if (IS_ERR(req))
       
  2392         return PTR_ERR(req);
       
  2393 
       
  2394     if (copy_to_user((void __user *) arg, &data, sizeof(data)))
       
  2395         return -EFAULT;
       
  2396 
       
  2397     return 0;
       
  2398 }
       
  2399 
       
  2400 /*****************************************************************************/
       
  2401 
       
  2402 /** Create a VoE handler.
       
  2403  */
       
  2404 int ec_cdev_ioctl_sc_create_voe_handler(
       
  2405         ec_master_t *master, /**< EtherCAT master. */
       
  2406         unsigned long arg, /**< ioctl() argument. */
       
  2407         ec_cdev_priv_t *priv /**< Private data structure of file handle. */
       
  2408         )
       
  2409 {
       
  2410     ec_ioctl_voe_t data;
       
  2411     ec_slave_config_t *sc;
       
  2412     ec_voe_handler_t *voe;
       
  2413 
       
  2414     if (unlikely(!priv->requested))
       
  2415         return -EPERM;
       
  2416 
       
  2417     if (copy_from_user(&data, (void __user *) arg, sizeof(data))) {
       
  2418         return -EFAULT;
       
  2419     }
       
  2420 
       
  2421     data.voe_index = 0;
       
  2422 
       
  2423     if (down_interruptible(&master->master_sem))
       
  2424         return -EINTR;
       
  2425 
       
  2426     sc = ec_master_get_config(master, data.config_index);
       
  2427     if (!sc) {
       
  2428         up(&master->master_sem);
       
  2429         return -ENOENT;
       
  2430     }
       
  2431 
       
  2432     list_for_each_entry(voe, &sc->voe_handlers, list) {
       
  2433         data.voe_index++;
       
  2434     }
       
  2435 
       
  2436     up(&master->master_sem); /** \fixme sc could be invalidated */
       
  2437 
       
  2438     voe = ecrt_slave_config_create_voe_handler_err(sc, data.size);
       
  2439     if (IS_ERR(voe))
       
  2440         return PTR_ERR(voe);
       
  2441 
       
  2442     if (copy_to_user((void __user *) arg, &data, sizeof(data)))
       
  2443         return -EFAULT;
       
  2444 
       
  2445     return 0;
       
  2446 }
       
  2447 
       
  2448 /*****************************************************************************/
       
  2449 
       
  2450 /** Get the slave configuration's state.
       
  2451  */
       
  2452 int ec_cdev_ioctl_sc_state(
       
  2453         ec_master_t *master, /**< EtherCAT master. */
       
  2454         unsigned long arg, /**< ioctl() argument. */
       
  2455         ec_cdev_priv_t *priv /**< Private data structure of file handle. */
       
  2456         )
       
  2457 {
       
  2458     ec_ioctl_sc_state_t data;
       
  2459     const ec_slave_config_t *sc;
       
  2460     ec_slave_config_state_t state;
       
  2461 
       
  2462     if (unlikely(!priv->requested))
       
  2463         return -EPERM;
       
  2464 
       
  2465     if (copy_from_user(&data, (void __user *) arg, sizeof(data))) {
       
  2466         return -EFAULT;
       
  2467     }
       
  2468 
       
  2469     /* no locking of master_sem needed, because sc will not be deleted in the
       
  2470      * meantime. */
       
  2471 
       
  2472     if (!(sc = ec_master_get_config_const(master, data.config_index))) {
       
  2473         return -ENOENT;
       
  2474     }
       
  2475 
       
  2476     ecrt_slave_config_state(sc, &state);
       
  2477 
       
  2478     if (copy_to_user((void __user *) data.state, &state, sizeof(state)))
       
  2479         return -EFAULT;
       
  2480 
       
  2481     return 0;
       
  2482 }
       
  2483 
       
  2484 /*****************************************************************************/
       
  2485 
       
  2486 /** Configures an IDN.
       
  2487  */
       
  2488 int ec_cdev_ioctl_sc_idn(
       
  2489         ec_master_t *master, /**< EtherCAT master. */
       
  2490         unsigned long arg, /**< ioctl() argument. */
       
  2491         ec_cdev_priv_t *priv /**< Private data structure of file handle. */
       
  2492         )
       
  2493 {
       
  2494     ec_ioctl_sc_idn_t ioctl;
       
  2495     ec_slave_config_t *sc;
       
  2496     uint8_t *data = NULL;
       
  2497     int ret;
       
  2498 
       
  2499     if (unlikely(!priv->requested))
       
  2500         return -EPERM;
       
  2501 
       
  2502     if (copy_from_user(&ioctl, (void __user *) arg, sizeof(ioctl)))
       
  2503         return -EFAULT;
       
  2504 
       
  2505     if (!ioctl.size)
       
  2506         return -EINVAL;
       
  2507 
       
  2508     if (!(data = kmalloc(ioctl.size, GFP_KERNEL))) {
       
  2509         return -ENOMEM;
       
  2510     }
       
  2511 
       
  2512     if (copy_from_user(data, (void __user *) ioctl.data, ioctl.size)) {
       
  2513         kfree(data);
       
  2514         return -EFAULT;
       
  2515     }
       
  2516 
       
  2517     if (down_interruptible(&master->master_sem)) {
       
  2518         kfree(data);
       
  2519         return -EINTR;
       
  2520     }
       
  2521 
       
  2522     if (!(sc = ec_master_get_config(master, ioctl.config_index))) {
       
  2523         up(&master->master_sem);
       
  2524         kfree(data);
       
  2525         return -ENOENT;
       
  2526     }
       
  2527 
       
  2528     up(&master->master_sem); /** \fixme sc could be invalidated */
       
  2529 
       
  2530     ret = ecrt_slave_config_idn(
       
  2531             sc, ioctl.drive_no, ioctl.idn, ioctl.al_state, data, ioctl.size);
       
  2532     kfree(data);
       
  2533     return ret;
       
  2534 }
       
  2535 
       
  2536 /*****************************************************************************/
       
  2537 
       
  2538 /** Gets the domain's offset in the total process data.
       
  2539  */
       
  2540 int ec_cdev_ioctl_domain_offset(
       
  2541         ec_master_t *master, /**< EtherCAT master. */
       
  2542         unsigned long arg, /**< ioctl() argument. */
       
  2543         ec_cdev_priv_t *priv /**< Private data structure of file handle. */
       
  2544         )
       
  2545 {
       
  2546     int offset = 0;
       
  2547     const ec_domain_t *domain;
       
  2548 
       
  2549     if (unlikely(!priv->requested))
       
  2550         return -EPERM;
       
  2551 
       
  2552     if (down_interruptible(&master->master_sem)) {
       
  2553         return -EINTR;
       
  2554     }
       
  2555 
       
  2556     list_for_each_entry(domain, &master->domains, list) {
       
  2557         if (domain->index == arg) {
       
  2558             up(&master->master_sem);
       
  2559             return offset;
       
  2560         }
       
  2561         offset += ecrt_domain_size(domain);
       
  2562     }
       
  2563 
       
  2564     up(&master->master_sem);
       
  2565     return -ENOENT;
       
  2566 }
       
  2567 
       
  2568 /*****************************************************************************/
       
  2569 
       
  2570 /** Process the domain.
       
  2571  */
       
  2572 int ec_cdev_ioctl_domain_process(
       
  2573         ec_master_t *master, /**< EtherCAT master. */
       
  2574         unsigned long arg, /**< ioctl() argument. */
       
  2575         ec_cdev_priv_t *priv /**< Private data structure of file handle. */
       
  2576         )
       
  2577 {
       
  2578     ec_domain_t *domain;
       
  2579 
       
  2580     if (unlikely(!priv->requested))
       
  2581         return -EPERM;
       
  2582 
       
  2583     /* no locking of master_sem needed, because domain will not be deleted in
       
  2584      * the meantime. */
       
  2585 
       
  2586     if (!(domain = ec_master_find_domain(master, arg))) {
       
  2587         return -ENOENT;
       
  2588     }
       
  2589 
       
  2590     ecrt_domain_process(domain);
       
  2591     return 0;
       
  2592 }
       
  2593 
       
  2594 /*****************************************************************************/
       
  2595 
       
  2596 /** Queue the domain.
       
  2597  */
       
  2598 int ec_cdev_ioctl_domain_queue(
       
  2599         ec_master_t *master, /**< EtherCAT master. */
       
  2600         unsigned long arg, /**< ioctl() argument. */
       
  2601         ec_cdev_priv_t *priv /**< Private data structure of file handle. */
       
  2602         )
       
  2603 {
       
  2604     ec_domain_t *domain;
       
  2605 
       
  2606     if (unlikely(!priv->requested))
       
  2607         return -EPERM;
       
  2608 
       
  2609     /* no locking of master_sem needed, because domain will not be deleted in
       
  2610      * the meantime. */
       
  2611 
       
  2612     if (!(domain = ec_master_find_domain(master, arg))) {
       
  2613         return -ENOENT;
       
  2614     }
       
  2615 
       
  2616     ecrt_domain_queue(domain);
       
  2617     return 0;
       
  2618 }
       
  2619 
       
  2620 /*****************************************************************************/
       
  2621 
       
  2622 /** Get the domain state.
       
  2623  */
       
  2624 int ec_cdev_ioctl_domain_state(
       
  2625         ec_master_t *master, /**< EtherCAT master. */
       
  2626         unsigned long arg, /**< ioctl() argument. */
       
  2627         ec_cdev_priv_t *priv /**< Private data structure of file handle. */
       
  2628         )
       
  2629 {
       
  2630     ec_ioctl_domain_state_t data;
       
  2631     const ec_domain_t *domain;
       
  2632     ec_domain_state_t state;
       
  2633 
       
  2634     if (unlikely(!priv->requested))
       
  2635         return -EPERM;
       
  2636 
       
  2637     if (copy_from_user(&data, (void __user *) arg, sizeof(data))) {
       
  2638         return -EFAULT;
       
  2639     }
       
  2640 
       
  2641     /* no locking of master_sem needed, because domain will not be deleted in
       
  2642      * the meantime. */
       
  2643 
       
  2644     if (!(domain = ec_master_find_domain_const(master, data.domain_index))) {
       
  2645         return -ENOENT;
       
  2646     }
       
  2647 
       
  2648     ecrt_domain_state(domain, &state);
       
  2649 
       
  2650     if (copy_to_user((void __user *) data.state, &state, sizeof(state)))
       
  2651         return -EFAULT;
       
  2652 
       
  2653     return 0;
       
  2654 }
       
  2655 
       
  2656 /*****************************************************************************/
       
  2657 
       
  2658 /** Sets an SDO request's timeout.
       
  2659  */
       
  2660 int ec_cdev_ioctl_sdo_request_timeout(
       
  2661         ec_master_t *master, /**< EtherCAT master. */
       
  2662         unsigned long arg, /**< ioctl() argument. */
       
  2663         ec_cdev_priv_t *priv /**< Private data structure of file handle. */
       
  2664         )
       
  2665 {
       
  2666     ec_ioctl_sdo_request_t data;
       
  2667     ec_slave_config_t *sc;
       
  2668     ec_sdo_request_t *req;
       
  2669 
       
  2670     if (unlikely(!priv->requested))
       
  2671         return -EPERM;
       
  2672 
       
  2673     if (copy_from_user(&data, (void __user *) arg, sizeof(data)))
       
  2674         return -EFAULT;
       
  2675 
       
  2676     /* no locking of master_sem needed, because neither sc nor req will not be
       
  2677      * deleted in the meantime. */
       
  2678 
       
  2679     if (!(sc = ec_master_get_config(master, data.config_index))) {
       
  2680         return -ENOENT;
       
  2681     }
       
  2682 
       
  2683     if (!(req = ec_slave_config_find_sdo_request(sc, data.request_index))) {
       
  2684         return -ENOENT;
       
  2685     }
       
  2686 
       
  2687     ecrt_sdo_request_timeout(req, data.timeout);
       
  2688     return 0;
       
  2689 }
       
  2690 
       
  2691 /*****************************************************************************/
       
  2692 
       
  2693 /** Gets an SDO request's state.
       
  2694  */
       
  2695 int ec_cdev_ioctl_sdo_request_state(
       
  2696         ec_master_t *master, /**< EtherCAT master. */
       
  2697         unsigned long arg, /**< ioctl() argument. */
       
  2698         ec_cdev_priv_t *priv /**< Private data structure of file handle. */
       
  2699         )
       
  2700 {
       
  2701     ec_ioctl_sdo_request_t data;
       
  2702     ec_slave_config_t *sc;
       
  2703     ec_sdo_request_t *req;
       
  2704 
       
  2705     if (unlikely(!priv->requested))
       
  2706         return -EPERM;
       
  2707 
       
  2708     if (copy_from_user(&data, (void __user *) arg, sizeof(data)))
       
  2709         return -EFAULT;
       
  2710 
       
  2711     /* no locking of master_sem needed, because neither sc nor req will not be
       
  2712      * deleted in the meantime. */
       
  2713 
       
  2714     if (!(sc = ec_master_get_config(master, data.config_index))) {
       
  2715         return -ENOENT;
       
  2716     }
       
  2717 
       
  2718     if (!(req = ec_slave_config_find_sdo_request(sc, data.request_index))) {
       
  2719         return -ENOENT;
       
  2720     }
       
  2721 
       
  2722     data.state = ecrt_sdo_request_state(req);
       
  2723     if (data.state == EC_REQUEST_SUCCESS && req->dir == EC_DIR_INPUT)
       
  2724         data.size = ecrt_sdo_request_data_size(req);
       
  2725     else
       
  2726         data.size = 0;
       
  2727 
       
  2728     if (copy_to_user((void __user *) arg, &data, sizeof(data)))
       
  2729         return -EFAULT;
       
  2730 
       
  2731     return 0;
       
  2732 }
       
  2733 
       
  2734 /*****************************************************************************/
       
  2735 
       
  2736 /** Starts an SDO read operation.
       
  2737  */
       
  2738 int ec_cdev_ioctl_sdo_request_read(
       
  2739         ec_master_t *master, /**< EtherCAT master. */
       
  2740         unsigned long arg, /**< ioctl() argument. */
       
  2741         ec_cdev_priv_t *priv /**< Private data structure of file handle. */
       
  2742         )
       
  2743 {
       
  2744     ec_ioctl_sdo_request_t data;
       
  2745     ec_slave_config_t *sc;
       
  2746     ec_sdo_request_t *req;
       
  2747 
       
  2748     if (unlikely(!priv->requested))
       
  2749         return -EPERM;
       
  2750 
       
  2751     if (copy_from_user(&data, (void __user *) arg, sizeof(data)))
       
  2752         return -EFAULT;
       
  2753 
       
  2754     /* no locking of master_sem needed, because neither sc nor req will not be
       
  2755      * deleted in the meantime. */
       
  2756 
       
  2757     if (!(sc = ec_master_get_config(master, data.config_index))) {
       
  2758         return -ENOENT;
       
  2759     }
       
  2760 
       
  2761     if (!(req = ec_slave_config_find_sdo_request(sc, data.request_index))) {
       
  2762         return -ENOENT;
       
  2763     }
       
  2764 
       
  2765     ecrt_sdo_request_read(req);
       
  2766     return 0;
       
  2767 }
       
  2768 
       
  2769 /*****************************************************************************/
       
  2770 
       
  2771 /** Starts an SDO write operation.
       
  2772  */
       
  2773 int ec_cdev_ioctl_sdo_request_write(
       
  2774         ec_master_t *master, /**< EtherCAT master. */
       
  2775         unsigned long arg, /**< ioctl() argument. */
       
  2776         ec_cdev_priv_t *priv /**< Private data structure of file handle. */
       
  2777         )
       
  2778 {
       
  2779     ec_ioctl_sdo_request_t data;
       
  2780     ec_slave_config_t *sc;
       
  2781     ec_sdo_request_t *req;
       
  2782     int ret;
       
  2783 
       
  2784     if (unlikely(!priv->requested))
       
  2785         return -EPERM;
       
  2786 
       
  2787     if (copy_from_user(&data, (void __user *) arg, sizeof(data)))
       
  2788         return -EFAULT;
       
  2789 
       
  2790     if (!data.size) {
       
  2791         EC_MASTER_ERR(master, "SDO download: Data size may not be zero!\n");
       
  2792         return -EINVAL;
       
  2793     }
       
  2794 
       
  2795     /* no locking of master_sem needed, because neither sc nor req will not be
       
  2796      * deleted in the meantime. */
       
  2797 
       
  2798     if (!(sc = ec_master_get_config(master, data.config_index))) {
       
  2799         return -ENOENT;
       
  2800     }
       
  2801 
       
  2802     if (!(req = ec_slave_config_find_sdo_request(sc, data.request_index))) {
       
  2803         return -ENOENT;
       
  2804     }
       
  2805 
       
  2806     ret = ec_sdo_request_alloc(req, data.size);
       
  2807     if (ret)
       
  2808         return ret;
       
  2809 
       
  2810     if (copy_from_user(req->data, (void __user *) data.data, data.size))
       
  2811         return -EFAULT;
       
  2812 
       
  2813     req->data_size = data.size;
       
  2814     ecrt_sdo_request_write(req);
       
  2815     return 0;
       
  2816 }
       
  2817 
       
  2818 /*****************************************************************************/
       
  2819 
       
  2820 /** Read SDO data.
       
  2821  */
       
  2822 int ec_cdev_ioctl_sdo_request_data(
       
  2823         ec_master_t *master, /**< EtherCAT master. */
       
  2824         unsigned long arg, /**< ioctl() argument. */
       
  2825         ec_cdev_priv_t *priv /**< Private data structure of file handle. */
       
  2826         )
       
  2827 {
       
  2828     ec_ioctl_sdo_request_t data;
       
  2829     ec_slave_config_t *sc;
       
  2830     ec_sdo_request_t *req;
       
  2831 
       
  2832     if (unlikely(!priv->requested))
       
  2833         return -EPERM;
       
  2834 
       
  2835     if (copy_from_user(&data, (void __user *) arg, sizeof(data)))
       
  2836         return -EFAULT;
       
  2837 
       
  2838     /* no locking of master_sem needed, because neither sc nor req will not be
       
  2839      * deleted in the meantime. */
       
  2840 
       
  2841     if (!(sc = ec_master_get_config(master, data.config_index))) {
       
  2842         return -ENOENT;
       
  2843     }
       
  2844 
       
  2845     if (!(req = ec_slave_config_find_sdo_request(sc, data.request_index))) {
       
  2846         return -ENOENT;
       
  2847     }
       
  2848 
       
  2849     if (copy_to_user((void __user *) data.data, ecrt_sdo_request_data(req),
       
  2850                 ecrt_sdo_request_data_size(req)))
       
  2851         return -EFAULT;
       
  2852 
       
  2853     return 0;
       
  2854 }
       
  2855 
       
  2856 /*****************************************************************************/
       
  2857 
       
  2858 /** Sets the VoE send header.
       
  2859  */
       
  2860 int ec_cdev_ioctl_voe_send_header(
       
  2861         ec_master_t *master, /**< EtherCAT master. */
       
  2862         unsigned long arg, /**< ioctl() argument. */
       
  2863         ec_cdev_priv_t *priv /**< Private data structure of file handle. */
       
  2864         )
       
  2865 {
       
  2866     ec_ioctl_voe_t data;
       
  2867     ec_slave_config_t *sc;
       
  2868     ec_voe_handler_t *voe;
       
  2869     uint32_t vendor_id;
       
  2870     uint16_t vendor_type;
       
  2871 
       
  2872     if (unlikely(!priv->requested))
       
  2873         return -EPERM;
       
  2874 
       
  2875     if (copy_from_user(&data, (void __user *) arg, sizeof(data)))
       
  2876         return -EFAULT;
       
  2877 
       
  2878     if (get_user(vendor_id, data.vendor_id))
       
  2879         return -EFAULT;
       
  2880 
       
  2881     if (get_user(vendor_type, data.vendor_type))
       
  2882         return -EFAULT;
       
  2883 
       
  2884     /* no locking of master_sem needed, because neither sc nor voe will not be
       
  2885      * deleted in the meantime. */
       
  2886 
       
  2887     if (!(sc = ec_master_get_config(master, data.config_index))) {
       
  2888         return -ENOENT;
       
  2889     }
       
  2890 
       
  2891     if (!(voe = ec_slave_config_find_voe_handler(sc, data.voe_index))) {
       
  2892         return -ENOENT;
       
  2893     }
       
  2894 
       
  2895     ecrt_voe_handler_send_header(voe, vendor_id, vendor_type);
       
  2896     return 0;
       
  2897 }
       
  2898 
       
  2899 /*****************************************************************************/
       
  2900 
       
  2901 /** Gets the received VoE header.
       
  2902  */
       
  2903 int ec_cdev_ioctl_voe_rec_header(
       
  2904         ec_master_t *master, /**< EtherCAT master. */
       
  2905         unsigned long arg, /**< ioctl() argument. */
       
  2906         ec_cdev_priv_t *priv /**< Private data structure of file handle. */
       
  2907         )
       
  2908 {
       
  2909     ec_ioctl_voe_t data;
       
  2910     ec_slave_config_t *sc;
       
  2911     ec_voe_handler_t *voe;
       
  2912     uint32_t vendor_id;
       
  2913     uint16_t vendor_type;
       
  2914 
       
  2915     if (unlikely(!priv->requested))
       
  2916         return -EPERM;
       
  2917 
       
  2918     if (copy_from_user(&data, (void __user *) arg, sizeof(data)))
       
  2919         return -EFAULT;
       
  2920 
       
  2921     /* no locking of master_sem needed, because neither sc nor voe will not be
       
  2922      * deleted in the meantime. */
       
  2923 
       
  2924     if (!(sc = ec_master_get_config(master, data.config_index))) {
       
  2925         return -ENOENT;
       
  2926     }
       
  2927 
       
  2928     if (!(voe = ec_slave_config_find_voe_handler(sc, data.voe_index))) {
       
  2929         return -ENOENT;
       
  2930     }
       
  2931 
       
  2932     ecrt_voe_handler_received_header(voe, &vendor_id, &vendor_type);
       
  2933 
       
  2934     if (likely(data.vendor_id))
       
  2935         if (put_user(vendor_id, data.vendor_id))
       
  2936             return -EFAULT;
       
  2937 
       
  2938     if (likely(data.vendor_type))
       
  2939         if (put_user(vendor_type, data.vendor_type))
       
  2940             return -EFAULT;
       
  2941 
       
  2942     return 0;
       
  2943 }
       
  2944 
       
  2945 /*****************************************************************************/
       
  2946 
       
  2947 /** Starts a VoE read operation.
       
  2948  */
       
  2949 int ec_cdev_ioctl_voe_read(
       
  2950         ec_master_t *master, /**< EtherCAT master. */
       
  2951         unsigned long arg, /**< ioctl() argument. */
       
  2952         ec_cdev_priv_t *priv /**< Private data structure of file handle. */
       
  2953         )
       
  2954 {
       
  2955     ec_ioctl_voe_t data;
       
  2956     ec_slave_config_t *sc;
       
  2957     ec_voe_handler_t *voe;
       
  2958 
       
  2959     if (unlikely(!priv->requested))
       
  2960         return -EPERM;
       
  2961 
       
  2962     if (copy_from_user(&data, (void __user *) arg, sizeof(data)))
       
  2963         return -EFAULT;
       
  2964 
       
  2965     /* no locking of master_sem needed, because neither sc nor voe will not be
       
  2966      * deleted in the meantime. */
       
  2967 
       
  2968     if (!(sc = ec_master_get_config(master, data.config_index))) {
       
  2969         return -ENOENT;
       
  2970     }
       
  2971 
       
  2972     if (!(voe = ec_slave_config_find_voe_handler(sc, data.voe_index))) {
       
  2973         return -ENOENT;
       
  2974     }
       
  2975 
       
  2976     ecrt_voe_handler_read(voe);
       
  2977     return 0;
       
  2978 }
       
  2979 
       
  2980 /*****************************************************************************/
       
  2981 
       
  2982 /** Starts a VoE read operation without sending a sync message first.
       
  2983  */
       
  2984 int ec_cdev_ioctl_voe_read_nosync(
       
  2985         ec_master_t *master, /**< EtherCAT master. */
       
  2986         unsigned long arg, /**< ioctl() argument. */
       
  2987         ec_cdev_priv_t *priv /**< Private data structure of file handle. */
       
  2988         )
       
  2989 {
       
  2990     ec_ioctl_voe_t data;
       
  2991     ec_slave_config_t *sc;
       
  2992     ec_voe_handler_t *voe;
       
  2993 
       
  2994     if (unlikely(!priv->requested))
       
  2995         return -EPERM;
       
  2996 
       
  2997     if (copy_from_user(&data, (void __user *) arg, sizeof(data)))
       
  2998         return -EFAULT;
       
  2999 
       
  3000     /* no locking of master_sem needed, because neither sc nor voe will not be
       
  3001      * deleted in the meantime. */
       
  3002 
       
  3003     if (!(sc = ec_master_get_config(master, data.config_index))) {
       
  3004         return -ENOENT;
       
  3005     }
       
  3006 
       
  3007     if (!(voe = ec_slave_config_find_voe_handler(sc, data.voe_index))) {
       
  3008         return -ENOENT;
       
  3009     }
       
  3010 
       
  3011     ecrt_voe_handler_read_nosync(voe);
       
  3012     return 0;
       
  3013 }
       
  3014 
       
  3015 /*****************************************************************************/
       
  3016 
       
  3017 /** Starts a VoE write operation.
       
  3018  */
       
  3019 int ec_cdev_ioctl_voe_write(
       
  3020         ec_master_t *master, /**< EtherCAT master. */
       
  3021         unsigned long arg, /**< ioctl() argument. */
       
  3022         ec_cdev_priv_t *priv /**< Private data structure of file handle. */
       
  3023         )
       
  3024 {
       
  3025     ec_ioctl_voe_t data;
       
  3026     ec_slave_config_t *sc;
       
  3027     ec_voe_handler_t *voe;
       
  3028 
       
  3029     if (unlikely(!priv->requested))
       
  3030         return -EPERM;
       
  3031 
       
  3032     if (copy_from_user(&data, (void __user *) arg, sizeof(data)))
       
  3033         return -EFAULT;
       
  3034 
       
  3035     /* no locking of master_sem needed, because neither sc nor voe will not be
       
  3036      * deleted in the meantime. */
       
  3037 
       
  3038     if (!(sc = ec_master_get_config(master, data.config_index))) {
       
  3039         return -ENOENT;
       
  3040     }
       
  3041 
       
  3042     if (!(voe = ec_slave_config_find_voe_handler(sc, data.voe_index))) {
       
  3043         return -ENOENT;
       
  3044     }
       
  3045 
       
  3046     if (data.size) {
       
  3047         if (data.size > ec_voe_handler_mem_size(voe))
       
  3048             return -EOVERFLOW;
       
  3049 
       
  3050         if (copy_from_user(ecrt_voe_handler_data(voe),
       
  3051                     (void __user *) data.data, data.size))
       
  3052             return -EFAULT;
       
  3053     }
       
  3054 
       
  3055     ecrt_voe_handler_write(voe, data.size);
       
  3056     return 0;
       
  3057 }
       
  3058 
       
  3059 /*****************************************************************************/
       
  3060 
       
  3061 /** Executes the VoE state machine.
       
  3062  */
       
  3063 int ec_cdev_ioctl_voe_exec(
       
  3064         ec_master_t *master, /**< EtherCAT master. */
       
  3065         unsigned long arg, /**< ioctl() argument. */
       
  3066         ec_cdev_priv_t *priv /**< Private data structure of file handle. */
       
  3067         )
       
  3068 {
       
  3069     ec_ioctl_voe_t data;
       
  3070     ec_slave_config_t *sc;
       
  3071     ec_voe_handler_t *voe;
       
  3072 
       
  3073     if (unlikely(!priv->requested))
       
  3074         return -EPERM;
       
  3075 
       
  3076     if (copy_from_user(&data, (void __user *) arg, sizeof(data)))
       
  3077         return -EFAULT;
       
  3078 
       
  3079     /* no locking of master_sem needed, because neither sc nor voe will not be
       
  3080      * deleted in the meantime. */
       
  3081 
       
  3082     if (!(sc = ec_master_get_config(master, data.config_index))) {
       
  3083         return -ENOENT;
       
  3084     }
       
  3085 
       
  3086     if (!(voe = ec_slave_config_find_voe_handler(sc, data.voe_index))) {
       
  3087         return -ENOENT;
       
  3088     }
       
  3089 
       
  3090     data.state = ecrt_voe_handler_execute(voe);
       
  3091     if (data.state == EC_REQUEST_SUCCESS && voe->dir == EC_DIR_INPUT)
       
  3092         data.size = ecrt_voe_handler_data_size(voe);
       
  3093     else
       
  3094         data.size = 0;
       
  3095 
       
  3096     if (copy_to_user((void __user *) arg, &data, sizeof(data)))
       
  3097         return -EFAULT;
       
  3098 
       
  3099     return 0;
       
  3100 }
       
  3101 
       
  3102 /*****************************************************************************/
       
  3103 
       
  3104 /** Reads the received VoE data.
       
  3105  */
       
  3106 int ec_cdev_ioctl_voe_data(
       
  3107         ec_master_t *master, /**< EtherCAT master. */
       
  3108         unsigned long arg, /**< ioctl() argument. */
       
  3109         ec_cdev_priv_t *priv /**< Private data structure of file handle. */
       
  3110         )
       
  3111 {
       
  3112     ec_ioctl_voe_t data;
       
  3113     ec_slave_config_t *sc;
       
  3114     ec_voe_handler_t *voe;
       
  3115 
       
  3116     if (unlikely(!priv->requested))
       
  3117         return -EPERM;
       
  3118 
       
  3119     if (copy_from_user(&data, (void __user *) arg, sizeof(data)))
       
  3120         return -EFAULT;
       
  3121 
       
  3122     /* no locking of master_sem needed, because neither sc nor voe will not be
       
  3123      * deleted in the meantime. */
       
  3124 
       
  3125     if (!(sc = ec_master_get_config(master, data.config_index))) {
       
  3126         return -ENOENT;
       
  3127     }
       
  3128 
       
  3129     if (!(voe = ec_slave_config_find_voe_handler(sc, data.voe_index))) {
       
  3130         return -ENOENT;
       
  3131     }
       
  3132 
       
  3133     if (copy_to_user((void __user *) data.data, ecrt_voe_handler_data(voe),
       
  3134                 ecrt_voe_handler_data_size(voe)))
       
  3135         return -EFAULT;
       
  3136 
       
  3137     return 0;
       
  3138 }
       
  3139 
       
  3140 /*****************************************************************************/
       
  3141 
       
  3142 /** Read a file from a slave via FoE.
       
  3143  */
       
  3144 int ec_cdev_ioctl_slave_foe_read(
       
  3145         ec_master_t *master, /**< EtherCAT master. */
       
  3146         unsigned long arg /**< ioctl() argument. */
       
  3147         )
       
  3148 {
       
  3149     ec_ioctl_slave_foe_t data;
       
  3150     ec_master_foe_request_t request;
       
  3151     int retval;
       
  3152 
       
  3153     if (copy_from_user(&data, (void __user *) arg, sizeof(data))) {
       
  3154         return -EFAULT;
       
  3155     }
       
  3156 
       
  3157     ec_foe_request_init(&request.req, data.file_name);
       
  3158     ec_foe_request_read(&request.req);
       
  3159     ec_foe_request_alloc(&request.req, 10000); // FIXME
       
  3160 
       
  3161     if (down_interruptible(&master->master_sem)) {
       
  3162         ec_foe_request_clear(&request.req);
       
  3163         return -EINTR;
       
  3164     }
       
  3165 
       
  3166     if (!(request.slave = ec_master_find_slave(
       
  3167                     master, 0, data.slave_position))) {
       
  3168         up(&master->master_sem);
       
  3169         ec_foe_request_clear(&request.req);
       
  3170         EC_MASTER_ERR(master, "Slave %u does not exist!\n",
       
  3171                 data.slave_position);
       
  3172         return -EINVAL;
       
  3173     }
       
  3174 
       
  3175     // schedule request.
       
  3176     list_add_tail(&request.list, &request.slave->foe_requests);
       
  3177 
       
  3178     up(&master->master_sem);
       
  3179 
       
  3180     EC_SLAVE_DBG(request.slave, 1, "Scheduled FoE read request.\n");
       
  3181 
       
  3182     // wait for processing through FSM
       
  3183     if (wait_event_interruptible(request.slave->foe_queue,
       
  3184                 request.req.state != EC_INT_REQUEST_QUEUED)) {
       
  3185         // interrupted by signal
       
  3186         down(&master->master_sem);
       
  3187         if (request.req.state == EC_INT_REQUEST_QUEUED) {
       
  3188             list_del(&request.list);
       
  3189             up(&master->master_sem);
       
  3190             ec_foe_request_clear(&request.req);
       
  3191             return -EINTR;
       
  3192         }
       
  3193         // request already processing: interrupt not possible.
       
  3194         up(&master->master_sem);
       
  3195     }
       
  3196 
       
  3197     // wait until master FSM has finished processing
       
  3198     wait_event(request.slave->foe_queue,
       
  3199             request.req.state != EC_INT_REQUEST_BUSY);
       
  3200 
       
  3201     data.result = request.req.result;
       
  3202     data.error_code = request.req.error_code;
       
  3203 
       
  3204     EC_SLAVE_DBG(request.slave, 1, "Read %zd bytes via FoE"
       
  3205             " (result = 0x%x).\n", request.req.data_size, request.req.result);
       
  3206 
       
  3207     if (request.req.state != EC_INT_REQUEST_SUCCESS) {
       
  3208         data.data_size = 0;
       
  3209         retval = -EIO;
       
  3210     } else {
       
  3211         if (request.req.data_size > data.buffer_size) {
       
  3212             EC_MASTER_ERR(master, "Buffer too small.\n");
       
  3213             ec_foe_request_clear(&request.req);
       
  3214             return -EOVERFLOW;
       
  3215         }
       
  3216         data.data_size = request.req.data_size;
       
  3217         if (copy_to_user((void __user *) data.buffer,
       
  3218                     request.req.buffer, data.data_size)) {
       
  3219             ec_foe_request_clear(&request.req);
       
  3220             return -EFAULT;
       
  3221         }
       
  3222         retval = 0;
       
  3223     }
       
  3224 
       
  3225     if (__copy_to_user((void __user *) arg, &data, sizeof(data))) {
       
  3226         retval = -EFAULT;
       
  3227     }
       
  3228 
       
  3229     EC_SLAVE_DBG(request.slave, 1, "Finished FoE read request.\n");
       
  3230 
       
  3231     ec_foe_request_clear(&request.req);
       
  3232 
       
  3233     return retval;
       
  3234 }
       
  3235 
       
  3236 /*****************************************************************************/
       
  3237 
       
  3238 /** Write a file to a slave via FoE
       
  3239  */
       
  3240 int ec_cdev_ioctl_slave_foe_write(
       
  3241         ec_master_t *master, /**< EtherCAT master. */
       
  3242         unsigned long arg /**< ioctl() argument. */
       
  3243         )
       
  3244 {
       
  3245     ec_ioctl_slave_foe_t data;
       
  3246     ec_master_foe_request_t request;
       
  3247     int retval;
       
  3248 
       
  3249     if (copy_from_user(&data, (void __user *) arg, sizeof(data))) {
       
  3250         return -EFAULT;
       
  3251     }
       
  3252 
       
  3253     INIT_LIST_HEAD(&request.list);
       
  3254 
       
  3255     ec_foe_request_init(&request.req, data.file_name);
       
  3256 
       
  3257     if (ec_foe_request_alloc(&request.req, data.buffer_size)) {
       
  3258         ec_foe_request_clear(&request.req);
       
  3259         return -ENOMEM;
       
  3260     }
       
  3261     if (copy_from_user(request.req.buffer,
       
  3262                 (void __user *) data.buffer, data.buffer_size)) {
       
  3263         ec_foe_request_clear(&request.req);
       
  3264         return -EFAULT;
       
  3265     }
       
  3266     request.req.data_size = data.buffer_size;
       
  3267     ec_foe_request_write(&request.req);
       
  3268 
       
  3269     if (down_interruptible(&master->master_sem)) {
       
  3270         ec_foe_request_clear(&request.req);
       
  3271         return -EINTR;
       
  3272     }
       
  3273 
       
  3274     if (!(request.slave = ec_master_find_slave(
       
  3275                     master, 0, data.slave_position))) {
       
  3276         up(&master->master_sem);
       
  3277         EC_MASTER_ERR(master, "Slave %u does not exist!\n",
       
  3278                 data.slave_position);
       
  3279         ec_foe_request_clear(&request.req);
       
  3280         return -EINVAL;
       
  3281     }
       
  3282 
       
  3283     EC_SLAVE_DBG(request.slave, 1, "Scheduling FoE write request.\n");
       
  3284 
       
  3285     // schedule FoE write request.
       
  3286     list_add_tail(&request.list, &request.slave->foe_requests);
       
  3287 
       
  3288     up(&master->master_sem);
       
  3289 
       
  3290     // wait for processing through FSM
       
  3291     if (wait_event_interruptible(request.slave->foe_queue,
       
  3292                 request.req.state != EC_INT_REQUEST_QUEUED)) {
       
  3293         // interrupted by signal
       
  3294         down(&master->master_sem);
       
  3295         if (request.req.state == EC_INT_REQUEST_QUEUED) {
       
  3296             // abort request
       
  3297             list_del(&request.list);
       
  3298             up(&master->master_sem);
       
  3299             ec_foe_request_clear(&request.req);
       
  3300             return -EINTR;
       
  3301         }
       
  3302         up(&master->master_sem);
       
  3303     }
       
  3304 
       
  3305     // wait until master FSM has finished processing
       
  3306     wait_event(request.slave->foe_queue,
       
  3307             request.req.state != EC_INT_REQUEST_BUSY);
       
  3308 
       
  3309     data.result = request.req.result;
       
  3310     data.error_code = request.req.error_code;
       
  3311 
       
  3312     retval = request.req.state == EC_INT_REQUEST_SUCCESS ? 0 : -EIO;
       
  3313 
       
  3314     if (__copy_to_user((void __user *) arg, &data, sizeof(data))) {
       
  3315         retval = -EFAULT;
       
  3316     }
       
  3317 
       
  3318     ec_foe_request_clear(&request.req);
       
  3319 
       
  3320     EC_SLAVE_DBG(request.slave, 1, "Finished FoE write request.\n");
       
  3321 
       
  3322     return retval;
       
  3323 }
       
  3324 
       
  3325 /*****************************************************************************/
       
  3326 
       
  3327 /** Read an SoE IDN.
       
  3328  */
       
  3329 int ec_cdev_ioctl_slave_soe_read(
       
  3330         ec_master_t *master, /**< EtherCAT master. */
       
  3331         unsigned long arg /**< ioctl() argument. */
       
  3332         )
       
  3333 {
       
  3334     ec_ioctl_slave_soe_read_t ioctl;
       
  3335     u8 *data;
       
  3336     int retval;
       
  3337 
       
  3338     if (copy_from_user(&ioctl, (void __user *) arg, sizeof(ioctl))) {
       
  3339         return -EFAULT;
       
  3340     }
       
  3341 
       
  3342     data = kmalloc(ioctl.mem_size, GFP_KERNEL);
       
  3343     if (!data) {
       
  3344         EC_MASTER_ERR(master, "Failed to allocate %u bytes of IDN data.\n",
       
  3345                 ioctl.mem_size);
       
  3346         return -ENOMEM;
       
  3347     }
       
  3348 
       
  3349     retval = ecrt_master_read_idn(master, ioctl.slave_position,
       
  3350             ioctl.drive_no, ioctl.idn, data, ioctl.mem_size, &ioctl.data_size,
       
  3351             &ioctl.error_code);
       
  3352     if (retval) {
       
  3353         kfree(data);
       
  3354         return retval;
       
  3355     }
       
  3356 
       
  3357     if (copy_to_user((void __user *) ioctl.data,
       
  3358                 data, ioctl.data_size)) {
       
  3359         kfree(data);
       
  3360         return -EFAULT;
       
  3361     }
       
  3362     kfree(data);
       
  3363 
       
  3364     if (__copy_to_user((void __user *) arg, &ioctl, sizeof(ioctl))) {
       
  3365         retval = -EFAULT;
       
  3366     }
       
  3367 
       
  3368     EC_MASTER_DBG(master, 1, "Finished SoE read request.\n");
       
  3369     return retval;
       
  3370 }
       
  3371 
       
  3372 /*****************************************************************************/
       
  3373 
       
  3374 /** Write an IDN to a slave via SoE.
       
  3375  */
       
  3376 int ec_cdev_ioctl_slave_soe_write(
       
  3377         ec_master_t *master, /**< EtherCAT master. */
       
  3378         unsigned long arg /**< ioctl() argument. */
       
  3379         )
       
  3380 {
       
  3381     ec_ioctl_slave_soe_write_t ioctl;
       
  3382     u8 *data;
       
  3383     int retval;
       
  3384 
       
  3385     if (copy_from_user(&ioctl, (void __user *) arg, sizeof(ioctl))) {
       
  3386         return -EFAULT;
       
  3387     }
       
  3388 
       
  3389     data = kmalloc(ioctl.data_size, GFP_KERNEL);
       
  3390     if (!data) {
       
  3391         EC_MASTER_ERR(master, "Failed to allocate %zu bytes of IDN data.\n",
       
  3392                 ioctl.data_size);
       
  3393         return -ENOMEM;
       
  3394     }
       
  3395     if (copy_from_user(data, (void __user *) ioctl.data, ioctl.data_size)) {
       
  3396         kfree(data);
       
  3397         return -EFAULT;
       
  3398     }
       
  3399 
       
  3400     retval = ecrt_master_write_idn(master, ioctl.slave_position,
       
  3401             ioctl.drive_no, ioctl.idn, data, ioctl.data_size,
       
  3402             &ioctl.error_code);
       
  3403     kfree(data);
       
  3404     if (retval) {
       
  3405         return retval;
       
  3406     }
       
  3407 
       
  3408     if (__copy_to_user((void __user *) arg, &ioctl, sizeof(ioctl))) {
       
  3409         retval = -EFAULT;
       
  3410     }
       
  3411 
       
  3412     EC_MASTER_DBG(master, 1, "Finished SoE write request.\n");
       
  3413     return retval;
       
  3414 }
   137 }
  3415 
   138 
  3416 /******************************************************************************
   139 /******************************************************************************
  3417  * File operations
   140  * File operations
  3418  *****************************************************************************/
   141  *****************************************************************************/
  3430                 "Failed to allocate memory for private data structure.\n");
   153                 "Failed to allocate memory for private data structure.\n");
  3431         return -ENOMEM;
   154         return -ENOMEM;
  3432     }
   155     }
  3433 
   156 
  3434     priv->cdev = cdev;
   157     priv->cdev = cdev;
  3435     priv->requested = 0;
   158     priv->ctx.writable = (filp->f_mode & FMODE_WRITE) != 0;
  3436     priv->process_data = NULL;
   159     priv->ctx.requested = 0;
  3437     priv->process_data_size = 0;
   160     priv->ctx.process_data = NULL;
       
   161     priv->ctx.process_data_size = 0;
  3438 
   162 
  3439     filp->private_data = priv;
   163     filp->private_data = priv;
  3440 
   164 
  3441 #if DEBUG_IOCTL
   165 #if DEBUG
  3442     EC_MASTER_DBG(cdev->master, 0, "File opened.\n");
   166     EC_MASTER_DBG(cdev->master, 0, "File opened.\n");
  3443 #endif
   167 #endif
  3444     return 0;
   168     return 0;
  3445 }
   169 }
  3446 
   170 
  3451 int eccdev_release(struct inode *inode, struct file *filp)
   175 int eccdev_release(struct inode *inode, struct file *filp)
  3452 {
   176 {
  3453     ec_cdev_priv_t *priv = (ec_cdev_priv_t *) filp->private_data;
   177     ec_cdev_priv_t *priv = (ec_cdev_priv_t *) filp->private_data;
  3454     ec_master_t *master = priv->cdev->master;
   178     ec_master_t *master = priv->cdev->master;
  3455 
   179 
  3456     if (priv->requested)
   180     if (priv->ctx.requested) {
  3457         ecrt_release_master(master);
   181         ecrt_release_master(master);
  3458 
   182     }
  3459     if (priv->process_data)
   183 
  3460         vfree(priv->process_data);
   184     if (priv->ctx.process_data) {
  3461 
   185         vfree(priv->ctx.process_data);
  3462 #if DEBUG_IOCTL
   186     }
       
   187 
       
   188 #if DEBUG
  3463     EC_MASTER_DBG(master, 0, "File closed.\n");
   189     EC_MASTER_DBG(master, 0, "File closed.\n");
  3464 #endif
   190 #endif
  3465 
   191 
  3466     kfree(priv);
   192     kfree(priv);
  3467     return 0;
   193     return 0;
  3471 
   197 
  3472 /** Called when an ioctl() command is issued.
   198 /** Called when an ioctl() command is issued.
  3473  */
   199  */
  3474 long eccdev_ioctl(struct file *filp, unsigned int cmd, unsigned long arg)
   200 long eccdev_ioctl(struct file *filp, unsigned int cmd, unsigned long arg)
  3475 {
   201 {
  3476 #if DEBUG_LATENCY
       
  3477     cycles_t a = get_cycles(), b;
       
  3478     unsigned int t;
       
  3479 #endif
       
  3480     ec_cdev_priv_t *priv = (ec_cdev_priv_t *) filp->private_data;
   202     ec_cdev_priv_t *priv = (ec_cdev_priv_t *) filp->private_data;
  3481     ec_master_t *master = priv->cdev->master;
   203 
  3482     int ret;
   204 #if DEBUG
  3483 
   205     EC_MASTER_DBG(priv->cdev->master, 0,
  3484 #if DEBUG_IOCTL
   206             "ioctl(filp = 0x%p, cmd = 0x%08x (0x%02x), arg = 0x%lx)\n",
  3485     EC_MASTER_DBG(master, 0, "ioctl(filp = 0x%p, cmd = 0x%08x (0x%02x),"
   207             filp, cmd, _IOC_NR(cmd), arg);
  3486             " arg = 0x%lx)\n", filp, cmd, _IOC_NR(cmd), arg);
   208 #endif
  3487 #endif
   209 
  3488 
   210     return ec_ioctl(priv->cdev->master, &priv->ctx, cmd, (void __user *) arg);
  3489     switch (cmd) {
       
  3490         case EC_IOCTL_MODULE:
       
  3491             ret = ec_cdev_ioctl_module(arg);
       
  3492             break;
       
  3493         case EC_IOCTL_MASTER:
       
  3494             ret = ec_cdev_ioctl_master(master, arg);
       
  3495             break;
       
  3496         case EC_IOCTL_SLAVE:
       
  3497             ret = ec_cdev_ioctl_slave(master, arg);
       
  3498             break;
       
  3499         case EC_IOCTL_SLAVE_SYNC:
       
  3500             ret = ec_cdev_ioctl_slave_sync(master, arg);
       
  3501             break;
       
  3502         case EC_IOCTL_SLAVE_SYNC_PDO:
       
  3503             ret = ec_cdev_ioctl_slave_sync_pdo(master, arg);
       
  3504             break;
       
  3505         case EC_IOCTL_SLAVE_SYNC_PDO_ENTRY:
       
  3506             ret = ec_cdev_ioctl_slave_sync_pdo_entry(master, arg);
       
  3507             break;
       
  3508         case EC_IOCTL_DOMAIN:
       
  3509             ret = ec_cdev_ioctl_domain(master, arg);
       
  3510             break;
       
  3511         case EC_IOCTL_DOMAIN_FMMU:
       
  3512             ret = ec_cdev_ioctl_domain_fmmu(master, arg);
       
  3513             break;
       
  3514         case EC_IOCTL_DOMAIN_DATA:
       
  3515             ret = ec_cdev_ioctl_domain_data(master, arg);
       
  3516             break;
       
  3517         case EC_IOCTL_MASTER_DEBUG:
       
  3518             if (!(filp->f_mode & FMODE_WRITE)) {
       
  3519                 ret = -EPERM;
       
  3520                 break;
       
  3521             }
       
  3522             ret = ec_cdev_ioctl_master_debug(master, arg);
       
  3523             break;
       
  3524         case EC_IOCTL_MASTER_RESCAN:
       
  3525             if (!(filp->f_mode & FMODE_WRITE)) {
       
  3526                 ret = -EPERM;
       
  3527                 break;
       
  3528             }
       
  3529             ret = ec_cdev_ioctl_master_rescan(master, arg);
       
  3530             break;
       
  3531         case EC_IOCTL_SLAVE_STATE:
       
  3532             if (!(filp->f_mode & FMODE_WRITE)) {
       
  3533                 ret = -EPERM;
       
  3534                 break;
       
  3535             }
       
  3536             ret = ec_cdev_ioctl_slave_state(master, arg);
       
  3537             break;
       
  3538         case EC_IOCTL_SLAVE_SDO:
       
  3539             ret = ec_cdev_ioctl_slave_sdo(master, arg);
       
  3540             break;
       
  3541         case EC_IOCTL_SLAVE_SDO_ENTRY:
       
  3542             ret = ec_cdev_ioctl_slave_sdo_entry(master, arg);
       
  3543             break;
       
  3544         case EC_IOCTL_SLAVE_SDO_UPLOAD:
       
  3545             ret = ec_cdev_ioctl_slave_sdo_upload(master, arg);
       
  3546             break;
       
  3547         case EC_IOCTL_SLAVE_SDO_DOWNLOAD:
       
  3548             if (!(filp->f_mode & FMODE_WRITE)) {
       
  3549                 ret = -EPERM;
       
  3550                 break;
       
  3551             }
       
  3552             ret = ec_cdev_ioctl_slave_sdo_download(master, arg);
       
  3553             break;
       
  3554         case EC_IOCTL_SLAVE_SII_READ:
       
  3555             ret = ec_cdev_ioctl_slave_sii_read(master, arg);
       
  3556             break;
       
  3557         case EC_IOCTL_SLAVE_SII_WRITE:
       
  3558             if (!(filp->f_mode & FMODE_WRITE)) {
       
  3559                 ret = -EPERM;
       
  3560                 break;
       
  3561             }
       
  3562             ret = ec_cdev_ioctl_slave_sii_write(master, arg);
       
  3563             break;
       
  3564         case EC_IOCTL_SLAVE_REG_READ:
       
  3565             ret = ec_cdev_ioctl_slave_reg_read(master, arg);
       
  3566             break;
       
  3567         case EC_IOCTL_SLAVE_REG_WRITE:
       
  3568             if (!(filp->f_mode & FMODE_WRITE)) {
       
  3569                 ret = -EPERM;
       
  3570                 break;
       
  3571             }
       
  3572             ret = ec_cdev_ioctl_slave_reg_write(master, arg);
       
  3573             break;
       
  3574         case EC_IOCTL_SLAVE_FOE_READ:
       
  3575             ret = ec_cdev_ioctl_slave_foe_read(master, arg);
       
  3576             break;
       
  3577         case EC_IOCTL_SLAVE_FOE_WRITE:
       
  3578             if (!(filp->f_mode & FMODE_WRITE)) {
       
  3579                 ret = -EPERM;
       
  3580                 break;
       
  3581             }
       
  3582             ret = ec_cdev_ioctl_slave_foe_write(master, arg);
       
  3583             break;
       
  3584         case EC_IOCTL_SLAVE_SOE_READ:
       
  3585             ret = ec_cdev_ioctl_slave_soe_read(master, arg);
       
  3586             break;
       
  3587         case EC_IOCTL_SLAVE_SOE_WRITE:
       
  3588             if (!(filp->f_mode & FMODE_WRITE)) {
       
  3589                 ret = -EPERM;
       
  3590                 break;
       
  3591             }
       
  3592             ret = ec_cdev_ioctl_slave_soe_write(master, arg);
       
  3593             break;
       
  3594         case EC_IOCTL_CONFIG:
       
  3595             ret = ec_cdev_ioctl_config(master, arg);
       
  3596             break;
       
  3597         case EC_IOCTL_CONFIG_PDO:
       
  3598             ret = ec_cdev_ioctl_config_pdo(master, arg);
       
  3599             break;
       
  3600         case EC_IOCTL_CONFIG_PDO_ENTRY:
       
  3601             ret = ec_cdev_ioctl_config_pdo_entry(master, arg);
       
  3602             break;
       
  3603         case EC_IOCTL_CONFIG_SDO:
       
  3604             ret = ec_cdev_ioctl_config_sdo(master, arg);
       
  3605             break;
       
  3606         case EC_IOCTL_CONFIG_IDN:
       
  3607             ret = ec_cdev_ioctl_config_idn(master, arg);
       
  3608             break;
       
  3609 #ifdef EC_EOE
       
  3610         case EC_IOCTL_EOE_HANDLER:
       
  3611             ret = ec_cdev_ioctl_eoe_handler(master, arg);
       
  3612             break;
       
  3613 #endif
       
  3614         case EC_IOCTL_REQUEST:
       
  3615             if (!(filp->f_mode & FMODE_WRITE)) {
       
  3616                 ret = -EPERM;
       
  3617                 break;
       
  3618             }
       
  3619             ret = ec_cdev_ioctl_request(master, arg, priv);
       
  3620             break;
       
  3621         case EC_IOCTL_CREATE_DOMAIN:
       
  3622             if (!(filp->f_mode & FMODE_WRITE)) {
       
  3623                 ret = -EPERM;
       
  3624                 break;
       
  3625             }
       
  3626             ret = ec_cdev_ioctl_create_domain(master, arg, priv);
       
  3627             break;
       
  3628         case EC_IOCTL_CREATE_SLAVE_CONFIG:
       
  3629             if (!(filp->f_mode & FMODE_WRITE)) {
       
  3630                 ret = -EPERM;
       
  3631                 break;
       
  3632             }
       
  3633             ret = ec_cdev_ioctl_create_slave_config(master, arg, priv);
       
  3634             break;
       
  3635         case EC_IOCTL_ACTIVATE:
       
  3636             if (!(filp->f_mode & FMODE_WRITE)) {
       
  3637                 ret = -EPERM;
       
  3638                 break;
       
  3639             }
       
  3640             ret = ec_cdev_ioctl_activate(master, arg, priv);
       
  3641             break;
       
  3642         case EC_IOCTL_DEACTIVATE:
       
  3643             if (!(filp->f_mode & FMODE_WRITE)) {
       
  3644                 ret = -EPERM;
       
  3645                 break;
       
  3646             }
       
  3647             ret = ec_cdev_ioctl_deactivate(master, arg, priv);
       
  3648             break;
       
  3649         case EC_IOCTL_SEND:
       
  3650             if (!(filp->f_mode & FMODE_WRITE)) {
       
  3651                 ret = -EPERM;
       
  3652                 break;
       
  3653             }
       
  3654             ret = ec_cdev_ioctl_send(master, arg, priv);
       
  3655             break;
       
  3656         case EC_IOCTL_RECEIVE:
       
  3657             if (!(filp->f_mode & FMODE_WRITE)) {
       
  3658                 ret = -EPERM;
       
  3659                 break;
       
  3660             }
       
  3661             ret = ec_cdev_ioctl_receive(master, arg, priv);
       
  3662             break;
       
  3663         case EC_IOCTL_MASTER_STATE:
       
  3664             ret = ec_cdev_ioctl_master_state(master, arg, priv);
       
  3665             break;
       
  3666         case EC_IOCTL_MASTER_LINK_STATE:
       
  3667             ret = ec_cdev_ioctl_master_link_state(master, arg, priv);
       
  3668             break;
       
  3669         case EC_IOCTL_APP_TIME:
       
  3670             if (!(filp->f_mode & FMODE_WRITE)) {
       
  3671                 ret = -EPERM;
       
  3672                 break;
       
  3673             }
       
  3674             ret = ec_cdev_ioctl_app_time(master, arg, priv);
       
  3675             break;
       
  3676         case EC_IOCTL_SYNC_REF:
       
  3677             if (!(filp->f_mode & FMODE_WRITE)) {
       
  3678                 ret = -EPERM;
       
  3679                 break;
       
  3680             }
       
  3681             ret = ec_cdev_ioctl_sync_ref(master, arg, priv);
       
  3682             break;
       
  3683         case EC_IOCTL_SYNC_SLAVES:
       
  3684             if (!(filp->f_mode & FMODE_WRITE)) {
       
  3685                 ret = -EPERM;
       
  3686                 break;
       
  3687             }
       
  3688             ret = ec_cdev_ioctl_sync_slaves(master, arg, priv);
       
  3689             break;
       
  3690         case EC_IOCTL_SYNC_MON_QUEUE:
       
  3691             if (!(filp->f_mode & FMODE_WRITE)) {
       
  3692                 ret = -EPERM;
       
  3693                 break;
       
  3694             }
       
  3695             ret = ec_cdev_ioctl_sync_mon_queue(master, arg, priv);
       
  3696             break;
       
  3697         case EC_IOCTL_SYNC_MON_PROCESS:
       
  3698             if (!(filp->f_mode & FMODE_WRITE)) {
       
  3699                 ret = -EPERM;
       
  3700                 break;
       
  3701             }
       
  3702             ret = ec_cdev_ioctl_sync_mon_process(master, arg, priv);
       
  3703             break;
       
  3704         case EC_IOCTL_RESET:
       
  3705             if (!(filp->f_mode & FMODE_WRITE)) {
       
  3706                 ret = -EPERM;
       
  3707                 break;
       
  3708             }
       
  3709             ret = ec_cdev_ioctl_reset(master, arg, priv);
       
  3710             break;
       
  3711         case EC_IOCTL_SC_SYNC:
       
  3712             if (!(filp->f_mode & FMODE_WRITE)) {
       
  3713                 ret = -EPERM;
       
  3714                 break;
       
  3715             }
       
  3716             ret = ec_cdev_ioctl_sc_sync(master, arg, priv);
       
  3717             break;
       
  3718         case EC_IOCTL_SC_WATCHDOG:
       
  3719             if (!(filp->f_mode & FMODE_WRITE)) {
       
  3720                 ret = -EPERM;
       
  3721                 break;
       
  3722             }
       
  3723             ret = ec_cdev_ioctl_sc_watchdog(master, arg, priv);
       
  3724             break;
       
  3725         case EC_IOCTL_SC_ADD_PDO:
       
  3726             if (!(filp->f_mode & FMODE_WRITE)) {
       
  3727                 ret = -EPERM;
       
  3728                 break;
       
  3729             }
       
  3730             ret = ec_cdev_ioctl_sc_add_pdo(master, arg, priv);
       
  3731             break;
       
  3732         case EC_IOCTL_SC_CLEAR_PDOS:
       
  3733             if (!(filp->f_mode & FMODE_WRITE)) {
       
  3734                 ret = -EPERM;
       
  3735                 break;
       
  3736             }
       
  3737             ret = ec_cdev_ioctl_sc_clear_pdos(master, arg, priv);
       
  3738             break;
       
  3739         case EC_IOCTL_SC_ADD_ENTRY:
       
  3740             if (!(filp->f_mode & FMODE_WRITE)) {
       
  3741                 ret = -EPERM;
       
  3742                 break;
       
  3743             }
       
  3744             ret = ec_cdev_ioctl_sc_add_entry(master, arg, priv);
       
  3745             break;
       
  3746         case EC_IOCTL_SC_CLEAR_ENTRIES:
       
  3747             if (!(filp->f_mode & FMODE_WRITE)) {
       
  3748                 ret = -EPERM;
       
  3749                 break;
       
  3750             }
       
  3751             ret = ec_cdev_ioctl_sc_clear_entries(master, arg, priv);
       
  3752             break;
       
  3753         case EC_IOCTL_SC_REG_PDO_ENTRY:
       
  3754             if (!(filp->f_mode & FMODE_WRITE)) {
       
  3755                 ret = -EPERM;
       
  3756                 break;
       
  3757             }
       
  3758             ret = ec_cdev_ioctl_sc_reg_pdo_entry(master, arg, priv);
       
  3759             break;
       
  3760         case EC_IOCTL_SC_DC:
       
  3761             if (!(filp->f_mode & FMODE_WRITE)) {
       
  3762                 ret = -EPERM;
       
  3763                 break;
       
  3764             }
       
  3765             ret = ec_cdev_ioctl_sc_dc(master, arg, priv);
       
  3766             break;
       
  3767         case EC_IOCTL_SC_SDO:
       
  3768             if (!(filp->f_mode & FMODE_WRITE)) {
       
  3769                 ret = -EPERM;
       
  3770                 break;
       
  3771             }
       
  3772             ret = ec_cdev_ioctl_sc_sdo(master, arg, priv);
       
  3773             break;
       
  3774         case EC_IOCTL_SC_SDO_REQUEST:
       
  3775             if (!(filp->f_mode & FMODE_WRITE)) {
       
  3776                 ret = -EPERM;
       
  3777                 break;
       
  3778             }
       
  3779             ret = ec_cdev_ioctl_sc_create_sdo_request(master, arg, priv);
       
  3780             break;
       
  3781         case EC_IOCTL_SC_VOE:
       
  3782             if (!(filp->f_mode & FMODE_WRITE)) {
       
  3783                 ret = -EPERM;
       
  3784                 break;
       
  3785             }
       
  3786             ret = ec_cdev_ioctl_sc_create_voe_handler(master, arg, priv);
       
  3787             break;
       
  3788         case EC_IOCTL_SC_STATE:
       
  3789             ret = ec_cdev_ioctl_sc_state(master, arg, priv);
       
  3790             break;
       
  3791         case EC_IOCTL_SC_IDN:
       
  3792             if (!(filp->f_mode & FMODE_WRITE)) {
       
  3793                 ret = -EPERM;
       
  3794                 break;
       
  3795             }
       
  3796             ret = ec_cdev_ioctl_sc_idn(master, arg, priv);
       
  3797             break;
       
  3798         case EC_IOCTL_DOMAIN_OFFSET:
       
  3799             ret = ec_cdev_ioctl_domain_offset(master, arg, priv);
       
  3800             break;
       
  3801         case EC_IOCTL_DOMAIN_PROCESS:
       
  3802             if (!(filp->f_mode & FMODE_WRITE)) {
       
  3803                 ret = -EPERM;
       
  3804                 break;
       
  3805             }
       
  3806             ret = ec_cdev_ioctl_domain_process(master, arg, priv);
       
  3807             break;
       
  3808         case EC_IOCTL_DOMAIN_QUEUE:
       
  3809             if (!(filp->f_mode & FMODE_WRITE)) {
       
  3810                 ret = -EPERM;
       
  3811                 break;
       
  3812             }
       
  3813             ret = ec_cdev_ioctl_domain_queue(master, arg, priv);
       
  3814             break;
       
  3815         case EC_IOCTL_DOMAIN_STATE:
       
  3816             ret = ec_cdev_ioctl_domain_state(master, arg, priv);
       
  3817             break;
       
  3818         case EC_IOCTL_SDO_REQUEST_TIMEOUT:
       
  3819             if (!(filp->f_mode & FMODE_WRITE)) {
       
  3820                 ret = -EPERM;
       
  3821                 break;
       
  3822             }
       
  3823             ret = ec_cdev_ioctl_sdo_request_timeout(master, arg, priv);
       
  3824             break;
       
  3825         case EC_IOCTL_SDO_REQUEST_STATE:
       
  3826             ret = ec_cdev_ioctl_sdo_request_state(master, arg, priv);
       
  3827             break;
       
  3828         case EC_IOCTL_SDO_REQUEST_READ:
       
  3829             if (!(filp->f_mode & FMODE_WRITE)) {
       
  3830                 ret = -EPERM;
       
  3831                 break;
       
  3832             }
       
  3833             ret = ec_cdev_ioctl_sdo_request_read(master, arg, priv);
       
  3834             break;
       
  3835         case EC_IOCTL_SDO_REQUEST_WRITE:
       
  3836             if (!(filp->f_mode & FMODE_WRITE)) {
       
  3837                 ret = -EPERM;
       
  3838                 break;
       
  3839             }
       
  3840             ret = ec_cdev_ioctl_sdo_request_write(master, arg, priv);
       
  3841             break;
       
  3842         case EC_IOCTL_SDO_REQUEST_DATA:
       
  3843             ret = ec_cdev_ioctl_sdo_request_data(master, arg, priv);
       
  3844             break;
       
  3845         case EC_IOCTL_VOE_SEND_HEADER:
       
  3846             if (!(filp->f_mode & FMODE_WRITE)) {
       
  3847                 ret = -EPERM;
       
  3848                 break;
       
  3849             }
       
  3850             ret = ec_cdev_ioctl_voe_send_header(master, arg, priv);
       
  3851             break;
       
  3852         case EC_IOCTL_VOE_REC_HEADER:
       
  3853             ret = ec_cdev_ioctl_voe_rec_header(master, arg, priv);
       
  3854             break;
       
  3855         case EC_IOCTL_VOE_READ:
       
  3856             if (!(filp->f_mode & FMODE_WRITE)) {
       
  3857                 ret = -EPERM;
       
  3858                 break;
       
  3859             }
       
  3860             ret = ec_cdev_ioctl_voe_read(master, arg, priv);
       
  3861             break;
       
  3862         case EC_IOCTL_VOE_READ_NOSYNC:
       
  3863             if (!(filp->f_mode & FMODE_WRITE)) {
       
  3864                 ret = -EPERM;
       
  3865                 break;
       
  3866             }
       
  3867             ret = ec_cdev_ioctl_voe_read_nosync(master, arg, priv);
       
  3868             break;
       
  3869         case EC_IOCTL_VOE_WRITE:
       
  3870             if (!(filp->f_mode & FMODE_WRITE)) {
       
  3871                 ret = -EPERM;
       
  3872                 break;
       
  3873             }
       
  3874             ret = ec_cdev_ioctl_voe_write(master, arg, priv);
       
  3875             break;
       
  3876         case EC_IOCTL_VOE_EXEC:
       
  3877             if (!(filp->f_mode & FMODE_WRITE)) {
       
  3878                 ret = -EPERM;
       
  3879                 break;
       
  3880             }
       
  3881             ret = ec_cdev_ioctl_voe_exec(master, arg, priv);
       
  3882             break;
       
  3883         case EC_IOCTL_VOE_DATA:
       
  3884             ret = ec_cdev_ioctl_voe_data(master, arg, priv);
       
  3885             break;
       
  3886         case EC_IOCTL_SET_SEND_INTERVAL:
       
  3887             if (!(filp->f_mode & FMODE_WRITE)) {
       
  3888                 ret = -EPERM;
       
  3889                 break;
       
  3890             }
       
  3891             ret = ec_cdev_ioctl_set_send_interval(master, arg, priv);
       
  3892             break;
       
  3893         default:
       
  3894             ret = -ENOTTY;
       
  3895             break;
       
  3896     }
       
  3897 
       
  3898 #if DEBUG_LATENCY
       
  3899     b = get_cycles();
       
  3900     t = (unsigned int) ((b - a) * 1000LL) / cpu_khz;
       
  3901     if (t > 50) {
       
  3902         EC_MASTER_WARN(master, "ioctl(0x%02x) took %u us.\n",
       
  3903                 _IOC_NR(cmd), t);
       
  3904     }
       
  3905 #endif
       
  3906 
       
  3907     return ret;
       
  3908 }
   211 }
  3909 
   212 
  3910 /*****************************************************************************/
   213 /*****************************************************************************/
  3911 
   214 
  3912 /** Memory-map callback for the EtherCAT character device.
   215 /** Memory-map callback for the EtherCAT character device.
  3946 {
   249 {
  3947     unsigned long offset = vmf->pgoff << PAGE_SHIFT;
   250     unsigned long offset = vmf->pgoff << PAGE_SHIFT;
  3948     ec_cdev_priv_t *priv = (ec_cdev_priv_t *) vma->vm_private_data;
   251     ec_cdev_priv_t *priv = (ec_cdev_priv_t *) vma->vm_private_data;
  3949     struct page *page;
   252     struct page *page;
  3950 
   253 
  3951     if (offset >= priv->process_data_size)
   254     if (offset >= priv->ctx.process_data_size)
  3952         return VM_FAULT_SIGBUS;
   255         return VM_FAULT_SIGBUS;
  3953 
   256 
  3954     page = vmalloc_to_page(priv->process_data + offset);
   257     page = vmalloc_to_page(priv->ctx.process_data + offset);
  3955     if (!page)
   258     if (!page)
  3956         return VM_FAULT_SIGBUS;
   259         return VM_FAULT_SIGBUS;
  3957 
   260 
  3958     get_page(page);
   261     get_page(page);
  3959     vmf->page = page;
   262     vmf->page = page;
  3983     ec_cdev_priv_t *priv = (ec_cdev_priv_t *) vma->vm_private_data;
   286     ec_cdev_priv_t *priv = (ec_cdev_priv_t *) vma->vm_private_data;
  3984     ec_master_t *master = priv->cdev->master;
   287     ec_master_t *master = priv->cdev->master;
  3985 
   288 
  3986     offset = (address - vma->vm_start) + (vma->vm_pgoff << PAGE_SHIFT);
   289     offset = (address - vma->vm_start) + (vma->vm_pgoff << PAGE_SHIFT);
  3987 
   290 
  3988     if (offset >= priv->process_data_size)
   291     if (offset >= priv->ctx.process_data_size)
  3989         return NOPAGE_SIGBUS;
   292         return NOPAGE_SIGBUS;
  3990 
   293 
  3991     page = vmalloc_to_page(priv->process_data + offset);
   294     page = vmalloc_to_page(priv->ctx.process_data + offset);
  3992 
   295 
  3993     EC_MASTER_DBG(master, 1, "Nopage fault vma, address = %#lx,"
   296     EC_MASTER_DBG(master, 1, "Nopage fault vma, address = %#lx,"
  3994             " offset = %#lx, page = %p\n", address, offset, page);
   297             " offset = %#lx, page = %p\n", address, offset, page);
  3995 
   298 
  3996     get_page(page);
   299     get_page(page);