--- a/master/cdev.c Thu Sep 06 14:21:02 2012 +0200
+++ b/master/cdev.c Mon Nov 03 15:20:05 2014 +0100
@@ -2,7 +2,7 @@
*
* $Id$
*
- * Copyright (C) 2006-2008 Florian Pose, Ingenieurgemeinschaft IgH
+ * Copyright (C) 2006-2012 Florian Pose, Ingenieurgemeinschaft IgH
*
* This file is part of the IgH EtherCAT Master.
*
@@ -45,15 +45,9 @@
#include "ethernet.h"
#include "ioctl.h"
-/** Set to 1 to enable ioctl() command debugging.
- */
-#define DEBUG_IOCTL 0
-
-/** Set to 1 to enable ioctl() latency warnings.
- *
- * Requires CPU timestamp counter!
- */
-#define DEBUG_LATENCY 0
+/** Set to 1 to enable device operations debugging.
+ */
+#define DEBUG 0
/*****************************************************************************/
@@ -102,15 +96,13 @@
*/
typedef struct {
ec_cdev_t *cdev; /**< Character device. */
- unsigned int requested; /**< Master wac requested via this file handle. */
- uint8_t *process_data; /**< Total process data area. */
- size_t process_data_size; /**< Size of the \a process_data. */
+ ec_ioctl_context_t ctx; /**< Context. */
} ec_cdev_priv_t;
/*****************************************************************************/
/** Constructor.
- *
+ *
* \return 0 in case of success, else < 0
*/
int ec_cdev_init(
@@ -144,3305 +136,6 @@
cdev_del(&cdev->cdev);
}
-/*****************************************************************************/
-
-/** Copies a string to an ioctl structure.
- */
-void ec_cdev_strcpy(
- char *target, /**< Target. */
- const char *source /**< Source. */
- )
-{
- if (source) {
- strncpy(target, source, EC_IOCTL_STRING_SIZE);
- target[EC_IOCTL_STRING_SIZE - 1] = 0;
- } else {
- target[0] = 0;
- }
-}
-
-/*****************************************************************************/
-
-/** Get module information.
- */
-int ec_cdev_ioctl_module(
- unsigned long arg /**< Userspace address to store the results. */
- )
-{
- ec_ioctl_module_t data;
-
- data.ioctl_version_magic = EC_IOCTL_VERSION_MAGIC;
- data.master_count = ec_master_count();
-
- if (copy_to_user((void __user *) arg, &data, sizeof(data)))
- return -EFAULT;
-
- return 0;
-}
-
-/*****************************************************************************/
-
-/** Get master information.
- */
-int ec_cdev_ioctl_master(
- ec_master_t *master, /**< EtherCAT master. */
- unsigned long arg /**< Userspace address to store the results. */
- )
-{
- ec_ioctl_master_t data;
- unsigned int i;
-
- if (ec_mutex_lock_interruptible(&master->master_mutex))
- return -EINTR;
- data.slave_count = master->slave_count;
- data.config_count = ec_master_config_count(master);
- data.domain_count = ec_master_domain_count(master);
-#ifdef EC_EOE
- data.eoe_handler_count = ec_master_eoe_handler_count(master);
-#endif
- data.phase = (uint8_t) master->phase;
- data.active = (uint8_t) master->active;
- data.scan_busy = master->scan_busy;
- ec_mutex_unlock(&master->master_mutex);
-
- if (ec_mutex_lock_interruptible(&master->device_mutex))
- return -EINTR;
-
- if (master->main_device.dev) {
- memcpy(data.devices[0].address,
- master->main_device.dev->dev_addr, ETH_ALEN);
- } else {
- memcpy(data.devices[0].address, master->main_mac, ETH_ALEN);
- }
- data.devices[0].attached = master->main_device.dev ? 1 : 0;
- data.devices[0].link_state = master->main_device.link_state ? 1 : 0;
- data.devices[0].tx_count = master->main_device.tx_count;
- data.devices[0].rx_count = master->main_device.rx_count;
- data.devices[0].tx_bytes = master->main_device.tx_bytes;
- data.devices[0].tx_errors = master->main_device.tx_errors;
- for (i = 0; i < EC_RATE_COUNT; i++) {
- data.devices[0].tx_frame_rates[i] =
- master->main_device.tx_frame_rates[i];
- data.devices[0].tx_byte_rates[i] =
- master->main_device.tx_byte_rates[i];
- data.devices[0].loss_rates[i] = master->main_device.loss_rates[i];
- }
-
- if (master->backup_device.dev) {
- memcpy(data.devices[1].address,
- master->backup_device.dev->dev_addr, ETH_ALEN);
- } else {
- memcpy(data.devices[1].address, master->backup_mac, ETH_ALEN);
- }
- data.devices[1].attached = master->backup_device.dev ? 1 : 0;
- data.devices[1].link_state = master->backup_device.link_state ? 1 : 0;
- data.devices[1].tx_count = master->backup_device.tx_count;
- data.devices[1].rx_count = master->backup_device.rx_count;
- data.devices[1].tx_bytes = master->backup_device.tx_bytes;
- data.devices[1].tx_errors = master->backup_device.tx_errors;
- for (i = 0; i < EC_RATE_COUNT; i++) {
- data.devices[1].tx_frame_rates[i] =
- master->backup_device.tx_frame_rates[i];
- data.devices[1].tx_byte_rates[i] =
- master->backup_device.tx_byte_rates[i];
- data.devices[1].loss_rates[i] = master->backup_device.loss_rates[i];
- }
-
- ec_mutex_unlock(&master->device_mutex);
-
- data.app_time = master->app_time;
- data.ref_clock =
- master->dc_ref_clock ? master->dc_ref_clock->ring_position : 0xffff;
-
- if (copy_to_user((void __user *) arg, &data, sizeof(data)))
- return -EFAULT;
-
- return 0;
-}
-
-/*****************************************************************************/
-
-/** Get slave information.
- */
-int ec_cdev_ioctl_slave(
- ec_master_t *master, /**< EtherCAT master. */
- unsigned long arg /**< Userspace address to store the results. */
- )
-{
- ec_ioctl_slave_t data;
- const ec_slave_t *slave;
- int i;
-
- if (copy_from_user(&data, (void __user *) arg, sizeof(data))) {
- return -EFAULT;
- }
-
- if (ec_mutex_lock_interruptible(&master->master_mutex))
- return -EINTR;
-
- if (!(slave = ec_master_find_slave_const(
- master, 0, data.position))) {
- ec_mutex_unlock(&master->master_mutex);
- EC_MASTER_ERR(master, "Slave %u does not exist!\n", data.position);
- return -EINVAL;
- }
-
- data.vendor_id = slave->sii.vendor_id;
- data.product_code = slave->sii.product_code;
- data.revision_number = slave->sii.revision_number;
- data.serial_number = slave->sii.serial_number;
- data.alias = slave->effective_alias;
- data.boot_rx_mailbox_offset = slave->sii.boot_rx_mailbox_offset;
- data.boot_rx_mailbox_size = slave->sii.boot_rx_mailbox_size;
- data.boot_tx_mailbox_offset = slave->sii.boot_tx_mailbox_offset;
- data.boot_tx_mailbox_size = slave->sii.boot_tx_mailbox_size;
- data.std_rx_mailbox_offset = slave->sii.std_rx_mailbox_offset;
- data.std_rx_mailbox_size = slave->sii.std_rx_mailbox_size;
- data.std_tx_mailbox_offset = slave->sii.std_tx_mailbox_offset;
- data.std_tx_mailbox_size = slave->sii.std_tx_mailbox_size;
- data.mailbox_protocols = slave->sii.mailbox_protocols;
- data.has_general_category = slave->sii.has_general;
- data.coe_details = slave->sii.coe_details;
- data.general_flags = slave->sii.general_flags;
- data.current_on_ebus = slave->sii.current_on_ebus;
- for (i = 0; i < EC_MAX_PORTS; i++) {
- data.ports[i].desc = slave->ports[i].desc;
- data.ports[i].link.link_up = slave->ports[i].link.link_up;
- data.ports[i].link.loop_closed = slave->ports[i].link.loop_closed;
- data.ports[i].link.signal_detected =
- slave->ports[i].link.signal_detected;
- data.ports[i].receive_time = slave->ports[i].receive_time;
- if (slave->ports[i].next_slave) {
- data.ports[i].next_slave =
- slave->ports[i].next_slave->ring_position;
- } else {
- data.ports[i].next_slave = 0xffff;
- }
- data.ports[i].delay_to_next_dc = slave->ports[i].delay_to_next_dc;
- }
- data.fmmu_bit = slave->base_fmmu_bit_operation;
- data.dc_supported = slave->base_dc_supported;
- data.dc_range = slave->base_dc_range;
- data.has_dc_system_time = slave->has_dc_system_time;
- data.transmission_delay = slave->transmission_delay;
- data.al_state = slave->current_state;
- data.error_flag = slave->error_flag;
-
- data.sync_count = slave->sii.sync_count;
- data.sdo_count = ec_slave_sdo_count(slave);
- data.sii_nwords = slave->sii_nwords;
- ec_cdev_strcpy(data.group, slave->sii.group);
- ec_cdev_strcpy(data.image, slave->sii.image);
- ec_cdev_strcpy(data.order, slave->sii.order);
- ec_cdev_strcpy(data.name, slave->sii.name);
-
- ec_mutex_unlock(&master->master_mutex);
-
- if (copy_to_user((void __user *) arg, &data, sizeof(data)))
- return -EFAULT;
-
- return 0;
-}
-
-/*****************************************************************************/
-
-/** Get slave sync manager information.
- */
-int ec_cdev_ioctl_slave_sync(
- ec_master_t *master, /**< EtherCAT master. */
- unsigned long arg /**< Userspace address to store the results. */
- )
-{
- ec_ioctl_slave_sync_t data;
- const ec_slave_t *slave;
- const ec_sync_t *sync;
-
- if (copy_from_user(&data, (void __user *) arg, sizeof(data))) {
- return -EFAULT;
- }
-
- if (ec_mutex_lock_interruptible(&master->master_mutex))
- return -EINTR;
-
- if (!(slave = ec_master_find_slave_const(
- master, 0, data.slave_position))) {
- ec_mutex_unlock(&master->master_mutex);
- EC_MASTER_ERR(master, "Slave %u does not exist!\n",
- data.slave_position);
- return -EINVAL;
- }
-
- if (data.sync_index >= slave->sii.sync_count) {
- ec_mutex_unlock(&master->master_mutex);
- EC_SLAVE_ERR(slave, "Sync manager %u does not exist!\n",
- data.sync_index);
- return -EINVAL;
- }
-
- sync = &slave->sii.syncs[data.sync_index];
-
- data.physical_start_address = sync->physical_start_address;
- data.default_size = sync->default_length;
- data.control_register = sync->control_register;
- data.enable = sync->enable;
- data.pdo_count = ec_pdo_list_count(&sync->pdos);
-
- ec_mutex_unlock(&master->master_mutex);
-
- if (copy_to_user((void __user *) arg, &data, sizeof(data)))
- return -EFAULT;
-
- return 0;
-}
-
-/*****************************************************************************/
-
-/** Get slave sync manager PDO information.
- */
-int ec_cdev_ioctl_slave_sync_pdo(
- ec_master_t *master, /**< EtherCAT master. */
- unsigned long arg /**< Userspace address to store the results. */
- )
-{
- ec_ioctl_slave_sync_pdo_t data;
- const ec_slave_t *slave;
- const ec_sync_t *sync;
- const ec_pdo_t *pdo;
-
- if (copy_from_user(&data, (void __user *) arg, sizeof(data))) {
- return -EFAULT;
- }
-
- if (ec_mutex_lock_interruptible(&master->master_mutex))
- return -EINTR;
-
- if (!(slave = ec_master_find_slave_const(
- master, 0, data.slave_position))) {
- ec_mutex_unlock(&master->master_mutex);
- EC_MASTER_ERR(master, "Slave %u does not exist!\n",
- data.slave_position);
- return -EINVAL;
- }
-
- if (data.sync_index >= slave->sii.sync_count) {
- ec_mutex_unlock(&master->master_mutex);
- EC_SLAVE_ERR(slave, "Sync manager %u does not exist!\n",
- data.sync_index);
- return -EINVAL;
- }
-
- sync = &slave->sii.syncs[data.sync_index];
- if (!(pdo = ec_pdo_list_find_pdo_by_pos_const(
- &sync->pdos, data.pdo_pos))) {
- ec_mutex_unlock(&master->master_mutex);
- EC_SLAVE_ERR(slave, "Sync manager %u does not contain a PDO with "
- "position %u!\n", data.sync_index, data.pdo_pos);
- return -EINVAL;
- }
-
- data.index = pdo->index;
- data.entry_count = ec_pdo_entry_count(pdo);
- ec_cdev_strcpy(data.name, pdo->name);
-
- ec_mutex_unlock(&master->master_mutex);
-
- if (copy_to_user((void __user *) arg, &data, sizeof(data)))
- return -EFAULT;
-
- return 0;
-}
-
-/*****************************************************************************/
-
-/** Get slave sync manager PDO entry information.
- */
-int ec_cdev_ioctl_slave_sync_pdo_entry(
- ec_master_t *master, /**< EtherCAT master. */
- unsigned long arg /**< Userspace address to store the results. */
- )
-{
- ec_ioctl_slave_sync_pdo_entry_t data;
- const ec_slave_t *slave;
- const ec_sync_t *sync;
- const ec_pdo_t *pdo;
- const ec_pdo_entry_t *entry;
-
- if (copy_from_user(&data, (void __user *) arg, sizeof(data))) {
- return -EFAULT;
- }
-
- if (ec_mutex_lock_interruptible(&master->master_mutex))
- return -EINTR;
-
- if (!(slave = ec_master_find_slave_const(
- master, 0, data.slave_position))) {
- ec_mutex_unlock(&master->master_mutex);
- EC_MASTER_ERR(master, "Slave %u does not exist!\n",
- data.slave_position);
- return -EINVAL;
- }
-
- if (data.sync_index >= slave->sii.sync_count) {
- ec_mutex_unlock(&master->master_mutex);
- EC_SLAVE_ERR(slave, "Sync manager %u does not exist!\n",
- data.sync_index);
- return -EINVAL;
- }
-
- sync = &slave->sii.syncs[data.sync_index];
- if (!(pdo = ec_pdo_list_find_pdo_by_pos_const(
- &sync->pdos, data.pdo_pos))) {
- ec_mutex_unlock(&master->master_mutex);
- EC_SLAVE_ERR(slave, "Sync manager %u does not contain a PDO with "
- "position %u!\n", data.sync_index, data.pdo_pos);
- return -EINVAL;
- }
-
- if (!(entry = ec_pdo_find_entry_by_pos_const(
- pdo, data.entry_pos))) {
- ec_mutex_unlock(&master->master_mutex);
- EC_SLAVE_ERR(slave, "PDO 0x%04X does not contain an entry with "
- "position %u!\n", data.pdo_pos, data.entry_pos);
- return -EINVAL;
- }
-
- data.index = entry->index;
- data.subindex = entry->subindex;
- data.bit_length = entry->bit_length;
- ec_cdev_strcpy(data.name, entry->name);
-
- ec_mutex_unlock(&master->master_mutex);
-
- if (copy_to_user((void __user *) arg, &data, sizeof(data)))
- return -EFAULT;
-
- return 0;
-}
-
-/*****************************************************************************/
-
-/** Get domain information.
- */
-int ec_cdev_ioctl_domain(
- ec_master_t *master, /**< EtherCAT master. */
- unsigned long arg /**< Userspace address to store the results. */
- )
-{
- ec_ioctl_domain_t data;
- const ec_domain_t *domain;
-
- if (copy_from_user(&data, (void __user *) arg, sizeof(data))) {
- return -EFAULT;
- }
-
- if (ec_mutex_lock_interruptible(&master->master_mutex))
- return -EINTR;
-
- if (!(domain = ec_master_find_domain_const(master, data.index))) {
- ec_mutex_unlock(&master->master_mutex);
- EC_MASTER_ERR(master, "Domain %u does not exist!\n", data.index);
- return -EINVAL;
- }
-
- data.data_size = domain->data_size;
- data.tx_size = domain->tx_size;
- data.logical_base_address = domain->logical_base_address;
- data.working_counter = domain->working_counter;
- data.expected_working_counter = domain->expected_working_counter;
- data.fmmu_count = ec_domain_fmmu_count(domain);
-
- ec_mutex_unlock(&master->master_mutex);
-
- if (copy_to_user((void __user *) arg, &data, sizeof(data)))
- return -EFAULT;
-
- return 0;
-}
-
-/*****************************************************************************/
-
-/** Get domain FMMU information.
- */
-int ec_cdev_ioctl_domain_fmmu(
- ec_master_t *master, /**< EtherCAT master. */
- unsigned long arg /**< Userspace address to store the results. */
- )
-{
- ec_ioctl_domain_fmmu_t data;
- const ec_domain_t *domain;
- const ec_fmmu_config_t *fmmu;
-
- if (copy_from_user(&data, (void __user *) arg, sizeof(data))) {
- return -EFAULT;
- }
-
- if (ec_mutex_lock_interruptible(&master->master_mutex))
- return -EINTR;
-
- if (!(domain = ec_master_find_domain_const(master, data.domain_index))) {
- ec_mutex_unlock(&master->master_mutex);
- EC_MASTER_ERR(master, "Domain %u does not exist!\n",
- data.domain_index);
- return -EINVAL;
- }
-
- if (!(fmmu = ec_domain_find_fmmu(domain, data.fmmu_index))) {
- ec_mutex_unlock(&master->master_mutex);
- EC_MASTER_ERR(master, "Domain %u has less than %u"
- " fmmu configurations.\n",
- data.domain_index, data.fmmu_index + 1);
- return -EINVAL;
- }
-
- data.slave_config_alias = fmmu->sc->alias;
- data.slave_config_position = fmmu->sc->position;
- data.sync_index = fmmu->sync_index;
- data.dir = fmmu->dir;
- data.logical_address = fmmu->logical_start_address;
- data.domain_address = fmmu->domain_address;
- data.data_size = fmmu->data_size;
-
- ec_mutex_unlock(&master->master_mutex);
-
- if (copy_to_user((void __user *) arg, &data, sizeof(data)))
- return -EFAULT;
-
- return 0;
-}
-
-/*****************************************************************************/
-
-/** Get domain data.
- */
-int ec_cdev_ioctl_domain_data(
- ec_master_t *master, /**< EtherCAT master. */
- unsigned long arg /**< Userspace address to store the results. */
- )
-{
- ec_ioctl_domain_data_t data;
- const ec_domain_t *domain;
-
- if (copy_from_user(&data, (void __user *) arg, sizeof(data))) {
- return -EFAULT;
- }
-
- if (ec_mutex_lock_interruptible(&master->master_mutex))
- return -EINTR;
-
- if (!(domain = ec_master_find_domain_const(master, data.domain_index))) {
- ec_mutex_unlock(&master->master_mutex);
- EC_MASTER_ERR(master, "Domain %u does not exist!\n",
- data.domain_index);
- return -EINVAL;
- }
-
- if (domain->data_size != data.data_size) {
- ec_mutex_unlock(&master->master_mutex);
- EC_MASTER_ERR(master, "Data size mismatch %u/%zu!\n",
- data.data_size, domain->data_size);
- return -EFAULT;
- }
-
- if (copy_to_user((void __user *) data.target, domain->data,
- domain->data_size)) {
- ec_mutex_unlock(&master->master_mutex);
- return -EFAULT;
- }
-
- ec_mutex_unlock(&master->master_mutex);
- return 0;
-}
-
-/*****************************************************************************/
-
-/** Set master debug level.
- */
-int ec_cdev_ioctl_master_debug(
- ec_master_t *master, /**< EtherCAT master. */
- unsigned long arg /**< ioctl() argument. */
- )
-{
- return ec_master_debug_level(master, (unsigned int) arg);
-}
-
-/*****************************************************************************/
-
-/** Issue a bus scan.
- */
-int ec_cdev_ioctl_master_rescan(
- ec_master_t *master, /**< EtherCAT master. */
- unsigned long arg /**< ioctl() argument. */
- )
-{
- master->fsm.rescan_required = 1;
- return 0;
-}
-
-/*****************************************************************************/
-
-/** Set slave state.
- */
-int ec_cdev_ioctl_slave_state(
- ec_master_t *master, /**< EtherCAT master. */
- unsigned long arg /**< ioctl() argument. */
- )
-{
- ec_ioctl_slave_state_t data;
- ec_slave_t *slave;
-
- if (copy_from_user(&data, (void __user *) arg, sizeof(data))) {
- return -EFAULT;
- }
-
- if (ec_mutex_lock_interruptible(&master->master_mutex))
- return -EINTR;
-
- if (!(slave = ec_master_find_slave(
- master, 0, data.slave_position))) {
- ec_mutex_unlock(&master->master_mutex);
- EC_MASTER_ERR(master, "Slave %u does not exist!\n",
- data.slave_position);
- return -EINVAL;
- }
-
- ec_slave_request_state(slave, data.al_state);
-
- ec_mutex_unlock(&master->master_mutex);
- return 0;
-}
-
-/*****************************************************************************/
-
-/** Get slave SDO information.
- */
-int ec_cdev_ioctl_slave_sdo(
- ec_master_t *master, /**< EtherCAT master. */
- unsigned long arg /**< ioctl() argument. */
- )
-{
- ec_ioctl_slave_sdo_t data;
- const ec_slave_t *slave;
- const ec_sdo_t *sdo;
-
- if (copy_from_user(&data, (void __user *) arg, sizeof(data))) {
- return -EFAULT;
- }
-
- if (ec_mutex_lock_interruptible(&master->master_mutex))
- return -EINTR;
-
- if (!(slave = ec_master_find_slave_const(
- master, 0, data.slave_position))) {
- ec_mutex_unlock(&master->master_mutex);
- EC_MASTER_ERR(master, "Slave %u does not exist!\n",
- data.slave_position);
- return -EINVAL;
- }
-
- if (!(sdo = ec_slave_get_sdo_by_pos_const(
- slave, data.sdo_position))) {
- ec_mutex_unlock(&master->master_mutex);
- EC_SLAVE_ERR(slave, "SDO %u does not exist!\n", data.sdo_position);
- return -EINVAL;
- }
-
- data.sdo_index = sdo->index;
- data.max_subindex = sdo->max_subindex;
- ec_cdev_strcpy(data.name, sdo->name);
-
- ec_mutex_unlock(&master->master_mutex);
-
- if (copy_to_user((void __user *) arg, &data, sizeof(data)))
- return -EFAULT;
-
- return 0;
-}
-
-/*****************************************************************************/
-
-/** Get slave SDO entry information.
- */
-int ec_cdev_ioctl_slave_sdo_entry(
- ec_master_t *master, /**< EtherCAT master. */
- unsigned long arg /**< ioctl() argument. */
- )
-{
- ec_ioctl_slave_sdo_entry_t data;
- const ec_slave_t *slave;
- const ec_sdo_t *sdo;
- const ec_sdo_entry_t *entry;
-
- if (copy_from_user(&data, (void __user *) arg, sizeof(data))) {
- return -EFAULT;
- }
-
- if (ec_mutex_lock_interruptible(&master->master_mutex))
- return -EINTR;
-
- if (!(slave = ec_master_find_slave_const(
- master, 0, data.slave_position))) {
- ec_mutex_unlock(&master->master_mutex);
- EC_MASTER_ERR(master, "Slave %u does not exist!\n",
- data.slave_position);
- return -EINVAL;
- }
-
- if (data.sdo_spec <= 0) {
- if (!(sdo = ec_slave_get_sdo_by_pos_const(
- slave, -data.sdo_spec))) {
- ec_mutex_unlock(&master->master_mutex);
- EC_SLAVE_ERR(slave, "SDO %u does not exist!\n", -data.sdo_spec);
- return -EINVAL;
- }
- } else {
- if (!(sdo = ec_slave_get_sdo_const(
- slave, data.sdo_spec))) {
- ec_mutex_unlock(&master->master_mutex);
- EC_SLAVE_ERR(slave, "SDO 0x%04X does not exist!\n",
- data.sdo_spec);
- return -EINVAL;
- }
- }
-
- if (!(entry = ec_sdo_get_entry_const(
- sdo, data.sdo_entry_subindex))) {
- ec_mutex_unlock(&master->master_mutex);
- EC_SLAVE_ERR(slave, "SDO entry 0x%04X:%02X does not exist!\n",
- sdo->index, data.sdo_entry_subindex);
- return -EINVAL;
- }
-
- data.data_type = entry->data_type;
- data.bit_length = entry->bit_length;
- data.read_access[EC_SDO_ENTRY_ACCESS_PREOP] =
- entry->read_access[EC_SDO_ENTRY_ACCESS_PREOP];
- data.read_access[EC_SDO_ENTRY_ACCESS_SAFEOP] =
- entry->read_access[EC_SDO_ENTRY_ACCESS_SAFEOP];
- data.read_access[EC_SDO_ENTRY_ACCESS_OP] =
- entry->read_access[EC_SDO_ENTRY_ACCESS_OP];
- data.write_access[EC_SDO_ENTRY_ACCESS_PREOP] =
- entry->write_access[EC_SDO_ENTRY_ACCESS_PREOP];
- data.write_access[EC_SDO_ENTRY_ACCESS_SAFEOP] =
- entry->write_access[EC_SDO_ENTRY_ACCESS_SAFEOP];
- data.write_access[EC_SDO_ENTRY_ACCESS_OP] =
- entry->write_access[EC_SDO_ENTRY_ACCESS_OP];
- ec_cdev_strcpy(data.description, entry->description);
-
- ec_mutex_unlock(&master->master_mutex);
-
- if (copy_to_user((void __user *) arg, &data, sizeof(data)))
- return -EFAULT;
-
- return 0;
-}
-
-/*****************************************************************************/
-
-/** Upload SDO.
- */
-int ec_cdev_ioctl_slave_sdo_upload(
- ec_master_t *master, /**< EtherCAT master. */
- unsigned long arg /**< ioctl() argument. */
- )
-{
- ec_ioctl_slave_sdo_upload_t data;
- uint8_t *target;
- int ret;
-
- if (copy_from_user(&data, (void __user *) arg, sizeof(data))) {
- return -EFAULT;
- }
-
- if (!(target = kmalloc(data.target_size, GFP_KERNEL))) {
- EC_MASTER_ERR(master, "Failed to allocate %u bytes"
- " for SDO upload.\n", data.target_size);
- return -ENOMEM;
- }
-
- ret = ecrt_master_sdo_upload(master, data.slave_position,
- data.sdo_index, data.sdo_entry_subindex, target,
- data.target_size, &data.data_size, &data.abort_code);
-
- if (!ret) {
- if (copy_to_user((void __user *) data.target,
- target, data.data_size)) {
- kfree(target);
- return -EFAULT;
- }
- }
-
- kfree(target);
-
- if (__copy_to_user((void __user *) arg, &data, sizeof(data))) {
- return -EFAULT;
- }
-
- return 0;
-}
-
-/*****************************************************************************/
-
-/** Download SDO.
- */
-int ec_cdev_ioctl_slave_sdo_download(
- ec_master_t *master, /**< EtherCAT master. */
- unsigned long arg /**< ioctl() argument. */
- )
-{
- ec_ioctl_slave_sdo_download_t data;
- uint8_t *sdo_data;
- int retval;
-
- if (copy_from_user(&data, (void __user *) arg, sizeof(data))) {
- return -EFAULT;
- }
-
- if (!(sdo_data = kmalloc(data.data_size, GFP_KERNEL))) {
- EC_MASTER_ERR(master, "Failed to allocate %u bytes"
- " for SDO download.\n", data.data_size);
- return -ENOMEM;
- }
-
- if (copy_from_user(sdo_data, (void __user *) data.data, data.data_size)) {
- kfree(sdo_data);
- return -EFAULT;
- }
-
- if (data.complete_access) {
- retval = ecrt_master_sdo_download_complete(master, data.slave_position,
- data.sdo_index, sdo_data, data.data_size, &data.abort_code);
- } else {
- retval = ecrt_master_sdo_download(master, data.slave_position,
- data.sdo_index, data.sdo_entry_subindex, sdo_data,
- data.data_size, &data.abort_code);
- }
-
- kfree(sdo_data);
-
- if (__copy_to_user((void __user *) arg, &data, sizeof(data))) {
- retval = -EFAULT;
- }
-
- return retval;
-}
-
-/*****************************************************************************/
-
-/** Read a slave's SII.
- */
-int ec_cdev_ioctl_slave_sii_read(
- ec_master_t *master, /**< EtherCAT master. */
- unsigned long arg /**< ioctl() argument. */
- )
-{
- ec_ioctl_slave_sii_t data;
- const ec_slave_t *slave;
- int retval;
-
- if (copy_from_user(&data, (void __user *) arg, sizeof(data))) {
- return -EFAULT;
- }
-
- if (ec_mutex_lock_interruptible(&master->master_mutex))
- return -EINTR;
-
- if (!(slave = ec_master_find_slave_const(
- master, 0, data.slave_position))) {
- ec_mutex_unlock(&master->master_mutex);
- EC_MASTER_ERR(master, "Slave %u does not exist!\n",
- data.slave_position);
- return -EINVAL;
- }
-
- if (!data.nwords
- || data.offset + data.nwords > slave->sii_nwords) {
- ec_mutex_unlock(&master->master_mutex);
- EC_SLAVE_ERR(slave, "Invalid SII read offset/size %u/%u for slave SII"
- " size %zu!\n", data.offset, data.nwords, slave->sii_nwords);
- return -EINVAL;
- }
-
- if (copy_to_user((void __user *) data.words,
- slave->sii_words + data.offset, data.nwords * 2))
- retval = -EFAULT;
- else
- retval = 0;
-
- ec_mutex_unlock(&master->master_mutex);
- return retval;
-}
-
-/*****************************************************************************/
-
-/** Write a slave's SII.
- */
-int ec_cdev_ioctl_slave_sii_write(
- ec_master_t *master, /**< EtherCAT master. */
- unsigned long arg /**< ioctl() argument. */
- )
-{
- ec_ioctl_slave_sii_t data;
- ec_slave_t *slave;
- unsigned int byte_size;
- uint16_t *words;
- ec_sii_write_request_t* request;
- int retval;
-
- if (copy_from_user(&data, (void __user *) arg, sizeof(data))) {
- return -EFAULT;
- }
-
- if (!data.nwords)
- return 0;
-
- byte_size = sizeof(uint16_t) * data.nwords;
- if (!(words = kmalloc(byte_size, GFP_KERNEL))) {
- EC_MASTER_ERR(master, "Failed to allocate %u bytes"
- " for SII contents.\n", byte_size);
- return -ENOMEM;
- }
-
- request = kmalloc(sizeof(*request), GFP_KERNEL);
- if (!request)
- return -ENOMEM;
- kref_init(&request->refcount);
-
- // init SII write request
- INIT_LIST_HEAD(&request->list);
- request->words = words; /* now "owned" by request, see
- * ec_master_sii_write_request_release */
- request->offset = data.offset;
- request->nwords = data.nwords;
-
- if (copy_from_user(words,
- (void __user *) data.words, byte_size)) {
- kref_put(&request->refcount, ec_master_sii_write_request_release);
- return -EFAULT;
- }
-
- if (ec_mutex_lock_interruptible(&master->master_mutex)) {
- kref_put(&request->refcount, ec_master_sii_write_request_release);
- return -EINTR;
- }
- if (!(slave = ec_master_find_slave(
- master, 0, data.slave_position))) {
- ec_mutex_unlock(&master->master_mutex);
- EC_MASTER_ERR(master, "Slave %u does not exist!\n",
- data.slave_position);
- kref_put(&request->refcount, ec_master_sii_write_request_release);
- return -EINVAL;
- }
-
- request->slave = slave;
- request->state = EC_INT_REQUEST_QUEUED;
-
- // schedule SII write request.
- list_add_tail(&request->list, &master->sii_requests);
- kref_get(&request->refcount);
-
- ec_mutex_unlock(&master->master_mutex);
-
- // wait for processing through FSM
- if (wait_event_interruptible(master->sii_queue,
- ((request->state == EC_INT_REQUEST_SUCCESS) ||
- (request->state == EC_INT_REQUEST_FAILURE)))) {
- // interrupted by signal
- kref_put(&request->refcount, ec_master_sii_write_request_release);
- return -EINTR;
- }
-
- retval = request->state == EC_INT_REQUEST_SUCCESS ? 0 : -EIO;
- kref_put(&request->refcount, ec_master_sii_write_request_release);
-
- return retval;
-}
-
-/*****************************************************************************/
-
-/** Read a slave's registers.
- */
-int ec_cdev_ioctl_slave_reg_read(
- ec_master_t *master, /**< EtherCAT master. */
- unsigned long arg /**< ioctl() argument. */
- )
-{
- ec_ioctl_slave_reg_t data;
- ec_slave_t *slave;
- uint8_t *contents;
- ec_reg_request_t* request;
- int retval;
-
- if (copy_from_user(&data, (void __user *) arg, sizeof(data))) {
- return -EFAULT;
- }
-
- if (!data.length)
- return 0;
-
- if (!(contents = kmalloc(data.length, GFP_KERNEL))) {
- EC_MASTER_ERR(master, "Failed to allocate %u bytes"
- " for register data.\n", data.length);
- return -ENOMEM;
- }
-
- request = kmalloc(sizeof(*request), GFP_KERNEL);
- if (!request)
- return -ENOMEM;
- kref_init(&request->refcount);
-
- // init register request
- INIT_LIST_HEAD(&request->list);
- request->dir = EC_DIR_INPUT;
- request->data = contents; /* now "owned" by request, see
- * ec_master_reg_request_release */
- request->offset = data.offset;
- request->length = data.length;
-
- if (ec_mutex_lock_interruptible(&master->master_mutex)) {
- kref_put(&request->refcount, ec_master_reg_request_release);
- return -EINTR;
- }
- if (!(slave = ec_master_find_slave(
- master, 0, data.slave_position))) {
- ec_mutex_unlock(&master->master_mutex);
- EC_MASTER_ERR(master, "Slave %u does not exist!\n",
- data.slave_position);
- kref_put(&request->refcount, ec_master_reg_request_release);
- return -EINVAL;
- }
-
- request->slave = slave;
- request->state = EC_INT_REQUEST_QUEUED;
-
- // schedule request.
- list_add_tail(&request->list, &master->reg_requests);
- kref_get(&request->refcount);
-
- ec_mutex_unlock(&master->master_mutex);
-
- // wait for processing through FSM
- if (wait_event_interruptible(master->reg_queue,
- ((request->state == EC_INT_REQUEST_SUCCESS) ||
- (request->state == EC_INT_REQUEST_FAILURE)))) {
- // interrupted by signal
- kref_put(&request->refcount, ec_master_reg_request_release);
- return -EINTR;
- }
-
- if (request->state == EC_INT_REQUEST_SUCCESS) {
- if (copy_to_user((void __user *) data.data, request->data,
- data.length)) {
- kref_put(&request->refcount, ec_master_reg_request_release);
- return -EFAULT;
- }
- }
- retval = request->state == EC_INT_REQUEST_SUCCESS ? 0 : -EIO;
-
- kref_put(&request->refcount, ec_master_reg_request_release);
- return retval;
-}
-
-/*****************************************************************************/
-
-/** Write a slave's registers.
- */
-int ec_cdev_ioctl_slave_reg_write(
- ec_master_t *master, /**< EtherCAT master. */
- unsigned long arg /**< ioctl() argument. */
- )
-{
- ec_ioctl_slave_reg_t data;
- ec_slave_t *slave;
- uint8_t *contents;
- ec_reg_request_t* request;
- int retval;
-
- if (copy_from_user(&data, (void __user *) arg, sizeof(data))) {
- return -EFAULT;
- }
-
- if (!data.length)
- return 0;
-
- if (!(contents = kmalloc(data.length, GFP_KERNEL))) {
- EC_MASTER_ERR(master, "Failed to allocate %u bytes"
- " for register data.\n", data.length);
- return -ENOMEM;
- }
-
- if (copy_from_user(contents, (void __user *) data.data, data.length)) {
- kfree(contents);
- return -EFAULT;
- }
-
- request = kmalloc(sizeof(*request), GFP_KERNEL);
- if (!request)
- return -ENOMEM;
- kref_init(&request->refcount);
- // init register request
- INIT_LIST_HEAD(&request->list);
- request->dir = EC_DIR_OUTPUT;
- request->data = contents; /* now "owned" by request, see
- * ec_master_reg_request_release */
- request->offset = data.offset;
- request->length = data.length;
-
- if (ec_mutex_lock_interruptible(&master->master_mutex)) {
- kref_put(&request->refcount, ec_master_reg_request_release);
- return -EINTR;
- }
-
- if (!(slave = ec_master_find_slave(
- master, 0, data.slave_position))) {
- ec_mutex_unlock(&master->master_mutex);
- EC_MASTER_ERR(master, "Slave %u does not exist!\n",
- data.slave_position);
- kref_put(&request->refcount, ec_master_reg_request_release);
- return -EINVAL;
- }
-
- request->slave = slave;
- request->state = EC_INT_REQUEST_QUEUED;
-
- // schedule request.
- list_add_tail(&request->list, &master->reg_requests);
- kref_get(&request->refcount);
-
- ec_mutex_unlock(&master->master_mutex);
-
- // wait for processing through FSM
- if (wait_event_interruptible(master->reg_queue,
- ((request->state == EC_INT_REQUEST_SUCCESS) ||
- (request->state == EC_INT_REQUEST_FAILURE)))) {
- // interrupted by signal
- kref_put(&request->refcount, ec_master_reg_request_release);
- return -EINTR;
- }
-
- retval = request->state == EC_INT_REQUEST_SUCCESS ? 0 : -EIO;
- kref_put(&request->refcount, ec_master_reg_request_release);
- return retval;
-}
-
-/*****************************************************************************/
-
-/** Get slave configuration information.
- */
-int ec_cdev_ioctl_config(
- ec_master_t *master, /**< EtherCAT master. */
- unsigned long arg /**< ioctl() argument. */
- )
-{
- ec_ioctl_config_t data;
- const ec_slave_config_t *sc;
- uint8_t i;
-
- if (copy_from_user(&data, (void __user *) arg, sizeof(data))) {
- return -EFAULT;
- }
-
- if (ec_mutex_lock_interruptible(&master->master_mutex))
- return -EINTR;
-
- if (!(sc = ec_master_get_config_const(
- master, data.config_index))) {
- ec_mutex_unlock(&master->master_mutex);
- EC_MASTER_ERR(master, "Slave config %u does not exist!\n",
- data.config_index);
- return -EINVAL;
- }
-
- data.alias = sc->alias;
- data.position = sc->position;
- data.vendor_id = sc->vendor_id;
- data.product_code = sc->product_code;
- for (i = 0; i < EC_MAX_SYNC_MANAGERS; i++) {
- data.syncs[i].dir = sc->sync_configs[i].dir;
- data.syncs[i].watchdog_mode = sc->sync_configs[i].watchdog_mode;
- data.syncs[i].pdo_count =
- ec_pdo_list_count(&sc->sync_configs[i].pdos);
- }
- data.watchdog_divider = sc->watchdog_divider;
- data.watchdog_intervals = sc->watchdog_intervals;
- data.sdo_count = ec_slave_config_sdo_count(sc);
- data.idn_count = ec_slave_config_idn_count(sc);
- data.slave_position = sc->slave ? sc->slave->ring_position : -1;
- data.dc_assign_activate = sc->dc_assign_activate;
- for (i = 0; i < EC_SYNC_SIGNAL_COUNT; i++) {
- data.dc_sync[i] = sc->dc_sync[i];
- }
-
- ec_mutex_unlock(&master->master_mutex);
-
- if (copy_to_user((void __user *) arg, &data, sizeof(data)))
- return -EFAULT;
-
- return 0;
-}
-
-/*****************************************************************************/
-
-/** Get slave configuration PDO information.
- */
-int ec_cdev_ioctl_config_pdo(
- ec_master_t *master, /**< EtherCAT master. */
- unsigned long arg /**< ioctl() argument. */
- )
-{
- ec_ioctl_config_pdo_t data;
- const ec_slave_config_t *sc;
- const ec_pdo_t *pdo;
-
- if (copy_from_user(&data, (void __user *) arg, sizeof(data))) {
- return -EFAULT;
- }
-
- if (data.sync_index >= EC_MAX_SYNC_MANAGERS) {
- EC_MASTER_ERR(master, "Invalid sync manager index %u!\n",
- data.sync_index);
- return -EINVAL;
- }
-
- if (ec_mutex_lock_interruptible(&master->master_mutex))
- return -EINTR;
-
- if (!(sc = ec_master_get_config_const(
- master, data.config_index))) {
- ec_mutex_unlock(&master->master_mutex);
- EC_MASTER_ERR(master, "Slave config %u does not exist!\n",
- data.config_index);
- return -EINVAL;
- }
-
- if (!(pdo = ec_pdo_list_find_pdo_by_pos_const(
- &sc->sync_configs[data.sync_index].pdos,
- data.pdo_pos))) {
- ec_mutex_unlock(&master->master_mutex);
- EC_MASTER_ERR(master, "Invalid PDO position!\n");
- return -EINVAL;
- }
-
- data.index = pdo->index;
- data.entry_count = ec_pdo_entry_count(pdo);
- ec_cdev_strcpy(data.name, pdo->name);
-
- ec_mutex_unlock(&master->master_mutex);
-
- if (copy_to_user((void __user *) arg, &data, sizeof(data)))
- return -EFAULT;
-
- return 0;
-}
-
-/*****************************************************************************/
-
-/** Get slave configuration PDO entry information.
- */
-int ec_cdev_ioctl_config_pdo_entry(
- ec_master_t *master, /**< EtherCAT master. */
- unsigned long arg /**< ioctl() argument. */
- )
-{
- ec_ioctl_config_pdo_entry_t data;
- const ec_slave_config_t *sc;
- const ec_pdo_t *pdo;
- const ec_pdo_entry_t *entry;
-
- if (copy_from_user(&data, (void __user *) arg, sizeof(data))) {
- return -EFAULT;
- }
-
- if (data.sync_index >= EC_MAX_SYNC_MANAGERS) {
- EC_MASTER_ERR(master, "Invalid sync manager index %u!\n",
- data.sync_index);
- return -EINVAL;
- }
-
- if (ec_mutex_lock_interruptible(&master->master_mutex))
- return -EINTR;
-
- if (!(sc = ec_master_get_config_const(
- master, data.config_index))) {
- ec_mutex_unlock(&master->master_mutex);
- EC_MASTER_ERR(master, "Slave config %u does not exist!\n",
- data.config_index);
- return -EINVAL;
- }
-
- if (!(pdo = ec_pdo_list_find_pdo_by_pos_const(
- &sc->sync_configs[data.sync_index].pdos,
- data.pdo_pos))) {
- ec_mutex_unlock(&master->master_mutex);
- EC_MASTER_ERR(master, "Invalid PDO position!\n");
- return -EINVAL;
- }
-
- if (!(entry = ec_pdo_find_entry_by_pos_const(
- pdo, data.entry_pos))) {
- ec_mutex_unlock(&master->master_mutex);
- EC_MASTER_ERR(master, "Entry not found!\n");
- return -EINVAL;
- }
-
- data.index = entry->index;
- data.subindex = entry->subindex;
- data.bit_length = entry->bit_length;
- ec_cdev_strcpy(data.name, entry->name);
-
- ec_mutex_unlock(&master->master_mutex);
-
- if (copy_to_user((void __user *) arg, &data, sizeof(data)))
- return -EFAULT;
-
- return 0;
-}
-
-/*****************************************************************************/
-
-/** Get slave configuration SDO information.
- */
-int ec_cdev_ioctl_config_sdo(
- ec_master_t *master, /**< EtherCAT master. */
- unsigned long arg /**< ioctl() argument. */
- )
-{
- ec_ioctl_config_sdo_t *ioctl;
- const ec_slave_config_t *sc;
- const ec_sdo_request_t *req;
-
- if (!(ioctl = kmalloc(sizeof(*ioctl), GFP_KERNEL))) {
- return -ENOMEM;
- }
-
- if (copy_from_user(ioctl, (void __user *) arg, sizeof(*ioctl))) {
- kfree(ioctl);
- return -EFAULT;
- }
-
- if (ec_mutex_lock_interruptible(&master->master_mutex)) {
- kfree(ioctl);
- return -EINTR;
- }
-
- if (!(sc = ec_master_get_config_const(
- master, ioctl->config_index))) {
- ec_mutex_unlock(&master->master_mutex);
- EC_MASTER_ERR(master, "Slave config %u does not exist!\n",
- ioctl->config_index);
- kfree(ioctl);
- return -EINVAL;
- }
-
- if (!(req = ec_slave_config_get_sdo_by_pos_const(
- sc, ioctl->sdo_pos))) {
- ec_mutex_unlock(&master->master_mutex);
- EC_MASTER_ERR(master, "Invalid SDO position!\n");
- kfree(ioctl);
- return -EINVAL;
- }
-
- ioctl->index = req->index;
- ioctl->subindex = req->subindex;
- ioctl->size = req->data_size;
- memcpy(ioctl->data, req->data,
- min((u32) ioctl->size, (u32) EC_MAX_SDO_DATA_SIZE));
-
- ec_mutex_unlock(&master->master_mutex);
-
- if (copy_to_user((void __user *) arg, ioctl, sizeof(*ioctl))) {
- kfree(ioctl);
- return -EFAULT;
- }
-
- kfree(ioctl);
- return 0;
-}
-
-/*****************************************************************************/
-
-/** Get slave configuration IDN information.
- */
-int ec_cdev_ioctl_config_idn(
- ec_master_t *master, /**< EtherCAT master. */
- unsigned long arg /**< ioctl() argument. */
- )
-{
- ec_ioctl_config_idn_t *ioctl;
- const ec_slave_config_t *sc;
- const ec_soe_request_t *req;
-
- if (!(ioctl = kmalloc(sizeof(*ioctl), GFP_KERNEL))) {
- return -ENOMEM;
- }
-
- if (copy_from_user(ioctl, (void __user *) arg, sizeof(*ioctl))) {
- kfree(ioctl);
- return -EFAULT;
- }
-
- if (ec_mutex_lock_interruptible(&master->master_mutex)) {
- kfree(ioctl);
- return -EINTR;
- }
-
- if (!(sc = ec_master_get_config_const(
- master, ioctl->config_index))) {
- ec_mutex_unlock(&master->master_mutex);
- EC_MASTER_ERR(master, "Slave config %u does not exist!\n",
- ioctl->config_index);
- kfree(ioctl);
- return -EINVAL;
- }
-
- if (!(req = ec_slave_config_get_idn_by_pos_const(
- sc, ioctl->idn_pos))) {
- ec_mutex_unlock(&master->master_mutex);
- EC_MASTER_ERR(master, "Invalid IDN position!\n");
- kfree(ioctl);
- return -EINVAL;
- }
-
- ioctl->drive_no = req->drive_no;
- ioctl->idn = req->idn;
- ioctl->state = req->state;
- ioctl->size = req->data_size;
- memcpy(ioctl->data, req->data,
- min((u32) ioctl->size, (u32) EC_MAX_IDN_DATA_SIZE));
-
- ec_mutex_unlock(&master->master_mutex);
-
- if (copy_to_user((void __user *) arg, ioctl, sizeof(*ioctl))) {
- kfree(ioctl);
- return -EFAULT;
- }
-
- kfree(ioctl);
- return 0;
-}
-
-/*****************************************************************************/
-
-#ifdef EC_EOE
-
-/** Get EoE handler information.
- */
-int ec_cdev_ioctl_eoe_handler(
- ec_master_t *master, /**< EtherCAT master. */
- unsigned long arg /**< ioctl() argument. */
- )
-{
- ec_ioctl_eoe_handler_t data;
- const ec_eoe_t *eoe;
-
- if (copy_from_user(&data, (void __user *) arg, sizeof(data))) {
- return -EFAULT;
- }
-
- if (ec_mutex_lock_interruptible(&master->master_mutex))
- return -EINTR;
-
- if (!(eoe = ec_master_get_eoe_handler_const(master, data.eoe_index))) {
- ec_mutex_unlock(&master->master_mutex);
- EC_MASTER_ERR(master, "EoE handler %u does not exist!\n",
- data.eoe_index);
- return -EINVAL;
- }
-
- if (eoe->slave) {
- data.slave_position = eoe->slave->ring_position;
- } else {
- data.slave_position = 0xffff;
- }
- snprintf(data.name, EC_DATAGRAM_NAME_SIZE, eoe->dev->name);
- data.open = eoe->opened;
- data.tx_bytes = eoe->stats.tx_bytes;
- data.tx_rate = eoe->tx_rate;
- data.rx_bytes = eoe->stats.rx_bytes;
- data.rx_rate = eoe->tx_rate;
- data.tx_queued_frames = eoe->tx_queued_frames;
- data.tx_queue_size = eoe->tx_queue_size;
-
- ec_mutex_unlock(&master->master_mutex);
-
- if (copy_to_user((void __user *) arg, &data, sizeof(data)))
- return -EFAULT;
-
- return 0;
-}
-
-#endif
-
-/*****************************************************************************/
-
-/** Request the master from userspace.
- */
-int ec_cdev_ioctl_request(
- ec_master_t *master, /**< EtherCAT master. */
- unsigned long arg, /**< ioctl() argument. */
- ec_cdev_priv_t *priv /**< Private data structure of file handle. */
- )
-{
- ec_master_t *m;
- int ret = 0;
-
- m = ecrt_request_master_err(master->index);
- if (IS_ERR(m)) {
- ret = PTR_ERR(m);
- } else {
- priv->requested = 1;
- }
-
- return ret;
-}
-
-/*****************************************************************************/
-
-/** Create a domain.
- */
-int ec_cdev_ioctl_create_domain(
- ec_master_t *master, /**< EtherCAT master. */
- unsigned long arg, /**< ioctl() argument. */
- ec_cdev_priv_t *priv /**< Private data structure of file handle. */
- )
-{
- ec_domain_t *domain;
-
- if (unlikely(!priv->requested))
- return -EPERM;
-
- domain = ecrt_master_create_domain_err(master);
- if (IS_ERR(domain))
- return PTR_ERR(domain);
-
- return domain->index;
-}
-
-/*****************************************************************************/
-
-/** Create a slave configuration.
- */
-int ec_cdev_ioctl_create_slave_config(
- ec_master_t *master, /**< EtherCAT master. */
- unsigned long arg, /**< ioctl() argument. */
- ec_cdev_priv_t *priv /**< Private data structure of file handle. */
- )
-{
- ec_ioctl_config_t data;
- ec_slave_config_t *sc, *entry;
-
- if (unlikely(!priv->requested))
- return -EPERM;
-
- if (copy_from_user(&data, (void __user *) arg, sizeof(data))) {
- return -EFAULT;
- }
-
- sc = ecrt_master_slave_config_err(master, data.alias, data.position,
- data.vendor_id, data.product_code);
- if (IS_ERR(sc))
- return PTR_ERR(sc);
-
- data.config_index = 0;
-
- if (ec_mutex_lock_interruptible(&master->master_mutex))
- return -EINTR;
-
- list_for_each_entry(entry, &master->configs, list) {
- if (entry == sc)
- break;
- data.config_index++;
- }
-
- ec_mutex_unlock(&master->master_mutex);
-
- if (copy_to_user((void __user *) arg, &data, sizeof(data)))
- return -EFAULT;
-
- return 0;
-}
-
-/*****************************************************************************/
-
-/** Activates the master.
- */
-int ec_cdev_ioctl_activate(
- ec_master_t *master, /**< EtherCAT master. */
- unsigned long arg, /**< ioctl() argument. */
- ec_cdev_priv_t *priv /**< Private data structure of file handle. */
- )
-{
- ec_domain_t *domain;
- off_t offset;
- int ret;
-
- if (unlikely(!priv->requested))
- return -EPERM;
-
- /* Get the sum of the domains' process data sizes. */
-
- priv->process_data_size = 0;
-
- if (ec_mutex_lock_interruptible(&master->master_mutex))
- return -EINTR;
-
- list_for_each_entry(domain, &master->domains, list) {
- priv->process_data_size += ecrt_domain_size(domain);
- }
-
- ec_mutex_unlock(&master->master_mutex);
-
- if (priv->process_data_size) {
- priv->process_data = vmalloc(priv->process_data_size);
- if (!priv->process_data) {
- priv->process_data_size = 0;
- return -ENOMEM;
- }
-
- /* Set the memory as external process data memory for the domains. */
-
- offset = 0;
- list_for_each_entry(domain, &master->domains, list) {
- ecrt_domain_external_memory(domain, priv->process_data + offset);
- offset += ecrt_domain_size(domain);
- }
- }
-
- ret = ecrt_master_activate(master);
- if (ret < 0)
- return ret;
-
- if (copy_to_user((void __user *) arg,
- &priv->process_data_size, sizeof(size_t)))
- return -EFAULT;
-
- return 0;
-}
-
-/*****************************************************************************/
-
-/** Deactivates the master.
- */
-int ec_cdev_ioctl_deactivate(
- ec_master_t *master, /**< EtherCAT master. */
- unsigned long arg, /**< ioctl() argument. */
- ec_cdev_priv_t *priv /**< Private data structure of file handle. */
- )
-{
- if (unlikely(!priv->requested))
- return -EPERM;
-
- ecrt_master_deactivate(master);
- return 0;
-}
-
-/*****************************************************************************/
-
-/** Set max. number of databytes in a cycle
- */
-int ec_cdev_ioctl_set_send_interval(
- ec_master_t *master, /**< EtherCAT master. */
- unsigned long arg, /**< ioctl() argument. */
- ec_cdev_priv_t *priv /**< Private data structure of file handle. */
- )
-{
- size_t send_interval;
-
- if (copy_from_user(&send_interval, (void __user *) arg,
- sizeof(send_interval))) {
- return -EFAULT;
- }
-
- if (ec_mutex_lock_interruptible(&master->master_mutex))
- return -EINTR;
-
- ec_master_set_send_interval(master, send_interval);
-
- ec_mutex_unlock(&master->master_mutex);
- return 0;
-}
-
-/*****************************************************************************/
-
-/** Send frames.
- */
-int ec_cdev_ioctl_send(
- ec_master_t *master, /**< EtherCAT master. */
- unsigned long arg, /**< ioctl() argument. */
- ec_cdev_priv_t *priv /**< Private data structure of file handle. */
- )
-{
- if (unlikely(!priv->requested))
- return -EPERM;
-
- ec_mutex_lock(&master->io_mutex);
- ecrt_master_send(master);
- ec_mutex_unlock(&master->io_mutex);
- return 0;
-}
-
-/*****************************************************************************/
-
-/** Receive frames.
- */
-int ec_cdev_ioctl_receive(
- ec_master_t *master, /**< EtherCAT master. */
- unsigned long arg, /**< ioctl() argument. */
- ec_cdev_priv_t *priv /**< Private data structure of file handle. */
- )
-{
- if (unlikely(!priv->requested))
- return -EPERM;
-
- ec_mutex_lock(&master->io_mutex);
- ecrt_master_receive(master);
- ec_mutex_unlock(&master->io_mutex);
- return 0;
-}
-
-/*****************************************************************************/
-
-/** Get the master state.
- */
-int ec_cdev_ioctl_master_state(
- ec_master_t *master, /**< EtherCAT master. */
- unsigned long arg, /**< ioctl() argument. */
- ec_cdev_priv_t *priv /**< Private data structure of file handle. */
- )
-{
- ec_master_state_t data;
-
- if (unlikely(!priv->requested))
- return -EPERM;
-
- ecrt_master_state(master, &data);
-
- if (copy_to_user((void __user *) arg, &data, sizeof(data)))
- return -EFAULT;
-
- return 0;
-}
-
-/*****************************************************************************/
-
-/** Get the master state of all configured slaves.
- */
-int ec_cdev_ioctl_master_sc_state(
- ec_master_t *master, /**< EtherCAT master. */
- unsigned long arg, /**< ioctl() argument. */
- ec_cdev_priv_t *priv /**< Private data structure of file handle. */
- )
-{
- ec_master_state_t data;
-
- if (unlikely(!priv->requested))
- return -EPERM;
-
- ecrt_master_configured_slaves_state(master, &data);
-
- if (copy_to_user((void __user *) arg, &data, sizeof(data)))
- return -EFAULT;
-
- return 0;
-}
-
-/*****************************************************************************/
-
-/** Get the master state.
- */
-int ec_cdev_ioctl_app_time(
- ec_master_t *master, /**< EtherCAT master. */
- unsigned long arg, /**< ioctl() argument. */
- ec_cdev_priv_t *priv /**< Private data structure of file handle. */
- )
-{
- ec_ioctl_app_time_t data;
-
- if (unlikely(!priv->requested))
- return -EPERM;
-
- if (copy_from_user(&data, (void __user *) arg, sizeof(data))) {
- return -EFAULT;
- }
-
- ecrt_master_application_time(master, data.app_time);
- return 0;
-}
-
-/*****************************************************************************/
-
-/** Sync the reference clock.
- */
-int ec_cdev_ioctl_sync_ref(
- ec_master_t *master, /**< EtherCAT master. */
- unsigned long arg, /**< ioctl() argument. */
- ec_cdev_priv_t *priv /**< Private data structure of file handle. */
- )
-{
- if (unlikely(!priv->requested))
- return -EPERM;
-
- ec_mutex_lock(&master->io_mutex);
- ecrt_master_sync_reference_clock(master);
- ec_mutex_unlock(&master->io_mutex);
- return 0;
-}
-
-/*****************************************************************************/
-
-/** Sync the slave clocks.
- */
-int ec_cdev_ioctl_sync_slaves(
- ec_master_t *master, /**< EtherCAT master. */
- unsigned long arg, /**< ioctl() argument. */
- ec_cdev_priv_t *priv /**< Private data structure of file handle. */
- )
-{
- if (unlikely(!priv->requested))
- return -EPERM;
-
- ec_mutex_lock(&master->io_mutex);
- ecrt_master_sync_slave_clocks(master);
- ec_mutex_unlock(&master->io_mutex);
- return 0;
-}
-
-/*****************************************************************************/
-
-/** Queue the sync monitoring datagram.
- */
-int ec_cdev_ioctl_sync_mon_queue(
- ec_master_t *master, /**< EtherCAT master. */
- unsigned long arg, /**< ioctl() argument. */
- ec_cdev_priv_t *priv /**< Private data structure of file handle. */
- )
-{
- if (unlikely(!priv->requested))
- return -EPERM;
-
- ec_mutex_lock(&master->io_mutex);
- ecrt_master_sync_monitor_queue(master);
- ec_mutex_unlock(&master->io_mutex);
- return 0;
-}
-
-/*****************************************************************************/
-
-/** Processes the sync monitoring datagram.
- */
-int ec_cdev_ioctl_sync_mon_process(
- ec_master_t *master, /**< EtherCAT master. */
- unsigned long arg, /**< ioctl() argument. */
- ec_cdev_priv_t *priv /**< Private data structure of file handle. */
- )
-{
- uint32_t time_diff;
-
- if (unlikely(!priv->requested))
- return -EPERM;
-
- ec_mutex_lock(&master->io_mutex);
- time_diff = ecrt_master_sync_monitor_process(master);
- ec_mutex_unlock(&master->io_mutex);
-
- if (copy_to_user((void __user *) arg, &time_diff, sizeof(time_diff)))
- return -EFAULT;
-
- return 0;
-}
-
-/*****************************************************************************/
-
-/** Reset configuration.
- */
-int ec_cdev_ioctl_reset(
- ec_master_t *master, /**< EtherCAT master. */
- unsigned long arg, /**< ioctl() argument. */
- ec_cdev_priv_t *priv /**< Private data structure of file handle. */
- )
-{
- if (unlikely(!priv->requested))
- return -EPERM;
-
- ec_mutex_lock(&master->master_mutex);
- ecrt_master_reset(master);
- ec_mutex_unlock(&master->master_mutex);
- return 0;
-}
-
-/*****************************************************************************/
-
-/** Configure a sync manager.
- */
-int ec_cdev_ioctl_sc_sync(
- ec_master_t *master, /**< EtherCAT master. */
- unsigned long arg, /**< ioctl() argument. */
- ec_cdev_priv_t *priv /**< Private data structure of file handle. */
- )
-{
- ec_ioctl_config_t data;
- ec_slave_config_t *sc;
- unsigned int i;
- int ret = 0;
-
- if (unlikely(!priv->requested)) {
- ret = -EPERM;
- goto out_return;
- }
-
- if (copy_from_user(&data, (void __user *) arg, sizeof(data))) {
- ret = -EFAULT;
- goto out_return;
- }
-
- if (ec_mutex_lock_interruptible(&master->master_mutex)) {
- ret = -EINTR;
- goto out_return;
- }
-
- if (!(sc = ec_master_get_config(master, data.config_index))) {
- ret = -ENOENT;
- goto out_up;
- }
-
- for (i = 0; i < EC_MAX_SYNC_MANAGERS; i++) {
- if (data.syncs[i].config_this) {
- if (ecrt_slave_config_sync_manager(sc, i, data.syncs[i].dir,
- data.syncs[i].watchdog_mode)) {
- ret = -EINVAL;
- goto out_up;
- }
- }
- }
-
-out_up:
- ec_mutex_unlock(&master->master_mutex);
-out_return:
- return ret;
-}
-
-/*****************************************************************************/
-
-/** Configure a slave's watchdogs.
- */
-int ec_cdev_ioctl_sc_watchdog(
- ec_master_t *master, /**< EtherCAT master. */
- unsigned long arg, /**< ioctl() argument. */
- ec_cdev_priv_t *priv /**< Private data structure of file handle. */
- )
-{
- ec_ioctl_config_t data;
- ec_slave_config_t *sc;
- int ret = 0;
-
- if (unlikely(!priv->requested)) {
- ret = -EPERM;
- goto out_return;
- }
-
- if (copy_from_user(&data, (void __user *) arg, sizeof(data))) {
- ret = -EFAULT;
- goto out_return;
- }
-
- if (ec_mutex_lock_interruptible(&master->master_mutex)) {
- ret = -EINTR;
- goto out_return;
- }
-
- if (!(sc = ec_master_get_config(master, data.config_index))) {
- ret = -ENOENT;
- goto out_up;
- }
-
- ecrt_slave_config_watchdog(sc,
- data.watchdog_divider, data.watchdog_intervals);
-
-out_up:
- ec_mutex_unlock(&master->master_mutex);
-out_return:
- return ret;
-}
-
-
-/*****************************************************************************/
-
-/** Configure wether a slave allows overlapping PDOs.
- */
-int ec_cdev_ioctl_sc_allow_overlapping_pdos(
- ec_master_t *master, /**< EtherCAT master. */
- unsigned long arg, /**< ioctl() argument. */
- ec_cdev_priv_t *priv /**< Private data structure of file handle. */
- )
-{
- ec_ioctl_config_t data;
- ec_slave_config_t *sc;
- int ret = 0;
-
- if (unlikely(!priv->requested)) {
- ret = -EPERM;
- goto out_return;
- }
-
- if (copy_from_user(&data, (void __user *) arg, sizeof(data))) {
- ret = -EFAULT;
- goto out_return;
- }
-
- if (ec_mutex_lock_interruptible(&master->master_mutex)) {
- ret = -EINTR;
- goto out_return;
- }
-
- if (!(sc = ec_master_get_config(master, data.config_index))) {
- ret = -ENOENT;
- goto out_up;
- }
-
- ecrt_slave_config_overlapping_pdos(sc,
- data.allow_overlapping_pdos);
-
-out_up:
- ec_mutex_unlock(&master->master_mutex);
-out_return:
- return ret;
-}
-
-/*****************************************************************************/
-
-/** Add a PDO to the assignment.
- */
-int ec_cdev_ioctl_sc_add_pdo(
- ec_master_t *master, /**< EtherCAT master. */
- unsigned long arg, /**< ioctl() argument. */
- ec_cdev_priv_t *priv /**< Private data structure of file handle. */
- )
-{
- ec_ioctl_config_pdo_t data;
- ec_slave_config_t *sc;
-
- if (unlikely(!priv->requested))
- return -EPERM;
-
- if (copy_from_user(&data, (void __user *) arg, sizeof(data)))
- return -EFAULT;
-
- if (ec_mutex_lock_interruptible(&master->master_mutex))
- return -EINTR;
-
- if (!(sc = ec_master_get_config(master, data.config_index))) {
- ec_mutex_unlock(&master->master_mutex);
- return -ENOENT;
- }
-
- ec_mutex_unlock(&master->master_mutex); /** \fixme sc could be invalidated
- */
-
- return ecrt_slave_config_pdo_assign_add(sc, data.sync_index, data.index);
-}
-
-/*****************************************************************************/
-
-/** Clears the PDO assignment.
- */
-int ec_cdev_ioctl_sc_clear_pdos(
- ec_master_t *master, /**< EtherCAT master. */
- unsigned long arg, /**< ioctl() argument. */
- ec_cdev_priv_t *priv /**< Private data structure of file handle. */
- )
-{
- ec_ioctl_config_pdo_t data;
- ec_slave_config_t *sc;
-
- if (unlikely(!priv->requested))
- return -EPERM;
-
- if (copy_from_user(&data, (void __user *) arg, sizeof(data)))
- return -EFAULT;
-
- if (ec_mutex_lock_interruptible(&master->master_mutex))
- return -EINTR;
-
- if (!(sc = ec_master_get_config(master, data.config_index))) {
- ec_mutex_unlock(&master->master_mutex);
- return -ENOENT;
- }
-
- ec_mutex_unlock(&master->master_mutex); /** \fixme sc could be invalidated
- */
-
- ecrt_slave_config_pdo_assign_clear(sc, data.sync_index);
- return 0;
-}
-
-/*****************************************************************************/
-
-/** Add an entry to a PDO's mapping.
- */
-int ec_cdev_ioctl_sc_add_entry(
- ec_master_t *master, /**< EtherCAT master. */
- unsigned long arg, /**< ioctl() argument. */
- ec_cdev_priv_t *priv /**< Private data structure of file handle. */
- )
-{
- ec_ioctl_add_pdo_entry_t data;
- ec_slave_config_t *sc;
-
- if (unlikely(!priv->requested))
- return -EPERM;
-
- if (copy_from_user(&data, (void __user *) arg, sizeof(data)))
- return -EFAULT;
-
- if (ec_mutex_lock_interruptible(&master->master_mutex))
- return -EINTR;
-
- if (!(sc = ec_master_get_config(master, data.config_index))) {
- ec_mutex_unlock(&master->master_mutex);
- return -ENOENT;
- }
-
- ec_mutex_unlock(&master->master_mutex); /** \fixme sc could be invalidated
- */
-
- return ecrt_slave_config_pdo_mapping_add(sc, data.pdo_index,
- data.entry_index, data.entry_subindex, data.entry_bit_length);
-}
-
-/*****************************************************************************/
-
-/** Clears the mapping of a PDO.
- */
-int ec_cdev_ioctl_sc_clear_entries(
- ec_master_t *master, /**< EtherCAT master. */
- unsigned long arg, /**< ioctl() argument. */
- ec_cdev_priv_t *priv /**< Private data structure of file handle. */
- )
-{
- ec_ioctl_config_pdo_t data;
- ec_slave_config_t *sc;
-
- if (unlikely(!priv->requested))
- return -EPERM;
-
- if (copy_from_user(&data, (void __user *) arg, sizeof(data)))
- return -EFAULT;
-
- if (ec_mutex_lock_interruptible(&master->master_mutex))
- return -EINTR;
-
- if (!(sc = ec_master_get_config(master, data.config_index))) {
- ec_mutex_unlock(&master->master_mutex);
- return -ENOENT;
- }
-
- ec_mutex_unlock(&master->master_mutex); /** \fixme sc could be invalidated
- */
-
- ecrt_slave_config_pdo_mapping_clear(sc, data.index);
- return 0;
-}
-
-/*****************************************************************************/
-
-/** Registers a PDO entry.
- */
-int ec_cdev_ioctl_sc_reg_pdo_entry(
- ec_master_t *master, /**< EtherCAT master. */
- unsigned long arg, /**< ioctl() argument. */
- ec_cdev_priv_t *priv /**< Private data structure of file handle. */
- )
-{
- ec_ioctl_reg_pdo_entry_t data;
- ec_slave_config_t *sc;
- ec_domain_t *domain;
- int ret;
-
- if (unlikely(!priv->requested))
- return -EPERM;
-
- if (copy_from_user(&data, (void __user *) arg, sizeof(data)))
- return -EFAULT;
-
- if (ec_mutex_lock_interruptible(&master->master_mutex))
- return -EINTR;
-
- if (!(sc = ec_master_get_config(master, data.config_index))) {
- ec_mutex_unlock(&master->master_mutex);
- return -ENOENT;
- }
-
- if (!(domain = ec_master_find_domain(master, data.domain_index))) {
- ec_mutex_unlock(&master->master_mutex);
- return -ENOENT;
- }
-
- ec_mutex_unlock(&master->master_mutex);/** \fixme sc or domain could be
- invalidated */
-
- ret = ecrt_slave_config_reg_pdo_entry(sc, data.entry_index,
- data.entry_subindex, domain, &data.bit_position);
-
- if (copy_to_user((void __user *) arg, &data, sizeof(data)))
- return -EFAULT;
-
- return ret;
-}
-
-/*****************************************************************************/
-
-/** Sets the DC AssignActivate word and the sync signal times.
- */
-int ec_cdev_ioctl_sc_dc(
- ec_master_t *master, /**< EtherCAT master. */
- unsigned long arg, /**< ioctl() argument. */
- ec_cdev_priv_t *priv /**< Private data structure of file handle. */
- )
-{
- ec_ioctl_config_t data;
- ec_slave_config_t *sc;
-
- if (unlikely(!priv->requested))
- return -EPERM;
-
- if (copy_from_user(&data, (void __user *) arg, sizeof(data)))
- return -EFAULT;
-
- if (ec_mutex_lock_interruptible(&master->master_mutex))
- return -EINTR;
-
- if (!(sc = ec_master_get_config(master, data.config_index))) {
- ec_mutex_unlock(&master->master_mutex);
- return -ENOENT;
- }
-
- ecrt_slave_config_dc(sc, data.dc_assign_activate,
- data.dc_sync[0].cycle_time,
- data.dc_sync[0].shift_time,
- data.dc_sync[1].cycle_time,
- data.dc_sync[1].shift_time);
-
- ec_mutex_unlock(&master->master_mutex);
-
- return 0;
-}
-
-/*****************************************************************************/
-
-/** Configures an SDO.
- */
-int ec_cdev_ioctl_sc_sdo(
- ec_master_t *master, /**< EtherCAT master. */
- unsigned long arg, /**< ioctl() argument. */
- ec_cdev_priv_t *priv /**< Private data structure of file handle. */
- )
-{
- ec_ioctl_sc_sdo_t data;
- ec_slave_config_t *sc;
- uint8_t *sdo_data = NULL;
- int ret;
-
- if (unlikely(!priv->requested))
- return -EPERM;
-
- if (copy_from_user(&data, (void __user *) arg, sizeof(data)))
- return -EFAULT;
-
- if (!data.size)
- return -EINVAL;
-
- if (!(sdo_data = kmalloc(data.size, GFP_KERNEL))) {
- return -ENOMEM;
- }
-
- if (copy_from_user(sdo_data, (void __user *) data.data, data.size)) {
- kfree(sdo_data);
- return -EFAULT;
- }
-
- if (ec_mutex_lock_interruptible(&master->master_mutex)) {
- kfree(sdo_data);
- return -EINTR;
- }
-
- if (!(sc = ec_master_get_config(master, data.config_index))) {
- ec_mutex_unlock(&master->master_mutex);
- kfree(sdo_data);
- return -ENOENT;
- }
-
- ec_mutex_unlock(&master->master_mutex); /** \fixme sc could be invalidated
- */
-
- if (data.complete_access) {
- ret = ecrt_slave_config_complete_sdo(sc,
- data.index, sdo_data, data.size);
- } else {
- ret = ecrt_slave_config_sdo(sc, data.index, data.subindex, sdo_data,
- data.size);
- }
- kfree(sdo_data);
- return ret;
-}
-
-/*****************************************************************************/
-
-/** Create an SDO request.
- */
-int ec_cdev_ioctl_sc_create_sdo_request(
- ec_master_t *master, /**< EtherCAT master. */
- unsigned long arg, /**< ioctl() argument. */
- ec_cdev_priv_t *priv /**< Private data structure of file handle. */
- )
-{
- ec_ioctl_sdo_request_t data;
- ec_slave_config_t *sc;
- ec_sdo_request_t *req;
-
- if (unlikely(!priv->requested))
- return -EPERM;
-
- if (copy_from_user(&data, (void __user *) arg, sizeof(data))) {
- return -EFAULT;
- }
-
- data.request_index = 0;
-
- if (ec_mutex_lock_interruptible(&master->master_mutex))
- return -EINTR;
-
- sc = ec_master_get_config(master, data.config_index);
- if (!sc) {
- ec_mutex_unlock(&master->master_mutex);
- return -ENOENT;
- }
-
- list_for_each_entry(req, &sc->sdo_requests, list) {
- data.request_index++;
- }
-
- ec_mutex_unlock(&master->master_mutex);
-
- req = ecrt_slave_config_create_sdo_request_err(sc, data.sdo_index,
- data.sdo_subindex, data.size);
- if (IS_ERR(req))
- return PTR_ERR(req);
-
- if (copy_to_user((void __user *) arg, &data, sizeof(data)))
- return -EFAULT;
-
- return 0;
-}
-
-/*****************************************************************************/
-
-/** Create a VoE handler.
- */
-int ec_cdev_ioctl_sc_create_voe_handler(
- ec_master_t *master, /**< EtherCAT master. */
- unsigned long arg, /**< ioctl() argument. */
- ec_cdev_priv_t *priv /**< Private data structure of file handle. */
- )
-{
- ec_ioctl_voe_t data;
- ec_slave_config_t *sc;
- ec_voe_handler_t *voe;
-
- if (unlikely(!priv->requested))
- return -EPERM;
-
- if (copy_from_user(&data, (void __user *) arg, sizeof(data))) {
- return -EFAULT;
- }
-
- data.voe_index = 0;
-
- if (ec_mutex_lock_interruptible(&master->master_mutex))
- return -EINTR;
-
- sc = ec_master_get_config(master, data.config_index);
- if (!sc) {
- ec_mutex_unlock(&master->master_mutex);
- return -ENOENT;
- }
-
- list_for_each_entry(voe, &sc->voe_handlers, list) {
- data.voe_index++;
- }
-
- ec_mutex_unlock(&master->master_mutex);
-
- voe = ecrt_slave_config_create_voe_handler_err(sc, data.size);
- if (IS_ERR(voe))
- return PTR_ERR(voe);
-
- if (copy_to_user((void __user *) arg, &data, sizeof(data)))
- return -EFAULT;
-
- return 0;
-}
-
-/*****************************************************************************/
-
-/** Get the slave configuration's state.
- */
-int ec_cdev_ioctl_sc_state(
- ec_master_t *master, /**< EtherCAT master. */
- unsigned long arg, /**< ioctl() argument. */
- ec_cdev_priv_t *priv /**< Private data structure of file handle. */
- )
-{
- ec_ioctl_sc_state_t data;
- const ec_slave_config_t *sc;
- ec_slave_config_state_t state;
-
- if (unlikely(!priv->requested))
- return -EPERM;
-
- if (copy_from_user(&data, (void __user *) arg, sizeof(data))) {
- return -EFAULT;
- }
-
- /* no locking of master_mutex needed, because sc will not be deleted in
- * the meantime. */
-
- if (!(sc = ec_master_get_config_const(master, data.config_index))) {
- return -ENOENT;
- }
-
- ecrt_slave_config_state(sc, &state);
-
- if (copy_to_user((void __user *) data.state, &state, sizeof(state)))
- return -EFAULT;
-
- return 0;
-}
-
-/*****************************************************************************/
-
-/** Configures an IDN.
- */
-int ec_cdev_ioctl_sc_idn(
- ec_master_t *master, /**< EtherCAT master. */
- unsigned long arg, /**< ioctl() argument. */
- ec_cdev_priv_t *priv /**< Private data structure of file handle. */
- )
-{
- ec_ioctl_sc_idn_t ioctl;
- ec_slave_config_t *sc;
- uint8_t *data = NULL;
- int ret;
-
- if (unlikely(!priv->requested))
- return -EPERM;
-
- if (copy_from_user(&ioctl, (void __user *) arg, sizeof(ioctl)))
- return -EFAULT;
-
- if (!ioctl.size)
- return -EINVAL;
-
- if (!(data = kmalloc(ioctl.size, GFP_KERNEL))) {
- return -ENOMEM;
- }
-
- if (copy_from_user(data, (void __user *) ioctl.data, ioctl.size)) {
- kfree(data);
- return -EFAULT;
- }
-
- if (ec_mutex_lock_interruptible(&master->master_mutex)) {
- kfree(data);
- return -EINTR;
- }
-
- if (!(sc = ec_master_get_config(master, ioctl.config_index))) {
- ec_mutex_unlock(&master->master_mutex);
- kfree(data);
- return -ENOENT;
- }
-
- ec_mutex_unlock(&master->master_mutex);/** \fixme sc could be invalidated
- */
-
- ret = ecrt_slave_config_idn(
- sc, ioctl.drive_no, ioctl.idn, ioctl.al_state, data, ioctl.size);
- kfree(data);
- return ret;
-}
-
-/*****************************************************************************/
-
-/** Gets the domain's offset in the total process data.
- */
-int ec_cdev_ioctl_domain_offset(
- ec_master_t *master, /**< EtherCAT master. */
- unsigned long arg, /**< ioctl() argument. */
- ec_cdev_priv_t *priv /**< Private data structure of file handle. */
- )
-{
- int offset = 0;
- const ec_domain_t *domain;
-
- if (unlikely(!priv->requested))
- return -EPERM;
-
- if (ec_mutex_lock_interruptible(&master->master_mutex)) {
- return -EINTR;
- }
-
- list_for_each_entry(domain, &master->domains, list) {
- if (domain->index == arg) {
- ec_mutex_unlock(&master->master_mutex);
- return offset;
- }
- offset += ecrt_domain_size(domain);
- }
-
- ec_mutex_unlock(&master->master_mutex);
- return -ENOENT;
-}
-
-/*****************************************************************************/
-
-/** Process the domain.
- */
-int ec_cdev_ioctl_domain_process(
- ec_master_t *master, /**< EtherCAT master. */
- unsigned long arg, /**< ioctl() argument. */
- ec_cdev_priv_t *priv /**< Private data structure of file handle. */
- )
-{
- ec_domain_t *domain;
-
- if (unlikely(!priv->requested))
- return -EPERM;
-
- /* no locking of master_mutex needed, because domain will not be deleted
- * in the meantime. */
-
- if (!(domain = ec_master_find_domain(master, arg))) {
- return -ENOENT;
- }
-
- ecrt_domain_process(domain);
- return 0;
-}
-
-/*****************************************************************************/
-
-/** Queue the domain.
- */
-int ec_cdev_ioctl_domain_queue(
- ec_master_t *master, /**< EtherCAT master. */
- unsigned long arg, /**< ioctl() argument. */
- ec_cdev_priv_t *priv /**< Private data structure of file handle. */
- )
-{
- ec_domain_t *domain;
-
- if (unlikely(!priv->requested))
- return -EPERM;
-
- /* no locking of master_mutex needed, because domain will not be deleted
- * in the meantime. */
-
- if (!(domain = ec_master_find_domain(master, arg))) {
- return -ENOENT;
- }
-
- ecrt_domain_queue(domain);
- return 0;
-}
-
-/*****************************************************************************/
-
-/** Get the domain state.
- */
-int ec_cdev_ioctl_domain_state(
- ec_master_t *master, /**< EtherCAT master. */
- unsigned long arg, /**< ioctl() argument. */
- ec_cdev_priv_t *priv /**< Private data structure of file handle. */
- )
-{
- ec_ioctl_domain_state_t data;
- const ec_domain_t *domain;
- ec_domain_state_t state;
-
- if (unlikely(!priv->requested))
- return -EPERM;
-
- if (copy_from_user(&data, (void __user *) arg, sizeof(data))) {
- return -EFAULT;
- }
-
- /* no locking of master_mutex needed, because domain will not be deleted
- * in the meantime. */
-
- if (!(domain = ec_master_find_domain_const(master, data.domain_index))) {
- return -ENOENT;
- }
-
- ecrt_domain_state(domain, &state);
-
- if (copy_to_user((void __user *) data.state, &state, sizeof(state)))
- return -EFAULT;
-
- return 0;
-}
-
-/*****************************************************************************/
-
-/** Sets an SDO request's timeout.
- */
-int ec_cdev_ioctl_sdo_request_timeout(
- ec_master_t *master, /**< EtherCAT master. */
- unsigned long arg, /**< ioctl() argument. */
- ec_cdev_priv_t *priv /**< Private data structure of file handle. */
- )
-{
- ec_ioctl_sdo_request_t data;
- ec_slave_config_t *sc;
- ec_sdo_request_t *req;
-
- if (unlikely(!priv->requested))
- return -EPERM;
-
- if (copy_from_user(&data, (void __user *) arg, sizeof(data)))
- return -EFAULT;
-
- /* no locking of master_mutex needed, because neither sc nor req will not
- * be deleted in the meantime. */
-
- if (!(sc = ec_master_get_config(master, data.config_index))) {
- return -ENOENT;
- }
-
- if (!(req = ec_slave_config_find_sdo_request(sc, data.request_index))) {
- return -ENOENT;
- }
-
- ecrt_sdo_request_timeout(req, data.timeout);
- return 0;
-}
-
-/*****************************************************************************/
-
-/** Gets an SDO request's state.
- */
-int ec_cdev_ioctl_sdo_request_state(
- ec_master_t *master, /**< EtherCAT master. */
- unsigned long arg, /**< ioctl() argument. */
- ec_cdev_priv_t *priv /**< Private data structure of file handle. */
- )
-{
- ec_ioctl_sdo_request_t data;
- ec_slave_config_t *sc;
- ec_sdo_request_t *req;
-
- if (unlikely(!priv->requested))
- return -EPERM;
-
- if (copy_from_user(&data, (void __user *) arg, sizeof(data)))
- return -EFAULT;
-
- /* no locking of master_mutex needed, because neither sc nor req will not
- * be deleted in the meantime. */
-
- if (!(sc = ec_master_get_config(master, data.config_index))) {
- return -ENOENT;
- }
-
- if (!(req = ec_slave_config_find_sdo_request(sc, data.request_index))) {
- return -ENOENT;
- }
-
- data.state = ecrt_sdo_request_state(req);
- if (data.state == EC_REQUEST_SUCCESS && req->dir == EC_DIR_INPUT)
- data.size = ecrt_sdo_request_data_size(req);
- else
- data.size = 0;
-
- if (copy_to_user((void __user *) arg, &data, sizeof(data)))
- return -EFAULT;
-
- return 0;
-}
-
-/*****************************************************************************/
-
-/** Starts an SDO read operation.
- */
-int ec_cdev_ioctl_sdo_request_read(
- ec_master_t *master, /**< EtherCAT master. */
- unsigned long arg, /**< ioctl() argument. */
- ec_cdev_priv_t *priv /**< Private data structure of file handle. */
- )
-{
- ec_ioctl_sdo_request_t data;
- ec_slave_config_t *sc;
- ec_sdo_request_t *req;
-
- if (unlikely(!priv->requested))
- return -EPERM;
-
- if (copy_from_user(&data, (void __user *) arg, sizeof(data)))
- return -EFAULT;
-
- /* no locking of master_mutex needed, because neither sc nor req will not
- * be deleted in the meantime. */
-
- if (!(sc = ec_master_get_config(master, data.config_index))) {
- return -ENOENT;
- }
-
- if (!(req = ec_slave_config_find_sdo_request(sc, data.request_index))) {
- return -ENOENT;
- }
-
- ecrt_sdo_request_read(req);
- return 0;
-}
-
-/*****************************************************************************/
-
-/** Starts an SDO write operation.
- */
-int ec_cdev_ioctl_sdo_request_write(
- ec_master_t *master, /**< EtherCAT master. */
- unsigned long arg, /**< ioctl() argument. */
- ec_cdev_priv_t *priv /**< Private data structure of file handle. */
- )
-{
- ec_ioctl_sdo_request_t data;
- ec_slave_config_t *sc;
- ec_sdo_request_t *req;
- int ret;
-
- if (unlikely(!priv->requested))
- return -EPERM;
-
- if (copy_from_user(&data, (void __user *) arg, sizeof(data)))
- return -EFAULT;
-
- if (!data.size) {
- EC_MASTER_ERR(master, "SDO download: Data size may not be zero!\n");
- return -EINVAL;
- }
-
- /* no locking of master_mutex needed, because neither sc nor req will not
- * be deleted in the meantime. */
-
- if (!(sc = ec_master_get_config(master, data.config_index))) {
- return -ENOENT;
- }
-
- if (!(req = ec_slave_config_find_sdo_request(sc, data.request_index))) {
- return -ENOENT;
- }
-
- ret = ec_sdo_request_alloc(req, data.size);
- if (ret)
- return ret;
-
- if (copy_from_user(req->data, (void __user *) data.data, data.size))
- return -EFAULT;
-
- req->data_size = data.size;
- ecrt_sdo_request_write(req);
- return 0;
-}
-
-/*****************************************************************************/
-
-/** Read SDO data.
- */
-int ec_cdev_ioctl_sdo_request_data(
- ec_master_t *master, /**< EtherCAT master. */
- unsigned long arg, /**< ioctl() argument. */
- ec_cdev_priv_t *priv /**< Private data structure of file handle. */
- )
-{
- ec_ioctl_sdo_request_t data;
- ec_slave_config_t *sc;
- ec_sdo_request_t *req;
-
- if (unlikely(!priv->requested))
- return -EPERM;
-
- if (copy_from_user(&data, (void __user *) arg, sizeof(data)))
- return -EFAULT;
-
- /* no locking of master_mutex needed, because neither sc nor req will not
- * be deleted in the meantime. */
-
- if (!(sc = ec_master_get_config(master, data.config_index))) {
- return -ENOENT;
- }
-
- if (!(req = ec_slave_config_find_sdo_request(sc, data.request_index))) {
- return -ENOENT;
- }
-
- if (copy_to_user((void __user *) data.data, ecrt_sdo_request_data(req),
- ecrt_sdo_request_data_size(req)))
- return -EFAULT;
-
- return 0;
-}
-
-/*****************************************************************************/
-
-/** Sets the VoE send header.
- */
-int ec_cdev_ioctl_voe_send_header(
- ec_master_t *master, /**< EtherCAT master. */
- unsigned long arg, /**< ioctl() argument. */
- ec_cdev_priv_t *priv /**< Private data structure of file handle. */
- )
-{
- ec_ioctl_voe_t data;
- ec_slave_config_t *sc;
- ec_voe_handler_t *voe;
- uint32_t vendor_id;
- uint16_t vendor_type;
-
- if (unlikely(!priv->requested))
- return -EPERM;
-
- if (copy_from_user(&data, (void __user *) arg, sizeof(data)))
- return -EFAULT;
-
- if (get_user(vendor_id, data.vendor_id))
- return -EFAULT;
-
- if (get_user(vendor_type, data.vendor_type))
- return -EFAULT;
-
- /* no locking of master_mutex needed, because neither sc nor voe will not
- * be deleted in the meantime. */
-
- if (!(sc = ec_master_get_config(master, data.config_index))) {
- return -ENOENT;
- }
-
- if (!(voe = ec_slave_config_find_voe_handler(sc, data.voe_index))) {
- return -ENOENT;
- }
-
- ecrt_voe_handler_send_header(voe, vendor_id, vendor_type);
- return 0;
-}
-
-/*****************************************************************************/
-
-/** Gets the received VoE header.
- */
-int ec_cdev_ioctl_voe_rec_header(
- ec_master_t *master, /**< EtherCAT master. */
- unsigned long arg, /**< ioctl() argument. */
- ec_cdev_priv_t *priv /**< Private data structure of file handle. */
- )
-{
- ec_ioctl_voe_t data;
- ec_slave_config_t *sc;
- ec_voe_handler_t *voe;
- uint32_t vendor_id;
- uint16_t vendor_type;
-
- if (unlikely(!priv->requested))
- return -EPERM;
-
- if (copy_from_user(&data, (void __user *) arg, sizeof(data)))
- return -EFAULT;
-
- /* no locking of master_mutex needed, because neither sc nor voe will not
- * be deleted in the meantime. */
-
- if (!(sc = ec_master_get_config(master, data.config_index))) {
- return -ENOENT;
- }
-
- if (!(voe = ec_slave_config_find_voe_handler(sc, data.voe_index))) {
- return -ENOENT;
- }
-
- ecrt_voe_handler_received_header(voe, &vendor_id, &vendor_type);
-
- if (likely(data.vendor_id))
- if (put_user(vendor_id, data.vendor_id))
- return -EFAULT;
-
- if (likely(data.vendor_type))
- if (put_user(vendor_type, data.vendor_type))
- return -EFAULT;
-
- return 0;
-}
-
-/*****************************************************************************/
-
-/** Starts a VoE read operation.
- */
-int ec_cdev_ioctl_voe_read(
- ec_master_t *master, /**< EtherCAT master. */
- unsigned long arg, /**< ioctl() argument. */
- ec_cdev_priv_t *priv /**< Private data structure of file handle. */
- )
-{
- ec_ioctl_voe_t data;
- ec_slave_config_t *sc;
- ec_voe_handler_t *voe;
-
- if (unlikely(!priv->requested))
- return -EPERM;
-
- if (copy_from_user(&data, (void __user *) arg, sizeof(data)))
- return -EFAULT;
-
- /* no locking of master_mutex needed, because neither sc nor voe will not
- * be deleted in the meantime. */
-
- if (!(sc = ec_master_get_config(master, data.config_index))) {
- return -ENOENT;
- }
-
- if (!(voe = ec_slave_config_find_voe_handler(sc, data.voe_index))) {
- return -ENOENT;
- }
-
- ecrt_voe_handler_read(voe);
- return 0;
-}
-
-/*****************************************************************************/
-
-/** Starts a VoE read operation without sending a sync message first.
- */
-int ec_cdev_ioctl_voe_read_nosync(
- ec_master_t *master, /**< EtherCAT master. */
- unsigned long arg, /**< ioctl() argument. */
- ec_cdev_priv_t *priv /**< Private data structure of file handle. */
- )
-{
- ec_ioctl_voe_t data;
- ec_slave_config_t *sc;
- ec_voe_handler_t *voe;
-
- if (unlikely(!priv->requested))
- return -EPERM;
-
- if (copy_from_user(&data, (void __user *) arg, sizeof(data)))
- return -EFAULT;
-
- /* no locking of master_mutex needed, because neither sc nor voe will not
- * be deleted in the meantime. */
-
- if (!(sc = ec_master_get_config(master, data.config_index))) {
- return -ENOENT;
- }
-
- if (!(voe = ec_slave_config_find_voe_handler(sc, data.voe_index))) {
- return -ENOENT;
- }
-
- ecrt_voe_handler_read_nosync(voe);
- return 0;
-}
-
-/*****************************************************************************/
-
-/** Starts a VoE write operation.
- */
-int ec_cdev_ioctl_voe_write(
- ec_master_t *master, /**< EtherCAT master. */
- unsigned long arg, /**< ioctl() argument. */
- ec_cdev_priv_t *priv /**< Private data structure of file handle. */
- )
-{
- ec_ioctl_voe_t data;
- ec_slave_config_t *sc;
- ec_voe_handler_t *voe;
-
- if (unlikely(!priv->requested))
- return -EPERM;
-
- if (copy_from_user(&data, (void __user *) arg, sizeof(data)))
- return -EFAULT;
-
- /* no locking of master_mutex needed, because neither sc nor voe will not
- * be deleted in the meantime. */
-
- if (!(sc = ec_master_get_config(master, data.config_index))) {
- return -ENOENT;
- }
-
- if (!(voe = ec_slave_config_find_voe_handler(sc, data.voe_index))) {
- return -ENOENT;
- }
-
- if (data.size) {
- if (data.size > ec_voe_handler_mem_size(voe))
- return -EOVERFLOW;
-
- if (copy_from_user(ecrt_voe_handler_data(voe),
- (void __user *) data.data, data.size))
- return -EFAULT;
- }
-
- ecrt_voe_handler_write(voe, data.size);
- return 0;
-}
-
-/*****************************************************************************/
-
-/** Executes the VoE state machine.
- */
-int ec_cdev_ioctl_voe_exec(
- ec_master_t *master, /**< EtherCAT master. */
- unsigned long arg, /**< ioctl() argument. */
- ec_cdev_priv_t *priv /**< Private data structure of file handle. */
- )
-{
- ec_ioctl_voe_t data;
- ec_slave_config_t *sc;
- ec_voe_handler_t *voe;
-
- if (unlikely(!priv->requested))
- return -EPERM;
-
- if (copy_from_user(&data, (void __user *) arg, sizeof(data)))
- return -EFAULT;
-
- /* no locking of master_mutex needed, because neither sc nor voe will not
- * be deleted in the meantime. */
-
- if (!(sc = ec_master_get_config(master, data.config_index))) {
- return -ENOENT;
- }
-
- if (!(voe = ec_slave_config_find_voe_handler(sc, data.voe_index))) {
- return -ENOENT;
- }
-
- data.state = ecrt_voe_handler_execute(voe);
- if (data.state == EC_REQUEST_SUCCESS && voe->dir == EC_DIR_INPUT)
- data.size = ecrt_voe_handler_data_size(voe);
- else
- data.size = 0;
-
- if (copy_to_user((void __user *) arg, &data, sizeof(data)))
- return -EFAULT;
-
- return 0;
-}
-
-/*****************************************************************************/
-
-/** Reads the received VoE data.
- */
-int ec_cdev_ioctl_voe_data(
- ec_master_t *master, /**< EtherCAT master. */
- unsigned long arg, /**< ioctl() argument. */
- ec_cdev_priv_t *priv /**< Private data structure of file handle. */
- )
-{
- ec_ioctl_voe_t data;
- ec_slave_config_t *sc;
- ec_voe_handler_t *voe;
-
- if (unlikely(!priv->requested))
- return -EPERM;
-
- if (copy_from_user(&data, (void __user *) arg, sizeof(data)))
- return -EFAULT;
-
- /* no locking of master_mutex needed, because neither sc nor voe will not
- * be deleted in the meantime. */
-
- if (!(sc = ec_master_get_config(master, data.config_index))) {
- return -ENOENT;
- }
-
- if (!(voe = ec_slave_config_find_voe_handler(sc, data.voe_index))) {
- return -ENOENT;
- }
-
- if (copy_to_user((void __user *) data.data, ecrt_voe_handler_data(voe),
- ecrt_voe_handler_data_size(voe)))
- return -EFAULT;
-
- return 0;
-}
-
-/*****************************************************************************/
-
-/** Read a file from a slave via FoE.
- */
-int ec_cdev_ioctl_slave_foe_read(
- ec_master_t *master, /**< EtherCAT master. */
- unsigned long arg /**< ioctl() argument. */
- )
-{
- ec_ioctl_slave_foe_t data;
- ec_master_foe_request_t* request;
- int retval;
-
- if (copy_from_user(&data, (void __user *) arg, sizeof(data))) {
- return -EFAULT;
- }
-
- request = kmalloc(sizeof(*request), GFP_KERNEL);
- if (!request)
- return -ENOMEM;
- kref_init(&request->refcount);
-
- ec_foe_request_init(&request->req, data.file_name);
- ec_foe_request_read(&request->req);
- ec_foe_request_alloc(&request->req, 10000); // FIXME
-
- if (ec_mutex_lock_interruptible(&master->master_mutex)) {
- kref_put(&request->refcount, ec_master_foe_request_release);
- return -EINTR;
- }
- if (!(request->slave = ec_master_find_slave(
- master, 0, data.slave_position))) {
- ec_mutex_unlock(&master->master_mutex);
- kref_put(&request->refcount, ec_master_foe_request_release);
- EC_MASTER_ERR(master, "Slave %u does not exist!\n",
- data.slave_position);
- return -EINVAL;
- }
-
- // schedule request.
- list_add_tail(&request->list, &request->slave->foe_requests);
- kref_get(&request->refcount);
-
- ec_mutex_unlock(&master->master_mutex);
-
- EC_SLAVE_DBG(request->slave, 1, "Scheduled FoE read request %p.\n",
- request);
-
- // wait for processing through FSM
- if (wait_event_interruptible(request->slave->foe_queue,
- ((request->req.state == EC_INT_REQUEST_SUCCESS) ||
- (request->req.state == EC_INT_REQUEST_FAILURE)))) {
- // interrupted by signal
- kref_put(&request->refcount, ec_master_foe_request_release);
- return -EINTR;
- }
-
- data.result = request->req.result;
- data.error_code = request->req.error_code;
-
- EC_SLAVE_DBG(request->slave, 1, "Read %zd bytes via FoE"
- " (result = 0x%x).\n", request->req.data_size,
- request->req.result);
-
- if (request->req.state != EC_INT_REQUEST_SUCCESS) {
- data.data_size = 0;
- retval = -EIO;
- } else {
- if (request->req.data_size > data.buffer_size) {
- EC_MASTER_ERR(master, "Buffer too small.\n");
- kref_put(&request->refcount, ec_master_foe_request_release);
- return -EOVERFLOW;
- }
- data.data_size = request->req.data_size;
- if (copy_to_user((void __user *) data.buffer,
- request->req.buffer, data.data_size)) {
- kref_put(&request->refcount, ec_master_foe_request_release);
- return -EFAULT;
- }
- retval = 0;
- }
-
- if (__copy_to_user((void __user *) arg, &data, sizeof(data))) {
- retval = -EFAULT;
- }
-
- EC_SLAVE_DBG(request->slave, 1, "Finished FoE read request %p.\n",
- request);
- kref_put(&request->refcount, ec_master_foe_request_release);
-
- return retval;
-}
-
-/*****************************************************************************/
-
-/** Write a file to a slave via FoE
- */
-int ec_cdev_ioctl_slave_foe_write(
- ec_master_t *master, /**< EtherCAT master. */
- unsigned long arg /**< ioctl() argument. */
- )
-{
- ec_ioctl_slave_foe_t data;
- ec_master_foe_request_t* request;
- int retval;
-
- if (copy_from_user(&data, (void __user *) arg, sizeof(data))) {
- return -EFAULT;
- }
-
- request = kmalloc(sizeof(*request), GFP_KERNEL);
- if (!request)
- return -ENOMEM;
- kref_init(&request->refcount);
-
- INIT_LIST_HEAD(&request->list);
-
- ec_foe_request_init(&request->req, data.file_name);
-
- if (ec_foe_request_alloc(&request->req, data.buffer_size)) {
- kref_put(&request->refcount, ec_master_foe_request_release);
- return -ENOMEM;
- }
- if (copy_from_user(request->req.buffer,
- (void __user *) data.buffer, data.buffer_size)) {
- kref_put(&request->refcount, ec_master_foe_request_release);
- return -EFAULT;
- }
- request->req.data_size = data.buffer_size;
- ec_foe_request_write(&request->req);
-
- if (ec_mutex_lock_interruptible(&master->master_mutex)) {
- kref_put(&request->refcount, ec_master_foe_request_release);
- return -EINTR;
- }
-
- if (!(request->slave = ec_master_find_slave(
- master, 0, data.slave_position))) {
- ec_mutex_unlock(&master->master_mutex);
- EC_MASTER_ERR(master, "Slave %u does not exist!\n",
- data.slave_position);
- kref_put(&request->refcount, ec_master_foe_request_release);
- return -EINVAL;
- }
-
- EC_SLAVE_DBG(request->slave, 1, "Scheduling FoE write request %p.\n",
- request);
-
- // schedule FoE write request.
- list_add_tail(&request->list, &request->slave->foe_requests);
- kref_get(&request->refcount);
-
- ec_mutex_unlock(&master->master_mutex);
-
- // wait for processing through FSM
- if (wait_event_interruptible(request->slave->foe_queue,
- ((request->req.state == EC_INT_REQUEST_SUCCESS) ||
- (request->req.state == EC_INT_REQUEST_FAILURE)))) {
- // interrupted by signal
- kref_put(&request->refcount, ec_master_foe_request_release);
- return -EINTR;
- }
-
- data.result = request->req.result;
- data.error_code = request->req.error_code;
-
- retval = request->req.state == EC_INT_REQUEST_SUCCESS ? 0 : -EIO;
-
- if (__copy_to_user((void __user *) arg, &data, sizeof(data))) {
- retval = -EFAULT;
- }
-
- EC_SLAVE_DBG(request->slave, 1, "Finished FoE write request %p.\n",
- request);
- kref_put(&request->refcount, ec_master_foe_request_release);
-
- return retval;
-}
-
-/*****************************************************************************/
-
-/** Read an SoE IDN.
- */
-int ec_cdev_ioctl_slave_soe_read(
- ec_master_t *master, /**< EtherCAT master. */
- unsigned long arg /**< ioctl() argument. */
- )
-{
- ec_ioctl_slave_soe_read_t ioctl;
- u8 *data;
- int retval;
-
- if (copy_from_user(&ioctl, (void __user *) arg, sizeof(ioctl))) {
- return -EFAULT;
- }
-
- data = kmalloc(ioctl.mem_size, GFP_KERNEL);
- if (!data) {
- EC_MASTER_ERR(master, "Failed to allocate %u bytes of IDN data.\n",
- ioctl.mem_size);
- return -ENOMEM;
- }
-
- retval = ecrt_master_read_idn(master, ioctl.slave_position,
- ioctl.drive_no, ioctl.idn, data, ioctl.mem_size, &ioctl.data_size,
- &ioctl.error_code);
- if (retval) {
- kfree(data);
- return retval;
- }
-
- if (copy_to_user((void __user *) ioctl.data, data, ioctl.data_size)) {
- kfree(data);
- return -EFAULT;
- }
- kfree(data);
-
- if (__copy_to_user((void __user *) arg, &ioctl, sizeof(ioctl))) {
- retval = -EFAULT;
- }
-
- EC_MASTER_DBG(master, 1, "Finished SoE read request.\n");
- return retval;
-}
-
-/*****************************************************************************/
-
-/** Write an IDN to a slave via SoE.
- */
-int ec_cdev_ioctl_slave_soe_write(
- ec_master_t *master, /**< EtherCAT master. */
- unsigned long arg /**< ioctl() argument. */
- )
-{
- ec_ioctl_slave_soe_write_t ioctl;
- u8 *data;
- int retval;
-
- if (copy_from_user(&ioctl, (void __user *) arg, sizeof(ioctl))) {
- return -EFAULT;
- }
-
- data = kmalloc(ioctl.data_size, GFP_KERNEL);
- if (!data) {
- EC_MASTER_ERR(master, "Failed to allocate %zu bytes of IDN data.\n",
- ioctl.data_size);
- return -ENOMEM;
- }
- if (copy_from_user(data, (void __user *) ioctl.data, ioctl.data_size)) {
- kfree(data);
- return -EFAULT;
- }
-
- retval = ecrt_master_write_idn(master, ioctl.slave_position,
- ioctl.drive_no, ioctl.idn, data, ioctl.data_size,
- &ioctl.error_code);
- kfree(data);
- if (retval) {
- return retval;
- }
-
- if (__copy_to_user((void __user *) arg, &ioctl, sizeof(ioctl))) {
- retval = -EFAULT;
- }
-
- EC_MASTER_DBG(master, 1, "Finished SoE write request.\n");
- return retval;
-}
-
/******************************************************************************
* File operations
*****************************************************************************/
@@ -3462,13 +155,14 @@
}
priv->cdev = cdev;
- priv->requested = 0;
- priv->process_data = NULL;
- priv->process_data_size = 0;
+ priv->ctx.writable = (filp->f_mode & FMODE_WRITE) != 0;
+ priv->ctx.requested = 0;
+ priv->ctx.process_data = NULL;
+ priv->ctx.process_data_size = 0;
filp->private_data = priv;
-#if DEBUG_IOCTL
+#if DEBUG
EC_MASTER_DBG(cdev->master, 0, "File opened.\n");
#endif
return 0;
@@ -3483,13 +177,15 @@
ec_cdev_priv_t *priv = (ec_cdev_priv_t *) filp->private_data;
ec_master_t *master = priv->cdev->master;
- if (priv->requested)
+ if (priv->ctx.requested) {
ecrt_release_master(master);
-
- if (priv->process_data)
- vfree(priv->process_data);
-
-#if DEBUG_IOCTL
+ }
+
+ if (priv->ctx.process_data) {
+ vfree(priv->ctx.process_data);
+ }
+
+#if DEBUG
EC_MASTER_DBG(master, 0, "File closed.\n");
#endif
@@ -3503,453 +199,31 @@
*/
long eccdev_ioctl(struct file *filp, unsigned int cmd, unsigned long arg)
{
-#if DEBUG_LATENCY
- cycles_t a = get_cycles(), b;
- unsigned int t;
-#endif
ec_cdev_priv_t *priv = (ec_cdev_priv_t *) filp->private_data;
- ec_master_t *master = priv->cdev->master;
- int ret;
-
-#if DEBUG_IOCTL
- EC_MASTER_DBG(master, 0, "ioctl(filp = 0x%p, cmd = 0x%08x (0x%02x),"
- " arg = 0x%lx)\n", filp, cmd, _IOC_NR(cmd), arg);
-#endif
-
- switch (cmd) {
- case EC_IOCTL_MODULE:
- ret = ec_cdev_ioctl_module(arg);
- break;
- case EC_IOCTL_MASTER:
- ret = ec_cdev_ioctl_master(master, arg);
- break;
- case EC_IOCTL_SLAVE:
- ret = ec_cdev_ioctl_slave(master, arg);
- break;
- case EC_IOCTL_SLAVE_SYNC:
- ret = ec_cdev_ioctl_slave_sync(master, arg);
- break;
- case EC_IOCTL_SLAVE_SYNC_PDO:
- ret = ec_cdev_ioctl_slave_sync_pdo(master, arg);
- break;
- case EC_IOCTL_SLAVE_SYNC_PDO_ENTRY:
- ret = ec_cdev_ioctl_slave_sync_pdo_entry(master, arg);
- break;
- case EC_IOCTL_DOMAIN:
- ret = ec_cdev_ioctl_domain(master, arg);
- break;
- case EC_IOCTL_DOMAIN_FMMU:
- ret = ec_cdev_ioctl_domain_fmmu(master, arg);
- break;
- case EC_IOCTL_DOMAIN_DATA:
- ret = ec_cdev_ioctl_domain_data(master, arg);
- break;
- case EC_IOCTL_MASTER_DEBUG:
- if (!(filp->f_mode & FMODE_WRITE)) {
- ret = -EPERM;
- break;
- }
- ret = ec_cdev_ioctl_master_debug(master, arg);
- break;
- case EC_IOCTL_MASTER_RESCAN:
- if (!(filp->f_mode & FMODE_WRITE)) {
- ret = -EPERM;
- break;
- }
- ret = ec_cdev_ioctl_master_rescan(master, arg);
- break;
- case EC_IOCTL_SLAVE_STATE:
- if (!(filp->f_mode & FMODE_WRITE)) {
- ret = -EPERM;
- break;
- }
- ret = ec_cdev_ioctl_slave_state(master, arg);
- break;
- case EC_IOCTL_SLAVE_SDO:
- ret = ec_cdev_ioctl_slave_sdo(master, arg);
- break;
- case EC_IOCTL_SLAVE_SDO_ENTRY:
- ret = ec_cdev_ioctl_slave_sdo_entry(master, arg);
- break;
- case EC_IOCTL_SLAVE_SDO_UPLOAD:
- ret = ec_cdev_ioctl_slave_sdo_upload(master, arg);
- break;
- case EC_IOCTL_SLAVE_SDO_DOWNLOAD:
- if (!(filp->f_mode & FMODE_WRITE)) {
- ret = -EPERM;
- break;
- }
- ret = ec_cdev_ioctl_slave_sdo_download(master, arg);
- break;
- case EC_IOCTL_SLAVE_SII_READ:
- ret = ec_cdev_ioctl_slave_sii_read(master, arg);
- break;
- case EC_IOCTL_SLAVE_SII_WRITE:
- if (!(filp->f_mode & FMODE_WRITE)) {
- ret = -EPERM;
- break;
- }
- ret = ec_cdev_ioctl_slave_sii_write(master, arg);
- break;
- case EC_IOCTL_SLAVE_REG_READ:
- ret = ec_cdev_ioctl_slave_reg_read(master, arg);
- break;
- case EC_IOCTL_SLAVE_REG_WRITE:
- if (!(filp->f_mode & FMODE_WRITE)) {
- ret = -EPERM;
- break;
- }
- ret = ec_cdev_ioctl_slave_reg_write(master, arg);
- break;
- case EC_IOCTL_SLAVE_FOE_READ:
- ret = ec_cdev_ioctl_slave_foe_read(master, arg);
- break;
- case EC_IOCTL_SLAVE_FOE_WRITE:
- if (!(filp->f_mode & FMODE_WRITE)) {
- ret = -EPERM;
- break;
- }
- ret = ec_cdev_ioctl_slave_foe_write(master, arg);
- break;
- case EC_IOCTL_SLAVE_SOE_READ:
- ret = ec_cdev_ioctl_slave_soe_read(master, arg);
- break;
- case EC_IOCTL_SLAVE_SOE_WRITE:
- if (!(filp->f_mode & FMODE_WRITE)) {
- ret = -EPERM;
- break;
- }
- ret = ec_cdev_ioctl_slave_soe_write(master, arg);
- break;
- case EC_IOCTL_CONFIG:
- ret = ec_cdev_ioctl_config(master, arg);
- break;
- case EC_IOCTL_CONFIG_PDO:
- ret = ec_cdev_ioctl_config_pdo(master, arg);
- break;
- case EC_IOCTL_CONFIG_PDO_ENTRY:
- ret = ec_cdev_ioctl_config_pdo_entry(master, arg);
- break;
- case EC_IOCTL_CONFIG_SDO:
- ret = ec_cdev_ioctl_config_sdo(master, arg);
- break;
- case EC_IOCTL_CONFIG_IDN:
- ret = ec_cdev_ioctl_config_idn(master, arg);
- break;
-#ifdef EC_EOE
- case EC_IOCTL_EOE_HANDLER:
- ret = ec_cdev_ioctl_eoe_handler(master, arg);
- break;
-#endif
- case EC_IOCTL_REQUEST:
- if (!(filp->f_mode & FMODE_WRITE)) {
- ret = -EPERM;
- break;
- }
- ret = ec_cdev_ioctl_request(master, arg, priv);
- break;
- case EC_IOCTL_CREATE_DOMAIN:
- if (!(filp->f_mode & FMODE_WRITE)) {
- ret = -EPERM;
- break;
- }
- ret = ec_cdev_ioctl_create_domain(master, arg, priv);
- break;
- case EC_IOCTL_CREATE_SLAVE_CONFIG:
- if (!(filp->f_mode & FMODE_WRITE)) {
- ret = -EPERM;
- break;
- }
- ret = ec_cdev_ioctl_create_slave_config(master, arg, priv);
- break;
- case EC_IOCTL_ACTIVATE:
- if (!(filp->f_mode & FMODE_WRITE)) {
- ret = -EPERM;
- break;
- }
- ret = ec_cdev_ioctl_activate(master, arg, priv);
- break;
- case EC_IOCTL_DEACTIVATE:
- if (!(filp->f_mode & FMODE_WRITE)) {
- ret = -EPERM;
- break;
- }
- ret = ec_cdev_ioctl_deactivate(master, arg, priv);
- break;
- case EC_IOCTL_SEND:
- if (!(filp->f_mode & FMODE_WRITE)) {
- ret = -EPERM;
- break;
- }
- ret = ec_cdev_ioctl_send(master, arg, priv);
- break;
- case EC_IOCTL_RECEIVE:
- if (!(filp->f_mode & FMODE_WRITE)) {
- ret = -EPERM;
- break;
- }
- ret = ec_cdev_ioctl_receive(master, arg, priv);
- break;
- case EC_IOCTL_MASTER_STATE:
- ret = ec_cdev_ioctl_master_state(master, arg, priv);
- break;
- case EC_IOCTL_MASTER_SC_STATE:
- ret = ec_cdev_ioctl_master_sc_state(master, arg, priv);
- break;
- case EC_IOCTL_APP_TIME:
- if (!(filp->f_mode & FMODE_WRITE)) {
- ret = -EPERM;
- break;
- }
- ret = ec_cdev_ioctl_app_time(master, arg, priv);
- break;
- case EC_IOCTL_SYNC_REF:
- if (!(filp->f_mode & FMODE_WRITE)) {
- ret = -EPERM;
- break;
- }
- ret = ec_cdev_ioctl_sync_ref(master, arg, priv);
- break;
- case EC_IOCTL_SYNC_SLAVES:
- if (!(filp->f_mode & FMODE_WRITE)) {
- ret = -EPERM;
- break;
- }
- ret = ec_cdev_ioctl_sync_slaves(master, arg, priv);
- break;
- case EC_IOCTL_SYNC_MON_QUEUE:
- if (!(filp->f_mode & FMODE_WRITE)) {
- ret = -EPERM;
- break;
- }
- ret = ec_cdev_ioctl_sync_mon_queue(master, arg, priv);
- break;
- case EC_IOCTL_SYNC_MON_PROCESS:
- if (!(filp->f_mode & FMODE_WRITE)) {
- ret = -EPERM;
- break;
- }
- ret = ec_cdev_ioctl_sync_mon_process(master, arg, priv);
- break;
- case EC_IOCTL_RESET:
- if (!(filp->f_mode & FMODE_WRITE)) {
- ret = -EPERM;
- break;
- }
- ret = ec_cdev_ioctl_reset(master, arg, priv);
- break;
- case EC_IOCTL_SC_SYNC:
- if (!(filp->f_mode & FMODE_WRITE)) {
- ret = -EPERM;
- break;
- }
- ret = ec_cdev_ioctl_sc_sync(master, arg, priv);
- break;
- case EC_IOCTL_SC_WATCHDOG:
- if (!(filp->f_mode & FMODE_WRITE)) {
- ret = -EPERM;
- break;
- }
- ret = ec_cdev_ioctl_sc_watchdog(master, arg, priv);
- break;
- case EC_IOCTL_SC_OVERLAPPING_IO:
- if (!(filp->f_mode & FMODE_WRITE)) {
- ret = -EPERM;
- break;
- }
- ret = ec_cdev_ioctl_sc_allow_overlapping_pdos(master, arg, priv);
- break;
- case EC_IOCTL_SC_ADD_PDO:
- if (!(filp->f_mode & FMODE_WRITE)) {
- ret = -EPERM;
- break;
- }
- ret = ec_cdev_ioctl_sc_add_pdo(master, arg, priv);
- break;
- case EC_IOCTL_SC_CLEAR_PDOS:
- if (!(filp->f_mode & FMODE_WRITE)) {
- ret = -EPERM;
- break;
- }
- ret = ec_cdev_ioctl_sc_clear_pdos(master, arg, priv);
- break;
- case EC_IOCTL_SC_ADD_ENTRY:
- if (!(filp->f_mode & FMODE_WRITE)) {
- ret = -EPERM;
- break;
- }
- ret = ec_cdev_ioctl_sc_add_entry(master, arg, priv);
- break;
- case EC_IOCTL_SC_CLEAR_ENTRIES:
- if (!(filp->f_mode & FMODE_WRITE)) {
- ret = -EPERM;
- break;
- }
- ret = ec_cdev_ioctl_sc_clear_entries(master, arg, priv);
- break;
- case EC_IOCTL_SC_REG_PDO_ENTRY:
- if (!(filp->f_mode & FMODE_WRITE)) {
- ret = -EPERM;
- break;
- }
- ret = ec_cdev_ioctl_sc_reg_pdo_entry(master, arg, priv);
- break;
- case EC_IOCTL_SC_DC:
- if (!(filp->f_mode & FMODE_WRITE)) {
- ret = -EPERM;
- break;
- }
- ret = ec_cdev_ioctl_sc_dc(master, arg, priv);
- break;
- case EC_IOCTL_SC_SDO:
- if (!(filp->f_mode & FMODE_WRITE)) {
- ret = -EPERM;
- break;
- }
- ret = ec_cdev_ioctl_sc_sdo(master, arg, priv);
- break;
- case EC_IOCTL_SC_SDO_REQUEST:
- if (!(filp->f_mode & FMODE_WRITE)) {
- ret = -EPERM;
- break;
- }
- ret = ec_cdev_ioctl_sc_create_sdo_request(master, arg, priv);
- break;
- case EC_IOCTL_SC_VOE:
- if (!(filp->f_mode & FMODE_WRITE)) {
- ret = -EPERM;
- break;
- }
- ret = ec_cdev_ioctl_sc_create_voe_handler(master, arg, priv);
- break;
- case EC_IOCTL_SC_STATE:
- ret = ec_cdev_ioctl_sc_state(master, arg, priv);
- break;
- case EC_IOCTL_SC_IDN:
- if (!(filp->f_mode & FMODE_WRITE)) {
- ret = -EPERM;
- break;
- }
- ret = ec_cdev_ioctl_sc_idn(master, arg, priv);
- break;
- case EC_IOCTL_DOMAIN_OFFSET:
- ret = ec_cdev_ioctl_domain_offset(master, arg, priv);
- break;
- case EC_IOCTL_DOMAIN_PROCESS:
- if (!(filp->f_mode & FMODE_WRITE)) {
- ret = -EPERM;
- break;
- }
- ret = ec_cdev_ioctl_domain_process(master, arg, priv);
- break;
- case EC_IOCTL_DOMAIN_QUEUE:
- if (!(filp->f_mode & FMODE_WRITE)) {
- ret = -EPERM;
- break;
- }
- ret = ec_cdev_ioctl_domain_queue(master, arg, priv);
- break;
- case EC_IOCTL_DOMAIN_STATE:
- ret = ec_cdev_ioctl_domain_state(master, arg, priv);
- break;
- case EC_IOCTL_SDO_REQUEST_TIMEOUT:
- if (!(filp->f_mode & FMODE_WRITE)) {
- ret = -EPERM;
- break;
- }
- ret = ec_cdev_ioctl_sdo_request_timeout(master, arg, priv);
- break;
- case EC_IOCTL_SDO_REQUEST_STATE:
- ret = ec_cdev_ioctl_sdo_request_state(master, arg, priv);
- break;
- case EC_IOCTL_SDO_REQUEST_READ:
- if (!(filp->f_mode & FMODE_WRITE)) {
- ret = -EPERM;
- break;
- }
- ret = ec_cdev_ioctl_sdo_request_read(master, arg, priv);
- break;
- case EC_IOCTL_SDO_REQUEST_WRITE:
- if (!(filp->f_mode & FMODE_WRITE)) {
- ret = -EPERM;
- break;
- }
- ret = ec_cdev_ioctl_sdo_request_write(master, arg, priv);
- break;
- case EC_IOCTL_SDO_REQUEST_DATA:
- ret = ec_cdev_ioctl_sdo_request_data(master, arg, priv);
- break;
- case EC_IOCTL_VOE_SEND_HEADER:
- if (!(filp->f_mode & FMODE_WRITE)) {
- ret = -EPERM;
- break;
- }
- ret = ec_cdev_ioctl_voe_send_header(master, arg, priv);
- break;
- case EC_IOCTL_VOE_REC_HEADER:
- ret = ec_cdev_ioctl_voe_rec_header(master, arg, priv);
- break;
- case EC_IOCTL_VOE_READ:
- if (!(filp->f_mode & FMODE_WRITE)) {
- ret = -EPERM;
- break;
- }
- ret = ec_cdev_ioctl_voe_read(master, arg, priv);
- break;
- case EC_IOCTL_VOE_READ_NOSYNC:
- if (!(filp->f_mode & FMODE_WRITE)) {
- ret = -EPERM;
- break;
- }
- ret = ec_cdev_ioctl_voe_read_nosync(master, arg, priv);
- break;
- case EC_IOCTL_VOE_WRITE:
- if (!(filp->f_mode & FMODE_WRITE)) {
- ret = -EPERM;
- break;
- }
- ret = ec_cdev_ioctl_voe_write(master, arg, priv);
- break;
- case EC_IOCTL_VOE_EXEC:
- if (!(filp->f_mode & FMODE_WRITE)) {
- ret = -EPERM;
- break;
- }
- ret = ec_cdev_ioctl_voe_exec(master, arg, priv);
- break;
- case EC_IOCTL_VOE_DATA:
- ret = ec_cdev_ioctl_voe_data(master, arg, priv);
- break;
- case EC_IOCTL_SET_SEND_INTERVAL:
- if (!(filp->f_mode & FMODE_WRITE)) {
- ret = -EPERM;
- break;
- }
- ret = ec_cdev_ioctl_set_send_interval(master, arg, priv);
- break;
- default:
- ret = -ENOTTY;
- break;
- }
-
-#if DEBUG_LATENCY
- b = get_cycles();
- t = (unsigned int) ((b - a) * 1000LL) / cpu_khz;
- if (t > 50) {
- EC_MASTER_WARN(master, "ioctl(0x%02x) took %u us.\n",
- _IOC_NR(cmd), t);
- }
-#endif
-
- return ret;
-}
-
-/*****************************************************************************/
+
+#if DEBUG
+ EC_MASTER_DBG(priv->cdev->master, 0,
+ "ioctl(filp = 0x%p, cmd = 0x%08x (0x%02x), arg = 0x%lx)\n",
+ filp, cmd, _IOC_NR(cmd), arg);
+#endif
+
+ return ec_ioctl(priv->cdev->master, &priv->ctx, cmd, (void __user *) arg);
+}
+
+/*****************************************************************************/
+
+#ifndef VM_DONTDUMP
+/** VM_RESERVED disappeared in 3.7.
+ */
+#define VM_DONTDUMP VM_RESERVED
+#endif
/** Memory-map callback for the EtherCAT character device.
*
* The actual mapping will be done in the eccdev_vma_nopage() callback of the
* virtual memory area.
+ *
+ * \return Always zero (success).
*/
int eccdev_mmap(
struct file *filp,
@@ -3961,7 +235,7 @@
EC_MASTER_DBG(priv->cdev->master, 1, "mmap()\n");
vma->vm_ops = &eccdev_vm_ops;
- vma->vm_flags |= VM_RESERVED; /* Pages will not be swapped out */
+ vma->vm_flags |= VM_DONTDUMP; /* Pages will not be swapped out */
vma->vm_private_data = priv;
return 0;
@@ -3975,6 +249,8 @@
*
* Called at the first access on a virtual-memory area retrieved with
* ecdev_mmap().
+ *
+ * \return Zero on success, otherwise a negative error code.
*/
static int eccdev_vma_fault(
struct vm_area_struct *vma, /**< Virtual memory area. */
@@ -3985,12 +261,14 @@
ec_cdev_priv_t *priv = (ec_cdev_priv_t *) vma->vm_private_data;
struct page *page;
- if (offset >= priv->process_data_size)
+ if (offset >= priv->ctx.process_data_size) {
return VM_FAULT_SIGBUS;
-
- page = vmalloc_to_page(priv->process_data + offset);
- if (!page)
+ }
+
+ page = vmalloc_to_page(priv->ctx.process_data + offset);
+ if (!page) {
return VM_FAULT_SIGBUS;
+ }
get_page(page);
vmf->page = page;
@@ -4022,10 +300,10 @@
offset = (address - vma->vm_start) + (vma->vm_pgoff << PAGE_SHIFT);
- if (offset >= priv->process_data_size)
+ if (offset >= priv->ctx.process_data_size)
return NOPAGE_SIGBUS;
- page = vmalloc_to_page(priv->process_data + offset);
+ page = vmalloc_to_page(priv->ctx.process_data + offset);
EC_MASTER_DBG(master, 1, "Nopage fault vma, address = %#lx,"
" offset = %#lx, page = %p\n", address, offset, page);