fp@922: /****************************************************************************** fp@922: * fp@922: * $Id$ fp@922: * fp@1685: * Copyright (C) 2006-2008 Florian Pose, Ingenieurgemeinschaft IgH fp@922: * fp@922: * This file is part of the IgH EtherCAT Master. fp@922: * fp@1685: * The IgH EtherCAT Master is free software; you can redistribute it and/or fp@1685: * modify it under the terms of the GNU General Public License version 2, as fp@1685: * published by the Free Software Foundation. fp@922: * fp@1685: * The IgH EtherCAT Master is distributed in the hope that it will be useful, fp@1685: * but WITHOUT ANY WARRANTY; without even the implied warranty of fp@1685: * MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the GNU General fp@1685: * Public License for more details. fp@922: * fp@1685: * You should have received a copy of the GNU General Public License along fp@1685: * with the IgH EtherCAT Master; if not, write to the Free Software fp@922: * Foundation, Inc., 51 Franklin St, Fifth Floor, Boston, MA 02110-1301 USA fp@922: * fp@1685: * Using the EtherCAT technology and brand is permitted in compliance with fp@1685: * the industrial property and similar rights of Beckhoff Automation GmbH. fp@922: * fp@922: *****************************************************************************/ fp@922: fp@922: /** fp@922: \file fp@922: EtherCAT master character device. fp@922: */ fp@922: fp@922: /*****************************************************************************/ fp@922: fp@922: #include fp@922: fp@922: #include "cdev.h" fp@922: #include "master.h" fp@950: #include "slave_config.h" fp@922: #include "ioctl.h" fp@922: fp@922: /*****************************************************************************/ fp@922: fp@922: /** \cond */ fp@922: fp@922: int eccdev_open(struct inode *, struct file *); fp@922: int eccdev_release(struct inode *, struct file *); fp@935: long eccdev_ioctl(struct file *, unsigned int, unsigned long); fp@922: fp@922: /*****************************************************************************/ fp@922: fp@922: static struct file_operations eccdev_fops = { fp@935: .owner = THIS_MODULE, fp@935: .open = eccdev_open, fp@935: .release = eccdev_release, fp@935: .unlocked_ioctl = eccdev_ioctl fp@922: }; fp@922: fp@922: /** \endcond */ fp@922: fp@922: /*****************************************************************************/ fp@922: fp@922: /** Constructor. fp@922: * fp@922: * \return 0 in case of success, else < 0 fp@922: */ fp@922: int ec_cdev_init( fp@922: ec_cdev_t *cdev, /**< EtherCAT master character device. */ fp@922: ec_master_t *master, /**< Parent master. */ fp@922: dev_t dev_num /**< Device number. */ fp@922: ) fp@922: { fp@922: cdev->master = master; fp@922: fp@922: cdev_init(&cdev->cdev, &eccdev_fops); fp@922: cdev->cdev.owner = THIS_MODULE; fp@922: fp@922: if (cdev_add(&cdev->cdev, fp@922: MKDEV(MAJOR(dev_num), master->index), 1)) { fp@922: EC_ERR("Failed to add character device!\n"); fp@922: return -1; fp@922: } fp@922: fp@922: return 0; fp@922: } fp@922: fp@922: /*****************************************************************************/ fp@922: fp@922: /** Destructor. fp@922: */ fp@922: void ec_cdev_clear(ec_cdev_t *cdev /**< EtherCAT XML device */) fp@922: { fp@922: cdev_del(&cdev->cdev); fp@922: } fp@922: fp@1079: /*****************************************************************************/ fp@1079: fp@1108: /** Copies a string to an ioctl structure. fp@1108: */ fp@1108: void ec_cdev_strcpy( fp@1108: char *target, /**< Target. */ fp@1108: const char *source /**< Source. */ fp@1108: ) fp@1108: { fp@1108: if (source) { fp@1108: strncpy(target, source, EC_IOCTL_STRING_SIZE); fp@1108: target[EC_IOCTL_STRING_SIZE - 1] = 0; fp@1108: } else { fp@1108: target[0] = 0; fp@1108: } fp@1108: } fp@1108: fp@1108: /*****************************************************************************/ fp@1108: fp@1079: /** Get master information. fp@1079: */ fp@1079: int ec_cdev_ioctl_master( fp@1079: ec_master_t *master, /**< EtherCAT master. */ fp@1079: unsigned long arg /**< Userspace address to store the results. */ fp@1079: ) fp@1079: { fp@1079: ec_ioctl_master_t data; fp@1079: fp@1189: if (down_interruptible(&master->master_sem)) fp@1189: return -EINTR; fp@1079: data.slave_count = master->slave_count; fp@1079: data.config_count = ec_master_config_count(master); fp@1079: data.domain_count = ec_master_domain_count(master); fp@1079: data.phase = (uint8_t) master->phase; fp@1079: up(&master->master_sem); fp@1079: fp@1189: if (down_interruptible(&master->device_sem)) fp@1189: return -EINTR; fp@1162: if (master->main_device.dev) { fp@1162: memcpy(data.devices[0].address, fp@1162: master->main_device.dev->dev_addr, ETH_ALEN); fp@1162: } else { fp@1162: memcpy(data.devices[0].address, master->main_mac, ETH_ALEN); fp@1162: } fp@1079: data.devices[0].attached = master->main_device.dev ? 1 : 0; fp@1079: data.devices[0].tx_count = master->main_device.tx_count; fp@1079: data.devices[0].rx_count = master->main_device.rx_count; fp@1162: fp@1162: if (master->backup_device.dev) { fp@1162: memcpy(data.devices[1].address, fp@1162: master->backup_device.dev->dev_addr, ETH_ALEN); fp@1162: } else { fp@1162: memcpy(data.devices[1].address, master->backup_mac, ETH_ALEN); fp@1162: } fp@1079: data.devices[1].attached = master->backup_device.dev ? 1 : 0; fp@1079: data.devices[1].tx_count = master->backup_device.tx_count; fp@1079: data.devices[1].rx_count = master->backup_device.rx_count; fp@1079: up(&master->device_sem); fp@1079: fp@1079: if (copy_to_user((void __user *) arg, &data, sizeof(data))) fp@1079: return -EFAULT; fp@1079: fp@1079: return 0; fp@1079: } fp@1079: fp@1079: /*****************************************************************************/ fp@1079: fp@1079: /** Get slave information. fp@1079: */ fp@1079: int ec_cdev_ioctl_slave( fp@1079: ec_master_t *master, /**< EtherCAT master. */ fp@1079: unsigned long arg /**< Userspace address to store the results. */ fp@1079: ) fp@1079: { fp@1079: ec_ioctl_slave_t data; fp@1079: const ec_slave_t *slave; fp@1079: fp@1079: if (copy_from_user(&data, (void __user *) arg, sizeof(data))) { fp@1079: return -EFAULT; fp@1079: } fp@1079: fp@1189: if (down_interruptible(&master->master_sem)) fp@1189: return -EINTR; fp@1079: fp@1079: if (!(slave = ec_master_find_slave_const( fp@1079: master, 0, data.position))) { fp@1079: up(&master->master_sem); fp@1079: EC_ERR("Slave %u does not exist!\n", data.position); fp@1079: return -EINVAL; fp@1079: } fp@1079: fp@1079: data.vendor_id = slave->sii.vendor_id; fp@1079: data.product_code = slave->sii.product_code; fp@1079: data.revision_number = slave->sii.revision_number; fp@1079: data.serial_number = slave->sii.serial_number; fp@1079: data.alias = slave->sii.alias; fp@1079: data.rx_mailbox_offset = slave->sii.rx_mailbox_offset; fp@1079: data.rx_mailbox_size = slave->sii.rx_mailbox_size; fp@1079: data.tx_mailbox_offset = slave->sii.tx_mailbox_offset; fp@1079: data.tx_mailbox_size = slave->sii.tx_mailbox_size; fp@1079: data.mailbox_protocols = slave->sii.mailbox_protocols; fp@1079: data.has_general_category = slave->sii.has_general; fp@1079: data.coe_details = slave->sii.coe_details; fp@1079: data.general_flags = slave->sii.general_flags; fp@1079: data.current_on_ebus = slave->sii.current_on_ebus; fp@1148: data.al_state = slave->current_state; fp@1079: data.error_flag = slave->error_flag; fp@1079: fp@1079: data.sync_count = slave->sii.sync_count; fp@1079: data.sdo_count = ec_slave_sdo_count(slave); fp@1079: data.sii_nwords = slave->sii_nwords; fp@1109: ec_cdev_strcpy(data.group, slave->sii.group); fp@1109: ec_cdev_strcpy(data.image, slave->sii.image); fp@1109: ec_cdev_strcpy(data.order, slave->sii.order); fp@1108: ec_cdev_strcpy(data.name, slave->sii.name); fp@1079: fp@1079: up(&master->master_sem); fp@1079: fp@1079: if (copy_to_user((void __user *) arg, &data, sizeof(data))) fp@1079: return -EFAULT; fp@1079: fp@1079: return 0; fp@1079: } fp@1079: fp@1079: /*****************************************************************************/ fp@1079: fp@1079: /** Get slave sync manager information. fp@1079: */ fp@1079: int ec_cdev_ioctl_slave_sync( fp@1079: ec_master_t *master, /**< EtherCAT master. */ fp@1079: unsigned long arg /**< Userspace address to store the results. */ fp@1079: ) fp@1079: { fp@1079: ec_ioctl_slave_sync_t data; fp@1079: const ec_slave_t *slave; fp@1079: const ec_sync_t *sync; fp@1079: fp@1079: if (copy_from_user(&data, (void __user *) arg, sizeof(data))) { fp@1079: return -EFAULT; fp@1079: } fp@1079: fp@1189: if (down_interruptible(&master->master_sem)) fp@1189: return -EINTR; fp@1079: fp@1079: if (!(slave = ec_master_find_slave_const( fp@1079: master, 0, data.slave_position))) { fp@1079: up(&master->master_sem); fp@1079: EC_ERR("Slave %u does not exist!\n", data.slave_position); fp@1079: return -EINVAL; fp@1079: } fp@1079: fp@1079: if (data.sync_index >= slave->sii.sync_count) { fp@1079: up(&master->master_sem); fp@1079: EC_ERR("Sync manager %u does not exist in slave %u!\n", fp@1079: data.sync_index, data.slave_position); fp@1079: return -EINVAL; fp@1079: } fp@1079: fp@1079: sync = &slave->sii.syncs[data.sync_index]; fp@1079: fp@1079: data.physical_start_address = sync->physical_start_address; fp@1079: data.default_size = sync->default_length; fp@1079: data.control_register = sync->control_register; fp@1079: data.enable = sync->enable; fp@1079: data.pdo_count = ec_pdo_list_count(&sync->pdos); fp@1079: fp@1079: up(&master->master_sem); fp@1079: fp@1079: if (copy_to_user((void __user *) arg, &data, sizeof(data))) fp@1079: return -EFAULT; fp@1079: fp@1079: return 0; fp@1079: } fp@1079: fp@1079: /*****************************************************************************/ fp@1079: fp@1079: /** Get slave sync manager Pdo information. fp@1079: */ fp@1079: int ec_cdev_ioctl_slave_sync_pdo( fp@1079: ec_master_t *master, /**< EtherCAT master. */ fp@1079: unsigned long arg /**< Userspace address to store the results. */ fp@1079: ) fp@1079: { fp@1079: ec_ioctl_slave_sync_pdo_t data; fp@1079: const ec_slave_t *slave; fp@1079: const ec_sync_t *sync; fp@1079: const ec_pdo_t *pdo; fp@1079: fp@1079: if (copy_from_user(&data, (void __user *) arg, sizeof(data))) { fp@1079: return -EFAULT; fp@1079: } fp@1079: fp@1189: if (down_interruptible(&master->master_sem)) fp@1189: return -EINTR; fp@1079: fp@1079: if (!(slave = ec_master_find_slave_const( fp@1079: master, 0, data.slave_position))) { fp@1079: up(&master->master_sem); fp@1079: EC_ERR("Slave %u does not exist!\n", data.slave_position); fp@1079: return -EINVAL; fp@1079: } fp@1079: fp@1079: if (data.sync_index >= slave->sii.sync_count) { fp@1079: up(&master->master_sem); fp@1079: EC_ERR("Sync manager %u does not exist in slave %u!\n", fp@1079: data.sync_index, data.slave_position); fp@1079: return -EINVAL; fp@1079: } fp@1079: fp@1079: sync = &slave->sii.syncs[data.sync_index]; fp@1079: if (!(pdo = ec_pdo_list_find_pdo_by_pos_const( fp@1079: &sync->pdos, data.pdo_pos))) { fp@1079: up(&master->master_sem); fp@1079: EC_ERR("Sync manager %u does not contain a Pdo with " fp@1079: "position %u in slave %u!\n", data.sync_index, fp@1079: data.pdo_pos, data.slave_position); fp@1079: return -EINVAL; fp@1079: } fp@1079: fp@1079: data.index = pdo->index; fp@1079: data.entry_count = ec_pdo_entry_count(pdo); fp@1108: ec_cdev_strcpy(data.name, pdo->name); fp@1079: fp@1079: up(&master->master_sem); fp@1079: fp@1079: if (copy_to_user((void __user *) arg, &data, sizeof(data))) fp@1079: return -EFAULT; fp@1079: fp@1079: return 0; fp@1079: } fp@1079: fp@1079: /*****************************************************************************/ fp@1079: fp@1079: /** Get slave sync manager Pdo entry information. fp@1079: */ fp@1079: int ec_cdev_ioctl_slave_sync_pdo_entry( fp@1079: ec_master_t *master, /**< EtherCAT master. */ fp@1079: unsigned long arg /**< Userspace address to store the results. */ fp@1079: ) fp@1079: { fp@1079: ec_ioctl_slave_sync_pdo_entry_t data; fp@1079: const ec_slave_t *slave; fp@1079: const ec_sync_t *sync; fp@1079: const ec_pdo_t *pdo; fp@1079: const ec_pdo_entry_t *entry; fp@1079: fp@1079: if (copy_from_user(&data, (void __user *) arg, sizeof(data))) { fp@1079: return -EFAULT; fp@1079: } fp@1079: fp@1189: if (down_interruptible(&master->master_sem)) fp@1189: return -EINTR; fp@1079: fp@1079: if (!(slave = ec_master_find_slave_const( fp@1079: master, 0, data.slave_position))) { fp@1079: up(&master->master_sem); fp@1079: EC_ERR("Slave %u does not exist!\n", data.slave_position); fp@1079: return -EINVAL; fp@1079: } fp@1079: fp@1079: if (data.sync_index >= slave->sii.sync_count) { fp@1079: up(&master->master_sem); fp@1079: EC_ERR("Sync manager %u does not exist in slave %u!\n", fp@1079: data.sync_index, data.slave_position); fp@1079: return -EINVAL; fp@1079: } fp@1079: fp@1079: sync = &slave->sii.syncs[data.sync_index]; fp@1079: if (!(pdo = ec_pdo_list_find_pdo_by_pos_const( fp@1079: &sync->pdos, data.pdo_pos))) { fp@1079: up(&master->master_sem); fp@1079: EC_ERR("Sync manager %u does not contain a Pdo with " fp@1079: "position %u in slave %u!\n", data.sync_index, fp@1079: data.pdo_pos, data.slave_position); fp@1079: return -EINVAL; fp@1079: } fp@1079: fp@1079: if (!(entry = ec_pdo_find_entry_by_pos_const( fp@1079: pdo, data.entry_pos))) { fp@1079: up(&master->master_sem); fp@1079: EC_ERR("Pdo 0x%04X does not contain an entry with " fp@1079: "position %u in slave %u!\n", data.pdo_pos, fp@1079: data.entry_pos, data.slave_position); fp@1079: return -EINVAL; fp@1079: } fp@1079: fp@1079: data.index = entry->index; fp@1079: data.subindex = entry->subindex; fp@1079: data.bit_length = entry->bit_length; fp@1108: ec_cdev_strcpy(data.name, entry->name); fp@1079: fp@1079: up(&master->master_sem); fp@1079: fp@1079: if (copy_to_user((void __user *) arg, &data, sizeof(data))) fp@1079: return -EFAULT; fp@1079: fp@1079: return 0; fp@1079: } fp@1079: fp@1079: /*****************************************************************************/ fp@1079: fp@1079: /** Get domain information. fp@1079: */ fp@1079: int ec_cdev_ioctl_domain( fp@1079: ec_master_t *master, /**< EtherCAT master. */ fp@1079: unsigned long arg /**< Userspace address to store the results. */ fp@1079: ) fp@1079: { fp@1079: ec_ioctl_domain_t data; fp@1079: const ec_domain_t *domain; fp@1079: fp@1079: if (copy_from_user(&data, (void __user *) arg, sizeof(data))) { fp@1079: return -EFAULT; fp@1079: } fp@1079: fp@1189: if (down_interruptible(&master->master_sem)) fp@1189: return -EINTR; fp@1079: fp@1079: if (!(domain = ec_master_find_domain_const(master, data.index))) { fp@1079: up(&master->master_sem); fp@1079: EC_ERR("Domain %u does not exist!\n", data.index); fp@1079: return -EINVAL; fp@1079: } fp@1079: fp@1079: data.data_size = domain->data_size; fp@1079: data.logical_base_address = domain->logical_base_address; fp@1079: data.working_counter = domain->working_counter; fp@1079: data.expected_working_counter = domain->expected_working_counter; fp@1079: data.fmmu_count = ec_domain_fmmu_count(domain); fp@1079: fp@1079: up(&master->master_sem); fp@1079: fp@1079: if (copy_to_user((void __user *) arg, &data, sizeof(data))) fp@1079: return -EFAULT; fp@1079: fp@1079: return 0; fp@1079: } fp@1079: fp@1079: /*****************************************************************************/ fp@1079: fp@1079: /** Get domain FMMU information. fp@1079: */ fp@1079: int ec_cdev_ioctl_domain_fmmu( fp@1079: ec_master_t *master, /**< EtherCAT master. */ fp@1079: unsigned long arg /**< Userspace address to store the results. */ fp@1079: ) fp@1079: { fp@1079: ec_ioctl_domain_fmmu_t data; fp@1079: const ec_domain_t *domain; fp@1079: const ec_fmmu_config_t *fmmu; fp@1079: fp@1079: if (copy_from_user(&data, (void __user *) arg, sizeof(data))) { fp@1079: return -EFAULT; fp@1079: } fp@1079: fp@1189: if (down_interruptible(&master->master_sem)) fp@1189: return -EINTR; fp@1079: fp@1079: if (!(domain = ec_master_find_domain_const(master, data.domain_index))) { fp@1079: up(&master->master_sem); fp@1079: EC_ERR("Domain %u does not exist!\n", data.domain_index); fp@1079: return -EINVAL; fp@1079: } fp@1079: fp@1079: if (!(fmmu = ec_domain_find_fmmu(domain, data.fmmu_index))) { fp@1079: up(&master->master_sem); fp@1079: EC_ERR("Domain %u has less than %u fmmu configurations.\n", fp@1079: data.domain_index, data.fmmu_index + 1); fp@1079: return -EINVAL; fp@1079: } fp@1079: fp@1079: data.slave_config_alias = fmmu->sc->alias; fp@1079: data.slave_config_position = fmmu->sc->position; fp@1079: data.sync_index = fmmu->sync_index; fp@1079: data.dir = fmmu->dir; fp@1079: data.logical_address = fmmu->logical_start_address; fp@1079: data.data_size = fmmu->data_size; fp@1079: fp@1079: up(&master->master_sem); fp@1079: fp@1079: if (copy_to_user((void __user *) arg, &data, sizeof(data))) fp@1079: return -EFAULT; fp@1079: fp@1079: return 0; fp@1079: } fp@1079: fp@1079: /*****************************************************************************/ fp@1079: fp@1079: /** Get domain data. fp@1079: */ fp@1079: int ec_cdev_ioctl_domain_data( fp@1079: ec_master_t *master, /**< EtherCAT master. */ fp@1079: unsigned long arg /**< Userspace address to store the results. */ fp@1079: ) fp@1079: { fp@1079: ec_ioctl_domain_data_t data; fp@1079: const ec_domain_t *domain; fp@1079: fp@1079: if (copy_from_user(&data, (void __user *) arg, sizeof(data))) { fp@1079: return -EFAULT; fp@1079: } fp@1079: fp@1189: if (down_interruptible(&master->master_sem)) fp@1189: return -EINTR; fp@1079: fp@1079: if (!(domain = ec_master_find_domain_const(master, data.domain_index))) { fp@1079: up(&master->master_sem); fp@1079: EC_ERR("Domain %u does not exist!\n", data.domain_index); fp@1079: return -EINVAL; fp@1079: } fp@1079: fp@1079: if (domain->data_size != data.data_size) { fp@1079: up(&master->master_sem); fp@1079: EC_ERR("Data size mismatch %u/%u!\n", fp@1079: data.data_size, domain->data_size); fp@1079: return -EFAULT; fp@1079: } fp@1079: fp@1079: if (copy_to_user((void __user *) data.target, domain->data, fp@1637: domain->data_size)) { fp@1637: up(&master->master_sem); fp@1637: return -EFAULT; fp@1637: } fp@1079: fp@1079: up(&master->master_sem); fp@1079: return 0; fp@1079: } fp@1079: fp@1079: /*****************************************************************************/ fp@1079: fp@1079: /** Set master debug level. fp@1079: */ fp@1079: int ec_cdev_ioctl_master_debug( fp@1079: ec_master_t *master, /**< EtherCAT master. */ fp@1079: unsigned long arg /**< ioctl() argument. */ fp@1079: ) fp@1079: { fp@1079: if (ec_master_debug_level(master, (unsigned int) arg)) fp@1079: return -EINVAL; fp@1079: fp@1079: return 0; fp@1079: } fp@1079: fp@1079: /*****************************************************************************/ fp@1079: fp@1079: /** Set slave state. fp@1079: */ fp@1079: int ec_cdev_ioctl_slave_state( fp@1079: ec_master_t *master, /**< EtherCAT master. */ fp@1079: unsigned long arg /**< ioctl() argument. */ fp@1079: ) fp@1079: { fp@1079: ec_ioctl_slave_state_t data; fp@1079: ec_slave_t *slave; fp@1079: fp@1079: if (copy_from_user(&data, (void __user *) arg, sizeof(data))) { fp@1079: return -EFAULT; fp@1079: } fp@1079: fp@1189: if (down_interruptible(&master->master_sem)) fp@1189: return -EINTR; fp@1079: fp@1079: if (!(slave = ec_master_find_slave( fp@1079: master, 0, data.slave_position))) { fp@1196: up(&master->master_sem); fp@1079: EC_ERR("Slave %u does not exist!\n", data.slave_position); fp@1079: return -EINVAL; fp@1079: } fp@1079: fp@1150: ec_slave_request_state(slave, data.al_state); fp@1079: fp@1079: up(&master->master_sem); fp@1079: return 0; fp@1079: } fp@1079: fp@1079: /*****************************************************************************/ fp@1079: fp@1079: /** Get slave Sdo information. fp@1079: */ fp@1079: int ec_cdev_ioctl_slave_sdo( fp@1079: ec_master_t *master, /**< EtherCAT master. */ fp@1079: unsigned long arg /**< ioctl() argument. */ fp@1079: ) fp@1079: { fp@1079: ec_ioctl_slave_sdo_t data; fp@1079: const ec_slave_t *slave; fp@1079: const ec_sdo_t *sdo; fp@1079: fp@1079: if (copy_from_user(&data, (void __user *) arg, sizeof(data))) { fp@1079: return -EFAULT; fp@1079: } fp@1079: fp@1189: if (down_interruptible(&master->master_sem)) fp@1189: return -EINTR; fp@1079: fp@1079: if (!(slave = ec_master_find_slave_const( fp@1079: master, 0, data.slave_position))) { fp@1079: up(&master->master_sem); fp@1079: EC_ERR("Slave %u does not exist!\n", data.slave_position); fp@1079: return -EINVAL; fp@1079: } fp@1079: fp@1079: if (!(sdo = ec_slave_get_sdo_by_pos_const( fp@1079: slave, data.sdo_position))) { fp@1079: up(&master->master_sem); fp@1079: EC_ERR("Sdo %u does not exist in slave %u!\n", fp@1079: data.sdo_position, data.slave_position); fp@1079: return -EINVAL; fp@1079: } fp@1079: fp@1079: data.sdo_index = sdo->index; fp@1079: data.max_subindex = sdo->max_subindex; fp@1108: ec_cdev_strcpy(data.name, sdo->name); fp@1079: fp@1079: up(&master->master_sem); fp@1079: fp@1079: if (copy_to_user((void __user *) arg, &data, sizeof(data))) fp@1079: return -EFAULT; fp@1079: fp@1079: return 0; fp@1079: } fp@1079: fp@1079: /*****************************************************************************/ fp@1079: fp@1079: /** Get slave Sdo entry information. fp@1079: */ fp@1079: int ec_cdev_ioctl_slave_sdo_entry( fp@1079: ec_master_t *master, /**< EtherCAT master. */ fp@1079: unsigned long arg /**< ioctl() argument. */ fp@1079: ) fp@1079: { fp@1079: ec_ioctl_slave_sdo_entry_t data; fp@1079: const ec_slave_t *slave; fp@1079: const ec_sdo_t *sdo; fp@1079: const ec_sdo_entry_t *entry; fp@1079: fp@1079: if (copy_from_user(&data, (void __user *) arg, sizeof(data))) { fp@1079: return -EFAULT; fp@1079: } fp@1079: fp@1189: if (down_interruptible(&master->master_sem)) fp@1189: return -EINTR; fp@1079: fp@1079: if (!(slave = ec_master_find_slave_const( fp@1079: master, 0, data.slave_position))) { fp@1079: up(&master->master_sem); fp@1079: EC_ERR("Slave %u does not exist!\n", data.slave_position); fp@1079: return -EINVAL; fp@1079: } fp@1079: fp@1079: if (data.sdo_spec <= 0) { fp@1079: if (!(sdo = ec_slave_get_sdo_by_pos_const( fp@1079: slave, -data.sdo_spec))) { fp@1079: up(&master->master_sem); fp@1079: EC_ERR("Sdo %u does not exist in slave %u!\n", fp@1079: -data.sdo_spec, data.slave_position); fp@1079: return -EINVAL; fp@1079: } fp@1079: } else { fp@1079: if (!(sdo = ec_slave_get_sdo_const( fp@1079: slave, data.sdo_spec))) { fp@1079: up(&master->master_sem); fp@1079: EC_ERR("Sdo 0x%04X does not exist in slave %u!\n", fp@1079: data.sdo_spec, data.slave_position); fp@1079: return -EINVAL; fp@1079: } fp@1079: } fp@1079: fp@1079: if (!(entry = ec_sdo_get_entry_const( fp@1079: sdo, data.sdo_entry_subindex))) { fp@1079: up(&master->master_sem); fp@1079: EC_ERR("Sdo entry 0x%04X:%02X does not exist " fp@1079: "in slave %u!\n", sdo->index, fp@1079: data.sdo_entry_subindex, data.slave_position); fp@1079: return -EINVAL; fp@1079: } fp@1079: fp@1079: data.data_type = entry->data_type; fp@1079: data.bit_length = entry->bit_length; fp@1108: ec_cdev_strcpy(data.description, entry->description); fp@1079: fp@1079: up(&master->master_sem); fp@1079: fp@1079: if (copy_to_user((void __user *) arg, &data, sizeof(data))) fp@1079: return -EFAULT; fp@1079: fp@1079: return 0; fp@1079: } fp@1079: fp@1079: /*****************************************************************************/ fp@1079: fp@1079: /** Upload Sdo. fp@1079: */ fp@1079: int ec_cdev_ioctl_slave_sdo_upload( fp@1079: ec_master_t *master, /**< EtherCAT master. */ fp@1079: unsigned long arg /**< ioctl() argument. */ fp@1079: ) fp@1079: { fp@1079: ec_ioctl_slave_sdo_upload_t data; fp@1079: ec_master_sdo_request_t request; fp@1079: int retval; fp@1079: fp@1079: if (copy_from_user(&data, (void __user *) arg, sizeof(data))) { fp@1079: return -EFAULT; fp@1079: } fp@1079: fp@1079: ec_sdo_request_init(&request.req); fp@1079: ec_sdo_request_address(&request.req, fp@1079: data.sdo_index, data.sdo_entry_subindex); fp@1079: ecrt_sdo_request_read(&request.req); fp@1079: fp@1189: if (down_interruptible(&master->master_sem)) fp@1189: return -EINTR; fp@1079: fp@1079: if (!(request.slave = ec_master_find_slave( fp@1079: master, 0, data.slave_position))) { fp@1079: up(&master->master_sem); fp@1079: ec_sdo_request_clear(&request.req); fp@1079: EC_ERR("Slave %u does not exist!\n", data.slave_position); fp@1079: return -EINVAL; fp@1079: } fp@1079: fp@1079: // schedule request. fp@1079: list_add_tail(&request.list, &master->slave_sdo_requests); fp@1079: fp@1079: up(&master->master_sem); fp@1079: fp@1079: // wait for processing through FSM fp@1079: if (wait_event_interruptible(master->sdo_queue, fp@1079: request.req.state != EC_REQUEST_QUEUED)) { fp@1079: // interrupted by signal fp@1079: down(&master->master_sem); fp@1079: if (request.req.state == EC_REQUEST_QUEUED) { fp@1079: list_del(&request.req.list); fp@1079: up(&master->master_sem); fp@1079: ec_sdo_request_clear(&request.req); fp@1079: return -EINTR; fp@1079: } fp@1079: // request already processing: interrupt not possible. fp@1079: up(&master->master_sem); fp@1079: } fp@1079: fp@1079: // wait until master FSM has finished processing fp@1079: wait_event(master->sdo_queue, request.req.state != EC_REQUEST_BUSY); fp@1079: fp@1079: data.abort_code = request.req.abort_code; fp@1079: fp@1079: if (request.req.state != EC_REQUEST_SUCCESS) { fp@1079: data.data_size = 0; fp@1079: retval = -EIO; fp@1079: } else { fp@1079: if (request.req.data_size > data.target_size) { fp@1079: EC_ERR("Buffer too small.\n"); fp@1079: ec_sdo_request_clear(&request.req); fp@1079: return -EOVERFLOW; fp@1079: } fp@1079: data.data_size = request.req.data_size; fp@1079: fp@1079: if (copy_to_user((void __user *) data.target, fp@1079: request.req.data, data.data_size)) { fp@1079: ec_sdo_request_clear(&request.req); fp@1079: return -EFAULT; fp@1079: } fp@1079: retval = 0; fp@1079: } fp@1079: fp@1079: if (__copy_to_user((void __user *) arg, &data, sizeof(data))) { fp@1079: retval = -EFAULT; fp@1079: } fp@1079: fp@1079: ec_sdo_request_clear(&request.req); fp@1079: return retval; fp@1079: } fp@1079: fp@1079: /*****************************************************************************/ fp@1079: fp@1079: /** Download Sdo. fp@1079: */ fp@1079: int ec_cdev_ioctl_slave_sdo_download( fp@1079: ec_master_t *master, /**< EtherCAT master. */ fp@1079: unsigned long arg /**< ioctl() argument. */ fp@1079: ) fp@1079: { fp@1079: ec_ioctl_slave_sdo_download_t data; fp@1079: ec_master_sdo_request_t request; fp@1079: int retval; fp@1079: fp@1079: if (copy_from_user(&data, (void __user *) arg, sizeof(data))) { fp@1079: return -EFAULT; fp@1079: } fp@1079: fp@1079: // copy data to download fp@1079: if (!data.data_size) { fp@1079: EC_ERR("Zero data size!\n"); fp@1079: return -EINVAL; fp@1079: } fp@1079: fp@1079: ec_sdo_request_init(&request.req); fp@1079: ec_sdo_request_address(&request.req, fp@1079: data.sdo_index, data.sdo_entry_subindex); fp@1079: if (ec_sdo_request_alloc(&request.req, data.data_size)) { fp@1079: ec_sdo_request_clear(&request.req); fp@1079: return -ENOMEM; fp@1079: } fp@1079: if (copy_from_user(request.req.data, fp@1079: (void __user *) data.data, data.data_size)) { fp@1079: ec_sdo_request_clear(&request.req); fp@1079: return -EFAULT; fp@1079: } fp@1079: request.req.data_size = data.data_size; fp@1079: ecrt_sdo_request_write(&request.req); fp@1079: fp@1189: if (down_interruptible(&master->master_sem)) fp@1189: return -EINTR; fp@1079: fp@1079: if (!(request.slave = ec_master_find_slave( fp@1079: master, 0, data.slave_position))) { fp@1079: up(&master->master_sem); fp@1079: EC_ERR("Slave %u does not exist!\n", data.slave_position); fp@1079: ec_sdo_request_clear(&request.req); fp@1079: return -EINVAL; fp@1079: } fp@1079: fp@1079: // schedule request. fp@1079: list_add_tail(&request.list, &master->slave_sdo_requests); fp@1079: fp@1079: up(&master->master_sem); fp@1079: fp@1079: // wait for processing through FSM fp@1079: if (wait_event_interruptible(master->sdo_queue, fp@1079: request.req.state != EC_REQUEST_QUEUED)) { fp@1079: // interrupted by signal fp@1079: down(&master->master_sem); fp@1079: if (request.req.state == EC_REQUEST_QUEUED) { fp@1079: list_del(&request.req.list); fp@1079: up(&master->master_sem); fp@1079: ec_sdo_request_clear(&request.req); fp@1079: return -EINTR; fp@1079: } fp@1079: // request already processing: interrupt not possible. fp@1079: up(&master->master_sem); fp@1079: } fp@1079: fp@1079: // wait until master FSM has finished processing fp@1079: wait_event(master->sdo_queue, request.req.state != EC_REQUEST_BUSY); fp@1079: fp@1079: data.abort_code = request.req.abort_code; fp@1079: fp@1079: retval = request.req.state == EC_REQUEST_SUCCESS ? 0 : -EIO; fp@1079: fp@1079: if (__copy_to_user((void __user *) arg, &data, sizeof(data))) { fp@1079: retval = -EFAULT; fp@1079: } fp@1079: fp@1079: ec_sdo_request_clear(&request.req); fp@1079: return retval; fp@1079: } fp@1079: fp@1079: /*****************************************************************************/ fp@1079: fp@1079: /** Read a slave's SII. fp@1079: */ fp@1079: int ec_cdev_ioctl_slave_sii_read( fp@1079: ec_master_t *master, /**< EtherCAT master. */ fp@1079: unsigned long arg /**< ioctl() argument. */ fp@1079: ) fp@1079: { fp@1079: ec_ioctl_slave_sii_t data; fp@1079: const ec_slave_t *slave; fp@1079: int retval; fp@1079: fp@1079: if (copy_from_user(&data, (void __user *) arg, sizeof(data))) { fp@1079: return -EFAULT; fp@1079: } fp@1079: fp@1189: if (down_interruptible(&master->master_sem)) fp@1189: return -EINTR; fp@1079: fp@1079: if (!(slave = ec_master_find_slave_const( fp@1079: master, 0, data.slave_position))) { fp@1079: up(&master->master_sem); fp@1079: EC_ERR("Slave %u does not exist!\n", data.slave_position); fp@1079: return -EINVAL; fp@1079: } fp@1079: fp@1079: if (!data.nwords fp@1079: || data.offset + data.nwords > slave->sii_nwords) { fp@1079: up(&master->master_sem); fp@1079: EC_ERR("Invalid SII read offset/size %u/%u for slave " fp@1079: "SII size %u!\n", data.offset, fp@1079: data.nwords, slave->sii_nwords); fp@1079: return -EINVAL; fp@1079: } fp@1079: fp@1079: if (copy_to_user((void __user *) data.words, fp@1079: slave->sii_words + data.offset, data.nwords * 2)) fp@1079: retval = -EFAULT; fp@1079: else fp@1079: retval = 0; fp@1079: fp@1079: up(&master->master_sem); fp@1079: return retval; fp@1079: } fp@1079: fp@1079: /*****************************************************************************/ fp@1079: fp@1079: /** Write a slave's SII. fp@1079: */ fp@1079: int ec_cdev_ioctl_slave_sii_write( fp@1079: ec_master_t *master, /**< EtherCAT master. */ fp@1079: unsigned long arg /**< ioctl() argument. */ fp@1079: ) fp@1079: { fp@1079: ec_ioctl_slave_sii_t data; fp@1079: ec_slave_t *slave; fp@1079: unsigned int byte_size; fp@1079: uint16_t *words; fp@1079: ec_sii_write_request_t request; fp@1079: fp@1079: if (copy_from_user(&data, (void __user *) arg, sizeof(data))) { fp@1079: return -EFAULT; fp@1079: } fp@1079: fp@1079: if (!data.nwords) fp@1079: return 0; fp@1079: fp@1079: byte_size = sizeof(uint16_t) * data.nwords; fp@1079: if (!(words = kmalloc(byte_size, GFP_KERNEL))) { fp@1079: EC_ERR("Failed to allocate %u bytes for SII contents.\n", fp@1079: byte_size); fp@1079: return -ENOMEM; fp@1079: } fp@1079: fp@1079: if (copy_from_user(words, fp@1079: (void __user *) data.words, byte_size)) { fp@1079: kfree(words); fp@1079: return -EFAULT; fp@1079: } fp@1079: fp@1189: if (down_interruptible(&master->master_sem)) fp@1189: return -EINTR; fp@1079: fp@1079: if (!(slave = ec_master_find_slave( fp@1079: master, 0, data.slave_position))) { fp@1079: up(&master->master_sem); fp@1079: EC_ERR("Slave %u does not exist!\n", data.slave_position); fp@1079: kfree(words); fp@1079: return -EINVAL; fp@1079: } fp@1079: fp@1079: // init SII write request fp@1079: INIT_LIST_HEAD(&request.list); fp@1079: request.slave = slave; fp@1079: request.words = words; fp@1079: request.offset = data.offset; fp@1079: request.nwords = data.nwords; fp@1079: request.state = EC_REQUEST_QUEUED; fp@1079: fp@1079: // schedule SII write request. fp@1079: list_add_tail(&request.list, &master->sii_requests); fp@1079: fp@1079: up(&master->master_sem); fp@1079: fp@1079: // wait for processing through FSM fp@1079: if (wait_event_interruptible(master->sii_queue, fp@1079: request.state != EC_REQUEST_QUEUED)) { fp@1079: // interrupted by signal fp@1079: down(&master->master_sem); fp@1079: if (request.state == EC_REQUEST_QUEUED) { fp@1079: // abort request fp@1079: list_del(&request.list); fp@1079: up(&master->master_sem); fp@1079: kfree(words); fp@1079: return -EINTR; fp@1079: } fp@1079: up(&master->master_sem); fp@1079: } fp@1079: fp@1079: // wait until master FSM has finished processing fp@1079: wait_event(master->sii_queue, request.state != EC_REQUEST_BUSY); fp@1079: fp@1079: kfree(words); fp@1079: fp@1079: return request.state == EC_REQUEST_SUCCESS ? 0 : -EIO; fp@1079: } fp@1079: fp@1079: /*****************************************************************************/ fp@1079: fp@1079: /** Get slave configuration information. fp@1079: */ fp@1079: int ec_cdev_ioctl_config( fp@1079: ec_master_t *master, /**< EtherCAT master. */ fp@1079: unsigned long arg /**< ioctl() argument. */ fp@1079: ) fp@1079: { fp@1079: ec_ioctl_config_t data; fp@1079: const ec_slave_config_t *sc; fp@1079: uint8_t i; fp@1079: fp@1079: if (copy_from_user(&data, (void __user *) arg, sizeof(data))) { fp@1079: return -EFAULT; fp@1079: } fp@1079: fp@1189: if (down_interruptible(&master->master_sem)) fp@1189: return -EINTR; fp@1079: fp@1079: if (!(sc = ec_master_get_config_const( fp@1079: master, data.config_index))) { fp@1079: up(&master->master_sem); fp@1079: EC_ERR("Slave config %u does not exist!\n", fp@1079: data.config_index); fp@1079: return -EINVAL; fp@1079: } fp@1079: fp@1079: data.alias = sc->alias; fp@1079: data.position = sc->position; fp@1079: data.vendor_id = sc->vendor_id; fp@1079: data.product_code = sc->product_code; fp@1082: for (i = 0; i < EC_MAX_SYNC_MANAGERS; i++) { fp@1079: data.syncs[i].dir = sc->sync_configs[i].dir; fp@1079: data.syncs[i].pdo_count = fp@1079: ec_pdo_list_count(&sc->sync_configs[i].pdos); fp@1079: } fp@1079: data.sdo_count = ec_slave_config_sdo_count(sc); fp@1147: data.slave_position = sc->slave ? sc->slave->ring_position : -1; fp@1079: fp@1079: up(&master->master_sem); fp@1079: fp@1079: if (copy_to_user((void __user *) arg, &data, sizeof(data))) fp@1079: return -EFAULT; fp@1079: fp@1079: return 0; fp@1079: } fp@1079: fp@1079: /*****************************************************************************/ fp@1079: fp@1079: /** Get slave configuration Pdo information. fp@1079: */ fp@1079: int ec_cdev_ioctl_config_pdo( fp@1079: ec_master_t *master, /**< EtherCAT master. */ fp@1079: unsigned long arg /**< ioctl() argument. */ fp@1079: ) fp@1079: { fp@1079: ec_ioctl_config_pdo_t data; fp@1079: const ec_slave_config_t *sc; fp@1079: const ec_pdo_t *pdo; fp@1079: fp@1079: if (copy_from_user(&data, (void __user *) arg, sizeof(data))) { fp@1079: return -EFAULT; fp@1079: } fp@1079: fp@1082: if (data.sync_index >= EC_MAX_SYNC_MANAGERS) { fp@1079: EC_ERR("Invalid sync manager index %u!\n", fp@1079: data.sync_index); fp@1079: return -EINVAL; fp@1079: } fp@1079: fp@1189: if (down_interruptible(&master->master_sem)) fp@1189: return -EINTR; fp@1079: fp@1079: if (!(sc = ec_master_get_config_const( fp@1079: master, data.config_index))) { fp@1079: up(&master->master_sem); fp@1079: EC_ERR("Slave config %u does not exist!\n", fp@1079: data.config_index); fp@1079: return -EINVAL; fp@1079: } fp@1079: fp@1079: if (!(pdo = ec_pdo_list_find_pdo_by_pos_const( fp@1079: &sc->sync_configs[data.sync_index].pdos, fp@1079: data.pdo_pos))) { fp@1079: up(&master->master_sem); fp@1079: EC_ERR("Invalid Pdo position!\n"); fp@1079: return -EINVAL; fp@1079: } fp@1079: fp@1079: data.index = pdo->index; fp@1079: data.entry_count = ec_pdo_entry_count(pdo); fp@1108: ec_cdev_strcpy(data.name, pdo->name); fp@1079: fp@1079: up(&master->master_sem); fp@1079: fp@1079: if (copy_to_user((void __user *) arg, &data, sizeof(data))) fp@1079: return -EFAULT; fp@1079: fp@1079: return 0; fp@1079: } fp@1079: fp@1079: /*****************************************************************************/ fp@1079: fp@1079: /** Get slave configuration Pdo entry information. fp@1079: */ fp@1079: int ec_cdev_ioctl_config_pdo_entry( fp@1079: ec_master_t *master, /**< EtherCAT master. */ fp@1079: unsigned long arg /**< ioctl() argument. */ fp@1079: ) fp@1079: { fp@1079: ec_ioctl_config_pdo_entry_t data; fp@1079: const ec_slave_config_t *sc; fp@1079: const ec_pdo_t *pdo; fp@1079: const ec_pdo_entry_t *entry; fp@1079: fp@1079: if (copy_from_user(&data, (void __user *) arg, sizeof(data))) { fp@1079: return -EFAULT; fp@1079: } fp@1079: fp@1082: if (data.sync_index >= EC_MAX_SYNC_MANAGERS) { fp@1079: EC_ERR("Invalid sync manager index %u!\n", fp@1079: data.sync_index); fp@1079: return -EINVAL; fp@1079: } fp@1079: fp@1189: if (down_interruptible(&master->master_sem)) fp@1189: return -EINTR; fp@1079: fp@1079: if (!(sc = ec_master_get_config_const( fp@1079: master, data.config_index))) { fp@1079: up(&master->master_sem); fp@1079: EC_ERR("Slave config %u does not exist!\n", fp@1079: data.config_index); fp@1079: return -EINVAL; fp@1079: } fp@1079: fp@1079: if (!(pdo = ec_pdo_list_find_pdo_by_pos_const( fp@1079: &sc->sync_configs[data.sync_index].pdos, fp@1079: data.pdo_pos))) { fp@1079: up(&master->master_sem); fp@1079: EC_ERR("Invalid Pdo position!\n"); fp@1079: return -EINVAL; fp@1079: } fp@1079: fp@1079: if (!(entry = ec_pdo_find_entry_by_pos_const( fp@1079: pdo, data.entry_pos))) { fp@1079: up(&master->master_sem); fp@1079: EC_ERR("Entry not found!\n"); fp@1079: return -EINVAL; fp@1079: } fp@1079: fp@1079: data.index = entry->index; fp@1079: data.subindex = entry->subindex; fp@1079: data.bit_length = entry->bit_length; fp@1108: ec_cdev_strcpy(data.name, entry->name); fp@1079: fp@1079: up(&master->master_sem); fp@1079: fp@1079: if (copy_to_user((void __user *) arg, &data, sizeof(data))) fp@1079: return -EFAULT; fp@1079: fp@1079: return 0; fp@1079: } fp@1079: fp@1079: /*****************************************************************************/ fp@1079: fp@1079: /** Get slave configuration Sdo information. fp@1079: */ fp@1079: int ec_cdev_ioctl_config_sdo( fp@1079: ec_master_t *master, /**< EtherCAT master. */ fp@1079: unsigned long arg /**< ioctl() argument. */ fp@1079: ) fp@1079: { fp@1079: ec_ioctl_config_sdo_t data; fp@1079: const ec_slave_config_t *sc; fp@1079: const ec_sdo_request_t *req; fp@1079: fp@1079: if (copy_from_user(&data, (void __user *) arg, sizeof(data))) { fp@1079: return -EFAULT; fp@1079: } fp@1079: fp@1189: if (down_interruptible(&master->master_sem)) fp@1189: return -EINTR; fp@1079: fp@1079: if (!(sc = ec_master_get_config_const( fp@1079: master, data.config_index))) { fp@1079: up(&master->master_sem); fp@1079: EC_ERR("Slave config %u does not exist!\n", fp@1079: data.config_index); fp@1079: return -EINVAL; fp@1079: } fp@1079: fp@1079: if (!(req = ec_slave_config_get_sdo_by_pos_const( fp@1079: sc, data.sdo_pos))) { fp@1079: up(&master->master_sem); fp@1079: EC_ERR("Invalid Sdo position!\n"); fp@1079: return -EINVAL; fp@1079: } fp@1079: fp@1079: data.index = req->index; fp@1079: data.subindex = req->subindex; fp@1079: data.size = req->data_size; fp@1079: memcpy(&data.data, req->data, min((u32) data.size, (u32) 4)); fp@1079: fp@1079: up(&master->master_sem); fp@1079: fp@1079: if (copy_to_user((void __user *) arg, &data, sizeof(data))) fp@1079: return -EFAULT; fp@1079: fp@1079: return 0; fp@1079: } fp@1079: fp@922: /****************************************************************************** fp@922: * File operations fp@922: *****************************************************************************/ fp@922: fp@1092: /** Called when the cdev is opened. fp@1092: */ fp@922: int eccdev_open(struct inode *inode, struct file *filp) fp@922: { fp@922: ec_cdev_t *cdev = container_of(inode->i_cdev, ec_cdev_t, cdev); fp@935: ec_master_t *master = cdev->master; fp@922: fp@922: filp->private_data = cdev; fp@935: if (master->debug_level) fp@935: EC_DBG("File opened.\n"); fp@922: return 0; fp@922: } fp@922: fp@922: /*****************************************************************************/ fp@922: fp@1092: /** Called when the cdev is closed. fp@1092: */ fp@922: int eccdev_release(struct inode *inode, struct file *filp) fp@922: { fp@935: ec_cdev_t *cdev = (ec_cdev_t *) filp->private_data; fp@935: ec_master_t *master = cdev->master; fp@935: fp@935: if (master->debug_level) fp@935: EC_DBG("File closed.\n"); fp@922: return 0; fp@922: } fp@922: fp@922: /*****************************************************************************/ fp@922: fp@1092: /** Called when an ioctl() command is issued. fp@1092: */ fp@935: long eccdev_ioctl(struct file *filp, unsigned int cmd, unsigned long arg) fp@935: { fp@935: ec_cdev_t *cdev = (ec_cdev_t *) filp->private_data; fp@922: ec_master_t *master = cdev->master; fp@922: fp@922: if (master->debug_level) fp@981: EC_DBG("ioctl(filp = %x, cmd = %u (%u), arg = %x)\n", fp@981: (u32) filp, (u32) cmd, (u32) _IOC_NR(cmd), (u32) arg); fp@935: fp@922: switch (cmd) { fp@957: case EC_IOCTL_MASTER: fp@1079: return ec_cdev_ioctl_master(master, arg); fp@935: case EC_IOCTL_SLAVE: fp@1079: return ec_cdev_ioctl_slave(master, arg); fp@1079: case EC_IOCTL_SLAVE_SYNC: fp@1079: return ec_cdev_ioctl_slave_sync(master, arg); fp@1079: case EC_IOCTL_SLAVE_SYNC_PDO: fp@1079: return ec_cdev_ioctl_slave_sync_pdo(master, arg); fp@1079: case EC_IOCTL_SLAVE_SYNC_PDO_ENTRY: fp@1079: return ec_cdev_ioctl_slave_sync_pdo_entry(master, arg); fp@948: case EC_IOCTL_DOMAIN: fp@1079: return ec_cdev_ioctl_domain(master, arg); fp@950: case EC_IOCTL_DOMAIN_FMMU: fp@1079: return ec_cdev_ioctl_domain_fmmu(master, arg); fp@1079: case EC_IOCTL_DOMAIN_DATA: fp@1079: return ec_cdev_ioctl_domain_data(master, arg); fp@1079: case EC_IOCTL_MASTER_DEBUG: fp@972: if (!(filp->f_mode & FMODE_WRITE)) fp@972: return -EPERM; fp@1079: return ec_cdev_ioctl_master_debug(master, arg); fp@960: case EC_IOCTL_SLAVE_STATE: fp@1079: if (!(filp->f_mode & FMODE_WRITE)) fp@1079: return -EPERM; fp@1079: return ec_cdev_ioctl_slave_state(master, arg); fp@1079: case EC_IOCTL_SLAVE_SDO: fp@1079: return ec_cdev_ioctl_slave_sdo(master, arg); fp@1079: case EC_IOCTL_SLAVE_SDO_ENTRY: fp@1079: return ec_cdev_ioctl_slave_sdo_entry(master, arg); fp@1079: case EC_IOCTL_SLAVE_SDO_UPLOAD: fp@1079: return ec_cdev_ioctl_slave_sdo_upload(master, arg); fp@1079: case EC_IOCTL_SLAVE_SDO_DOWNLOAD: fp@1079: if (!(filp->f_mode & FMODE_WRITE)) fp@1079: return -EPERM; fp@1079: return ec_cdev_ioctl_slave_sdo_download(master, arg); fp@1079: case EC_IOCTL_SLAVE_SII_READ: fp@1079: return ec_cdev_ioctl_slave_sii_read(master, arg); fp@1079: case EC_IOCTL_SLAVE_SII_WRITE: fp@1079: if (!(filp->f_mode & FMODE_WRITE)) fp@1079: return -EPERM; fp@1079: return ec_cdev_ioctl_slave_sii_write(master, arg); fp@990: case EC_IOCTL_CONFIG: fp@1079: return ec_cdev_ioctl_config(master, arg); fp@990: case EC_IOCTL_CONFIG_PDO: fp@1079: return ec_cdev_ioctl_config_pdo(master, arg); fp@990: case EC_IOCTL_CONFIG_PDO_ENTRY: fp@1079: return ec_cdev_ioctl_config_pdo_entry(master, arg); fp@990: case EC_IOCTL_CONFIG_SDO: fp@1079: return ec_cdev_ioctl_config_sdo(master, arg); fp@922: default: fp@1079: return -ENOTTY; fp@1079: } fp@1079: } fp@1079: fp@1079: /*****************************************************************************/