master/ioctl.c
changeset 2589 2b9c78543663
child 2597 0e145bb05859
equal deleted inserted replaced
2415:af21f0bdc7c9 2589:2b9c78543663
       
     1 /******************************************************************************
       
     2  *
       
     3  *  $Id$
       
     4  *
       
     5  *  Copyright (C) 2006-2012  Florian Pose, Ingenieurgemeinschaft IgH
       
     6  *
       
     7  *  This file is part of the IgH EtherCAT Master.
       
     8  *
       
     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
       
    11  *  published by the Free Software Foundation.
       
    12  *
       
    13  *  The IgH EtherCAT Master is distributed in the hope that it will be useful,
       
    14  *  but WITHOUT ANY WARRANTY; without even the implied warranty of
       
    15  *  MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE.  See the GNU General
       
    16  *  Public License for more details.
       
    17  *
       
    18  *  You should have received a copy of the GNU General Public License along
       
    19  *  with the IgH EtherCAT Master; if not, write to the Free Software
       
    20  *  Foundation, Inc., 51 Franklin St, Fifth Floor, Boston, MA  02110-1301  USA
       
    21  *
       
    22  *  ---
       
    23  *
       
    24  *  The license mentioned above concerns the source code only. Using the
       
    25  *  EtherCAT technology and brand is only permitted in compliance with the
       
    26  *  industrial property and similar rights of Beckhoff Automation GmbH.
       
    27  *
       
    28  *****************************************************************************/
       
    29 
       
    30 /**
       
    31    \file
       
    32    EtherCAT master character device.
       
    33 */
       
    34 
       
    35 /*****************************************************************************/
       
    36 
       
    37 #include <linux/module.h>
       
    38 #include <linux/vmalloc.h>
       
    39 
       
    40 #include "master.h"
       
    41 #include "slave_config.h"
       
    42 #include "voe_handler.h"
       
    43 #include "ethernet.h"
       
    44 #include "ioctl.h"
       
    45 
       
    46 /** Set to 1 to enable ioctl() latency tracing.
       
    47  *
       
    48  * Requires CPU timestamp counter!
       
    49  */
       
    50 #define DEBUG_LATENCY 0
       
    51 
       
    52 /** Optional compiler attributes fo ioctl() functions.
       
    53  */
       
    54 #if 0
       
    55 #define ATTRIBUTES __attribute__ ((__noinline__))
       
    56 #else
       
    57 #define ATTRIBUTES
       
    58 #endif
       
    59 
       
    60 /*****************************************************************************/
       
    61 
       
    62 /** Copies a string to an ioctl structure.
       
    63  */
       
    64 static void ec_ioctl_strcpy(
       
    65         char *target, /**< Target. */
       
    66         const char *source /**< Source. */
       
    67         )
       
    68 {
       
    69     if (source) {
       
    70         strncpy(target, source, EC_IOCTL_STRING_SIZE);
       
    71         target[EC_IOCTL_STRING_SIZE - 1] = 0;
       
    72     } else {
       
    73         target[0] = 0;
       
    74     }
       
    75 }
       
    76 
       
    77 /*****************************************************************************/
       
    78 
       
    79 /** Get module information.
       
    80  *
       
    81  * \return Zero on success, otherwise a negative error code.
       
    82  */
       
    83 static ATTRIBUTES int ec_ioctl_module(
       
    84         void *arg /**< Userspace address to store the results. */
       
    85         )
       
    86 {
       
    87     ec_ioctl_module_t data;
       
    88 
       
    89     data.ioctl_version_magic = EC_IOCTL_VERSION_MAGIC;
       
    90     data.master_count = ec_master_count();
       
    91 
       
    92     if (copy_to_user((void __user *) arg, &data, sizeof(data)))
       
    93         return -EFAULT;
       
    94 
       
    95     return 0;
       
    96 }
       
    97 
       
    98 /*****************************************************************************/
       
    99 
       
   100 /** Get master information.
       
   101  *
       
   102  * \return Zero on success, otherwise a negative error code.
       
   103  */
       
   104 static ATTRIBUTES int ec_ioctl_master(
       
   105         ec_master_t *master, /**< EtherCAT master. */
       
   106         void *arg /**< Userspace address to store the results. */
       
   107         )
       
   108 {
       
   109     ec_ioctl_master_t io;
       
   110     unsigned int dev_idx, j;
       
   111 
       
   112     if (down_interruptible(&master->master_sem)) {
       
   113         return -EINTR;
       
   114     }
       
   115 
       
   116     io.slave_count = master->slave_count;
       
   117     io.config_count = ec_master_config_count(master);
       
   118     io.domain_count = ec_master_domain_count(master);
       
   119 #ifdef EC_EOE
       
   120     io.eoe_handler_count = ec_master_eoe_handler_count(master);
       
   121 #endif
       
   122     io.phase = (uint8_t) master->phase;
       
   123     io.active = (uint8_t) master->active;
       
   124     io.scan_busy = master->scan_busy;
       
   125 
       
   126     up(&master->master_sem);
       
   127 
       
   128     if (down_interruptible(&master->device_sem)) {
       
   129         return -EINTR;
       
   130     }
       
   131 
       
   132     for (dev_idx = EC_DEVICE_MAIN;
       
   133             dev_idx < ec_master_num_devices(master); dev_idx++) {
       
   134         ec_device_t *device = &master->devices[dev_idx];
       
   135 
       
   136         if (device->dev) {
       
   137             memcpy(io.devices[dev_idx].address, device->dev->dev_addr,
       
   138                     ETH_ALEN);
       
   139         } else {
       
   140             memcpy(io.devices[dev_idx].address, master->macs[dev_idx],
       
   141                     ETH_ALEN);
       
   142         }
       
   143         io.devices[dev_idx].attached = device->dev ? 1 : 0;
       
   144         io.devices[dev_idx].link_state = device->link_state ? 1 : 0;
       
   145         io.devices[dev_idx].tx_count = device->tx_count;
       
   146         io.devices[dev_idx].rx_count = device->rx_count;
       
   147         io.devices[dev_idx].tx_bytes = device->tx_bytes;
       
   148         io.devices[dev_idx].rx_bytes = device->rx_bytes;
       
   149         io.devices[dev_idx].tx_errors = device->tx_errors;
       
   150         for (j = 0; j < EC_RATE_COUNT; j++) {
       
   151             io.devices[dev_idx].tx_frame_rates[j] =
       
   152                 device->tx_frame_rates[j];
       
   153             io.devices[dev_idx].rx_frame_rates[j] =
       
   154                 device->rx_frame_rates[j];
       
   155             io.devices[dev_idx].tx_byte_rates[j] =
       
   156                 device->tx_byte_rates[j];
       
   157             io.devices[dev_idx].rx_byte_rates[j] =
       
   158                 device->rx_byte_rates[j];
       
   159         }
       
   160     }
       
   161     io.num_devices = ec_master_num_devices(master);
       
   162 
       
   163     io.tx_count = master->device_stats.tx_count;
       
   164     io.rx_count = master->device_stats.rx_count;
       
   165     io.tx_bytes = master->device_stats.tx_bytes;
       
   166     io.rx_bytes = master->device_stats.rx_bytes;
       
   167     for (j = 0; j < EC_RATE_COUNT; j++) {
       
   168         io.tx_frame_rates[j] =
       
   169             master->device_stats.tx_frame_rates[j];
       
   170         io.rx_frame_rates[j] =
       
   171             master->device_stats.rx_frame_rates[j];
       
   172         io.tx_byte_rates[j] =
       
   173             master->device_stats.tx_byte_rates[j];
       
   174         io.rx_byte_rates[j] =
       
   175             master->device_stats.rx_byte_rates[j];
       
   176         io.loss_rates[j] =
       
   177             master->device_stats.loss_rates[j];
       
   178     }
       
   179 
       
   180     up(&master->device_sem);
       
   181 
       
   182     io.app_time = master->app_time;
       
   183     io.ref_clock =
       
   184         master->dc_ref_clock ? master->dc_ref_clock->ring_position : 0xffff;
       
   185 
       
   186     if (copy_to_user((void __user *) arg, &io, sizeof(io))) {
       
   187         return -EFAULT;
       
   188     }
       
   189 
       
   190     return 0;
       
   191 }
       
   192 
       
   193 /*****************************************************************************/
       
   194 
       
   195 /** Get slave information.
       
   196  *
       
   197  * \return Zero on success, otherwise a negative error code.
       
   198  */
       
   199 static ATTRIBUTES int ec_ioctl_slave(
       
   200         ec_master_t *master, /**< EtherCAT master. */
       
   201         void *arg /**< Userspace address to store the results. */
       
   202         )
       
   203 {
       
   204     ec_ioctl_slave_t data;
       
   205     const ec_slave_t *slave;
       
   206     int i;
       
   207 
       
   208     if (copy_from_user(&data, (void __user *) arg, sizeof(data))) {
       
   209         return -EFAULT;
       
   210     }
       
   211 
       
   212     if (down_interruptible(&master->master_sem))
       
   213         return -EINTR;
       
   214 
       
   215     if (!(slave = ec_master_find_slave_const(
       
   216                     master, 0, data.position))) {
       
   217         up(&master->master_sem);
       
   218         EC_MASTER_ERR(master, "Slave %u does not exist!\n", data.position);
       
   219         return -EINVAL;
       
   220     }
       
   221 
       
   222     data.device_index = slave->device_index;
       
   223     data.vendor_id = slave->sii.vendor_id;
       
   224     data.product_code = slave->sii.product_code;
       
   225     data.revision_number = slave->sii.revision_number;
       
   226     data.serial_number = slave->sii.serial_number;
       
   227     data.alias = slave->effective_alias;
       
   228     data.boot_rx_mailbox_offset = slave->sii.boot_rx_mailbox_offset;
       
   229     data.boot_rx_mailbox_size = slave->sii.boot_rx_mailbox_size;
       
   230     data.boot_tx_mailbox_offset = slave->sii.boot_tx_mailbox_offset;
       
   231     data.boot_tx_mailbox_size = slave->sii.boot_tx_mailbox_size;
       
   232     data.std_rx_mailbox_offset = slave->sii.std_rx_mailbox_offset;
       
   233     data.std_rx_mailbox_size = slave->sii.std_rx_mailbox_size;
       
   234     data.std_tx_mailbox_offset = slave->sii.std_tx_mailbox_offset;
       
   235     data.std_tx_mailbox_size = slave->sii.std_tx_mailbox_size;
       
   236     data.mailbox_protocols = slave->sii.mailbox_protocols;
       
   237     data.has_general_category = slave->sii.has_general;
       
   238     data.coe_details = slave->sii.coe_details;
       
   239     data.general_flags = slave->sii.general_flags;
       
   240     data.current_on_ebus = slave->sii.current_on_ebus;
       
   241     for (i = 0; i < EC_MAX_PORTS; i++) {
       
   242         data.ports[i].desc = slave->ports[i].desc;
       
   243         data.ports[i].link.link_up = slave->ports[i].link.link_up;
       
   244         data.ports[i].link.loop_closed = slave->ports[i].link.loop_closed;
       
   245         data.ports[i].link.signal_detected =
       
   246             slave->ports[i].link.signal_detected;
       
   247         data.ports[i].receive_time = slave->ports[i].receive_time;
       
   248         if (slave->ports[i].next_slave) {
       
   249             data.ports[i].next_slave =
       
   250                 slave->ports[i].next_slave->ring_position;
       
   251         } else {
       
   252             data.ports[i].next_slave = 0xffff;
       
   253         }
       
   254         data.ports[i].delay_to_next_dc = slave->ports[i].delay_to_next_dc;
       
   255     }
       
   256     data.fmmu_bit = slave->base_fmmu_bit_operation;
       
   257     data.dc_supported = slave->base_dc_supported;
       
   258     data.dc_range = slave->base_dc_range;
       
   259     data.has_dc_system_time = slave->has_dc_system_time;
       
   260     data.transmission_delay = slave->transmission_delay;
       
   261     data.al_state = slave->current_state;
       
   262     data.error_flag = slave->error_flag;
       
   263 
       
   264     data.sync_count = slave->sii.sync_count;
       
   265     data.sdo_count = ec_slave_sdo_count(slave);
       
   266     data.sii_nwords = slave->sii_nwords;
       
   267     ec_ioctl_strcpy(data.group, slave->sii.group);
       
   268     ec_ioctl_strcpy(data.image, slave->sii.image);
       
   269     ec_ioctl_strcpy(data.order, slave->sii.order);
       
   270     ec_ioctl_strcpy(data.name, slave->sii.name);
       
   271 
       
   272     up(&master->master_sem);
       
   273 
       
   274     if (copy_to_user((void __user *) arg, &data, sizeof(data)))
       
   275         return -EFAULT;
       
   276 
       
   277     return 0;
       
   278 }
       
   279 
       
   280 /*****************************************************************************/
       
   281 
       
   282 /** Get slave sync manager information.
       
   283  *
       
   284  * \return Zero on success, otherwise a negative error code.
       
   285  */
       
   286 static ATTRIBUTES int ec_ioctl_slave_sync(
       
   287         ec_master_t *master, /**< EtherCAT master. */
       
   288         void *arg /**< Userspace address to store the results. */
       
   289         )
       
   290 {
       
   291     ec_ioctl_slave_sync_t data;
       
   292     const ec_slave_t *slave;
       
   293     const ec_sync_t *sync;
       
   294 
       
   295     if (copy_from_user(&data, (void __user *) arg, sizeof(data))) {
       
   296         return -EFAULT;
       
   297     }
       
   298 
       
   299     if (down_interruptible(&master->master_sem))
       
   300         return -EINTR;
       
   301 
       
   302     if (!(slave = ec_master_find_slave_const(
       
   303                     master, 0, data.slave_position))) {
       
   304         up(&master->master_sem);
       
   305         EC_MASTER_ERR(master, "Slave %u does not exist!\n",
       
   306                 data.slave_position);
       
   307         return -EINVAL;
       
   308     }
       
   309 
       
   310     if (data.sync_index >= slave->sii.sync_count) {
       
   311         up(&master->master_sem);
       
   312         EC_SLAVE_ERR(slave, "Sync manager %u does not exist!\n",
       
   313                 data.sync_index);
       
   314         return -EINVAL;
       
   315     }
       
   316 
       
   317     sync = &slave->sii.syncs[data.sync_index];
       
   318 
       
   319     data.physical_start_address = sync->physical_start_address;
       
   320     data.default_size = sync->default_length;
       
   321     data.control_register = sync->control_register;
       
   322     data.enable = sync->enable;
       
   323     data.pdo_count = ec_pdo_list_count(&sync->pdos);
       
   324 
       
   325     up(&master->master_sem);
       
   326 
       
   327     if (copy_to_user((void __user *) arg, &data, sizeof(data)))
       
   328         return -EFAULT;
       
   329 
       
   330     return 0;
       
   331 }
       
   332 
       
   333 /*****************************************************************************/
       
   334 
       
   335 /** Get slave sync manager PDO information.
       
   336  *
       
   337  * \return Zero on success, otherwise a negative error code.
       
   338  */
       
   339 static ATTRIBUTES int ec_ioctl_slave_sync_pdo(
       
   340         ec_master_t *master, /**< EtherCAT master. */
       
   341         void *arg /**< Userspace address to store the results. */
       
   342         )
       
   343 {
       
   344     ec_ioctl_slave_sync_pdo_t data;
       
   345     const ec_slave_t *slave;
       
   346     const ec_sync_t *sync;
       
   347     const ec_pdo_t *pdo;
       
   348 
       
   349     if (copy_from_user(&data, (void __user *) arg, sizeof(data))) {
       
   350         return -EFAULT;
       
   351     }
       
   352 
       
   353     if (down_interruptible(&master->master_sem))
       
   354         return -EINTR;
       
   355 
       
   356     if (!(slave = ec_master_find_slave_const(
       
   357                     master, 0, data.slave_position))) {
       
   358         up(&master->master_sem);
       
   359         EC_MASTER_ERR(master, "Slave %u does not exist!\n",
       
   360                 data.slave_position);
       
   361         return -EINVAL;
       
   362     }
       
   363 
       
   364     if (data.sync_index >= slave->sii.sync_count) {
       
   365         up(&master->master_sem);
       
   366         EC_SLAVE_ERR(slave, "Sync manager %u does not exist!\n",
       
   367                 data.sync_index);
       
   368         return -EINVAL;
       
   369     }
       
   370 
       
   371     sync = &slave->sii.syncs[data.sync_index];
       
   372     if (!(pdo = ec_pdo_list_find_pdo_by_pos_const(
       
   373                     &sync->pdos, data.pdo_pos))) {
       
   374         up(&master->master_sem);
       
   375         EC_SLAVE_ERR(slave, "Sync manager %u does not contain a PDO with "
       
   376                 "position %u!\n", data.sync_index, data.pdo_pos);
       
   377         return -EINVAL;
       
   378     }
       
   379 
       
   380     data.index = pdo->index;
       
   381     data.entry_count = ec_pdo_entry_count(pdo);
       
   382     ec_ioctl_strcpy(data.name, pdo->name);
       
   383 
       
   384     up(&master->master_sem);
       
   385 
       
   386     if (copy_to_user((void __user *) arg, &data, sizeof(data)))
       
   387         return -EFAULT;
       
   388 
       
   389     return 0;
       
   390 }
       
   391 
       
   392 /*****************************************************************************/
       
   393 
       
   394 /** Get slave sync manager PDO entry information.
       
   395  *
       
   396  * \return Zero on success, otherwise a negative error code.
       
   397  */
       
   398 static ATTRIBUTES int ec_ioctl_slave_sync_pdo_entry(
       
   399         ec_master_t *master, /**< EtherCAT master. */
       
   400         void *arg /**< Userspace address to store the results. */
       
   401         )
       
   402 {
       
   403     ec_ioctl_slave_sync_pdo_entry_t data;
       
   404     const ec_slave_t *slave;
       
   405     const ec_sync_t *sync;
       
   406     const ec_pdo_t *pdo;
       
   407     const ec_pdo_entry_t *entry;
       
   408 
       
   409     if (copy_from_user(&data, (void __user *) arg, sizeof(data))) {
       
   410         return -EFAULT;
       
   411     }
       
   412 
       
   413     if (down_interruptible(&master->master_sem))
       
   414         return -EINTR;
       
   415 
       
   416     if (!(slave = ec_master_find_slave_const(
       
   417                     master, 0, data.slave_position))) {
       
   418         up(&master->master_sem);
       
   419         EC_MASTER_ERR(master, "Slave %u does not exist!\n",
       
   420                 data.slave_position);
       
   421         return -EINVAL;
       
   422     }
       
   423 
       
   424     if (data.sync_index >= slave->sii.sync_count) {
       
   425         up(&master->master_sem);
       
   426         EC_SLAVE_ERR(slave, "Sync manager %u does not exist!\n",
       
   427                 data.sync_index);
       
   428         return -EINVAL;
       
   429     }
       
   430 
       
   431     sync = &slave->sii.syncs[data.sync_index];
       
   432     if (!(pdo = ec_pdo_list_find_pdo_by_pos_const(
       
   433                     &sync->pdos, data.pdo_pos))) {
       
   434         up(&master->master_sem);
       
   435         EC_SLAVE_ERR(slave, "Sync manager %u does not contain a PDO with "
       
   436                 "position %u!\n", data.sync_index, data.pdo_pos);
       
   437         return -EINVAL;
       
   438     }
       
   439 
       
   440     if (!(entry = ec_pdo_find_entry_by_pos_const(
       
   441                     pdo, data.entry_pos))) {
       
   442         up(&master->master_sem);
       
   443         EC_SLAVE_ERR(slave, "PDO 0x%04X does not contain an entry with "
       
   444                 "position %u!\n", data.pdo_pos, data.entry_pos);
       
   445         return -EINVAL;
       
   446     }
       
   447 
       
   448     data.index = entry->index;
       
   449     data.subindex = entry->subindex;
       
   450     data.bit_length = entry->bit_length;
       
   451     ec_ioctl_strcpy(data.name, entry->name);
       
   452 
       
   453     up(&master->master_sem);
       
   454 
       
   455     if (copy_to_user((void __user *) arg, &data, sizeof(data)))
       
   456         return -EFAULT;
       
   457 
       
   458     return 0;
       
   459 }
       
   460 
       
   461 /*****************************************************************************/
       
   462 
       
   463 /** Get domain information.
       
   464  *
       
   465  * \return Zero on success, otherwise a negative error code.
       
   466  */
       
   467 static ATTRIBUTES int ec_ioctl_domain(
       
   468         ec_master_t *master, /**< EtherCAT master. */
       
   469         void *arg /**< Userspace address to store the results. */
       
   470         )
       
   471 {
       
   472     ec_ioctl_domain_t data;
       
   473     const ec_domain_t *domain;
       
   474     unsigned int dev_idx;
       
   475 
       
   476     if (copy_from_user(&data, (void __user *) arg, sizeof(data))) {
       
   477         return -EFAULT;
       
   478     }
       
   479 
       
   480     if (down_interruptible(&master->master_sem))
       
   481         return -EINTR;
       
   482 
       
   483     if (!(domain = ec_master_find_domain_const(master, data.index))) {
       
   484         up(&master->master_sem);
       
   485         EC_MASTER_ERR(master, "Domain %u does not exist!\n", data.index);
       
   486         return -EINVAL;
       
   487     }
       
   488 
       
   489     data.data_size = domain->data_size;
       
   490     data.logical_base_address = domain->logical_base_address;
       
   491     for (dev_idx = EC_DEVICE_MAIN;
       
   492             dev_idx < ec_master_num_devices(domain->master); dev_idx++) {
       
   493         data.working_counter[dev_idx] = domain->working_counter[dev_idx];
       
   494     }
       
   495     data.expected_working_counter = domain->expected_working_counter;
       
   496     data.fmmu_count = ec_domain_fmmu_count(domain);
       
   497 
       
   498     up(&master->master_sem);
       
   499 
       
   500     if (copy_to_user((void __user *) arg, &data, sizeof(data)))
       
   501         return -EFAULT;
       
   502 
       
   503     return 0;
       
   504 }
       
   505 
       
   506 /*****************************************************************************/
       
   507 
       
   508 /** Get domain FMMU information.
       
   509  *
       
   510  * \return Zero on success, otherwise a negative error code.
       
   511  */
       
   512 static ATTRIBUTES int ec_ioctl_domain_fmmu(
       
   513         ec_master_t *master, /**< EtherCAT master. */
       
   514         void *arg /**< Userspace address to store the results. */
       
   515         )
       
   516 {
       
   517     ec_ioctl_domain_fmmu_t data;
       
   518     const ec_domain_t *domain;
       
   519     const ec_fmmu_config_t *fmmu;
       
   520 
       
   521     if (copy_from_user(&data, (void __user *) arg, sizeof(data))) {
       
   522         return -EFAULT;
       
   523     }
       
   524 
       
   525     if (down_interruptible(&master->master_sem))
       
   526         return -EINTR;
       
   527 
       
   528     if (!(domain = ec_master_find_domain_const(master, data.domain_index))) {
       
   529         up(&master->master_sem);
       
   530         EC_MASTER_ERR(master, "Domain %u does not exist!\n",
       
   531                 data.domain_index);
       
   532         return -EINVAL;
       
   533     }
       
   534 
       
   535     if (!(fmmu = ec_domain_find_fmmu(domain, data.fmmu_index))) {
       
   536         up(&master->master_sem);
       
   537         EC_MASTER_ERR(master, "Domain %u has less than %u"
       
   538                 " fmmu configurations.\n",
       
   539                 data.domain_index, data.fmmu_index + 1);
       
   540         return -EINVAL;
       
   541     }
       
   542 
       
   543     data.slave_config_alias = fmmu->sc->alias;
       
   544     data.slave_config_position = fmmu->sc->position;
       
   545     data.sync_index = fmmu->sync_index;
       
   546     data.dir = fmmu->dir;
       
   547     data.logical_address = fmmu->logical_start_address;
       
   548     data.data_size = fmmu->data_size;
       
   549 
       
   550     up(&master->master_sem);
       
   551 
       
   552     if (copy_to_user((void __user *) arg, &data, sizeof(data)))
       
   553         return -EFAULT;
       
   554 
       
   555     return 0;
       
   556 }
       
   557 
       
   558 /*****************************************************************************/
       
   559 
       
   560 /** Get domain data.
       
   561  *
       
   562  * \return Zero on success, otherwise a negative error code.
       
   563  */
       
   564 static ATTRIBUTES int ec_ioctl_domain_data(
       
   565         ec_master_t *master, /**< EtherCAT master. */
       
   566         void *arg /**< Userspace address to store the results. */
       
   567         )
       
   568 {
       
   569     ec_ioctl_domain_data_t data;
       
   570     const ec_domain_t *domain;
       
   571 
       
   572     if (copy_from_user(&data, (void __user *) arg, sizeof(data))) {
       
   573         return -EFAULT;
       
   574     }
       
   575 
       
   576     if (down_interruptible(&master->master_sem))
       
   577         return -EINTR;
       
   578 
       
   579     if (!(domain = ec_master_find_domain_const(master, data.domain_index))) {
       
   580         up(&master->master_sem);
       
   581         EC_MASTER_ERR(master, "Domain %u does not exist!\n",
       
   582                 data.domain_index);
       
   583         return -EINVAL;
       
   584     }
       
   585 
       
   586     if (domain->data_size != data.data_size) {
       
   587         up(&master->master_sem);
       
   588         EC_MASTER_ERR(master, "Data size mismatch %u/%zu!\n",
       
   589                 data.data_size, domain->data_size);
       
   590         return -EFAULT;
       
   591     }
       
   592 
       
   593     if (copy_to_user((void __user *) data.target, domain->data,
       
   594                 domain->data_size)) {
       
   595         up(&master->master_sem);
       
   596         return -EFAULT;
       
   597     }
       
   598 
       
   599     up(&master->master_sem);
       
   600     return 0;
       
   601 }
       
   602 
       
   603 /*****************************************************************************/
       
   604 
       
   605 /** Set master debug level.
       
   606  *
       
   607  * \return Zero on success, otherwise a negative error code.
       
   608  */
       
   609 static ATTRIBUTES int ec_ioctl_master_debug(
       
   610         ec_master_t *master, /**< EtherCAT master. */
       
   611         void *arg /**< ioctl() argument. */
       
   612         )
       
   613 {
       
   614     return ec_master_debug_level(master, (unsigned long) arg);
       
   615 }
       
   616 
       
   617 /*****************************************************************************/
       
   618 
       
   619 /** Issue a bus scan.
       
   620  *
       
   621  * \return Always zero (success).
       
   622  */
       
   623 static ATTRIBUTES int ec_ioctl_master_rescan(
       
   624         ec_master_t *master, /**< EtherCAT master. */
       
   625         void *arg /**< ioctl() argument. */
       
   626         )
       
   627 {
       
   628     master->fsm.rescan_required = 1;
       
   629     return 0;
       
   630 }
       
   631 
       
   632 /*****************************************************************************/
       
   633 
       
   634 /** Set slave state.
       
   635  *
       
   636  * \return Zero on success, otherwise a negative error code.
       
   637  */
       
   638 static ATTRIBUTES int ec_ioctl_slave_state(
       
   639         ec_master_t *master, /**< EtherCAT master. */
       
   640         void *arg /**< ioctl() argument. */
       
   641         )
       
   642 {
       
   643     ec_ioctl_slave_state_t data;
       
   644     ec_slave_t *slave;
       
   645 
       
   646     if (copy_from_user(&data, (void __user *) arg, sizeof(data))) {
       
   647         return -EFAULT;
       
   648     }
       
   649 
       
   650     if (down_interruptible(&master->master_sem))
       
   651         return -EINTR;
       
   652 
       
   653     if (!(slave = ec_master_find_slave(
       
   654                     master, 0, data.slave_position))) {
       
   655         up(&master->master_sem);
       
   656         EC_MASTER_ERR(master, "Slave %u does not exist!\n",
       
   657                 data.slave_position);
       
   658         return -EINVAL;
       
   659     }
       
   660 
       
   661     ec_slave_request_state(slave, data.al_state);
       
   662 
       
   663     up(&master->master_sem);
       
   664     return 0;
       
   665 }
       
   666 
       
   667 /*****************************************************************************/
       
   668 
       
   669 /** Get slave SDO information.
       
   670  *
       
   671  * \return Zero on success, otherwise a negative error code.
       
   672  */
       
   673 static ATTRIBUTES int ec_ioctl_slave_sdo(
       
   674         ec_master_t *master, /**< EtherCAT master. */
       
   675         void *arg /**< ioctl() argument. */
       
   676         )
       
   677 {
       
   678     ec_ioctl_slave_sdo_t data;
       
   679     const ec_slave_t *slave;
       
   680     const ec_sdo_t *sdo;
       
   681 
       
   682     if (copy_from_user(&data, (void __user *) arg, sizeof(data))) {
       
   683         return -EFAULT;
       
   684     }
       
   685 
       
   686     if (down_interruptible(&master->master_sem))
       
   687         return -EINTR;
       
   688 
       
   689     if (!(slave = ec_master_find_slave_const(
       
   690                     master, 0, data.slave_position))) {
       
   691         up(&master->master_sem);
       
   692         EC_MASTER_ERR(master, "Slave %u does not exist!\n",
       
   693                 data.slave_position);
       
   694         return -EINVAL;
       
   695     }
       
   696 
       
   697     if (!(sdo = ec_slave_get_sdo_by_pos_const(
       
   698                     slave, data.sdo_position))) {
       
   699         up(&master->master_sem);
       
   700         EC_SLAVE_ERR(slave, "SDO %u does not exist!\n", data.sdo_position);
       
   701         return -EINVAL;
       
   702     }
       
   703 
       
   704     data.sdo_index = sdo->index;
       
   705     data.max_subindex = sdo->max_subindex;
       
   706     ec_ioctl_strcpy(data.name, sdo->name);
       
   707 
       
   708     up(&master->master_sem);
       
   709 
       
   710     if (copy_to_user((void __user *) arg, &data, sizeof(data)))
       
   711         return -EFAULT;
       
   712 
       
   713     return 0;
       
   714 }
       
   715 
       
   716 /*****************************************************************************/
       
   717 
       
   718 /** Get slave SDO entry information.
       
   719  *
       
   720  * \return Zero on success, otherwise a negative error code.
       
   721  */
       
   722 static ATTRIBUTES int ec_ioctl_slave_sdo_entry(
       
   723         ec_master_t *master, /**< EtherCAT master. */
       
   724         void *arg /**< ioctl() argument. */
       
   725         )
       
   726 {
       
   727     ec_ioctl_slave_sdo_entry_t data;
       
   728     const ec_slave_t *slave;
       
   729     const ec_sdo_t *sdo;
       
   730     const ec_sdo_entry_t *entry;
       
   731 
       
   732     if (copy_from_user(&data, (void __user *) arg, sizeof(data))) {
       
   733         return -EFAULT;
       
   734     }
       
   735 
       
   736     if (down_interruptible(&master->master_sem))
       
   737         return -EINTR;
       
   738 
       
   739     if (!(slave = ec_master_find_slave_const(
       
   740                     master, 0, data.slave_position))) {
       
   741         up(&master->master_sem);
       
   742         EC_MASTER_ERR(master, "Slave %u does not exist!\n",
       
   743                 data.slave_position);
       
   744         return -EINVAL;
       
   745     }
       
   746 
       
   747     if (data.sdo_spec <= 0) {
       
   748         if (!(sdo = ec_slave_get_sdo_by_pos_const(
       
   749                         slave, -data.sdo_spec))) {
       
   750             up(&master->master_sem);
       
   751             EC_SLAVE_ERR(slave, "SDO %u does not exist!\n", -data.sdo_spec);
       
   752             return -EINVAL;
       
   753         }
       
   754     } else {
       
   755         if (!(sdo = ec_slave_get_sdo_const(
       
   756                         slave, data.sdo_spec))) {
       
   757             up(&master->master_sem);
       
   758             EC_SLAVE_ERR(slave, "SDO 0x%04X does not exist!\n",
       
   759                     data.sdo_spec);
       
   760             return -EINVAL;
       
   761         }
       
   762     }
       
   763 
       
   764     if (!(entry = ec_sdo_get_entry_const(
       
   765                     sdo, data.sdo_entry_subindex))) {
       
   766         up(&master->master_sem);
       
   767         EC_SLAVE_ERR(slave, "SDO entry 0x%04X:%02X does not exist!\n",
       
   768                 sdo->index, data.sdo_entry_subindex);
       
   769         return -EINVAL;
       
   770     }
       
   771 
       
   772     data.data_type = entry->data_type;
       
   773     data.bit_length = entry->bit_length;
       
   774     data.read_access[EC_SDO_ENTRY_ACCESS_PREOP] =
       
   775         entry->read_access[EC_SDO_ENTRY_ACCESS_PREOP];
       
   776     data.read_access[EC_SDO_ENTRY_ACCESS_SAFEOP] =
       
   777         entry->read_access[EC_SDO_ENTRY_ACCESS_SAFEOP];
       
   778     data.read_access[EC_SDO_ENTRY_ACCESS_OP] =
       
   779         entry->read_access[EC_SDO_ENTRY_ACCESS_OP];
       
   780     data.write_access[EC_SDO_ENTRY_ACCESS_PREOP] =
       
   781         entry->write_access[EC_SDO_ENTRY_ACCESS_PREOP];
       
   782     data.write_access[EC_SDO_ENTRY_ACCESS_SAFEOP] =
       
   783         entry->write_access[EC_SDO_ENTRY_ACCESS_SAFEOP];
       
   784     data.write_access[EC_SDO_ENTRY_ACCESS_OP] =
       
   785         entry->write_access[EC_SDO_ENTRY_ACCESS_OP];
       
   786     ec_ioctl_strcpy(data.description, entry->description);
       
   787 
       
   788     up(&master->master_sem);
       
   789 
       
   790     if (copy_to_user((void __user *) arg, &data, sizeof(data)))
       
   791         return -EFAULT;
       
   792 
       
   793     return 0;
       
   794 }
       
   795 
       
   796 /*****************************************************************************/
       
   797 
       
   798 /** Upload SDO.
       
   799  *
       
   800  * \return Zero on success, otherwise a negative error code.
       
   801  */
       
   802 static ATTRIBUTES int ec_ioctl_slave_sdo_upload(
       
   803         ec_master_t *master, /**< EtherCAT master. */
       
   804         void *arg /**< ioctl() argument. */
       
   805         )
       
   806 {
       
   807     ec_ioctl_slave_sdo_upload_t data;
       
   808     uint8_t *target;
       
   809     int ret;
       
   810 
       
   811     if (copy_from_user(&data, (void __user *) arg, sizeof(data))) {
       
   812         return -EFAULT;
       
   813     }
       
   814 
       
   815     if (!(target = kmalloc(data.target_size, GFP_KERNEL))) {
       
   816         EC_MASTER_ERR(master, "Failed to allocate %zu bytes"
       
   817                 " for SDO upload.\n", data.target_size);
       
   818         return -ENOMEM;
       
   819     }
       
   820 
       
   821     ret = ecrt_master_sdo_upload(master, data.slave_position,
       
   822             data.sdo_index, data.sdo_entry_subindex, target,
       
   823             data.target_size, &data.data_size, &data.abort_code);
       
   824 
       
   825     if (!ret) {
       
   826         if (copy_to_user((void __user *) data.target,
       
   827                     target, data.data_size)) {
       
   828             kfree(target);
       
   829             return -EFAULT;
       
   830         }
       
   831     }
       
   832 
       
   833     kfree(target);
       
   834 
       
   835     if (__copy_to_user((void __user *) arg, &data, sizeof(data))) {
       
   836         return -EFAULT;
       
   837     }
       
   838 
       
   839     return ret;
       
   840 }
       
   841 
       
   842 /*****************************************************************************/
       
   843 
       
   844 /** Download SDO.
       
   845  *
       
   846  * \return Zero on success, otherwise a negative error code.
       
   847  */
       
   848 static ATTRIBUTES int ec_ioctl_slave_sdo_download(
       
   849         ec_master_t *master, /**< EtherCAT master. */
       
   850         void *arg /**< ioctl() argument. */
       
   851         )
       
   852 {
       
   853     ec_ioctl_slave_sdo_download_t data;
       
   854     uint8_t *sdo_data;
       
   855     int retval;
       
   856 
       
   857     if (copy_from_user(&data, (void __user *) arg, sizeof(data))) {
       
   858         return -EFAULT;
       
   859     }
       
   860 
       
   861     if (!(sdo_data = kmalloc(data.data_size, GFP_KERNEL))) {
       
   862         EC_MASTER_ERR(master, "Failed to allocate %zu bytes"
       
   863                 " for SDO download.\n", data.data_size);
       
   864         return -ENOMEM;
       
   865     }
       
   866 
       
   867     if (copy_from_user(sdo_data, (void __user *) data.data, data.data_size)) {
       
   868         kfree(sdo_data);
       
   869         return -EFAULT;
       
   870     }
       
   871 
       
   872     if (data.complete_access) {
       
   873         retval = ecrt_master_sdo_download_complete(master, data.slave_position,
       
   874                 data.sdo_index, sdo_data, data.data_size, &data.abort_code);
       
   875     } else {
       
   876         retval = ecrt_master_sdo_download(master, data.slave_position,
       
   877                 data.sdo_index, data.sdo_entry_subindex, sdo_data,
       
   878                 data.data_size, &data.abort_code);
       
   879     }
       
   880 
       
   881     kfree(sdo_data);
       
   882 
       
   883     if (__copy_to_user((void __user *) arg, &data, sizeof(data))) {
       
   884         retval = -EFAULT;
       
   885     }
       
   886 
       
   887     return retval;
       
   888 }
       
   889 
       
   890 /*****************************************************************************/
       
   891 
       
   892 /** Read a slave's SII.
       
   893  *
       
   894  * \return Zero on success, otherwise a negative error code.
       
   895  */
       
   896 static ATTRIBUTES int ec_ioctl_slave_sii_read(
       
   897         ec_master_t *master, /**< EtherCAT master. */
       
   898         void *arg /**< ioctl() argument. */
       
   899         )
       
   900 {
       
   901     ec_ioctl_slave_sii_t data;
       
   902     const ec_slave_t *slave;
       
   903     int retval;
       
   904 
       
   905     if (copy_from_user(&data, (void __user *) arg, sizeof(data))) {
       
   906         return -EFAULT;
       
   907     }
       
   908 
       
   909     if (down_interruptible(&master->master_sem))
       
   910         return -EINTR;
       
   911 
       
   912     if (!(slave = ec_master_find_slave_const(
       
   913                     master, 0, data.slave_position))) {
       
   914         up(&master->master_sem);
       
   915         EC_MASTER_ERR(master, "Slave %u does not exist!\n",
       
   916                 data.slave_position);
       
   917         return -EINVAL;
       
   918     }
       
   919 
       
   920     if (!data.nwords
       
   921             || data.offset + data.nwords > slave->sii_nwords) {
       
   922         up(&master->master_sem);
       
   923         EC_SLAVE_ERR(slave, "Invalid SII read offset/size %u/%u for slave SII"
       
   924                 " size %zu!\n", data.offset, data.nwords, slave->sii_nwords);
       
   925         return -EINVAL;
       
   926     }
       
   927 
       
   928     if (copy_to_user((void __user *) data.words,
       
   929                 slave->sii_words + data.offset, data.nwords * 2))
       
   930         retval = -EFAULT;
       
   931     else
       
   932         retval = 0;
       
   933 
       
   934     up(&master->master_sem);
       
   935     return retval;
       
   936 }
       
   937 
       
   938 /*****************************************************************************/
       
   939 
       
   940 /** Write a slave's SII.
       
   941  *
       
   942  * \return Zero on success, otherwise a negative error code.
       
   943  */
       
   944 static ATTRIBUTES int ec_ioctl_slave_sii_write(
       
   945         ec_master_t *master, /**< EtherCAT master. */
       
   946         void *arg /**< ioctl() argument. */
       
   947         )
       
   948 {
       
   949     ec_ioctl_slave_sii_t data;
       
   950     ec_slave_t *slave;
       
   951     unsigned int byte_size;
       
   952     uint16_t *words;
       
   953     ec_sii_write_request_t request;
       
   954 
       
   955     if (copy_from_user(&data, (void __user *) arg, sizeof(data))) {
       
   956         return -EFAULT;
       
   957     }
       
   958 
       
   959     if (!data.nwords) {
       
   960         return 0;
       
   961     }
       
   962 
       
   963     byte_size = sizeof(uint16_t) * data.nwords;
       
   964     if (!(words = kmalloc(byte_size, GFP_KERNEL))) {
       
   965         EC_MASTER_ERR(master, "Failed to allocate %u bytes"
       
   966                 " for SII contents.\n", byte_size);
       
   967         return -ENOMEM;
       
   968     }
       
   969 
       
   970     if (copy_from_user(words,
       
   971                 (void __user *) data.words, byte_size)) {
       
   972         kfree(words);
       
   973         return -EFAULT;
       
   974     }
       
   975 
       
   976     if (down_interruptible(&master->master_sem)) {
       
   977         kfree(words);
       
   978         return -EINTR;
       
   979     }
       
   980 
       
   981     if (!(slave = ec_master_find_slave(
       
   982                     master, 0, data.slave_position))) {
       
   983         up(&master->master_sem);
       
   984         EC_MASTER_ERR(master, "Slave %u does not exist!\n",
       
   985                 data.slave_position);
       
   986         kfree(words);
       
   987         return -EINVAL;
       
   988     }
       
   989 
       
   990     // init SII write request
       
   991     INIT_LIST_HEAD(&request.list);
       
   992     request.slave = slave;
       
   993     request.words = words;
       
   994     request.offset = data.offset;
       
   995     request.nwords = data.nwords;
       
   996     request.state = EC_INT_REQUEST_QUEUED;
       
   997 
       
   998     // schedule SII write request.
       
   999     list_add_tail(&request.list, &master->sii_requests);
       
  1000 
       
  1001     up(&master->master_sem);
       
  1002 
       
  1003     // wait for processing through FSM
       
  1004     if (wait_event_interruptible(master->request_queue,
       
  1005                 request.state != EC_INT_REQUEST_QUEUED)) {
       
  1006         // interrupted by signal
       
  1007         down(&master->master_sem);
       
  1008         if (request.state == EC_INT_REQUEST_QUEUED) {
       
  1009             // abort request
       
  1010             list_del(&request.list);
       
  1011             up(&master->master_sem);
       
  1012             kfree(words);
       
  1013             return -EINTR;
       
  1014         }
       
  1015         up(&master->master_sem);
       
  1016     }
       
  1017 
       
  1018     // wait until master FSM has finished processing
       
  1019     wait_event(master->request_queue, request.state != EC_INT_REQUEST_BUSY);
       
  1020 
       
  1021     kfree(words);
       
  1022 
       
  1023     return request.state == EC_INT_REQUEST_SUCCESS ? 0 : -EIO;
       
  1024 }
       
  1025 
       
  1026 /*****************************************************************************/
       
  1027 
       
  1028 /** Read a slave's registers.
       
  1029  *
       
  1030  * \return Zero on success, otherwise a negative error code.
       
  1031  */
       
  1032 static ATTRIBUTES int ec_ioctl_slave_reg_read(
       
  1033         ec_master_t *master, /**< EtherCAT master. */
       
  1034         void *arg /**< ioctl() argument. */
       
  1035         )
       
  1036 {
       
  1037     ec_ioctl_slave_reg_t io;
       
  1038     ec_slave_t *slave;
       
  1039     ec_reg_request_t request;
       
  1040     int ret;
       
  1041 
       
  1042     if (copy_from_user(&io, (void __user *) arg, sizeof(io))) {
       
  1043         return -EFAULT;
       
  1044     }
       
  1045 
       
  1046     if (!io.size) {
       
  1047         return 0;
       
  1048     }
       
  1049 
       
  1050     // init register request
       
  1051     ret = ec_reg_request_init(&request, io.size);
       
  1052     if (ret) {
       
  1053         return ret;
       
  1054     }
       
  1055 
       
  1056     ecrt_reg_request_read(&request, io.address, io.size);
       
  1057 
       
  1058     if (down_interruptible(&master->master_sem)) {
       
  1059         ec_reg_request_clear(&request);
       
  1060         return -EINTR;
       
  1061     }
       
  1062 
       
  1063     if (!(slave = ec_master_find_slave(
       
  1064                     master, 0, io.slave_position))) {
       
  1065         up(&master->master_sem);
       
  1066         ec_reg_request_clear(&request);
       
  1067         EC_MASTER_ERR(master, "Slave %u does not exist!\n",
       
  1068                 io.slave_position);
       
  1069         return -EINVAL;
       
  1070     }
       
  1071 
       
  1072     // schedule request.
       
  1073     list_add_tail(&request.list, &slave->reg_requests);
       
  1074 
       
  1075     up(&master->master_sem);
       
  1076 
       
  1077     // wait for processing through FSM
       
  1078     if (wait_event_interruptible(master->request_queue,
       
  1079                 request.state != EC_INT_REQUEST_QUEUED)) {
       
  1080         // interrupted by signal
       
  1081         down(&master->master_sem);
       
  1082         if (request.state == EC_INT_REQUEST_QUEUED) {
       
  1083             // abort request
       
  1084             list_del(&request.list);
       
  1085             up(&master->master_sem);
       
  1086             ec_reg_request_clear(&request);
       
  1087             return -EINTR;
       
  1088         }
       
  1089         up(&master->master_sem);
       
  1090     }
       
  1091 
       
  1092     // wait until master FSM has finished processing
       
  1093     wait_event(master->request_queue, request.state != EC_INT_REQUEST_BUSY);
       
  1094 
       
  1095     if (request.state == EC_INT_REQUEST_SUCCESS) {
       
  1096         if (copy_to_user((void __user *) io.data, request.data, io.size)) {
       
  1097             return -EFAULT;
       
  1098         }
       
  1099     }
       
  1100     ec_reg_request_clear(&request);
       
  1101 
       
  1102     return request.state == EC_INT_REQUEST_SUCCESS ? 0 : -EIO;
       
  1103 }
       
  1104 
       
  1105 /*****************************************************************************/
       
  1106 
       
  1107 /** Write a slave's registers.
       
  1108  *
       
  1109  * \return Zero on success, otherwise a negative error code.
       
  1110  */
       
  1111 static ATTRIBUTES int ec_ioctl_slave_reg_write(
       
  1112         ec_master_t *master, /**< EtherCAT master. */
       
  1113         void *arg /**< ioctl() argument. */
       
  1114         )
       
  1115 {
       
  1116     ec_ioctl_slave_reg_t io;
       
  1117     ec_slave_t *slave;
       
  1118     ec_reg_request_t request;
       
  1119     int ret;
       
  1120 
       
  1121     if (copy_from_user(&io, (void __user *) arg, sizeof(io))) {
       
  1122         return -EFAULT;
       
  1123     }
       
  1124 
       
  1125     if (!io.size) {
       
  1126         return 0;
       
  1127     }
       
  1128 
       
  1129     // init register request
       
  1130     ret = ec_reg_request_init(&request, io.size);
       
  1131     if (ret) {
       
  1132         return ret;
       
  1133     }
       
  1134 
       
  1135     if (copy_from_user(request.data, (void __user *) io.data, io.size)) {
       
  1136         ec_reg_request_clear(&request);
       
  1137         return -EFAULT;
       
  1138     }
       
  1139 
       
  1140     ecrt_reg_request_write(&request, io.address, io.size);
       
  1141 
       
  1142     if (down_interruptible(&master->master_sem)) {
       
  1143         ec_reg_request_clear(&request);
       
  1144         return -EINTR;
       
  1145     }
       
  1146 
       
  1147     if (io.emergency) {
       
  1148         request.ring_position = io.slave_position;
       
  1149         // schedule request.
       
  1150         list_add_tail(&request.list, &master->emerg_reg_requests);
       
  1151     }
       
  1152     else {
       
  1153         if (!(slave = ec_master_find_slave(master, 0, io.slave_position))) {
       
  1154             up(&master->master_sem);
       
  1155             ec_reg_request_clear(&request);
       
  1156             EC_MASTER_ERR(master, "Slave %u does not exist!\n",
       
  1157                     io.slave_position);
       
  1158             return -EINVAL;
       
  1159         }
       
  1160 
       
  1161         // schedule request.
       
  1162         list_add_tail(&request.list, &slave->reg_requests);
       
  1163     }
       
  1164 
       
  1165     up(&master->master_sem);
       
  1166 
       
  1167     // wait for processing through FSM
       
  1168     if (wait_event_interruptible(master->request_queue,
       
  1169                 request.state != EC_INT_REQUEST_QUEUED)) {
       
  1170         // interrupted by signal
       
  1171         down(&master->master_sem);
       
  1172         if (request.state == EC_INT_REQUEST_QUEUED) {
       
  1173             // abort request
       
  1174             list_del(&request.list);
       
  1175             up(&master->master_sem);
       
  1176             ec_reg_request_clear(&request);
       
  1177             return -EINTR;
       
  1178         }
       
  1179         up(&master->master_sem);
       
  1180     }
       
  1181 
       
  1182     // wait until master FSM has finished processing
       
  1183     wait_event(master->request_queue, request.state != EC_INT_REQUEST_BUSY);
       
  1184 
       
  1185     ec_reg_request_clear(&request);
       
  1186 
       
  1187     return request.state == EC_INT_REQUEST_SUCCESS ? 0 : -EIO;
       
  1188 }
       
  1189 
       
  1190 /*****************************************************************************/
       
  1191 
       
  1192 /** Get slave configuration information.
       
  1193  *
       
  1194  * \return Zero on success, otherwise a negative error code.
       
  1195  */
       
  1196 static ATTRIBUTES int ec_ioctl_config(
       
  1197         ec_master_t *master, /**< EtherCAT master. */
       
  1198         void *arg /**< ioctl() argument. */
       
  1199         )
       
  1200 {
       
  1201     ec_ioctl_config_t data;
       
  1202     const ec_slave_config_t *sc;
       
  1203     uint8_t i;
       
  1204 
       
  1205     if (copy_from_user(&data, (void __user *) arg, sizeof(data))) {
       
  1206         return -EFAULT;
       
  1207     }
       
  1208 
       
  1209     if (down_interruptible(&master->master_sem))
       
  1210         return -EINTR;
       
  1211 
       
  1212     if (!(sc = ec_master_get_config_const(
       
  1213                     master, data.config_index))) {
       
  1214         up(&master->master_sem);
       
  1215         EC_MASTER_ERR(master, "Slave config %u does not exist!\n",
       
  1216                 data.config_index);
       
  1217         return -EINVAL;
       
  1218     }
       
  1219 
       
  1220     data.alias = sc->alias;
       
  1221     data.position = sc->position;
       
  1222     data.vendor_id = sc->vendor_id;
       
  1223     data.product_code = sc->product_code;
       
  1224     for (i = 0; i < EC_MAX_SYNC_MANAGERS; i++) {
       
  1225         data.syncs[i].dir = sc->sync_configs[i].dir;
       
  1226         data.syncs[i].watchdog_mode = sc->sync_configs[i].watchdog_mode;
       
  1227         data.syncs[i].pdo_count =
       
  1228             ec_pdo_list_count(&sc->sync_configs[i].pdos);
       
  1229     }
       
  1230     data.watchdog_divider = sc->watchdog_divider;
       
  1231     data.watchdog_intervals = sc->watchdog_intervals;
       
  1232     data.sdo_count = ec_slave_config_sdo_count(sc);
       
  1233     data.idn_count = ec_slave_config_idn_count(sc);
       
  1234     data.slave_position = sc->slave ? sc->slave->ring_position : -1;
       
  1235     data.dc_assign_activate = sc->dc_assign_activate;
       
  1236     for (i = 0; i < EC_SYNC_SIGNAL_COUNT; i++) {
       
  1237         data.dc_sync[i] = sc->dc_sync[i];
       
  1238     }
       
  1239 
       
  1240     up(&master->master_sem);
       
  1241 
       
  1242     if (copy_to_user((void __user *) arg, &data, sizeof(data)))
       
  1243         return -EFAULT;
       
  1244 
       
  1245     return 0;
       
  1246 }
       
  1247 
       
  1248 /*****************************************************************************/
       
  1249 
       
  1250 /** Get slave configuration PDO information.
       
  1251  *
       
  1252  * \return Zero on success, otherwise a negative error code.
       
  1253  */
       
  1254 static ATTRIBUTES int ec_ioctl_config_pdo(
       
  1255         ec_master_t *master, /**< EtherCAT master. */
       
  1256         void *arg /**< ioctl() argument. */
       
  1257         )
       
  1258 {
       
  1259     ec_ioctl_config_pdo_t data;
       
  1260     const ec_slave_config_t *sc;
       
  1261     const ec_pdo_t *pdo;
       
  1262 
       
  1263     if (copy_from_user(&data, (void __user *) arg, sizeof(data))) {
       
  1264         return -EFAULT;
       
  1265     }
       
  1266 
       
  1267     if (data.sync_index >= EC_MAX_SYNC_MANAGERS) {
       
  1268         EC_MASTER_ERR(master, "Invalid sync manager index %u!\n",
       
  1269                 data.sync_index);
       
  1270         return -EINVAL;
       
  1271     }
       
  1272 
       
  1273     if (down_interruptible(&master->master_sem))
       
  1274         return -EINTR;
       
  1275 
       
  1276     if (!(sc = ec_master_get_config_const(
       
  1277                     master, data.config_index))) {
       
  1278         up(&master->master_sem);
       
  1279         EC_MASTER_ERR(master, "Slave config %u does not exist!\n",
       
  1280                 data.config_index);
       
  1281         return -EINVAL;
       
  1282     }
       
  1283 
       
  1284     if (!(pdo = ec_pdo_list_find_pdo_by_pos_const(
       
  1285                     &sc->sync_configs[data.sync_index].pdos,
       
  1286                     data.pdo_pos))) {
       
  1287         up(&master->master_sem);
       
  1288         EC_MASTER_ERR(master, "Invalid PDO position!\n");
       
  1289         return -EINVAL;
       
  1290     }
       
  1291 
       
  1292     data.index = pdo->index;
       
  1293     data.entry_count = ec_pdo_entry_count(pdo);
       
  1294     ec_ioctl_strcpy(data.name, pdo->name);
       
  1295 
       
  1296     up(&master->master_sem);
       
  1297 
       
  1298     if (copy_to_user((void __user *) arg, &data, sizeof(data)))
       
  1299         return -EFAULT;
       
  1300 
       
  1301     return 0;
       
  1302 }
       
  1303 
       
  1304 /*****************************************************************************/
       
  1305 
       
  1306 /** Get slave configuration PDO entry information.
       
  1307  *
       
  1308  * \return Zero on success, otherwise a negative error code.
       
  1309  */
       
  1310 static ATTRIBUTES int ec_ioctl_config_pdo_entry(
       
  1311         ec_master_t *master, /**< EtherCAT master. */
       
  1312         void *arg /**< ioctl() argument. */
       
  1313         )
       
  1314 {
       
  1315     ec_ioctl_config_pdo_entry_t data;
       
  1316     const ec_slave_config_t *sc;
       
  1317     const ec_pdo_t *pdo;
       
  1318     const ec_pdo_entry_t *entry;
       
  1319 
       
  1320     if (copy_from_user(&data, (void __user *) arg, sizeof(data))) {
       
  1321         return -EFAULT;
       
  1322     }
       
  1323 
       
  1324     if (data.sync_index >= EC_MAX_SYNC_MANAGERS) {
       
  1325         EC_MASTER_ERR(master, "Invalid sync manager index %u!\n",
       
  1326                 data.sync_index);
       
  1327         return -EINVAL;
       
  1328     }
       
  1329 
       
  1330     if (down_interruptible(&master->master_sem))
       
  1331         return -EINTR;
       
  1332 
       
  1333     if (!(sc = ec_master_get_config_const(
       
  1334                     master, data.config_index))) {
       
  1335         up(&master->master_sem);
       
  1336         EC_MASTER_ERR(master, "Slave config %u does not exist!\n",
       
  1337                 data.config_index);
       
  1338         return -EINVAL;
       
  1339     }
       
  1340 
       
  1341     if (!(pdo = ec_pdo_list_find_pdo_by_pos_const(
       
  1342                     &sc->sync_configs[data.sync_index].pdos,
       
  1343                     data.pdo_pos))) {
       
  1344         up(&master->master_sem);
       
  1345         EC_MASTER_ERR(master, "Invalid PDO position!\n");
       
  1346         return -EINVAL;
       
  1347     }
       
  1348 
       
  1349     if (!(entry = ec_pdo_find_entry_by_pos_const(
       
  1350                     pdo, data.entry_pos))) {
       
  1351         up(&master->master_sem);
       
  1352         EC_MASTER_ERR(master, "Entry not found!\n");
       
  1353         return -EINVAL;
       
  1354     }
       
  1355 
       
  1356     data.index = entry->index;
       
  1357     data.subindex = entry->subindex;
       
  1358     data.bit_length = entry->bit_length;
       
  1359     ec_ioctl_strcpy(data.name, entry->name);
       
  1360 
       
  1361     up(&master->master_sem);
       
  1362 
       
  1363     if (copy_to_user((void __user *) arg, &data, sizeof(data)))
       
  1364         return -EFAULT;
       
  1365 
       
  1366     return 0;
       
  1367 }
       
  1368 
       
  1369 /*****************************************************************************/
       
  1370 
       
  1371 /** Get slave configuration SDO information.
       
  1372  *
       
  1373  * \return Zero on success, otherwise a negative error code.
       
  1374  */
       
  1375 static ATTRIBUTES int ec_ioctl_config_sdo(
       
  1376         ec_master_t *master, /**< EtherCAT master. */
       
  1377         void *arg /**< ioctl() argument. */
       
  1378         )
       
  1379 {
       
  1380     ec_ioctl_config_sdo_t *ioctl;
       
  1381     const ec_slave_config_t *sc;
       
  1382     const ec_sdo_request_t *req;
       
  1383 
       
  1384     if (!(ioctl = kmalloc(sizeof(*ioctl), GFP_KERNEL))) {
       
  1385         return -ENOMEM;
       
  1386     }
       
  1387 
       
  1388     if (copy_from_user(ioctl, (void __user *) arg, sizeof(*ioctl))) {
       
  1389         kfree(ioctl);
       
  1390         return -EFAULT;
       
  1391     }
       
  1392 
       
  1393     if (down_interruptible(&master->master_sem)) {
       
  1394         kfree(ioctl);
       
  1395         return -EINTR;
       
  1396     }
       
  1397 
       
  1398     if (!(sc = ec_master_get_config_const(
       
  1399                     master, ioctl->config_index))) {
       
  1400         up(&master->master_sem);
       
  1401         EC_MASTER_ERR(master, "Slave config %u does not exist!\n",
       
  1402                 ioctl->config_index);
       
  1403         kfree(ioctl);
       
  1404         return -EINVAL;
       
  1405     }
       
  1406 
       
  1407     if (!(req = ec_slave_config_get_sdo_by_pos_const(
       
  1408                     sc, ioctl->sdo_pos))) {
       
  1409         up(&master->master_sem);
       
  1410         EC_MASTER_ERR(master, "Invalid SDO position!\n");
       
  1411         kfree(ioctl);
       
  1412         return -EINVAL;
       
  1413     }
       
  1414 
       
  1415     ioctl->index = req->index;
       
  1416     ioctl->subindex = req->subindex;
       
  1417     ioctl->size = req->data_size;
       
  1418     memcpy(ioctl->data, req->data,
       
  1419             min((u32) ioctl->size, (u32) EC_MAX_SDO_DATA_SIZE));
       
  1420     ioctl->complete_access = req->complete_access;
       
  1421 
       
  1422     up(&master->master_sem);
       
  1423 
       
  1424     if (copy_to_user((void __user *) arg, ioctl, sizeof(*ioctl))) {
       
  1425         kfree(ioctl);
       
  1426         return -EFAULT;
       
  1427     }
       
  1428 
       
  1429     kfree(ioctl);
       
  1430     return 0;
       
  1431 }
       
  1432 
       
  1433 /*****************************************************************************/
       
  1434 
       
  1435 /** Get slave configuration IDN information.
       
  1436  *
       
  1437  * \return Zero on success, otherwise a negative error code.
       
  1438  */
       
  1439 static ATTRIBUTES int ec_ioctl_config_idn(
       
  1440         ec_master_t *master, /**< EtherCAT master. */
       
  1441         void *arg /**< ioctl() argument. */
       
  1442         )
       
  1443 {
       
  1444     ec_ioctl_config_idn_t *ioctl;
       
  1445     const ec_slave_config_t *sc;
       
  1446     const ec_soe_request_t *req;
       
  1447 
       
  1448     if (!(ioctl = kmalloc(sizeof(*ioctl), GFP_KERNEL))) {
       
  1449         return -ENOMEM;
       
  1450     }
       
  1451 
       
  1452     if (copy_from_user(ioctl, (void __user *) arg, sizeof(*ioctl))) {
       
  1453         kfree(ioctl);
       
  1454         return -EFAULT;
       
  1455     }
       
  1456 
       
  1457     if (down_interruptible(&master->master_sem)) {
       
  1458         kfree(ioctl);
       
  1459         return -EINTR;
       
  1460     }
       
  1461 
       
  1462     if (!(sc = ec_master_get_config_const(
       
  1463                     master, ioctl->config_index))) {
       
  1464         up(&master->master_sem);
       
  1465         EC_MASTER_ERR(master, "Slave config %u does not exist!\n",
       
  1466                 ioctl->config_index);
       
  1467         kfree(ioctl);
       
  1468         return -EINVAL;
       
  1469     }
       
  1470 
       
  1471     if (!(req = ec_slave_config_get_idn_by_pos_const(
       
  1472                     sc, ioctl->idn_pos))) {
       
  1473         up(&master->master_sem);
       
  1474         EC_MASTER_ERR(master, "Invalid IDN position!\n");
       
  1475         kfree(ioctl);
       
  1476         return -EINVAL;
       
  1477     }
       
  1478 
       
  1479     ioctl->drive_no = req->drive_no;
       
  1480     ioctl->idn = req->idn;
       
  1481     ioctl->state = req->state;
       
  1482     ioctl->size = req->data_size;
       
  1483     memcpy(ioctl->data, req->data,
       
  1484             min((u32) ioctl->size, (u32) EC_MAX_IDN_DATA_SIZE));
       
  1485 
       
  1486     up(&master->master_sem);
       
  1487 
       
  1488     if (copy_to_user((void __user *) arg, ioctl, sizeof(*ioctl))) {
       
  1489         kfree(ioctl);
       
  1490         return -EFAULT;
       
  1491     }
       
  1492 
       
  1493     kfree(ioctl);
       
  1494     return 0;
       
  1495 }
       
  1496 
       
  1497 /*****************************************************************************/
       
  1498 
       
  1499 #ifdef EC_EOE
       
  1500 
       
  1501 /** Get EoE handler information.
       
  1502  *
       
  1503  * \return Zero on success, otherwise a negative error code.
       
  1504  */
       
  1505 static ATTRIBUTES int ec_ioctl_eoe_handler(
       
  1506         ec_master_t *master, /**< EtherCAT master. */
       
  1507         void *arg /**< ioctl() argument. */
       
  1508         )
       
  1509 {
       
  1510     ec_ioctl_eoe_handler_t data;
       
  1511     const ec_eoe_t *eoe;
       
  1512 
       
  1513     if (copy_from_user(&data, (void __user *) arg, sizeof(data))) {
       
  1514         return -EFAULT;
       
  1515     }
       
  1516 
       
  1517     if (down_interruptible(&master->master_sem))
       
  1518         return -EINTR;
       
  1519 
       
  1520     if (!(eoe = ec_master_get_eoe_handler_const(master, data.eoe_index))) {
       
  1521         up(&master->master_sem);
       
  1522         EC_MASTER_ERR(master, "EoE handler %u does not exist!\n",
       
  1523                 data.eoe_index);
       
  1524         return -EINVAL;
       
  1525     }
       
  1526 
       
  1527     if (eoe->slave) {
       
  1528         data.slave_position = eoe->slave->ring_position;
       
  1529     } else {
       
  1530         data.slave_position = 0xffff;
       
  1531     }
       
  1532     snprintf(data.name, EC_DATAGRAM_NAME_SIZE, eoe->dev->name);
       
  1533     data.open = eoe->opened;
       
  1534     data.rx_bytes = eoe->stats.tx_bytes;
       
  1535     data.rx_rate = eoe->tx_rate;
       
  1536     data.tx_bytes = eoe->stats.rx_bytes;
       
  1537     data.tx_rate = eoe->tx_rate;
       
  1538     data.tx_queued_frames = eoe->tx_queued_frames;
       
  1539     data.tx_queue_size = eoe->tx_queue_size;
       
  1540 
       
  1541     up(&master->master_sem);
       
  1542 
       
  1543     if (copy_to_user((void __user *) arg, &data, sizeof(data)))
       
  1544         return -EFAULT;
       
  1545 
       
  1546     return 0;
       
  1547 }
       
  1548 
       
  1549 #endif
       
  1550 
       
  1551 /*****************************************************************************/
       
  1552 
       
  1553 /** Request the master from userspace.
       
  1554  *
       
  1555  * \return Zero on success, otherwise a negative error code.
       
  1556  */
       
  1557 static ATTRIBUTES int ec_ioctl_request(
       
  1558         ec_master_t *master, /**< EtherCAT master. */
       
  1559         void *arg, /**< ioctl() argument. */
       
  1560         ec_ioctl_context_t *ctx /**< Private data structure of file handle. */
       
  1561         )
       
  1562 {
       
  1563     ec_master_t *m;
       
  1564     int ret = 0;
       
  1565 
       
  1566     m = ecrt_request_master_err(master->index);
       
  1567     if (IS_ERR(m)) {
       
  1568         ret = PTR_ERR(m);
       
  1569     } else {
       
  1570         ctx->requested = 1;
       
  1571     }
       
  1572 
       
  1573     return ret;
       
  1574 }
       
  1575 
       
  1576 /*****************************************************************************/
       
  1577 
       
  1578 /** Create a domain.
       
  1579  *
       
  1580  * \return Domain index on success, otherwise a negative error code.
       
  1581  */
       
  1582 static ATTRIBUTES int ec_ioctl_create_domain(
       
  1583         ec_master_t *master, /**< EtherCAT master. */
       
  1584         void *arg, /**< ioctl() argument. */
       
  1585         ec_ioctl_context_t *ctx /**< Private data structure of file handle. */
       
  1586         )
       
  1587 {
       
  1588     ec_domain_t *domain;
       
  1589 
       
  1590     if (unlikely(!ctx->requested))
       
  1591         return -EPERM;
       
  1592 
       
  1593     domain = ecrt_master_create_domain_err(master);
       
  1594     if (IS_ERR(domain))
       
  1595         return PTR_ERR(domain);
       
  1596 
       
  1597     return domain->index;
       
  1598 }
       
  1599 
       
  1600 /*****************************************************************************/
       
  1601 
       
  1602 /** Create a slave configuration.
       
  1603  *
       
  1604  * \return Zero on success, otherwise a negative error code.
       
  1605  */
       
  1606 static ATTRIBUTES int ec_ioctl_create_slave_config(
       
  1607         ec_master_t *master, /**< EtherCAT master. */
       
  1608         void *arg, /**< ioctl() argument. */
       
  1609         ec_ioctl_context_t *ctx /**< Private data structure of file handle. */
       
  1610         )
       
  1611 {
       
  1612     ec_ioctl_config_t data;
       
  1613     ec_slave_config_t *sc, *entry;
       
  1614 
       
  1615     if (unlikely(!ctx->requested))
       
  1616         return -EPERM;
       
  1617 
       
  1618     if (copy_from_user(&data, (void __user *) arg, sizeof(data))) {
       
  1619         return -EFAULT;
       
  1620     }
       
  1621 
       
  1622     sc = ecrt_master_slave_config_err(master, data.alias, data.position,
       
  1623             data.vendor_id, data.product_code);
       
  1624     if (IS_ERR(sc))
       
  1625         return PTR_ERR(sc);
       
  1626 
       
  1627     data.config_index = 0;
       
  1628 
       
  1629     if (down_interruptible(&master->master_sem))
       
  1630         return -EINTR;
       
  1631 
       
  1632     list_for_each_entry(entry, &master->configs, list) {
       
  1633         if (entry == sc)
       
  1634             break;
       
  1635         data.config_index++;
       
  1636     }
       
  1637 
       
  1638     up(&master->master_sem);
       
  1639 
       
  1640     if (copy_to_user((void __user *) arg, &data, sizeof(data)))
       
  1641         return -EFAULT;
       
  1642 
       
  1643     return 0;
       
  1644 }
       
  1645 
       
  1646 /*****************************************************************************/
       
  1647 
       
  1648 /** Select the DC reference clock.
       
  1649  *
       
  1650  * \return Zero on success, otherwise a negative error code.
       
  1651  */
       
  1652 static ATTRIBUTES int ec_ioctl_select_ref_clock(
       
  1653         ec_master_t *master, /**< EtherCAT master. */
       
  1654         void *arg, /**< ioctl() argument. */
       
  1655         ec_ioctl_context_t *ctx /**< Private data structure of file handle. */
       
  1656         )
       
  1657 {
       
  1658     unsigned long config_index = (unsigned long) arg;
       
  1659     ec_slave_config_t *sc = NULL;
       
  1660     int ret = 0;
       
  1661 
       
  1662     if (unlikely(!ctx->requested)) {
       
  1663         ret = -EPERM;
       
  1664         goto out_return;
       
  1665     }
       
  1666 
       
  1667     if (down_interruptible(&master->master_sem)) {
       
  1668         ret = -EINTR;
       
  1669         goto out_return;
       
  1670     }
       
  1671 
       
  1672     if (config_index != 0xFFFFFFFF) {
       
  1673         if (!(sc = ec_master_get_config(master, config_index))) {
       
  1674             ret = -ENOENT;
       
  1675             goto out_up;
       
  1676         }
       
  1677     }
       
  1678 
       
  1679     ecrt_master_select_reference_clock(master, sc);
       
  1680 
       
  1681 out_up:
       
  1682     up(&master->master_sem);
       
  1683 out_return:
       
  1684     return ret;
       
  1685 }
       
  1686 
       
  1687 /*****************************************************************************/
       
  1688 
       
  1689 /** Activates the master.
       
  1690  *
       
  1691  * \return Zero on success, otherwise a negative error code.
       
  1692  */
       
  1693 static ATTRIBUTES int ec_ioctl_activate(
       
  1694         ec_master_t *master, /**< EtherCAT master. */
       
  1695         void *arg, /**< ioctl() argument. */
       
  1696         ec_ioctl_context_t *ctx /**< Private data structure of file handle. */
       
  1697         )
       
  1698 {
       
  1699     ec_ioctl_master_activate_t io;
       
  1700     ec_domain_t *domain;
       
  1701     off_t offset;
       
  1702     int ret;
       
  1703 
       
  1704     if (unlikely(!ctx->requested))
       
  1705         return -EPERM;
       
  1706 
       
  1707     io.process_data = NULL;
       
  1708 
       
  1709     /* Get the sum of the domains' process data sizes. */
       
  1710 
       
  1711     ctx->process_data_size = 0;
       
  1712 
       
  1713     if (down_interruptible(&master->master_sem))
       
  1714         return -EINTR;
       
  1715 
       
  1716     list_for_each_entry(domain, &master->domains, list) {
       
  1717         ctx->process_data_size += ecrt_domain_size(domain);
       
  1718     }
       
  1719 
       
  1720     up(&master->master_sem);
       
  1721 
       
  1722     if (ctx->process_data_size) {
       
  1723         ctx->process_data = vmalloc(ctx->process_data_size);
       
  1724         if (!ctx->process_data) {
       
  1725             ctx->process_data_size = 0;
       
  1726             return -ENOMEM;
       
  1727         }
       
  1728 
       
  1729         /* Set the memory as external process data memory for the
       
  1730          * domains.
       
  1731          */
       
  1732         offset = 0;
       
  1733         list_for_each_entry(domain, &master->domains, list) {
       
  1734             ecrt_domain_external_memory(domain,
       
  1735                     ctx->process_data + offset);
       
  1736             offset += ecrt_domain_size(domain);
       
  1737         }
       
  1738 
       
  1739 #ifdef EC_IOCTL_RTDM
       
  1740         /* RTDM uses a different approach for memory-mapping, which has to be
       
  1741          * initiated by the kernel.
       
  1742          */
       
  1743         ret = ec_rtdm_mmap(ctx, &io.process_data);
       
  1744         if (ret < 0) {
       
  1745             EC_MASTER_ERR(master, "Failed to map process data"
       
  1746                     " memory to user space (code %i).\n", ret);
       
  1747             return ret;
       
  1748         }
       
  1749 #endif
       
  1750     }
       
  1751 
       
  1752     io.process_data_size = ctx->process_data_size;
       
  1753 
       
  1754 #ifndef EC_IOCTL_RTDM
       
  1755     ecrt_master_callbacks(master, ec_master_internal_send_cb,
       
  1756             ec_master_internal_receive_cb, master);
       
  1757 #endif
       
  1758 
       
  1759     ret = ecrt_master_activate(master);
       
  1760     if (ret < 0)
       
  1761         return ret;
       
  1762 
       
  1763     if (copy_to_user((void __user *) arg, &io,
       
  1764                 sizeof(ec_ioctl_master_activate_t)))
       
  1765         return -EFAULT;
       
  1766 
       
  1767     return 0;
       
  1768 }
       
  1769 
       
  1770 /*****************************************************************************/
       
  1771 
       
  1772 /** Deactivates the master.
       
  1773  *
       
  1774  * \return Zero on success, otherwise a negative error code.
       
  1775  */
       
  1776 static ATTRIBUTES int ec_ioctl_deactivate(
       
  1777         ec_master_t *master, /**< EtherCAT master. */
       
  1778         void *arg, /**< ioctl() argument. */
       
  1779         ec_ioctl_context_t *ctx /**< Private data structure of file handle. */
       
  1780         )
       
  1781 {
       
  1782     if (unlikely(!ctx->requested))
       
  1783         return -EPERM;
       
  1784 
       
  1785     ecrt_master_deactivate(master);
       
  1786     return 0;
       
  1787 }
       
  1788 
       
  1789 /*****************************************************************************/
       
  1790 
       
  1791 /** Set max. number of databytes in a cycle
       
  1792  *
       
  1793  * \return Zero on success, otherwise a negative error code.
       
  1794  */
       
  1795 static ATTRIBUTES int ec_ioctl_set_send_interval(
       
  1796         ec_master_t *master, /**< EtherCAT master. */
       
  1797         void *arg, /**< ioctl() argument. */
       
  1798         ec_ioctl_context_t *ctx /**< Private data structure of file handle. */
       
  1799         )
       
  1800 {
       
  1801     size_t send_interval;
       
  1802 
       
  1803     if (unlikely(!ctx->requested)) {
       
  1804         return -EPERM;
       
  1805     }
       
  1806 
       
  1807     if (copy_from_user(&send_interval, (void __user *) arg,
       
  1808                 sizeof(send_interval))) {
       
  1809         return -EFAULT;
       
  1810     }
       
  1811 
       
  1812     if (down_interruptible(&master->master_sem))
       
  1813         return -EINTR;
       
  1814 
       
  1815     ec_master_set_send_interval(master, send_interval);
       
  1816 
       
  1817     up(&master->master_sem);
       
  1818     return 0;
       
  1819 }
       
  1820 
       
  1821 /*****************************************************************************/
       
  1822 
       
  1823 /** Send frames.
       
  1824  *
       
  1825  * \return Zero on success, otherwise a negative error code.
       
  1826  */
       
  1827 static ATTRIBUTES int ec_ioctl_send(
       
  1828         ec_master_t *master, /**< EtherCAT master. */
       
  1829         void *arg, /**< ioctl() argument. */
       
  1830         ec_ioctl_context_t *ctx /**< Private data structure of file handle. */
       
  1831         )
       
  1832 {
       
  1833     if (unlikely(!ctx->requested)) {
       
  1834         return -EPERM;
       
  1835     }
       
  1836 
       
  1837     ecrt_master_send(master);
       
  1838     return 0;
       
  1839 }
       
  1840 
       
  1841 /*****************************************************************************/
       
  1842 
       
  1843 /** Receive frames.
       
  1844  *
       
  1845  * \return Zero on success, otherwise a negative error code.
       
  1846  */
       
  1847 static ATTRIBUTES int ec_ioctl_receive(
       
  1848         ec_master_t *master, /**< EtherCAT master. */
       
  1849         void *arg, /**< ioctl() argument. */
       
  1850         ec_ioctl_context_t *ctx /**< Private data structure of file handle. */
       
  1851         )
       
  1852 {
       
  1853     if (unlikely(!ctx->requested)) {
       
  1854         return -EPERM;
       
  1855     }
       
  1856 
       
  1857     ecrt_master_receive(master);
       
  1858     return 0;
       
  1859 }
       
  1860 
       
  1861 /*****************************************************************************/
       
  1862 
       
  1863 /** Get the master state.
       
  1864  *
       
  1865  * \return Zero on success, otherwise a negative error code.
       
  1866  */
       
  1867 static ATTRIBUTES int ec_ioctl_master_state(
       
  1868         ec_master_t *master, /**< EtherCAT master. */
       
  1869         void *arg, /**< ioctl() argument. */
       
  1870         ec_ioctl_context_t *ctx /**< Private data structure of file handle. */
       
  1871         )
       
  1872 {
       
  1873     ec_master_state_t data;
       
  1874 
       
  1875     ecrt_master_state(master, &data);
       
  1876 
       
  1877     if (copy_to_user((void __user *) arg, &data, sizeof(data)))
       
  1878         return -EFAULT;
       
  1879 
       
  1880     return 0;
       
  1881 }
       
  1882 
       
  1883 /*****************************************************************************/
       
  1884 
       
  1885 /** Get the link state.
       
  1886  *
       
  1887  * \return Zero on success, otherwise a negative error code.
       
  1888  */
       
  1889 static ATTRIBUTES int ec_ioctl_master_link_state(
       
  1890         ec_master_t *master, /**< EtherCAT master. */
       
  1891         void *arg, /**< ioctl() argument. */
       
  1892         ec_ioctl_context_t *ctx /**< Private data structure of file handle. */
       
  1893         )
       
  1894 {
       
  1895     ec_ioctl_link_state_t ioctl;
       
  1896     ec_master_link_state_t state;
       
  1897     int ret;
       
  1898 
       
  1899     if (copy_from_user(&ioctl, (void __user *) arg, sizeof(ioctl))) {
       
  1900         return -EFAULT;
       
  1901     }
       
  1902 
       
  1903     ret = ecrt_master_link_state(master, ioctl.dev_idx, &state);
       
  1904     if (ret < 0) {
       
  1905         return ret;
       
  1906     }
       
  1907 
       
  1908     if (copy_to_user((void __user *) ioctl.state, &state, sizeof(state))) {
       
  1909         return -EFAULT;
       
  1910     }
       
  1911 
       
  1912     return 0;
       
  1913 }
       
  1914 
       
  1915 /*****************************************************************************/
       
  1916 
       
  1917 /** Set the master DC application time.
       
  1918  *
       
  1919  * \return Zero on success, otherwise a negative error code.
       
  1920  */
       
  1921 static ATTRIBUTES int ec_ioctl_app_time(
       
  1922         ec_master_t *master, /**< EtherCAT master. */
       
  1923         void *arg, /**< ioctl() argument. */
       
  1924         ec_ioctl_context_t *ctx /**< Private data structure of file handle. */
       
  1925         )
       
  1926 {
       
  1927     ec_ioctl_app_time_t data;
       
  1928 
       
  1929     if (unlikely(!ctx->requested))
       
  1930         return -EPERM;
       
  1931 
       
  1932     if (copy_from_user(&data, (void __user *) arg, sizeof(data))) {
       
  1933         return -EFAULT;
       
  1934     }
       
  1935 
       
  1936     ecrt_master_application_time(master, data.app_time);
       
  1937     return 0;
       
  1938 }
       
  1939 
       
  1940 /*****************************************************************************/
       
  1941 
       
  1942 /** Sync the reference clock.
       
  1943  *
       
  1944  * \return Zero on success, otherwise a negative error code.
       
  1945  */
       
  1946 static ATTRIBUTES int ec_ioctl_sync_ref(
       
  1947         ec_master_t *master, /**< EtherCAT master. */
       
  1948         void *arg, /**< ioctl() argument. */
       
  1949         ec_ioctl_context_t *ctx /**< Private data structure of file handle. */
       
  1950         )
       
  1951 {
       
  1952     if (unlikely(!ctx->requested)) {
       
  1953         return -EPERM;
       
  1954     }
       
  1955 
       
  1956     ecrt_master_sync_reference_clock(master);
       
  1957     return 0;
       
  1958 }
       
  1959 
       
  1960 /*****************************************************************************/
       
  1961 
       
  1962 /** Sync the slave clocks.
       
  1963  *
       
  1964  * \return Zero on success, otherwise a negative error code.
       
  1965  */
       
  1966 static ATTRIBUTES int ec_ioctl_sync_slaves(
       
  1967         ec_master_t *master, /**< EtherCAT master. */
       
  1968         void *arg, /**< ioctl() argument. */
       
  1969         ec_ioctl_context_t *ctx /**< Private data structure of file handle. */
       
  1970         )
       
  1971 {
       
  1972     if (unlikely(!ctx->requested)) {
       
  1973         return -EPERM;
       
  1974     }
       
  1975 
       
  1976     ecrt_master_sync_slave_clocks(master);
       
  1977     return 0;
       
  1978 }
       
  1979 
       
  1980 /*****************************************************************************/
       
  1981 
       
  1982 /** Get the system time of the reference clock.
       
  1983  *
       
  1984  * \return Zero on success, otherwise a negative error code.
       
  1985  */
       
  1986 static ATTRIBUTES int ec_ioctl_ref_clock_time(
       
  1987         ec_master_t *master, /**< EtherCAT master. */
       
  1988         void *arg, /**< ioctl() argument. */
       
  1989         ec_ioctl_context_t *ctx /**< Private data structure of file handle. */
       
  1990         )
       
  1991 {
       
  1992     uint32_t time;
       
  1993     int ret;
       
  1994 
       
  1995     if (unlikely(!ctx->requested)) {
       
  1996         return -EPERM;
       
  1997     }
       
  1998 
       
  1999     ret = ecrt_master_reference_clock_time(master, &time);
       
  2000     if (ret) {
       
  2001         return ret;
       
  2002     }
       
  2003 
       
  2004     if (copy_to_user((void __user *) arg, &time, sizeof(time))) {
       
  2005         return -EFAULT;
       
  2006     }
       
  2007 
       
  2008     return 0;
       
  2009 }
       
  2010 
       
  2011 /*****************************************************************************/
       
  2012 
       
  2013 /** Queue the sync monitoring datagram.
       
  2014  *
       
  2015  * \return Zero on success, otherwise a negative error code.
       
  2016  */
       
  2017 static ATTRIBUTES int ec_ioctl_sync_mon_queue(
       
  2018         ec_master_t *master, /**< EtherCAT master. */
       
  2019         void *arg, /**< ioctl() argument. */
       
  2020         ec_ioctl_context_t *ctx /**< Private data structure of file handle. */
       
  2021         )
       
  2022 {
       
  2023     if (unlikely(!ctx->requested)) {
       
  2024         return -EPERM;
       
  2025     }
       
  2026 
       
  2027     ecrt_master_sync_monitor_queue(master);
       
  2028     return 0;
       
  2029 }
       
  2030 
       
  2031 /*****************************************************************************/
       
  2032 
       
  2033 /** Processes the sync monitoring datagram.
       
  2034  *
       
  2035  * \return Zero on success, otherwise a negative error code.
       
  2036  */
       
  2037 static ATTRIBUTES int ec_ioctl_sync_mon_process(
       
  2038         ec_master_t *master, /**< EtherCAT master. */
       
  2039         void *arg, /**< ioctl() argument. */
       
  2040         ec_ioctl_context_t *ctx /**< Private data structure of file handle. */
       
  2041         )
       
  2042 {
       
  2043     uint32_t time_diff;
       
  2044 
       
  2045     if (unlikely(!ctx->requested))
       
  2046         return -EPERM;
       
  2047 
       
  2048     time_diff = ecrt_master_sync_monitor_process(master);
       
  2049 
       
  2050     if (copy_to_user((void __user *) arg, &time_diff, sizeof(time_diff)))
       
  2051         return -EFAULT;
       
  2052 
       
  2053     return 0;
       
  2054 }
       
  2055 
       
  2056 /*****************************************************************************/
       
  2057 
       
  2058 /** Reset configuration.
       
  2059  *
       
  2060  * \return Always zero (success).
       
  2061  */
       
  2062 static ATTRIBUTES int ec_ioctl_reset(
       
  2063         ec_master_t *master, /**< EtherCAT master. */
       
  2064         void *arg, /**< ioctl() argument. */
       
  2065         ec_ioctl_context_t *ctx /**< Private data structure of file handle. */
       
  2066         )
       
  2067 {
       
  2068     down(&master->master_sem);
       
  2069     ecrt_master_reset(master);
       
  2070     up(&master->master_sem);
       
  2071     return 0;
       
  2072 }
       
  2073 
       
  2074 /*****************************************************************************/
       
  2075 
       
  2076 /** Configure a sync manager.
       
  2077  *
       
  2078  * \return Zero on success, otherwise a negative error code.
       
  2079  */
       
  2080 static ATTRIBUTES int ec_ioctl_sc_sync(
       
  2081         ec_master_t *master, /**< EtherCAT master. */
       
  2082         void *arg, /**< ioctl() argument. */
       
  2083         ec_ioctl_context_t *ctx /**< Private data structure of file handle. */
       
  2084         )
       
  2085 {
       
  2086     ec_ioctl_config_t data;
       
  2087     ec_slave_config_t *sc;
       
  2088     unsigned int i;
       
  2089     int ret = 0;
       
  2090 
       
  2091     if (unlikely(!ctx->requested)) {
       
  2092         ret = -EPERM;
       
  2093         goto out_return;
       
  2094     }
       
  2095 
       
  2096     if (copy_from_user(&data, (void __user *) arg, sizeof(data))) {
       
  2097         ret = -EFAULT;
       
  2098         goto out_return;
       
  2099     }
       
  2100 
       
  2101     if (down_interruptible(&master->master_sem)) {
       
  2102         ret = -EINTR;
       
  2103         goto out_return;
       
  2104     }
       
  2105 
       
  2106     if (!(sc = ec_master_get_config(master, data.config_index))) {
       
  2107         ret = -ENOENT;
       
  2108         goto out_up;
       
  2109     }
       
  2110 
       
  2111     for (i = 0; i < EC_MAX_SYNC_MANAGERS; i++) {
       
  2112         if (data.syncs[i].config_this) {
       
  2113             ret = ecrt_slave_config_sync_manager(sc, i, data.syncs[i].dir,
       
  2114                         data.syncs[i].watchdog_mode);
       
  2115             if (ret) {
       
  2116                 goto out_up;
       
  2117             }
       
  2118         }
       
  2119     }
       
  2120 
       
  2121 out_up:
       
  2122     up(&master->master_sem);
       
  2123 out_return:
       
  2124     return ret;
       
  2125 }
       
  2126 
       
  2127 /*****************************************************************************/
       
  2128 
       
  2129 /** Configure a slave's watchdogs.
       
  2130  *
       
  2131  * \return Zero on success, otherwise a negative error code.
       
  2132  */
       
  2133 static ATTRIBUTES int ec_ioctl_sc_watchdog(
       
  2134         ec_master_t *master, /**< EtherCAT master. */
       
  2135         void *arg, /**< ioctl() argument. */
       
  2136         ec_ioctl_context_t *ctx /**< Private data structure of file handle. */
       
  2137         )
       
  2138 {
       
  2139     ec_ioctl_config_t data;
       
  2140     ec_slave_config_t *sc;
       
  2141     int ret = 0;
       
  2142 
       
  2143     if (unlikely(!ctx->requested)) {
       
  2144         ret = -EPERM;
       
  2145         goto out_return;
       
  2146     }
       
  2147 
       
  2148     if (copy_from_user(&data, (void __user *) arg, sizeof(data))) {
       
  2149         ret = -EFAULT;
       
  2150         goto out_return;
       
  2151     }
       
  2152 
       
  2153     if (down_interruptible(&master->master_sem)) {
       
  2154         ret = -EINTR;
       
  2155         goto out_return;
       
  2156     }
       
  2157 
       
  2158     if (!(sc = ec_master_get_config(master, data.config_index))) {
       
  2159         ret = -ENOENT;
       
  2160         goto out_up;
       
  2161     }
       
  2162 
       
  2163     ecrt_slave_config_watchdog(sc,
       
  2164             data.watchdog_divider, data.watchdog_intervals);
       
  2165 
       
  2166 out_up:
       
  2167     up(&master->master_sem);
       
  2168 out_return:
       
  2169     return ret;
       
  2170 }
       
  2171 
       
  2172 /*****************************************************************************/
       
  2173 
       
  2174 /** Add a PDO to the assignment.
       
  2175  *
       
  2176  * \return Zero on success, otherwise a negative error code.
       
  2177  */
       
  2178 static ATTRIBUTES int ec_ioctl_sc_add_pdo(
       
  2179         ec_master_t *master, /**< EtherCAT master. */
       
  2180         void *arg, /**< ioctl() argument. */
       
  2181         ec_ioctl_context_t *ctx /**< Private data structure of file handle. */
       
  2182         )
       
  2183 {
       
  2184     ec_ioctl_config_pdo_t data;
       
  2185     ec_slave_config_t *sc;
       
  2186 
       
  2187     if (unlikely(!ctx->requested))
       
  2188         return -EPERM;
       
  2189 
       
  2190     if (copy_from_user(&data, (void __user *) arg, sizeof(data)))
       
  2191         return -EFAULT;
       
  2192 
       
  2193     if (down_interruptible(&master->master_sem))
       
  2194         return -EINTR;
       
  2195 
       
  2196     if (!(sc = ec_master_get_config(master, data.config_index))) {
       
  2197         up(&master->master_sem);
       
  2198         return -ENOENT;
       
  2199     }
       
  2200 
       
  2201     up(&master->master_sem); /** \todo sc could be invalidated */
       
  2202 
       
  2203     return ecrt_slave_config_pdo_assign_add(sc, data.sync_index, data.index);
       
  2204 }
       
  2205 
       
  2206 /*****************************************************************************/
       
  2207 
       
  2208 /** Clears the PDO assignment.
       
  2209  *
       
  2210  * \return Zero on success, otherwise a negative error code.
       
  2211  */
       
  2212 static ATTRIBUTES int ec_ioctl_sc_clear_pdos(
       
  2213         ec_master_t *master, /**< EtherCAT master. */
       
  2214         void *arg, /**< ioctl() argument. */
       
  2215         ec_ioctl_context_t *ctx /**< Private data structure of file handle. */
       
  2216         )
       
  2217 {
       
  2218     ec_ioctl_config_pdo_t data;
       
  2219     ec_slave_config_t *sc;
       
  2220 
       
  2221     if (unlikely(!ctx->requested))
       
  2222         return -EPERM;
       
  2223 
       
  2224     if (copy_from_user(&data, (void __user *) arg, sizeof(data)))
       
  2225         return -EFAULT;
       
  2226 
       
  2227     if (down_interruptible(&master->master_sem))
       
  2228         return -EINTR;
       
  2229 
       
  2230     if (!(sc = ec_master_get_config(master, data.config_index))) {
       
  2231         up(&master->master_sem);
       
  2232         return -ENOENT;
       
  2233     }
       
  2234 
       
  2235     up(&master->master_sem); /** \todo sc could be invalidated */
       
  2236 
       
  2237     ecrt_slave_config_pdo_assign_clear(sc, data.sync_index);
       
  2238     return 0;
       
  2239 }
       
  2240 
       
  2241 /*****************************************************************************/
       
  2242 
       
  2243 /** Add an entry to a PDO's mapping.
       
  2244  *
       
  2245  * \return Zero on success, otherwise a negative error code.
       
  2246  */
       
  2247 static ATTRIBUTES int ec_ioctl_sc_add_entry(
       
  2248         ec_master_t *master, /**< EtherCAT master. */
       
  2249         void *arg, /**< ioctl() argument. */
       
  2250         ec_ioctl_context_t *ctx /**< Private data structure of file handle. */
       
  2251         )
       
  2252 {
       
  2253     ec_ioctl_add_pdo_entry_t data;
       
  2254     ec_slave_config_t *sc;
       
  2255 
       
  2256     if (unlikely(!ctx->requested))
       
  2257         return -EPERM;
       
  2258 
       
  2259     if (copy_from_user(&data, (void __user *) arg, sizeof(data)))
       
  2260         return -EFAULT;
       
  2261 
       
  2262     if (down_interruptible(&master->master_sem))
       
  2263         return -EINTR;
       
  2264 
       
  2265     if (!(sc = ec_master_get_config(master, data.config_index))) {
       
  2266         up(&master->master_sem);
       
  2267         return -ENOENT;
       
  2268     }
       
  2269 
       
  2270     up(&master->master_sem); /** \todo sc could be invalidated */
       
  2271 
       
  2272     return ecrt_slave_config_pdo_mapping_add(sc, data.pdo_index,
       
  2273             data.entry_index, data.entry_subindex, data.entry_bit_length);
       
  2274 }
       
  2275 
       
  2276 /*****************************************************************************/
       
  2277 
       
  2278 /** Clears the mapping of a PDO.
       
  2279  *
       
  2280  * \return Zero on success, otherwise a negative error code.
       
  2281  */
       
  2282 static ATTRIBUTES int ec_ioctl_sc_clear_entries(
       
  2283         ec_master_t *master, /**< EtherCAT master. */
       
  2284         void *arg, /**< ioctl() argument. */
       
  2285         ec_ioctl_context_t *ctx /**< Private data structure of file handle. */
       
  2286         )
       
  2287 {
       
  2288     ec_ioctl_config_pdo_t data;
       
  2289     ec_slave_config_t *sc;
       
  2290 
       
  2291     if (unlikely(!ctx->requested))
       
  2292         return -EPERM;
       
  2293 
       
  2294     if (copy_from_user(&data, (void __user *) arg, sizeof(data)))
       
  2295         return -EFAULT;
       
  2296 
       
  2297     if (down_interruptible(&master->master_sem))
       
  2298         return -EINTR;
       
  2299 
       
  2300     if (!(sc = ec_master_get_config(master, data.config_index))) {
       
  2301         up(&master->master_sem);
       
  2302         return -ENOENT;
       
  2303     }
       
  2304 
       
  2305     up(&master->master_sem); /** \todo sc could be invalidated */
       
  2306 
       
  2307     ecrt_slave_config_pdo_mapping_clear(sc, data.index);
       
  2308     return 0;
       
  2309 }
       
  2310 
       
  2311 /*****************************************************************************/
       
  2312 
       
  2313 /** Registers a PDO entry.
       
  2314  *
       
  2315  * \return Process data offset on success, otherwise a negative error code.
       
  2316  */
       
  2317 static ATTRIBUTES int ec_ioctl_sc_reg_pdo_entry(
       
  2318         ec_master_t *master, /**< EtherCAT master. */
       
  2319         void *arg, /**< ioctl() argument. */
       
  2320         ec_ioctl_context_t *ctx /**< Private data structure of file handle. */
       
  2321         )
       
  2322 {
       
  2323     ec_ioctl_reg_pdo_entry_t data;
       
  2324     ec_slave_config_t *sc;
       
  2325     ec_domain_t *domain;
       
  2326     int ret;
       
  2327 
       
  2328     if (unlikely(!ctx->requested))
       
  2329         return -EPERM;
       
  2330 
       
  2331     if (copy_from_user(&data, (void __user *) arg, sizeof(data)))
       
  2332         return -EFAULT;
       
  2333 
       
  2334     if (down_interruptible(&master->master_sem))
       
  2335         return -EINTR;
       
  2336 
       
  2337     if (!(sc = ec_master_get_config(master, data.config_index))) {
       
  2338         up(&master->master_sem);
       
  2339         return -ENOENT;
       
  2340     }
       
  2341 
       
  2342     if (!(domain = ec_master_find_domain(master, data.domain_index))) {
       
  2343         up(&master->master_sem);
       
  2344         return -ENOENT;
       
  2345     }
       
  2346 
       
  2347     up(&master->master_sem); /** \todo sc or domain could be invalidated */
       
  2348 
       
  2349     ret = ecrt_slave_config_reg_pdo_entry(sc, data.entry_index,
       
  2350             data.entry_subindex, domain, &data.bit_position);
       
  2351 
       
  2352     if (copy_to_user((void __user *) arg, &data, sizeof(data)))
       
  2353         return -EFAULT;
       
  2354 
       
  2355     return ret;
       
  2356 }
       
  2357 
       
  2358 /*****************************************************************************/
       
  2359 
       
  2360 /** Registers a PDO entry by its position.
       
  2361  *
       
  2362  * \return Process data offset on success, otherwise a negative error code.
       
  2363  */
       
  2364 static ATTRIBUTES int ec_ioctl_sc_reg_pdo_pos(
       
  2365         ec_master_t *master, /**< EtherCAT master. */
       
  2366         void *arg, /**< ioctl() argument. */
       
  2367         ec_ioctl_context_t *ctx /**< Private data structure of file handle. */
       
  2368         )
       
  2369 {
       
  2370     ec_ioctl_reg_pdo_pos_t io;
       
  2371     ec_slave_config_t *sc;
       
  2372     ec_domain_t *domain;
       
  2373     int ret;
       
  2374 
       
  2375     if (unlikely(!ctx->requested)) {
       
  2376         return -EPERM;
       
  2377     }
       
  2378 
       
  2379     if (copy_from_user(&io, (void __user *) arg, sizeof(io))) {
       
  2380         return -EFAULT;
       
  2381     }
       
  2382 
       
  2383     if (down_interruptible(&master->master_sem)) {
       
  2384         return -EINTR;
       
  2385     }
       
  2386 
       
  2387     if (!(sc = ec_master_get_config(master, io.config_index))) {
       
  2388         up(&master->master_sem);
       
  2389         return -ENOENT;
       
  2390     }
       
  2391 
       
  2392     if (!(domain = ec_master_find_domain(master, io.domain_index))) {
       
  2393         up(&master->master_sem);
       
  2394         return -ENOENT;
       
  2395     }
       
  2396 
       
  2397     up(&master->master_sem); /** \todo sc or domain could be invalidated */
       
  2398 
       
  2399     ret = ecrt_slave_config_reg_pdo_entry_pos(sc, io.sync_index,
       
  2400             io.pdo_pos, io.entry_pos, domain, &io.bit_position);
       
  2401 
       
  2402     if (copy_to_user((void __user *) arg, &io, sizeof(io)))
       
  2403         return -EFAULT;
       
  2404 
       
  2405     return ret;
       
  2406 }
       
  2407 
       
  2408 /*****************************************************************************/
       
  2409 
       
  2410 /** Sets the DC AssignActivate word and the sync signal times.
       
  2411  *
       
  2412  * \return Zero on success, otherwise a negative error code.
       
  2413  */
       
  2414 static ATTRIBUTES int ec_ioctl_sc_dc(
       
  2415         ec_master_t *master, /**< EtherCAT master. */
       
  2416         void *arg, /**< ioctl() argument. */
       
  2417         ec_ioctl_context_t *ctx /**< Private data structure of file handle. */
       
  2418         )
       
  2419 {
       
  2420     ec_ioctl_config_t data;
       
  2421     ec_slave_config_t *sc;
       
  2422 
       
  2423     if (unlikely(!ctx->requested))
       
  2424         return -EPERM;
       
  2425 
       
  2426     if (copy_from_user(&data, (void __user *) arg, sizeof(data)))
       
  2427         return -EFAULT;
       
  2428 
       
  2429     if (down_interruptible(&master->master_sem))
       
  2430         return -EINTR;
       
  2431 
       
  2432     if (!(sc = ec_master_get_config(master, data.config_index))) {
       
  2433         up(&master->master_sem);
       
  2434         return -ENOENT;
       
  2435     }
       
  2436 
       
  2437     ecrt_slave_config_dc(sc, data.dc_assign_activate,
       
  2438             data.dc_sync[0].cycle_time,
       
  2439             data.dc_sync[0].shift_time,
       
  2440             data.dc_sync[1].cycle_time,
       
  2441             data.dc_sync[1].shift_time);
       
  2442 
       
  2443     up(&master->master_sem);
       
  2444 
       
  2445     return 0;
       
  2446 }
       
  2447 
       
  2448 /*****************************************************************************/
       
  2449 
       
  2450 /** Configures an SDO.
       
  2451  *
       
  2452  * \return Zero on success, otherwise a negative error code.
       
  2453  */
       
  2454 static ATTRIBUTES int ec_ioctl_sc_sdo(
       
  2455         ec_master_t *master, /**< EtherCAT master. */
       
  2456         void *arg, /**< ioctl() argument. */
       
  2457         ec_ioctl_context_t *ctx /**< Private data structure of file handle. */
       
  2458         )
       
  2459 {
       
  2460     ec_ioctl_sc_sdo_t data;
       
  2461     ec_slave_config_t *sc;
       
  2462     uint8_t *sdo_data = NULL;
       
  2463     int ret;
       
  2464 
       
  2465     if (unlikely(!ctx->requested))
       
  2466         return -EPERM;
       
  2467 
       
  2468     if (copy_from_user(&data, (void __user *) arg, sizeof(data)))
       
  2469         return -EFAULT;
       
  2470 
       
  2471     if (!data.size)
       
  2472         return -EINVAL;
       
  2473 
       
  2474     if (!(sdo_data = kmalloc(data.size, GFP_KERNEL))) {
       
  2475         return -ENOMEM;
       
  2476     }
       
  2477 
       
  2478     if (copy_from_user(sdo_data, (void __user *) data.data, data.size)) {
       
  2479         kfree(sdo_data);
       
  2480         return -EFAULT;
       
  2481     }
       
  2482 
       
  2483     if (down_interruptible(&master->master_sem)) {
       
  2484         kfree(sdo_data);
       
  2485         return -EINTR;
       
  2486     }
       
  2487 
       
  2488     if (!(sc = ec_master_get_config(master, data.config_index))) {
       
  2489         up(&master->master_sem);
       
  2490         kfree(sdo_data);
       
  2491         return -ENOENT;
       
  2492     }
       
  2493 
       
  2494     up(&master->master_sem); /** \todo sc could be invalidated */
       
  2495 
       
  2496     if (data.complete_access) {
       
  2497         ret = ecrt_slave_config_complete_sdo(sc,
       
  2498                 data.index, sdo_data, data.size);
       
  2499     } else {
       
  2500         ret = ecrt_slave_config_sdo(sc, data.index, data.subindex, sdo_data,
       
  2501                 data.size);
       
  2502     }
       
  2503     kfree(sdo_data);
       
  2504     return ret;
       
  2505 }
       
  2506 
       
  2507 /*****************************************************************************/
       
  2508 
       
  2509 /** Set the emergency ring buffer size.
       
  2510  *
       
  2511  * \return Zero on success, otherwise a negative error code.
       
  2512  */
       
  2513 static ATTRIBUTES int ec_ioctl_sc_emerg_size(
       
  2514         ec_master_t *master, /**< EtherCAT master. */
       
  2515         void *arg, /**< ioctl() argument. */
       
  2516         ec_ioctl_context_t *ctx /**< Private data structure of file handle. */
       
  2517         )
       
  2518 {
       
  2519     ec_ioctl_sc_emerg_t io;
       
  2520     ec_slave_config_t *sc;
       
  2521     int ret;
       
  2522 
       
  2523     if (unlikely(!ctx->requested))
       
  2524         return -EPERM;
       
  2525 
       
  2526     if (copy_from_user(&io, (void __user *) arg, sizeof(io)))
       
  2527         return -EFAULT;
       
  2528 
       
  2529     if (down_interruptible(&master->master_sem)) {
       
  2530         return -EINTR;
       
  2531     }
       
  2532 
       
  2533     if (!(sc = ec_master_get_config(master, io.config_index))) {
       
  2534         up(&master->master_sem);
       
  2535         return -ENOENT;
       
  2536     }
       
  2537 
       
  2538     ret = ecrt_slave_config_emerg_size(sc, io.size);
       
  2539 
       
  2540     up(&master->master_sem);
       
  2541 
       
  2542     return ret;
       
  2543 }
       
  2544 
       
  2545 /*****************************************************************************/
       
  2546 
       
  2547 /** Get an emergency message from the ring.
       
  2548  *
       
  2549  * \return Zero on success, otherwise a negative error code.
       
  2550  */
       
  2551 static ATTRIBUTES int ec_ioctl_sc_emerg_pop(
       
  2552         ec_master_t *master, /**< EtherCAT master. */
       
  2553         void *arg, /**< ioctl() argument. */
       
  2554         ec_ioctl_context_t *ctx /**< Private data structure of file handle. */
       
  2555         )
       
  2556 {
       
  2557     ec_ioctl_sc_emerg_t io;
       
  2558     ec_slave_config_t *sc;
       
  2559     u8 msg[EC_COE_EMERGENCY_MSG_SIZE];
       
  2560     int ret;
       
  2561 
       
  2562     if (unlikely(!ctx->requested)) {
       
  2563         return -EPERM;
       
  2564     }
       
  2565 
       
  2566     if (copy_from_user(&io, (void __user *) arg, sizeof(io))) {
       
  2567         return -EFAULT;
       
  2568     }
       
  2569 
       
  2570     /* no locking of master_sem needed, because configuration will not be
       
  2571      * deleted in the meantime. */
       
  2572 
       
  2573     if (!(sc = ec_master_get_config(master, io.config_index))) {
       
  2574         return -ENOENT;
       
  2575     }
       
  2576 
       
  2577     ret = ecrt_slave_config_emerg_pop(sc, msg);
       
  2578     if (ret < 0) {
       
  2579         return ret;
       
  2580     }
       
  2581 
       
  2582     if (copy_to_user((void __user *) io.target, msg, sizeof(msg))) {
       
  2583         return -EFAULT;
       
  2584     }
       
  2585 
       
  2586     return ret;
       
  2587 }
       
  2588 
       
  2589 /*****************************************************************************/
       
  2590 
       
  2591 /** Clear the emergency ring.
       
  2592  *
       
  2593  * \return Zero on success, otherwise a negative error code.
       
  2594  */
       
  2595 static ATTRIBUTES int ec_ioctl_sc_emerg_clear(
       
  2596         ec_master_t *master, /**< EtherCAT master. */
       
  2597         void *arg, /**< ioctl() argument. */
       
  2598         ec_ioctl_context_t *ctx /**< Private data structure of file handle. */
       
  2599         )
       
  2600 {
       
  2601     ec_ioctl_sc_emerg_t io;
       
  2602     ec_slave_config_t *sc;
       
  2603 
       
  2604     if (unlikely(!ctx->requested)) {
       
  2605         return -EPERM;
       
  2606     }
       
  2607 
       
  2608     if (copy_from_user(&io, (void __user *) arg, sizeof(io))) {
       
  2609         return -EFAULT;
       
  2610     }
       
  2611 
       
  2612     /* no locking of master_sem needed, because configuration will not be
       
  2613      * deleted in the meantime. */
       
  2614 
       
  2615     if (!(sc = ec_master_get_config(master, io.config_index))) {
       
  2616         return -ENOENT;
       
  2617     }
       
  2618 
       
  2619     return ecrt_slave_config_emerg_clear(sc);
       
  2620 }
       
  2621 
       
  2622 /*****************************************************************************/
       
  2623 
       
  2624 /** Get the number of emergency overruns.
       
  2625  *
       
  2626  * \return Zero on success, otherwise a negative error code.
       
  2627  */
       
  2628 static ATTRIBUTES int ec_ioctl_sc_emerg_overruns(
       
  2629         ec_master_t *master, /**< EtherCAT master. */
       
  2630         void *arg, /**< ioctl() argument. */
       
  2631         ec_ioctl_context_t *ctx /**< Private data structure of file handle. */
       
  2632         )
       
  2633 {
       
  2634     ec_ioctl_sc_emerg_t io;
       
  2635     ec_slave_config_t *sc;
       
  2636     int ret;
       
  2637 
       
  2638     if (unlikely(!ctx->requested)) {
       
  2639         return -EPERM;
       
  2640     }
       
  2641 
       
  2642     if (copy_from_user(&io, (void __user *) arg, sizeof(io))) {
       
  2643         return -EFAULT;
       
  2644     }
       
  2645 
       
  2646     /* no locking of master_sem needed, because configuration will not be
       
  2647      * deleted in the meantime. */
       
  2648 
       
  2649     if (!(sc = ec_master_get_config(master, io.config_index))) {
       
  2650         return -ENOENT;
       
  2651     }
       
  2652 
       
  2653     ret = ecrt_slave_config_emerg_overruns(sc);
       
  2654     if (ret < 0) {
       
  2655         return ret;
       
  2656     }
       
  2657 
       
  2658     io.overruns = ret;
       
  2659 
       
  2660     if (copy_to_user((void __user *) arg, &io, sizeof(io))) {
       
  2661         return -EFAULT;
       
  2662     }
       
  2663 
       
  2664     return 0;
       
  2665 }
       
  2666 
       
  2667 /*****************************************************************************/
       
  2668 
       
  2669 /** Create an SDO request.
       
  2670  *
       
  2671  * \return Zero on success, otherwise a negative error code.
       
  2672  */
       
  2673 static ATTRIBUTES int ec_ioctl_sc_create_sdo_request(
       
  2674         ec_master_t *master, /**< EtherCAT master. */
       
  2675         void *arg, /**< ioctl() argument. */
       
  2676         ec_ioctl_context_t *ctx /**< Private data structure of file handle. */
       
  2677         )
       
  2678 {
       
  2679     ec_ioctl_sdo_request_t data;
       
  2680     ec_slave_config_t *sc;
       
  2681     ec_sdo_request_t *req;
       
  2682 
       
  2683     if (unlikely(!ctx->requested))
       
  2684         return -EPERM;
       
  2685 
       
  2686     if (copy_from_user(&data, (void __user *) arg, sizeof(data))) {
       
  2687         return -EFAULT;
       
  2688     }
       
  2689 
       
  2690     data.request_index = 0;
       
  2691 
       
  2692     if (down_interruptible(&master->master_sem))
       
  2693         return -EINTR;
       
  2694 
       
  2695     sc = ec_master_get_config(master, data.config_index);
       
  2696     if (!sc) {
       
  2697         up(&master->master_sem);
       
  2698         return -ENOENT;
       
  2699     }
       
  2700 
       
  2701     list_for_each_entry(req, &sc->sdo_requests, list) {
       
  2702         data.request_index++;
       
  2703     }
       
  2704 
       
  2705     up(&master->master_sem); /** \todo sc could be invalidated */
       
  2706 
       
  2707     req = ecrt_slave_config_create_sdo_request_err(sc, data.sdo_index,
       
  2708             data.sdo_subindex, data.size);
       
  2709     if (IS_ERR(req))
       
  2710         return PTR_ERR(req);
       
  2711 
       
  2712     if (copy_to_user((void __user *) arg, &data, sizeof(data)))
       
  2713         return -EFAULT;
       
  2714 
       
  2715     return 0;
       
  2716 }
       
  2717 
       
  2718 /*****************************************************************************/
       
  2719 
       
  2720 /** Create a register request.
       
  2721  *
       
  2722  * \return Zero on success, otherwise a negative error code.
       
  2723  */
       
  2724 static ATTRIBUTES int ec_ioctl_sc_create_reg_request(
       
  2725         ec_master_t *master, /**< EtherCAT master. */
       
  2726         void *arg, /**< ioctl() argument. */
       
  2727         ec_ioctl_context_t *ctx /**< Private data structure of file handle. */
       
  2728         )
       
  2729 {
       
  2730     ec_ioctl_reg_request_t io;
       
  2731     ec_slave_config_t *sc;
       
  2732     ec_reg_request_t *reg;
       
  2733 
       
  2734     if (unlikely(!ctx->requested)) {
       
  2735         return -EPERM;
       
  2736     }
       
  2737 
       
  2738     if (copy_from_user(&io, (void __user *) arg, sizeof(io))) {
       
  2739         return -EFAULT;
       
  2740     }
       
  2741 
       
  2742     io.request_index = 0;
       
  2743 
       
  2744     if (down_interruptible(&master->master_sem)) {
       
  2745         return -EINTR;
       
  2746     }
       
  2747 
       
  2748     sc = ec_master_get_config(master, io.config_index);
       
  2749     if (!sc) {
       
  2750         up(&master->master_sem);
       
  2751         return -ENOENT;
       
  2752     }
       
  2753 
       
  2754     list_for_each_entry(reg, &sc->reg_requests, list) {
       
  2755         io.request_index++;
       
  2756     }
       
  2757 
       
  2758     up(&master->master_sem); /** \todo sc could be invalidated */
       
  2759 
       
  2760     reg = ecrt_slave_config_create_reg_request_err(sc, io.mem_size);
       
  2761     if (IS_ERR(reg)) {
       
  2762         return PTR_ERR(reg);
       
  2763     }
       
  2764 
       
  2765     if (copy_to_user((void __user *) arg, &io, sizeof(io))) {
       
  2766         return -EFAULT;
       
  2767     }
       
  2768 
       
  2769     return 0;
       
  2770 }
       
  2771 
       
  2772 /*****************************************************************************/
       
  2773 
       
  2774 /** Create a VoE handler.
       
  2775  *
       
  2776  * \return Zero on success, otherwise a negative error code.
       
  2777  */
       
  2778 static ATTRIBUTES int ec_ioctl_sc_create_voe_handler(
       
  2779         ec_master_t *master, /**< EtherCAT master. */
       
  2780         void *arg, /**< ioctl() argument. */
       
  2781         ec_ioctl_context_t *ctx /**< Private data structure of file handle. */
       
  2782         )
       
  2783 {
       
  2784     ec_ioctl_voe_t data;
       
  2785     ec_slave_config_t *sc;
       
  2786     ec_voe_handler_t *voe;
       
  2787 
       
  2788     if (unlikely(!ctx->requested))
       
  2789         return -EPERM;
       
  2790 
       
  2791     if (copy_from_user(&data, (void __user *) arg, sizeof(data))) {
       
  2792         return -EFAULT;
       
  2793     }
       
  2794 
       
  2795     data.voe_index = 0;
       
  2796 
       
  2797     if (down_interruptible(&master->master_sem))
       
  2798         return -EINTR;
       
  2799 
       
  2800     sc = ec_master_get_config(master, data.config_index);
       
  2801     if (!sc) {
       
  2802         up(&master->master_sem);
       
  2803         return -ENOENT;
       
  2804     }
       
  2805 
       
  2806     list_for_each_entry(voe, &sc->voe_handlers, list) {
       
  2807         data.voe_index++;
       
  2808     }
       
  2809 
       
  2810     up(&master->master_sem); /** \todo sc could be invalidated */
       
  2811 
       
  2812     voe = ecrt_slave_config_create_voe_handler_err(sc, data.size);
       
  2813     if (IS_ERR(voe))
       
  2814         return PTR_ERR(voe);
       
  2815 
       
  2816     if (copy_to_user((void __user *) arg, &data, sizeof(data)))
       
  2817         return -EFAULT;
       
  2818 
       
  2819     return 0;
       
  2820 }
       
  2821 
       
  2822 /*****************************************************************************/
       
  2823 
       
  2824 /** Get the slave configuration's state.
       
  2825  *
       
  2826  * \return Zero on success, otherwise a negative error code.
       
  2827  */
       
  2828 static ATTRIBUTES int ec_ioctl_sc_state(
       
  2829         ec_master_t *master, /**< EtherCAT master. */
       
  2830         void *arg, /**< ioctl() argument. */
       
  2831         ec_ioctl_context_t *ctx /**< Private data structure of file handle. */
       
  2832         )
       
  2833 {
       
  2834     ec_ioctl_sc_state_t data;
       
  2835     const ec_slave_config_t *sc;
       
  2836     ec_slave_config_state_t state;
       
  2837 
       
  2838     if (unlikely(!ctx->requested))
       
  2839         return -EPERM;
       
  2840 
       
  2841     if (copy_from_user(&data, (void __user *) arg, sizeof(data))) {
       
  2842         return -EFAULT;
       
  2843     }
       
  2844 
       
  2845     /* no locking of master_sem needed, because sc will not be deleted in the
       
  2846      * meantime. */
       
  2847 
       
  2848     if (!(sc = ec_master_get_config_const(master, data.config_index))) {
       
  2849         return -ENOENT;
       
  2850     }
       
  2851 
       
  2852     ecrt_slave_config_state(sc, &state);
       
  2853 
       
  2854     if (copy_to_user((void __user *) data.state, &state, sizeof(state)))
       
  2855         return -EFAULT;
       
  2856 
       
  2857     return 0;
       
  2858 }
       
  2859 
       
  2860 /*****************************************************************************/
       
  2861 
       
  2862 /** Configures an IDN.
       
  2863  *
       
  2864  * \return Zero on success, otherwise a negative error code.
       
  2865  */
       
  2866 static ATTRIBUTES int ec_ioctl_sc_idn(
       
  2867         ec_master_t *master, /**< EtherCAT master. */
       
  2868         void *arg, /**< ioctl() argument. */
       
  2869         ec_ioctl_context_t *ctx /**< Private data structure of file handle. */
       
  2870         )
       
  2871 {
       
  2872     ec_ioctl_sc_idn_t ioctl;
       
  2873     ec_slave_config_t *sc;
       
  2874     uint8_t *data = NULL;
       
  2875     int ret;
       
  2876 
       
  2877     if (unlikely(!ctx->requested))
       
  2878         return -EPERM;
       
  2879 
       
  2880     if (copy_from_user(&ioctl, (void __user *) arg, sizeof(ioctl)))
       
  2881         return -EFAULT;
       
  2882 
       
  2883     if (!ioctl.size)
       
  2884         return -EINVAL;
       
  2885 
       
  2886     if (!(data = kmalloc(ioctl.size, GFP_KERNEL))) {
       
  2887         return -ENOMEM;
       
  2888     }
       
  2889 
       
  2890     if (copy_from_user(data, (void __user *) ioctl.data, ioctl.size)) {
       
  2891         kfree(data);
       
  2892         return -EFAULT;
       
  2893     }
       
  2894 
       
  2895     if (down_interruptible(&master->master_sem)) {
       
  2896         kfree(data);
       
  2897         return -EINTR;
       
  2898     }
       
  2899 
       
  2900     if (!(sc = ec_master_get_config(master, ioctl.config_index))) {
       
  2901         up(&master->master_sem);
       
  2902         kfree(data);
       
  2903         return -ENOENT;
       
  2904     }
       
  2905 
       
  2906     up(&master->master_sem); /** \todo sc could be invalidated */
       
  2907 
       
  2908     ret = ecrt_slave_config_idn(
       
  2909             sc, ioctl.drive_no, ioctl.idn, ioctl.al_state, data, ioctl.size);
       
  2910     kfree(data);
       
  2911     return ret;
       
  2912 }
       
  2913 
       
  2914 /*****************************************************************************/
       
  2915 
       
  2916 /** Gets the domain's data size.
       
  2917  *
       
  2918  * \return Domain size, or a negative error code.
       
  2919  */
       
  2920 static ATTRIBUTES int ec_ioctl_domain_size(
       
  2921         ec_master_t *master, /**< EtherCAT master. */
       
  2922         void *arg, /**< ioctl() argument. */
       
  2923         ec_ioctl_context_t *ctx /**< Private data structure of file handle. */
       
  2924         )
       
  2925 {
       
  2926     const ec_domain_t *domain;
       
  2927 
       
  2928     if (unlikely(!ctx->requested)) {
       
  2929         return -EPERM;
       
  2930     }
       
  2931 
       
  2932     if (down_interruptible(&master->master_sem)) {
       
  2933         return -EINTR;
       
  2934     }
       
  2935 
       
  2936     list_for_each_entry(domain, &master->domains, list) {
       
  2937         if (domain->index == (unsigned long) arg) {
       
  2938             size_t size = ecrt_domain_size(domain);
       
  2939             up(&master->master_sem);
       
  2940             return size;
       
  2941         }
       
  2942     }
       
  2943 
       
  2944     up(&master->master_sem);
       
  2945     return -ENOENT;
       
  2946 }
       
  2947 
       
  2948 /*****************************************************************************/
       
  2949 
       
  2950 /** Gets the domain's offset in the total process data.
       
  2951  *
       
  2952  * \return Domain offset, or a negative error code.
       
  2953  */
       
  2954 static ATTRIBUTES int ec_ioctl_domain_offset(
       
  2955         ec_master_t *master, /**< EtherCAT master. */
       
  2956         void *arg, /**< ioctl() argument. */
       
  2957         ec_ioctl_context_t *ctx /**< Private data structure of file handle. */
       
  2958         )
       
  2959 {
       
  2960     int offset = 0;
       
  2961     const ec_domain_t *domain;
       
  2962 
       
  2963     if (unlikely(!ctx->requested))
       
  2964         return -EPERM;
       
  2965 
       
  2966     if (down_interruptible(&master->master_sem)) {
       
  2967         return -EINTR;
       
  2968     }
       
  2969 
       
  2970     list_for_each_entry(domain, &master->domains, list) {
       
  2971         if (domain->index == (unsigned long) arg) {
       
  2972             up(&master->master_sem);
       
  2973             return offset;
       
  2974         }
       
  2975         offset += ecrt_domain_size(domain);
       
  2976     }
       
  2977 
       
  2978     up(&master->master_sem);
       
  2979     return -ENOENT;
       
  2980 }
       
  2981 
       
  2982 /*****************************************************************************/
       
  2983 
       
  2984 /** Process the domain.
       
  2985  *
       
  2986  * \return Zero on success, otherwise a negative error code.
       
  2987  */
       
  2988 static ATTRIBUTES int ec_ioctl_domain_process(
       
  2989         ec_master_t *master, /**< EtherCAT master. */
       
  2990         void *arg, /**< ioctl() argument. */
       
  2991         ec_ioctl_context_t *ctx /**< Private data structure of file handle. */
       
  2992         )
       
  2993 {
       
  2994     ec_domain_t *domain;
       
  2995 
       
  2996     if (unlikely(!ctx->requested))
       
  2997         return -EPERM;
       
  2998 
       
  2999     /* no locking of master_sem needed, because domain will not be deleted in
       
  3000      * the meantime. */
       
  3001 
       
  3002     if (!(domain = ec_master_find_domain(master, (unsigned long) arg))) {
       
  3003         return -ENOENT;
       
  3004     }
       
  3005 
       
  3006     ecrt_domain_process(domain);
       
  3007     return 0;
       
  3008 }
       
  3009 
       
  3010 /*****************************************************************************/
       
  3011 
       
  3012 /** Queue the domain.
       
  3013  *
       
  3014  * \return Zero on success, otherwise a negative error code.
       
  3015  */
       
  3016 static ATTRIBUTES int ec_ioctl_domain_queue(
       
  3017         ec_master_t *master, /**< EtherCAT master. */
       
  3018         void *arg, /**< ioctl() argument. */
       
  3019         ec_ioctl_context_t *ctx /**< Private data structure of file handle. */
       
  3020         )
       
  3021 {
       
  3022     ec_domain_t *domain;
       
  3023 
       
  3024     if (unlikely(!ctx->requested))
       
  3025         return -EPERM;
       
  3026 
       
  3027     /* no locking of master_sem needed, because domain will not be deleted in
       
  3028      * the meantime. */
       
  3029 
       
  3030     if (!(domain = ec_master_find_domain(master, (unsigned long) arg))) {
       
  3031         return -ENOENT;
       
  3032     }
       
  3033 
       
  3034     ecrt_domain_queue(domain);
       
  3035     return 0;
       
  3036 }
       
  3037 
       
  3038 /*****************************************************************************/
       
  3039 
       
  3040 /** Get the domain state.
       
  3041  *
       
  3042  * \return Zero on success, otherwise a negative error code.
       
  3043  */
       
  3044 static ATTRIBUTES int ec_ioctl_domain_state(
       
  3045         ec_master_t *master, /**< EtherCAT master. */
       
  3046         void *arg, /**< ioctl() argument. */
       
  3047         ec_ioctl_context_t *ctx /**< Private data structure of file handle. */
       
  3048         )
       
  3049 {
       
  3050     ec_ioctl_domain_state_t data;
       
  3051     const ec_domain_t *domain;
       
  3052     ec_domain_state_t state;
       
  3053 
       
  3054     if (unlikely(!ctx->requested))
       
  3055         return -EPERM;
       
  3056 
       
  3057     if (copy_from_user(&data, (void __user *) arg, sizeof(data))) {
       
  3058         return -EFAULT;
       
  3059     }
       
  3060 
       
  3061     /* no locking of master_sem needed, because domain will not be deleted in
       
  3062      * the meantime. */
       
  3063 
       
  3064     if (!(domain = ec_master_find_domain_const(master, data.domain_index))) {
       
  3065         return -ENOENT;
       
  3066     }
       
  3067 
       
  3068     ecrt_domain_state(domain, &state);
       
  3069 
       
  3070     if (copy_to_user((void __user *) data.state, &state, sizeof(state)))
       
  3071         return -EFAULT;
       
  3072 
       
  3073     return 0;
       
  3074 }
       
  3075 
       
  3076 /*****************************************************************************/
       
  3077 
       
  3078 /** Sets an SDO request's SDO index and subindex.
       
  3079  *
       
  3080  * \return Zero on success, otherwise a negative error code.
       
  3081  */
       
  3082 static ATTRIBUTES int ec_ioctl_sdo_request_index(
       
  3083         ec_master_t *master, /**< EtherCAT master. */
       
  3084         void *arg, /**< ioctl() argument. */
       
  3085         ec_ioctl_context_t *ctx /**< Private data structure of file handle. */
       
  3086         )
       
  3087 {
       
  3088     ec_ioctl_sdo_request_t data;
       
  3089     ec_slave_config_t *sc;
       
  3090     ec_sdo_request_t *req;
       
  3091 
       
  3092     if (unlikely(!ctx->requested))
       
  3093         return -EPERM;
       
  3094 
       
  3095     if (copy_from_user(&data, (void __user *) arg, sizeof(data)))
       
  3096         return -EFAULT;
       
  3097 
       
  3098     /* no locking of master_sem needed, because neither sc nor req will not be
       
  3099      * deleted in the meantime. */
       
  3100 
       
  3101     if (!(sc = ec_master_get_config(master, data.config_index))) {
       
  3102         return -ENOENT;
       
  3103     }
       
  3104 
       
  3105     if (!(req = ec_slave_config_find_sdo_request(sc, data.request_index))) {
       
  3106         return -ENOENT;
       
  3107     }
       
  3108 
       
  3109     ecrt_sdo_request_index(req, data.sdo_index, data.sdo_subindex);
       
  3110     return 0;
       
  3111 }
       
  3112 
       
  3113 /*****************************************************************************/
       
  3114 
       
  3115 /** Sets an SDO request's timeout.
       
  3116  *
       
  3117  * \return Zero on success, otherwise a negative error code.
       
  3118  */
       
  3119 static ATTRIBUTES int ec_ioctl_sdo_request_timeout(
       
  3120         ec_master_t *master, /**< EtherCAT master. */
       
  3121         void *arg, /**< ioctl() argument. */
       
  3122         ec_ioctl_context_t *ctx /**< Private data structure of file handle. */
       
  3123         )
       
  3124 {
       
  3125     ec_ioctl_sdo_request_t data;
       
  3126     ec_slave_config_t *sc;
       
  3127     ec_sdo_request_t *req;
       
  3128 
       
  3129     if (unlikely(!ctx->requested))
       
  3130         return -EPERM;
       
  3131 
       
  3132     if (copy_from_user(&data, (void __user *) arg, sizeof(data)))
       
  3133         return -EFAULT;
       
  3134 
       
  3135     /* no locking of master_sem needed, because neither sc nor req will not be
       
  3136      * deleted in the meantime. */
       
  3137 
       
  3138     if (!(sc = ec_master_get_config(master, data.config_index))) {
       
  3139         return -ENOENT;
       
  3140     }
       
  3141 
       
  3142     if (!(req = ec_slave_config_find_sdo_request(sc, data.request_index))) {
       
  3143         return -ENOENT;
       
  3144     }
       
  3145 
       
  3146     ecrt_sdo_request_timeout(req, data.timeout);
       
  3147     return 0;
       
  3148 }
       
  3149 
       
  3150 /*****************************************************************************/
       
  3151 
       
  3152 /** Gets an SDO request's state.
       
  3153  *
       
  3154  * \return Zero on success, otherwise a negative error code.
       
  3155  */
       
  3156 static ATTRIBUTES int ec_ioctl_sdo_request_state(
       
  3157         ec_master_t *master, /**< EtherCAT master. */
       
  3158         void *arg, /**< ioctl() argument. */
       
  3159         ec_ioctl_context_t *ctx /**< Private data structure of file handle. */
       
  3160         )
       
  3161 {
       
  3162     ec_ioctl_sdo_request_t data;
       
  3163     ec_slave_config_t *sc;
       
  3164     ec_sdo_request_t *req;
       
  3165 
       
  3166     if (unlikely(!ctx->requested))
       
  3167         return -EPERM;
       
  3168 
       
  3169     if (copy_from_user(&data, (void __user *) arg, sizeof(data)))
       
  3170         return -EFAULT;
       
  3171 
       
  3172     /* no locking of master_sem needed, because neither sc nor req will not be
       
  3173      * deleted in the meantime. */
       
  3174 
       
  3175     if (!(sc = ec_master_get_config(master, data.config_index))) {
       
  3176         return -ENOENT;
       
  3177     }
       
  3178 
       
  3179     if (!(req = ec_slave_config_find_sdo_request(sc, data.request_index))) {
       
  3180         return -ENOENT;
       
  3181     }
       
  3182 
       
  3183     data.state = ecrt_sdo_request_state(req);
       
  3184     if (data.state == EC_REQUEST_SUCCESS && req->dir == EC_DIR_INPUT)
       
  3185         data.size = ecrt_sdo_request_data_size(req);
       
  3186     else
       
  3187         data.size = 0;
       
  3188 
       
  3189     if (copy_to_user((void __user *) arg, &data, sizeof(data)))
       
  3190         return -EFAULT;
       
  3191 
       
  3192     return 0;
       
  3193 }
       
  3194 
       
  3195 /*****************************************************************************/
       
  3196 
       
  3197 /** Starts an SDO read operation.
       
  3198  *
       
  3199  * \return Zero on success, otherwise a negative error code.
       
  3200  */
       
  3201 static ATTRIBUTES int ec_ioctl_sdo_request_read(
       
  3202         ec_master_t *master, /**< EtherCAT master. */
       
  3203         void *arg, /**< ioctl() argument. */
       
  3204         ec_ioctl_context_t *ctx /**< Private data structure of file handle. */
       
  3205         )
       
  3206 {
       
  3207     ec_ioctl_sdo_request_t data;
       
  3208     ec_slave_config_t *sc;
       
  3209     ec_sdo_request_t *req;
       
  3210 
       
  3211     if (unlikely(!ctx->requested))
       
  3212         return -EPERM;
       
  3213 
       
  3214     if (copy_from_user(&data, (void __user *) arg, sizeof(data)))
       
  3215         return -EFAULT;
       
  3216 
       
  3217     /* no locking of master_sem needed, because neither sc nor req will not be
       
  3218      * deleted in the meantime. */
       
  3219 
       
  3220     if (!(sc = ec_master_get_config(master, data.config_index))) {
       
  3221         return -ENOENT;
       
  3222     }
       
  3223 
       
  3224     if (!(req = ec_slave_config_find_sdo_request(sc, data.request_index))) {
       
  3225         return -ENOENT;
       
  3226     }
       
  3227 
       
  3228     ecrt_sdo_request_read(req);
       
  3229     return 0;
       
  3230 }
       
  3231 
       
  3232 /*****************************************************************************/
       
  3233 
       
  3234 /** Starts an SDO write operation.
       
  3235  *
       
  3236  * \return Zero on success, otherwise a negative error code.
       
  3237  */
       
  3238 static ATTRIBUTES int ec_ioctl_sdo_request_write(
       
  3239         ec_master_t *master, /**< EtherCAT master. */
       
  3240         void *arg, /**< ioctl() argument. */
       
  3241         ec_ioctl_context_t *ctx /**< Private data structure of file handle. */
       
  3242         )
       
  3243 {
       
  3244     ec_ioctl_sdo_request_t data;
       
  3245     ec_slave_config_t *sc;
       
  3246     ec_sdo_request_t *req;
       
  3247     int ret;
       
  3248 
       
  3249     if (unlikely(!ctx->requested))
       
  3250         return -EPERM;
       
  3251 
       
  3252     if (copy_from_user(&data, (void __user *) arg, sizeof(data)))
       
  3253         return -EFAULT;
       
  3254 
       
  3255     if (!data.size) {
       
  3256         EC_MASTER_ERR(master, "SDO download: Data size may not be zero!\n");
       
  3257         return -EINVAL;
       
  3258     }
       
  3259 
       
  3260     /* no locking of master_sem needed, because neither sc nor req will not be
       
  3261      * deleted in the meantime. */
       
  3262 
       
  3263     if (!(sc = ec_master_get_config(master, data.config_index))) {
       
  3264         return -ENOENT;
       
  3265     }
       
  3266 
       
  3267     if (!(req = ec_slave_config_find_sdo_request(sc, data.request_index))) {
       
  3268         return -ENOENT;
       
  3269     }
       
  3270 
       
  3271     ret = ec_sdo_request_alloc(req, data.size);
       
  3272     if (ret)
       
  3273         return ret;
       
  3274 
       
  3275     if (copy_from_user(req->data, (void __user *) data.data, data.size))
       
  3276         return -EFAULT;
       
  3277 
       
  3278     req->data_size = data.size;
       
  3279     ecrt_sdo_request_write(req);
       
  3280     return 0;
       
  3281 }
       
  3282 
       
  3283 /*****************************************************************************/
       
  3284 
       
  3285 /** Read SDO data.
       
  3286  *
       
  3287  * \return Zero on success, otherwise a negative error code.
       
  3288  */
       
  3289 static ATTRIBUTES int ec_ioctl_sdo_request_data(
       
  3290         ec_master_t *master, /**< EtherCAT master. */
       
  3291         void *arg, /**< ioctl() argument. */
       
  3292         ec_ioctl_context_t *ctx /**< Private data structure of file handle. */
       
  3293         )
       
  3294 {
       
  3295     ec_ioctl_sdo_request_t data;
       
  3296     ec_slave_config_t *sc;
       
  3297     ec_sdo_request_t *req;
       
  3298 
       
  3299     if (unlikely(!ctx->requested))
       
  3300         return -EPERM;
       
  3301 
       
  3302     if (copy_from_user(&data, (void __user *) arg, sizeof(data)))
       
  3303         return -EFAULT;
       
  3304 
       
  3305     /* no locking of master_sem needed, because neither sc nor req will not be
       
  3306      * deleted in the meantime. */
       
  3307 
       
  3308     if (!(sc = ec_master_get_config(master, data.config_index))) {
       
  3309         return -ENOENT;
       
  3310     }
       
  3311 
       
  3312     if (!(req = ec_slave_config_find_sdo_request(sc, data.request_index))) {
       
  3313         return -ENOENT;
       
  3314     }
       
  3315 
       
  3316     if (copy_to_user((void __user *) data.data, ecrt_sdo_request_data(req),
       
  3317                 ecrt_sdo_request_data_size(req)))
       
  3318         return -EFAULT;
       
  3319 
       
  3320     return 0;
       
  3321 }
       
  3322 
       
  3323 /*****************************************************************************/
       
  3324 
       
  3325 /** Read register data.
       
  3326  *
       
  3327  * \return Zero on success, otherwise a negative error code.
       
  3328  */
       
  3329 static ATTRIBUTES int ec_ioctl_reg_request_data(
       
  3330         ec_master_t *master, /**< EtherCAT master. */
       
  3331         void *arg, /**< ioctl() argument. */
       
  3332         ec_ioctl_context_t *ctx /**< Private data structure of file handle. */
       
  3333         )
       
  3334 {
       
  3335     ec_ioctl_reg_request_t io;
       
  3336     ec_slave_config_t *sc;
       
  3337     ec_reg_request_t *reg;
       
  3338 
       
  3339     if (unlikely(!ctx->requested)) {
       
  3340         return -EPERM;
       
  3341     }
       
  3342 
       
  3343     if (copy_from_user(&io, (void __user *) arg, sizeof(io))) {
       
  3344         return -EFAULT;
       
  3345     }
       
  3346 
       
  3347     if (io.mem_size <= 0) {
       
  3348         return 0;
       
  3349     }
       
  3350 
       
  3351     /* no locking of master_sem needed, because neither sc nor reg will not be
       
  3352      * deleted in the meantime. */
       
  3353 
       
  3354     if (!(sc = ec_master_get_config(master, io.config_index))) {
       
  3355         return -ENOENT;
       
  3356     }
       
  3357 
       
  3358     if (!(reg = ec_slave_config_find_reg_request(sc, io.request_index))) {
       
  3359         return -ENOENT;
       
  3360     }
       
  3361 
       
  3362     if (copy_to_user((void __user *) io.data, ecrt_reg_request_data(reg),
       
  3363                 min(reg->mem_size, io.mem_size))) {
       
  3364         return -EFAULT;
       
  3365     }
       
  3366 
       
  3367     return 0;
       
  3368 }
       
  3369 
       
  3370 /*****************************************************************************/
       
  3371 
       
  3372 /** Gets an register request's state.
       
  3373  *
       
  3374  * \return Zero on success, otherwise a negative error code.
       
  3375  */
       
  3376 static ATTRIBUTES int ec_ioctl_reg_request_state(
       
  3377         ec_master_t *master, /**< EtherCAT master. */
       
  3378         void *arg, /**< ioctl() argument. */
       
  3379         ec_ioctl_context_t *ctx /**< Private data structure of file handle. */
       
  3380         )
       
  3381 {
       
  3382     ec_ioctl_reg_request_t io;
       
  3383     ec_slave_config_t *sc;
       
  3384     ec_reg_request_t *reg;
       
  3385 
       
  3386     if (unlikely(!ctx->requested)) {
       
  3387         return -EPERM;
       
  3388     }
       
  3389 
       
  3390     if (copy_from_user(&io, (void __user *) arg, sizeof(io))) {
       
  3391         return -EFAULT;
       
  3392     }
       
  3393 
       
  3394     /* no locking of master_sem needed, because neither sc nor reg will not be
       
  3395      * deleted in the meantime. */
       
  3396 
       
  3397     if (!(sc = ec_master_get_config(master, io.config_index))) {
       
  3398         return -ENOENT;
       
  3399     }
       
  3400 
       
  3401     if (!(reg = ec_slave_config_find_reg_request(sc, io.request_index))) {
       
  3402         return -ENOENT;
       
  3403     }
       
  3404 
       
  3405     io.state = ecrt_reg_request_state(reg);
       
  3406     io.new_data = io.state == EC_REQUEST_SUCCESS && reg->dir == EC_DIR_INPUT;
       
  3407 
       
  3408     if (copy_to_user((void __user *) arg, &io, sizeof(io))) {
       
  3409         return -EFAULT;
       
  3410     }
       
  3411 
       
  3412     return 0;
       
  3413 }
       
  3414 
       
  3415 /*****************************************************************************/
       
  3416 
       
  3417 /** Starts an register write operation.
       
  3418  *
       
  3419  * \return Zero on success, otherwise a negative error code.
       
  3420  */
       
  3421 static ATTRIBUTES int ec_ioctl_reg_request_write(
       
  3422         ec_master_t *master, /**< EtherCAT master. */
       
  3423         void *arg, /**< ioctl() argument. */
       
  3424         ec_ioctl_context_t *ctx /**< Private data structure of file handle. */
       
  3425         )
       
  3426 {
       
  3427     ec_ioctl_reg_request_t io;
       
  3428     ec_slave_config_t *sc;
       
  3429     ec_reg_request_t *reg;
       
  3430 
       
  3431     if (unlikely(!ctx->requested)) {
       
  3432         return -EPERM;
       
  3433     }
       
  3434 
       
  3435     if (copy_from_user(&io, (void __user *) arg, sizeof(io))) {
       
  3436         return -EFAULT;
       
  3437     }
       
  3438 
       
  3439     /* no locking of master_sem needed, because neither sc nor reg will not be
       
  3440      * deleted in the meantime. */
       
  3441 
       
  3442     if (!(sc = ec_master_get_config(master, io.config_index))) {
       
  3443         return -ENOENT;
       
  3444     }
       
  3445 
       
  3446     if (!(reg = ec_slave_config_find_reg_request(sc, io.request_index))) {
       
  3447         return -ENOENT;
       
  3448     }
       
  3449 
       
  3450     if (io.transfer_size > reg->mem_size) {
       
  3451         return -EOVERFLOW;
       
  3452     }
       
  3453 
       
  3454     if (copy_from_user(reg->data, (void __user *) io.data,
       
  3455                 io.transfer_size)) {
       
  3456         return -EFAULT;
       
  3457     }
       
  3458 
       
  3459     ecrt_reg_request_write(reg, io.address, io.transfer_size);
       
  3460     return 0;
       
  3461 }
       
  3462 
       
  3463 /*****************************************************************************/
       
  3464 
       
  3465 /** Starts an register read operation.
       
  3466  *
       
  3467  * \return Zero on success, otherwise a negative error code.
       
  3468  */
       
  3469 static ATTRIBUTES int ec_ioctl_reg_request_read(
       
  3470         ec_master_t *master, /**< EtherCAT master. */
       
  3471         void *arg, /**< ioctl() argument. */
       
  3472         ec_ioctl_context_t *ctx /**< Private data structure of file handle. */
       
  3473         )
       
  3474 {
       
  3475     ec_ioctl_reg_request_t io;
       
  3476     ec_slave_config_t *sc;
       
  3477     ec_reg_request_t *reg;
       
  3478 
       
  3479     if (unlikely(!ctx->requested)) {
       
  3480         return -EPERM;
       
  3481     }
       
  3482 
       
  3483     if (copy_from_user(&io, (void __user *) arg, sizeof(io))) {
       
  3484         return -EFAULT;
       
  3485     }
       
  3486 
       
  3487     /* no locking of master_sem needed, because neither sc nor reg will not be
       
  3488      * deleted in the meantime. */
       
  3489 
       
  3490     if (!(sc = ec_master_get_config(master, io.config_index))) {
       
  3491         return -ENOENT;
       
  3492     }
       
  3493 
       
  3494     if (!(reg = ec_slave_config_find_reg_request(sc, io.request_index))) {
       
  3495         return -ENOENT;
       
  3496     }
       
  3497 
       
  3498     if (io.transfer_size > reg->mem_size) {
       
  3499         return -EOVERFLOW;
       
  3500     }
       
  3501 
       
  3502     ecrt_reg_request_read(reg, io.address, io.transfer_size);
       
  3503     return 0;
       
  3504 }
       
  3505 
       
  3506 /*****************************************************************************/
       
  3507 
       
  3508 /** Sets the VoE send header.
       
  3509  *
       
  3510  * \return Zero on success, otherwise a negative error code.
       
  3511  */
       
  3512 static ATTRIBUTES int ec_ioctl_voe_send_header(
       
  3513         ec_master_t *master, /**< EtherCAT master. */
       
  3514         void *arg, /**< ioctl() argument. */
       
  3515         ec_ioctl_context_t *ctx /**< Private data structure of file handle. */
       
  3516         )
       
  3517 {
       
  3518     ec_ioctl_voe_t data;
       
  3519     ec_slave_config_t *sc;
       
  3520     ec_voe_handler_t *voe;
       
  3521     uint32_t vendor_id;
       
  3522     uint16_t vendor_type;
       
  3523 
       
  3524     if (unlikely(!ctx->requested))
       
  3525         return -EPERM;
       
  3526 
       
  3527     if (copy_from_user(&data, (void __user *) arg, sizeof(data)))
       
  3528         return -EFAULT;
       
  3529 
       
  3530     if (get_user(vendor_id, data.vendor_id))
       
  3531         return -EFAULT;
       
  3532 
       
  3533     if (get_user(vendor_type, data.vendor_type))
       
  3534         return -EFAULT;
       
  3535 
       
  3536     /* no locking of master_sem needed, because neither sc nor voe will not be
       
  3537      * deleted in the meantime. */
       
  3538 
       
  3539     if (!(sc = ec_master_get_config(master, data.config_index))) {
       
  3540         return -ENOENT;
       
  3541     }
       
  3542 
       
  3543     if (!(voe = ec_slave_config_find_voe_handler(sc, data.voe_index))) {
       
  3544         return -ENOENT;
       
  3545     }
       
  3546 
       
  3547     ecrt_voe_handler_send_header(voe, vendor_id, vendor_type);
       
  3548     return 0;
       
  3549 }
       
  3550 
       
  3551 /*****************************************************************************/
       
  3552 
       
  3553 /** Gets the received VoE header.
       
  3554  *
       
  3555  * \return Zero on success, otherwise a negative error code.
       
  3556  */
       
  3557 static ATTRIBUTES int ec_ioctl_voe_rec_header(
       
  3558         ec_master_t *master, /**< EtherCAT master. */
       
  3559         void *arg, /**< ioctl() argument. */
       
  3560         ec_ioctl_context_t *ctx /**< Private data structure of file handle. */
       
  3561         )
       
  3562 {
       
  3563     ec_ioctl_voe_t data;
       
  3564     ec_slave_config_t *sc;
       
  3565     ec_voe_handler_t *voe;
       
  3566     uint32_t vendor_id;
       
  3567     uint16_t vendor_type;
       
  3568 
       
  3569     if (unlikely(!ctx->requested))
       
  3570         return -EPERM;
       
  3571 
       
  3572     if (copy_from_user(&data, (void __user *) arg, sizeof(data)))
       
  3573         return -EFAULT;
       
  3574 
       
  3575     /* no locking of master_sem needed, because neither sc nor voe will not be
       
  3576      * deleted in the meantime. */
       
  3577 
       
  3578     if (!(sc = ec_master_get_config(master, data.config_index))) {
       
  3579         return -ENOENT;
       
  3580     }
       
  3581 
       
  3582     if (!(voe = ec_slave_config_find_voe_handler(sc, data.voe_index))) {
       
  3583         return -ENOENT;
       
  3584     }
       
  3585 
       
  3586     ecrt_voe_handler_received_header(voe, &vendor_id, &vendor_type);
       
  3587 
       
  3588     if (likely(data.vendor_id))
       
  3589         if (put_user(vendor_id, data.vendor_id))
       
  3590             return -EFAULT;
       
  3591 
       
  3592     if (likely(data.vendor_type))
       
  3593         if (put_user(vendor_type, data.vendor_type))
       
  3594             return -EFAULT;
       
  3595 
       
  3596     return 0;
       
  3597 }
       
  3598 
       
  3599 /*****************************************************************************/
       
  3600 
       
  3601 /** Starts a VoE read operation.
       
  3602  *
       
  3603  * \return Zero on success, otherwise a negative error code.
       
  3604  */
       
  3605 static ATTRIBUTES int ec_ioctl_voe_read(
       
  3606         ec_master_t *master, /**< EtherCAT master. */
       
  3607         void *arg, /**< ioctl() argument. */
       
  3608         ec_ioctl_context_t *ctx /**< Private data structure of file handle. */
       
  3609         )
       
  3610 {
       
  3611     ec_ioctl_voe_t data;
       
  3612     ec_slave_config_t *sc;
       
  3613     ec_voe_handler_t *voe;
       
  3614 
       
  3615     if (unlikely(!ctx->requested))
       
  3616         return -EPERM;
       
  3617 
       
  3618     if (copy_from_user(&data, (void __user *) arg, sizeof(data)))
       
  3619         return -EFAULT;
       
  3620 
       
  3621     /* no locking of master_sem needed, because neither sc nor voe will not be
       
  3622      * deleted in the meantime. */
       
  3623 
       
  3624     if (!(sc = ec_master_get_config(master, data.config_index))) {
       
  3625         return -ENOENT;
       
  3626     }
       
  3627 
       
  3628     if (!(voe = ec_slave_config_find_voe_handler(sc, data.voe_index))) {
       
  3629         return -ENOENT;
       
  3630     }
       
  3631 
       
  3632     ecrt_voe_handler_read(voe);
       
  3633     return 0;
       
  3634 }
       
  3635 
       
  3636 /*****************************************************************************/
       
  3637 
       
  3638 /** Starts a VoE read operation without sending a sync message first.
       
  3639  *
       
  3640  * \return Zero on success, otherwise a negative error code.
       
  3641  */
       
  3642 static ATTRIBUTES int ec_ioctl_voe_read_nosync(
       
  3643         ec_master_t *master, /**< EtherCAT master. */
       
  3644         void *arg, /**< ioctl() argument. */
       
  3645         ec_ioctl_context_t *ctx /**< Private data structure of file handle. */
       
  3646         )
       
  3647 {
       
  3648     ec_ioctl_voe_t data;
       
  3649     ec_slave_config_t *sc;
       
  3650     ec_voe_handler_t *voe;
       
  3651 
       
  3652     if (unlikely(!ctx->requested))
       
  3653         return -EPERM;
       
  3654 
       
  3655     if (copy_from_user(&data, (void __user *) arg, sizeof(data)))
       
  3656         return -EFAULT;
       
  3657 
       
  3658     /* no locking of master_sem needed, because neither sc nor voe will not be
       
  3659      * deleted in the meantime. */
       
  3660 
       
  3661     if (!(sc = ec_master_get_config(master, data.config_index))) {
       
  3662         return -ENOENT;
       
  3663     }
       
  3664 
       
  3665     if (!(voe = ec_slave_config_find_voe_handler(sc, data.voe_index))) {
       
  3666         return -ENOENT;
       
  3667     }
       
  3668 
       
  3669     ecrt_voe_handler_read_nosync(voe);
       
  3670     return 0;
       
  3671 }
       
  3672 
       
  3673 /*****************************************************************************/
       
  3674 
       
  3675 /** Starts a VoE write operation.
       
  3676  *
       
  3677  * \return Zero on success, otherwise a negative error code.
       
  3678  */
       
  3679 static ATTRIBUTES int ec_ioctl_voe_write(
       
  3680         ec_master_t *master, /**< EtherCAT master. */
       
  3681         void *arg, /**< ioctl() argument. */
       
  3682         ec_ioctl_context_t *ctx /**< Private data structure of file handle. */
       
  3683         )
       
  3684 {
       
  3685     ec_ioctl_voe_t data;
       
  3686     ec_slave_config_t *sc;
       
  3687     ec_voe_handler_t *voe;
       
  3688 
       
  3689     if (unlikely(!ctx->requested))
       
  3690         return -EPERM;
       
  3691 
       
  3692     if (copy_from_user(&data, (void __user *) arg, sizeof(data)))
       
  3693         return -EFAULT;
       
  3694 
       
  3695     /* no locking of master_sem needed, because neither sc nor voe will not be
       
  3696      * deleted in the meantime. */
       
  3697 
       
  3698     if (!(sc = ec_master_get_config(master, data.config_index))) {
       
  3699         return -ENOENT;
       
  3700     }
       
  3701 
       
  3702     if (!(voe = ec_slave_config_find_voe_handler(sc, data.voe_index))) {
       
  3703         return -ENOENT;
       
  3704     }
       
  3705 
       
  3706     if (data.size) {
       
  3707         if (data.size > ec_voe_handler_mem_size(voe))
       
  3708             return -EOVERFLOW;
       
  3709 
       
  3710         if (copy_from_user(ecrt_voe_handler_data(voe),
       
  3711                     (void __user *) data.data, data.size))
       
  3712             return -EFAULT;
       
  3713     }
       
  3714 
       
  3715     ecrt_voe_handler_write(voe, data.size);
       
  3716     return 0;
       
  3717 }
       
  3718 
       
  3719 /*****************************************************************************/
       
  3720 
       
  3721 /** Executes the VoE state machine.
       
  3722  *
       
  3723  * \return Zero on success, otherwise a negative error code.
       
  3724  */
       
  3725 static ATTRIBUTES int ec_ioctl_voe_exec(
       
  3726         ec_master_t *master, /**< EtherCAT master. */
       
  3727         void *arg, /**< ioctl() argument. */
       
  3728         ec_ioctl_context_t *ctx /**< Private data structure of file handle. */
       
  3729         )
       
  3730 {
       
  3731     ec_ioctl_voe_t data;
       
  3732     ec_slave_config_t *sc;
       
  3733     ec_voe_handler_t *voe;
       
  3734 
       
  3735     if (unlikely(!ctx->requested))
       
  3736         return -EPERM;
       
  3737 
       
  3738     if (copy_from_user(&data, (void __user *) arg, sizeof(data)))
       
  3739         return -EFAULT;
       
  3740 
       
  3741     /* no locking of master_sem needed, because neither sc nor voe will not be
       
  3742      * deleted in the meantime. */
       
  3743 
       
  3744     if (!(sc = ec_master_get_config(master, data.config_index))) {
       
  3745         return -ENOENT;
       
  3746     }
       
  3747 
       
  3748     if (!(voe = ec_slave_config_find_voe_handler(sc, data.voe_index))) {
       
  3749         return -ENOENT;
       
  3750     }
       
  3751 
       
  3752     data.state = ecrt_voe_handler_execute(voe);
       
  3753     if (data.state == EC_REQUEST_SUCCESS && voe->dir == EC_DIR_INPUT)
       
  3754         data.size = ecrt_voe_handler_data_size(voe);
       
  3755     else
       
  3756         data.size = 0;
       
  3757 
       
  3758     if (copy_to_user((void __user *) arg, &data, sizeof(data)))
       
  3759         return -EFAULT;
       
  3760 
       
  3761     return 0;
       
  3762 }
       
  3763 
       
  3764 /*****************************************************************************/
       
  3765 
       
  3766 /** Reads the received VoE data.
       
  3767  *
       
  3768  * \return Zero on success, otherwise a negative error code.
       
  3769  */
       
  3770 static ATTRIBUTES int ec_ioctl_voe_data(
       
  3771         ec_master_t *master, /**< EtherCAT master. */
       
  3772         void *arg, /**< ioctl() argument. */
       
  3773         ec_ioctl_context_t *ctx /**< Private data structure of file handle. */
       
  3774         )
       
  3775 {
       
  3776     ec_ioctl_voe_t data;
       
  3777     ec_slave_config_t *sc;
       
  3778     ec_voe_handler_t *voe;
       
  3779 
       
  3780     if (unlikely(!ctx->requested))
       
  3781         return -EPERM;
       
  3782 
       
  3783     if (copy_from_user(&data, (void __user *) arg, sizeof(data)))
       
  3784         return -EFAULT;
       
  3785 
       
  3786     /* no locking of master_sem needed, because neither sc nor voe will not be
       
  3787      * deleted in the meantime. */
       
  3788 
       
  3789     if (!(sc = ec_master_get_config(master, data.config_index))) {
       
  3790         return -ENOENT;
       
  3791     }
       
  3792 
       
  3793     if (!(voe = ec_slave_config_find_voe_handler(sc, data.voe_index))) {
       
  3794         return -ENOENT;
       
  3795     }
       
  3796 
       
  3797     if (copy_to_user((void __user *) data.data, ecrt_voe_handler_data(voe),
       
  3798                 ecrt_voe_handler_data_size(voe)))
       
  3799         return -EFAULT;
       
  3800 
       
  3801     return 0;
       
  3802 }
       
  3803 
       
  3804 /*****************************************************************************/
       
  3805 
       
  3806 /** Read a file from a slave via FoE.
       
  3807  *
       
  3808  * \return Zero on success, otherwise a negative error code.
       
  3809  */
       
  3810 static ATTRIBUTES int ec_ioctl_slave_foe_read(
       
  3811         ec_master_t *master, /**< EtherCAT master. */
       
  3812         void *arg /**< ioctl() argument. */
       
  3813         )
       
  3814 {
       
  3815     ec_ioctl_slave_foe_t io;
       
  3816     ec_foe_request_t request;
       
  3817     ec_slave_t *slave;
       
  3818     int ret;
       
  3819 
       
  3820     if (copy_from_user(&io, (void __user *) arg, sizeof(io))) {
       
  3821         return -EFAULT;
       
  3822     }
       
  3823 
       
  3824     ec_foe_request_init(&request, io.file_name);
       
  3825     ret = ec_foe_request_alloc(&request, 10000); // FIXME
       
  3826     if (ret) {
       
  3827         ec_foe_request_clear(&request);
       
  3828         return ret;
       
  3829     }
       
  3830 
       
  3831     ec_foe_request_read(&request);
       
  3832 
       
  3833     if (down_interruptible(&master->master_sem)) {
       
  3834         ec_foe_request_clear(&request);
       
  3835         return -EINTR;
       
  3836     }
       
  3837 
       
  3838     if (!(slave = ec_master_find_slave(master, 0, io.slave_position))) {
       
  3839         up(&master->master_sem);
       
  3840         ec_foe_request_clear(&request);
       
  3841         EC_MASTER_ERR(master, "Slave %u does not exist!\n",
       
  3842                 io.slave_position);
       
  3843         return -EINVAL;
       
  3844     }
       
  3845 
       
  3846     EC_SLAVE_DBG(slave, 1, "Scheduling FoE read request.\n");
       
  3847 
       
  3848     // schedule request.
       
  3849     list_add_tail(&request.list, &slave->foe_requests);
       
  3850 
       
  3851     up(&master->master_sem);
       
  3852 
       
  3853     // wait for processing through FSM
       
  3854     if (wait_event_interruptible(master->request_queue,
       
  3855                 request.state != EC_INT_REQUEST_QUEUED)) {
       
  3856         // interrupted by signal
       
  3857         down(&master->master_sem);
       
  3858         if (request.state == EC_INT_REQUEST_QUEUED) {
       
  3859             list_del(&request.list);
       
  3860             up(&master->master_sem);
       
  3861             ec_foe_request_clear(&request);
       
  3862             return -EINTR;
       
  3863         }
       
  3864         // request already processing: interrupt not possible.
       
  3865         up(&master->master_sem);
       
  3866     }
       
  3867 
       
  3868     // wait until master FSM has finished processing
       
  3869     wait_event(master->request_queue, request.state != EC_INT_REQUEST_BUSY);
       
  3870 
       
  3871     io.result = request.result;
       
  3872     io.error_code = request.error_code;
       
  3873 
       
  3874     if (request.state != EC_INT_REQUEST_SUCCESS) {
       
  3875         io.data_size = 0;
       
  3876         ret = -EIO;
       
  3877     } else {
       
  3878         if (request.data_size > io.buffer_size) {
       
  3879             EC_MASTER_ERR(master, "Buffer too small.\n");
       
  3880             ec_foe_request_clear(&request);
       
  3881             return -EOVERFLOW;
       
  3882         }
       
  3883         io.data_size = request.data_size;
       
  3884         if (copy_to_user((void __user *) io.buffer,
       
  3885                     request.buffer, io.data_size)) {
       
  3886             ec_foe_request_clear(&request);
       
  3887             return -EFAULT;
       
  3888         }
       
  3889         ret = 0;
       
  3890     }
       
  3891 
       
  3892     if (__copy_to_user((void __user *) arg, &io, sizeof(io))) {
       
  3893         ret = -EFAULT;
       
  3894     }
       
  3895 
       
  3896     ec_foe_request_clear(&request);
       
  3897     return ret;
       
  3898 }
       
  3899 
       
  3900 /*****************************************************************************/
       
  3901 
       
  3902 /** Write a file to a slave via FoE
       
  3903  *
       
  3904  * \return Zero on success, otherwise a negative error code.
       
  3905  */
       
  3906 static ATTRIBUTES int ec_ioctl_slave_foe_write(
       
  3907         ec_master_t *master, /**< EtherCAT master. */
       
  3908         void *arg /**< ioctl() argument. */
       
  3909         )
       
  3910 {
       
  3911     ec_ioctl_slave_foe_t io;
       
  3912     ec_foe_request_t request;
       
  3913     ec_slave_t *slave;
       
  3914     int ret;
       
  3915 
       
  3916     if (copy_from_user(&io, (void __user *) arg, sizeof(io))) {
       
  3917         return -EFAULT;
       
  3918     }
       
  3919 
       
  3920     ec_foe_request_init(&request, io.file_name);
       
  3921 
       
  3922     ret = ec_foe_request_alloc(&request, io.buffer_size);
       
  3923     if (ret) {
       
  3924         ec_foe_request_clear(&request);
       
  3925         return ret;
       
  3926     }
       
  3927 
       
  3928     if (copy_from_user(request.buffer,
       
  3929                 (void __user *) io.buffer, io.buffer_size)) {
       
  3930         ec_foe_request_clear(&request);
       
  3931         return -EFAULT;
       
  3932     }
       
  3933 
       
  3934     request.data_size = io.buffer_size;
       
  3935     ec_foe_request_write(&request);
       
  3936 
       
  3937     if (down_interruptible(&master->master_sem)) {
       
  3938         ec_foe_request_clear(&request);
       
  3939         return -EINTR;
       
  3940     }
       
  3941 
       
  3942     if (!(slave = ec_master_find_slave(master, 0, io.slave_position))) {
       
  3943         up(&master->master_sem);
       
  3944         EC_MASTER_ERR(master, "Slave %u does not exist!\n",
       
  3945                 io.slave_position);
       
  3946         ec_foe_request_clear(&request);
       
  3947         return -EINVAL;
       
  3948     }
       
  3949 
       
  3950     EC_SLAVE_DBG(slave, 1, "Scheduling FoE write request.\n");
       
  3951 
       
  3952     // schedule FoE write request.
       
  3953     list_add_tail(&request.list, &slave->foe_requests);
       
  3954 
       
  3955     up(&master->master_sem);
       
  3956 
       
  3957     // wait for processing through FSM
       
  3958     if (wait_event_interruptible(master->request_queue,
       
  3959                 request.state != EC_INT_REQUEST_QUEUED)) {
       
  3960         // interrupted by signal
       
  3961         down(&master->master_sem);
       
  3962         if (request.state == EC_INT_REQUEST_QUEUED) {
       
  3963             // abort request
       
  3964             list_del(&request.list);
       
  3965             up(&master->master_sem);
       
  3966             ec_foe_request_clear(&request);
       
  3967             return -EINTR;
       
  3968         }
       
  3969         up(&master->master_sem);
       
  3970     }
       
  3971 
       
  3972     // wait until master FSM has finished processing
       
  3973     wait_event(master->request_queue, request.state != EC_INT_REQUEST_BUSY);
       
  3974 
       
  3975     io.result = request.result;
       
  3976     io.error_code = request.error_code;
       
  3977 
       
  3978     ret = request.state == EC_INT_REQUEST_SUCCESS ? 0 : -EIO;
       
  3979 
       
  3980     if (__copy_to_user((void __user *) arg, &io, sizeof(io))) {
       
  3981         ret = -EFAULT;
       
  3982     }
       
  3983 
       
  3984     ec_foe_request_clear(&request);
       
  3985     return ret;
       
  3986 }
       
  3987 
       
  3988 /*****************************************************************************/
       
  3989 
       
  3990 /** Read an SoE IDN.
       
  3991  *
       
  3992  * \return Zero on success, otherwise a negative error code.
       
  3993  */
       
  3994 static ATTRIBUTES int ec_ioctl_slave_soe_read(
       
  3995         ec_master_t *master, /**< EtherCAT master. */
       
  3996         void *arg /**< ioctl() argument. */
       
  3997         )
       
  3998 {
       
  3999     ec_ioctl_slave_soe_read_t ioctl;
       
  4000     u8 *data;
       
  4001     int retval;
       
  4002 
       
  4003     if (copy_from_user(&ioctl, (void __user *) arg, sizeof(ioctl))) {
       
  4004         return -EFAULT;
       
  4005     }
       
  4006 
       
  4007     data = kmalloc(ioctl.mem_size, GFP_KERNEL);
       
  4008     if (!data) {
       
  4009         EC_MASTER_ERR(master, "Failed to allocate %zu bytes of IDN data.\n",
       
  4010                 ioctl.mem_size);
       
  4011         return -ENOMEM;
       
  4012     }
       
  4013 
       
  4014     retval = ecrt_master_read_idn(master, ioctl.slave_position,
       
  4015             ioctl.drive_no, ioctl.idn, data, ioctl.mem_size, &ioctl.data_size,
       
  4016             &ioctl.error_code);
       
  4017     if (retval) {
       
  4018         kfree(data);
       
  4019         return retval;
       
  4020     }
       
  4021 
       
  4022     if (copy_to_user((void __user *) ioctl.data,
       
  4023                 data, ioctl.data_size)) {
       
  4024         kfree(data);
       
  4025         return -EFAULT;
       
  4026     }
       
  4027     kfree(data);
       
  4028 
       
  4029     if (__copy_to_user((void __user *) arg, &ioctl, sizeof(ioctl))) {
       
  4030         retval = -EFAULT;
       
  4031     }
       
  4032 
       
  4033     EC_MASTER_DBG(master, 1, "Finished SoE read request.\n");
       
  4034     return retval;
       
  4035 }
       
  4036 
       
  4037 /*****************************************************************************/
       
  4038 
       
  4039 /** Write an IDN to a slave via SoE.
       
  4040  *
       
  4041  * \return Zero on success, otherwise a negative error code.
       
  4042  */
       
  4043 static ATTRIBUTES int ec_ioctl_slave_soe_write(
       
  4044         ec_master_t *master, /**< EtherCAT master. */
       
  4045         void *arg /**< ioctl() argument. */
       
  4046         )
       
  4047 {
       
  4048     ec_ioctl_slave_soe_write_t ioctl;
       
  4049     u8 *data;
       
  4050     int retval;
       
  4051 
       
  4052     if (copy_from_user(&ioctl, (void __user *) arg, sizeof(ioctl))) {
       
  4053         return -EFAULT;
       
  4054     }
       
  4055 
       
  4056     data = kmalloc(ioctl.data_size, GFP_KERNEL);
       
  4057     if (!data) {
       
  4058         EC_MASTER_ERR(master, "Failed to allocate %zu bytes of IDN data.\n",
       
  4059                 ioctl.data_size);
       
  4060         return -ENOMEM;
       
  4061     }
       
  4062     if (copy_from_user(data, (void __user *) ioctl.data, ioctl.data_size)) {
       
  4063         kfree(data);
       
  4064         return -EFAULT;
       
  4065     }
       
  4066 
       
  4067     retval = ecrt_master_write_idn(master, ioctl.slave_position,
       
  4068             ioctl.drive_no, ioctl.idn, data, ioctl.data_size,
       
  4069             &ioctl.error_code);
       
  4070     kfree(data);
       
  4071     if (retval) {
       
  4072         return retval;
       
  4073     }
       
  4074 
       
  4075     if (__copy_to_user((void __user *) arg, &ioctl, sizeof(ioctl))) {
       
  4076         retval = -EFAULT;
       
  4077     }
       
  4078 
       
  4079     EC_MASTER_DBG(master, 1, "Finished SoE write request.\n");
       
  4080     return retval;
       
  4081 }
       
  4082 
       
  4083 /*****************************************************************************/
       
  4084 
       
  4085 /** ioctl() function to use.
       
  4086  */
       
  4087 #ifdef EC_IOCTL_RTDM
       
  4088 #define EC_IOCTL ec_ioctl_rtdm
       
  4089 #else
       
  4090 #define EC_IOCTL ec_ioctl
       
  4091 #endif
       
  4092 
       
  4093 /** Called when an ioctl() command is issued.
       
  4094  *
       
  4095  * \return ioctl() return code.
       
  4096  */
       
  4097 long EC_IOCTL(
       
  4098         ec_master_t *master, /**< EtherCAT master. */
       
  4099         ec_ioctl_context_t *ctx, /**< Device context. */
       
  4100         unsigned int cmd, /**< ioctl() command identifier. */
       
  4101         void *arg /**< ioctl() argument. */
       
  4102         )
       
  4103 {
       
  4104 #if DEBUG_LATENCY
       
  4105     cycles_t a = get_cycles(), b;
       
  4106     unsigned int t;
       
  4107 #endif
       
  4108     int ret;
       
  4109 
       
  4110     switch (cmd) {
       
  4111         case EC_IOCTL_MODULE:
       
  4112             ret = ec_ioctl_module(arg);
       
  4113             break;
       
  4114         case EC_IOCTL_MASTER:
       
  4115             ret = ec_ioctl_master(master, arg);
       
  4116             break;
       
  4117         case EC_IOCTL_SLAVE:
       
  4118             ret = ec_ioctl_slave(master, arg);
       
  4119             break;
       
  4120         case EC_IOCTL_SLAVE_SYNC:
       
  4121             ret = ec_ioctl_slave_sync(master, arg);
       
  4122             break;
       
  4123         case EC_IOCTL_SLAVE_SYNC_PDO:
       
  4124             ret = ec_ioctl_slave_sync_pdo(master, arg);
       
  4125             break;
       
  4126         case EC_IOCTL_SLAVE_SYNC_PDO_ENTRY:
       
  4127             ret = ec_ioctl_slave_sync_pdo_entry(master, arg);
       
  4128             break;
       
  4129         case EC_IOCTL_DOMAIN:
       
  4130             ret = ec_ioctl_domain(master, arg);
       
  4131             break;
       
  4132         case EC_IOCTL_DOMAIN_FMMU:
       
  4133             ret = ec_ioctl_domain_fmmu(master, arg);
       
  4134             break;
       
  4135         case EC_IOCTL_DOMAIN_DATA:
       
  4136             ret = ec_ioctl_domain_data(master, arg);
       
  4137             break;
       
  4138         case EC_IOCTL_MASTER_DEBUG:
       
  4139             if (!ctx->writable) {
       
  4140                 ret = -EPERM;
       
  4141                 break;
       
  4142             }
       
  4143             ret = ec_ioctl_master_debug(master, arg);
       
  4144             break;
       
  4145         case EC_IOCTL_MASTER_RESCAN:
       
  4146             if (!ctx->writable) {
       
  4147                 ret = -EPERM;
       
  4148                 break;
       
  4149             }
       
  4150             ret = ec_ioctl_master_rescan(master, arg);
       
  4151             break;
       
  4152         case EC_IOCTL_SLAVE_STATE:
       
  4153             if (!ctx->writable) {
       
  4154                 ret = -EPERM;
       
  4155                 break;
       
  4156             }
       
  4157             ret = ec_ioctl_slave_state(master, arg);
       
  4158             break;
       
  4159         case EC_IOCTL_SLAVE_SDO:
       
  4160             ret = ec_ioctl_slave_sdo(master, arg);
       
  4161             break;
       
  4162         case EC_IOCTL_SLAVE_SDO_ENTRY:
       
  4163             ret = ec_ioctl_slave_sdo_entry(master, arg);
       
  4164             break;
       
  4165         case EC_IOCTL_SLAVE_SDO_UPLOAD:
       
  4166             ret = ec_ioctl_slave_sdo_upload(master, arg);
       
  4167             break;
       
  4168         case EC_IOCTL_SLAVE_SDO_DOWNLOAD:
       
  4169             if (!ctx->writable) {
       
  4170                 ret = -EPERM;
       
  4171                 break;
       
  4172             }
       
  4173             ret = ec_ioctl_slave_sdo_download(master, arg);
       
  4174             break;
       
  4175         case EC_IOCTL_SLAVE_SII_READ:
       
  4176             ret = ec_ioctl_slave_sii_read(master, arg);
       
  4177             break;
       
  4178         case EC_IOCTL_SLAVE_SII_WRITE:
       
  4179             if (!ctx->writable) {
       
  4180                 ret = -EPERM;
       
  4181                 break;
       
  4182             }
       
  4183             ret = ec_ioctl_slave_sii_write(master, arg);
       
  4184             break;
       
  4185         case EC_IOCTL_SLAVE_REG_READ:
       
  4186             ret = ec_ioctl_slave_reg_read(master, arg);
       
  4187             break;
       
  4188         case EC_IOCTL_SLAVE_REG_WRITE:
       
  4189             if (!ctx->writable) {
       
  4190                 ret = -EPERM;
       
  4191                 break;
       
  4192             }
       
  4193             ret = ec_ioctl_slave_reg_write(master, arg);
       
  4194             break;
       
  4195         case EC_IOCTL_SLAVE_FOE_READ:
       
  4196             ret = ec_ioctl_slave_foe_read(master, arg);
       
  4197             break;
       
  4198         case EC_IOCTL_SLAVE_FOE_WRITE:
       
  4199             if (!ctx->writable) {
       
  4200                 ret = -EPERM;
       
  4201                 break;
       
  4202             }
       
  4203             ret = ec_ioctl_slave_foe_write(master, arg);
       
  4204             break;
       
  4205         case EC_IOCTL_SLAVE_SOE_READ:
       
  4206             ret = ec_ioctl_slave_soe_read(master, arg);
       
  4207             break;
       
  4208         case EC_IOCTL_SLAVE_SOE_WRITE:
       
  4209             if (!ctx->writable) {
       
  4210                 ret = -EPERM;
       
  4211                 break;
       
  4212             }
       
  4213             ret = ec_ioctl_slave_soe_write(master, arg);
       
  4214             break;
       
  4215         case EC_IOCTL_CONFIG:
       
  4216             ret = ec_ioctl_config(master, arg);
       
  4217             break;
       
  4218         case EC_IOCTL_CONFIG_PDO:
       
  4219             ret = ec_ioctl_config_pdo(master, arg);
       
  4220             break;
       
  4221         case EC_IOCTL_CONFIG_PDO_ENTRY:
       
  4222             ret = ec_ioctl_config_pdo_entry(master, arg);
       
  4223             break;
       
  4224         case EC_IOCTL_CONFIG_SDO:
       
  4225             ret = ec_ioctl_config_sdo(master, arg);
       
  4226             break;
       
  4227         case EC_IOCTL_CONFIG_IDN:
       
  4228             ret = ec_ioctl_config_idn(master, arg);
       
  4229             break;
       
  4230 #ifdef EC_EOE
       
  4231         case EC_IOCTL_EOE_HANDLER:
       
  4232             ret = ec_ioctl_eoe_handler(master, arg);
       
  4233             break;
       
  4234 #endif
       
  4235         case EC_IOCTL_REQUEST:
       
  4236             if (!ctx->writable) {
       
  4237                 ret = -EPERM;
       
  4238                 break;
       
  4239             }
       
  4240             ret = ec_ioctl_request(master, arg, ctx);
       
  4241             break;
       
  4242         case EC_IOCTL_CREATE_DOMAIN:
       
  4243             if (!ctx->writable) {
       
  4244                 ret = -EPERM;
       
  4245                 break;
       
  4246             }
       
  4247             ret = ec_ioctl_create_domain(master, arg, ctx);
       
  4248             break;
       
  4249         case EC_IOCTL_CREATE_SLAVE_CONFIG:
       
  4250             if (!ctx->writable) {
       
  4251                 ret = -EPERM;
       
  4252                 break;
       
  4253             }
       
  4254             ret = ec_ioctl_create_slave_config(master, arg, ctx);
       
  4255             break;
       
  4256         case EC_IOCTL_SELECT_REF_CLOCK:
       
  4257             if (!ctx->writable) {
       
  4258                 ret = -EPERM;
       
  4259                 break;
       
  4260             }
       
  4261             ret = ec_ioctl_select_ref_clock(master, arg, ctx);
       
  4262             break;
       
  4263         case EC_IOCTL_ACTIVATE:
       
  4264             if (!ctx->writable) {
       
  4265                 ret = -EPERM;
       
  4266                 break;
       
  4267             }
       
  4268             ret = ec_ioctl_activate(master, arg, ctx);
       
  4269             break;
       
  4270         case EC_IOCTL_DEACTIVATE:
       
  4271             if (!ctx->writable) {
       
  4272                 ret = -EPERM;
       
  4273                 break;
       
  4274             }
       
  4275             ret = ec_ioctl_deactivate(master, arg, ctx);
       
  4276             break;
       
  4277         case EC_IOCTL_SEND:
       
  4278             if (!ctx->writable) {
       
  4279                 ret = -EPERM;
       
  4280                 break;
       
  4281             }
       
  4282             ret = ec_ioctl_send(master, arg, ctx);
       
  4283             break;
       
  4284         case EC_IOCTL_RECEIVE:
       
  4285             if (!ctx->writable) {
       
  4286                 ret = -EPERM;
       
  4287                 break;
       
  4288             }
       
  4289             ret = ec_ioctl_receive(master, arg, ctx);
       
  4290             break;
       
  4291         case EC_IOCTL_MASTER_STATE:
       
  4292             ret = ec_ioctl_master_state(master, arg, ctx);
       
  4293             break;
       
  4294         case EC_IOCTL_MASTER_LINK_STATE:
       
  4295             ret = ec_ioctl_master_link_state(master, arg, ctx);
       
  4296             break;
       
  4297         case EC_IOCTL_APP_TIME:
       
  4298             if (!ctx->writable) {
       
  4299                 ret = -EPERM;
       
  4300                 break;
       
  4301             }
       
  4302             ret = ec_ioctl_app_time(master, arg, ctx);
       
  4303             break;
       
  4304         case EC_IOCTL_SYNC_REF:
       
  4305             if (!ctx->writable) {
       
  4306                 ret = -EPERM;
       
  4307                 break;
       
  4308             }
       
  4309             ret = ec_ioctl_sync_ref(master, arg, ctx);
       
  4310             break;
       
  4311         case EC_IOCTL_SYNC_SLAVES:
       
  4312             if (!ctx->writable) {
       
  4313                 ret = -EPERM;
       
  4314                 break;
       
  4315             }
       
  4316             ret = ec_ioctl_sync_slaves(master, arg, ctx);
       
  4317             break;
       
  4318         case EC_IOCTL_REF_CLOCK_TIME:
       
  4319             if (!ctx->writable) {
       
  4320                 ret = -EPERM;
       
  4321                 break;
       
  4322             }
       
  4323             ret = ec_ioctl_ref_clock_time(master, arg, ctx);
       
  4324             break;
       
  4325         case EC_IOCTL_SYNC_MON_QUEUE:
       
  4326             if (!ctx->writable) {
       
  4327                 ret = -EPERM;
       
  4328                 break;
       
  4329             }
       
  4330             ret = ec_ioctl_sync_mon_queue(master, arg, ctx);
       
  4331             break;
       
  4332         case EC_IOCTL_SYNC_MON_PROCESS:
       
  4333             if (!ctx->writable) {
       
  4334                 ret = -EPERM;
       
  4335                 break;
       
  4336             }
       
  4337             ret = ec_ioctl_sync_mon_process(master, arg, ctx);
       
  4338             break;
       
  4339         case EC_IOCTL_RESET:
       
  4340             if (!ctx->writable) {
       
  4341                 ret = -EPERM;
       
  4342                 break;
       
  4343             }
       
  4344             ret = ec_ioctl_reset(master, arg, ctx);
       
  4345             break;
       
  4346         case EC_IOCTL_SC_SYNC:
       
  4347             if (!ctx->writable) {
       
  4348                 ret = -EPERM;
       
  4349                 break;
       
  4350             }
       
  4351             ret = ec_ioctl_sc_sync(master, arg, ctx);
       
  4352             break;
       
  4353         case EC_IOCTL_SC_WATCHDOG:
       
  4354             if (!ctx->writable) {
       
  4355                 ret = -EPERM;
       
  4356                 break;
       
  4357             }
       
  4358             ret = ec_ioctl_sc_watchdog(master, arg, ctx);
       
  4359             break;
       
  4360         case EC_IOCTL_SC_ADD_PDO:
       
  4361             if (!ctx->writable) {
       
  4362                 ret = -EPERM;
       
  4363                 break;
       
  4364             }
       
  4365             ret = ec_ioctl_sc_add_pdo(master, arg, ctx);
       
  4366             break;
       
  4367         case EC_IOCTL_SC_CLEAR_PDOS:
       
  4368             if (!ctx->writable) {
       
  4369                 ret = -EPERM;
       
  4370                 break;
       
  4371             }
       
  4372             ret = ec_ioctl_sc_clear_pdos(master, arg, ctx);
       
  4373             break;
       
  4374         case EC_IOCTL_SC_ADD_ENTRY:
       
  4375             if (!ctx->writable) {
       
  4376                 ret = -EPERM;
       
  4377                 break;
       
  4378             }
       
  4379             ret = ec_ioctl_sc_add_entry(master, arg, ctx);
       
  4380             break;
       
  4381         case EC_IOCTL_SC_CLEAR_ENTRIES:
       
  4382             if (!ctx->writable) {
       
  4383                 ret = -EPERM;
       
  4384                 break;
       
  4385             }
       
  4386             ret = ec_ioctl_sc_clear_entries(master, arg, ctx);
       
  4387             break;
       
  4388         case EC_IOCTL_SC_REG_PDO_ENTRY:
       
  4389             if (!ctx->writable) {
       
  4390                 ret = -EPERM;
       
  4391                 break;
       
  4392             }
       
  4393             ret = ec_ioctl_sc_reg_pdo_entry(master, arg, ctx);
       
  4394             break;
       
  4395         case EC_IOCTL_SC_REG_PDO_POS:
       
  4396             if (!ctx->writable) {
       
  4397                 ret = -EPERM;
       
  4398                 break;
       
  4399             }
       
  4400             ret = ec_ioctl_sc_reg_pdo_pos(master, arg, ctx);
       
  4401             break;
       
  4402         case EC_IOCTL_SC_DC:
       
  4403             if (!ctx->writable) {
       
  4404                 ret = -EPERM;
       
  4405                 break;
       
  4406             }
       
  4407             ret = ec_ioctl_sc_dc(master, arg, ctx);
       
  4408             break;
       
  4409         case EC_IOCTL_SC_SDO:
       
  4410             if (!ctx->writable) {
       
  4411                 ret = -EPERM;
       
  4412                 break;
       
  4413             }
       
  4414             ret = ec_ioctl_sc_sdo(master, arg, ctx);
       
  4415             break;
       
  4416         case EC_IOCTL_SC_EMERG_SIZE:
       
  4417             if (!ctx->writable) {
       
  4418                 ret = -EPERM;
       
  4419                 break;
       
  4420             }
       
  4421             ret = ec_ioctl_sc_emerg_size(master, arg, ctx);
       
  4422             break;
       
  4423         case EC_IOCTL_SC_EMERG_POP:
       
  4424             if (!ctx->writable) {
       
  4425                 ret = -EPERM;
       
  4426                 break;
       
  4427             }
       
  4428             ret = ec_ioctl_sc_emerg_pop(master, arg, ctx);
       
  4429             break;
       
  4430         case EC_IOCTL_SC_EMERG_CLEAR:
       
  4431             if (!ctx->writable) {
       
  4432                 ret = -EPERM;
       
  4433                 break;
       
  4434             }
       
  4435             ret = ec_ioctl_sc_emerg_clear(master, arg, ctx);
       
  4436             break;
       
  4437         case EC_IOCTL_SC_EMERG_OVERRUNS:
       
  4438             ret = ec_ioctl_sc_emerg_overruns(master, arg, ctx);
       
  4439             break;
       
  4440         case EC_IOCTL_SC_SDO_REQUEST:
       
  4441             if (!ctx->writable) {
       
  4442                 ret = -EPERM;
       
  4443                 break;
       
  4444             }
       
  4445             ret = ec_ioctl_sc_create_sdo_request(master, arg, ctx);
       
  4446             break;
       
  4447         case EC_IOCTL_SC_REG_REQUEST:
       
  4448             if (!ctx->writable) {
       
  4449                 ret = -EPERM;
       
  4450                 break;
       
  4451             }
       
  4452             ret = ec_ioctl_sc_create_reg_request(master, arg, ctx);
       
  4453             break;
       
  4454         case EC_IOCTL_SC_VOE:
       
  4455             if (!ctx->writable) {
       
  4456                 ret = -EPERM;
       
  4457                 break;
       
  4458             }
       
  4459             ret = ec_ioctl_sc_create_voe_handler(master, arg, ctx);
       
  4460             break;
       
  4461         case EC_IOCTL_SC_STATE:
       
  4462             ret = ec_ioctl_sc_state(master, arg, ctx);
       
  4463             break;
       
  4464         case EC_IOCTL_SC_IDN:
       
  4465             if (!ctx->writable) {
       
  4466                 ret = -EPERM;
       
  4467                 break;
       
  4468             }
       
  4469             ret = ec_ioctl_sc_idn(master, arg, ctx);
       
  4470             break;
       
  4471         case EC_IOCTL_DOMAIN_SIZE:
       
  4472             ret = ec_ioctl_domain_size(master, arg, ctx);
       
  4473             break;
       
  4474         case EC_IOCTL_DOMAIN_OFFSET:
       
  4475             ret = ec_ioctl_domain_offset(master, arg, ctx);
       
  4476             break;
       
  4477         case EC_IOCTL_DOMAIN_PROCESS:
       
  4478             if (!ctx->writable) {
       
  4479                 ret = -EPERM;
       
  4480                 break;
       
  4481             }
       
  4482             ret = ec_ioctl_domain_process(master, arg, ctx);
       
  4483             break;
       
  4484         case EC_IOCTL_DOMAIN_QUEUE:
       
  4485             if (!ctx->writable) {
       
  4486                 ret = -EPERM;
       
  4487                 break;
       
  4488             }
       
  4489             ret = ec_ioctl_domain_queue(master, arg, ctx);
       
  4490             break;
       
  4491         case EC_IOCTL_DOMAIN_STATE:
       
  4492             ret = ec_ioctl_domain_state(master, arg, ctx);
       
  4493             break;
       
  4494         case EC_IOCTL_SDO_REQUEST_INDEX:
       
  4495             if (!ctx->writable) {
       
  4496                 ret = -EPERM;
       
  4497                 break;
       
  4498             }
       
  4499             ret = ec_ioctl_sdo_request_index(master, arg, ctx);
       
  4500             break;
       
  4501         case EC_IOCTL_SDO_REQUEST_TIMEOUT:
       
  4502             if (!ctx->writable) {
       
  4503                 ret = -EPERM;
       
  4504                 break;
       
  4505             }
       
  4506             ret = ec_ioctl_sdo_request_timeout(master, arg, ctx);
       
  4507             break;
       
  4508         case EC_IOCTL_SDO_REQUEST_STATE:
       
  4509             ret = ec_ioctl_sdo_request_state(master, arg, ctx);
       
  4510             break;
       
  4511         case EC_IOCTL_SDO_REQUEST_READ:
       
  4512             if (!ctx->writable) {
       
  4513                 ret = -EPERM;
       
  4514                 break;
       
  4515             }
       
  4516             ret = ec_ioctl_sdo_request_read(master, arg, ctx);
       
  4517             break;
       
  4518         case EC_IOCTL_SDO_REQUEST_WRITE:
       
  4519             if (!ctx->writable) {
       
  4520                 ret = -EPERM;
       
  4521                 break;
       
  4522             }
       
  4523             ret = ec_ioctl_sdo_request_write(master, arg, ctx);
       
  4524             break;
       
  4525         case EC_IOCTL_SDO_REQUEST_DATA:
       
  4526             ret = ec_ioctl_sdo_request_data(master, arg, ctx);
       
  4527             break;
       
  4528         case EC_IOCTL_REG_REQUEST_DATA:
       
  4529             ret = ec_ioctl_reg_request_data(master, arg, ctx);
       
  4530             break;
       
  4531         case EC_IOCTL_REG_REQUEST_STATE:
       
  4532             ret = ec_ioctl_reg_request_state(master, arg, ctx);
       
  4533             break;
       
  4534         case EC_IOCTL_REG_REQUEST_WRITE:
       
  4535             if (!ctx->writable) {
       
  4536                 ret = -EPERM;
       
  4537                 break;
       
  4538             }
       
  4539             ret = ec_ioctl_reg_request_write(master, arg, ctx);
       
  4540             break;
       
  4541         case EC_IOCTL_REG_REQUEST_READ:
       
  4542             if (!ctx->writable) {
       
  4543                 ret = -EPERM;
       
  4544                 break;
       
  4545             }
       
  4546             ret = ec_ioctl_reg_request_read(master, arg, ctx);
       
  4547             break;
       
  4548         case EC_IOCTL_VOE_SEND_HEADER:
       
  4549             if (!ctx->writable) {
       
  4550                 ret = -EPERM;
       
  4551                 break;
       
  4552             }
       
  4553             ret = ec_ioctl_voe_send_header(master, arg, ctx);
       
  4554             break;
       
  4555         case EC_IOCTL_VOE_REC_HEADER:
       
  4556             ret = ec_ioctl_voe_rec_header(master, arg, ctx);
       
  4557             break;
       
  4558         case EC_IOCTL_VOE_READ:
       
  4559             if (!ctx->writable) {
       
  4560                 ret = -EPERM;
       
  4561                 break;
       
  4562             }
       
  4563             ret = ec_ioctl_voe_read(master, arg, ctx);
       
  4564             break;
       
  4565         case EC_IOCTL_VOE_READ_NOSYNC:
       
  4566             if (!ctx->writable) {
       
  4567                 ret = -EPERM;
       
  4568                 break;
       
  4569             }
       
  4570             ret = ec_ioctl_voe_read_nosync(master, arg, ctx);
       
  4571             break;
       
  4572         case EC_IOCTL_VOE_WRITE:
       
  4573             if (!ctx->writable) {
       
  4574                 ret = -EPERM;
       
  4575                 break;
       
  4576             }
       
  4577             ret = ec_ioctl_voe_write(master, arg, ctx);
       
  4578             break;
       
  4579         case EC_IOCTL_VOE_EXEC:
       
  4580             if (!ctx->writable) {
       
  4581                 ret = -EPERM;
       
  4582                 break;
       
  4583             }
       
  4584             ret = ec_ioctl_voe_exec(master, arg, ctx);
       
  4585             break;
       
  4586         case EC_IOCTL_VOE_DATA:
       
  4587             ret = ec_ioctl_voe_data(master, arg, ctx);
       
  4588             break;
       
  4589         case EC_IOCTL_SET_SEND_INTERVAL:
       
  4590             if (!ctx->writable) {
       
  4591                 ret = -EPERM;
       
  4592                 break;
       
  4593             }
       
  4594             ret = ec_ioctl_set_send_interval(master, arg, ctx);
       
  4595             break;
       
  4596         default:
       
  4597             ret = -ENOTTY;
       
  4598             break;
       
  4599     }
       
  4600 
       
  4601 #if DEBUG_LATENCY
       
  4602     b = get_cycles();
       
  4603     t = (unsigned int) ((b - a) * 1000LL) / cpu_khz;
       
  4604     if (t > 50) {
       
  4605         EC_MASTER_WARN(master, "ioctl(0x%02x) took %u us.\n",
       
  4606                 _IOC_NR(cmd), t);
       
  4607     }
       
  4608 #endif
       
  4609 
       
  4610     return ret;
       
  4611 }
       
  4612 
       
  4613 /*****************************************************************************/