fp@1831: /****************************************************************************** fp@1831: * fp@1831: * $Id$ fp@1831: * fp@1831: * Copyright (C) 2006-2008 Florian Pose, Ingenieurgemeinschaft IgH fp@1831: * fp@1831: * This file is part of the IgH EtherCAT Master. fp@1831: * fp@1831: * The IgH EtherCAT Master is free software; you can redistribute it and/or fp@1831: * modify it under the terms of the GNU General Public License version 2, as fp@1831: * published by the Free Software Foundation. fp@1831: * fp@1831: * The IgH EtherCAT Master is distributed in the hope that it will be useful, fp@1831: * but WITHOUT ANY WARRANTY; without even the implied warranty of fp@1831: * MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the GNU General fp@1831: * Public License for more details. fp@1831: * fp@1831: * You should have received a copy of the GNU General Public License along fp@1831: * with the IgH EtherCAT Master; if not, write to the Free Software fp@1831: * Foundation, Inc., 51 Franklin St, Fifth Floor, Boston, MA 02110-1301 USA fp@1831: * fp@1831: * --- fp@1831: * fp@1831: * The license mentioned above concerns the source code only. Using the fp@1831: * EtherCAT technology and brand is only permitted in compliance with the fp@1831: * industrial property and similar rights of Beckhoff Automation GmbH. fp@1831: * fp@1831: *****************************************************************************/ fp@1831: fp@1831: /** \file fp@1831: * Sercos-over-EtherCAT request functions. fp@1831: */ fp@1831: fp@1831: /*****************************************************************************/ fp@1831: fp@1831: #include fp@1831: #include fp@1975: #include fp@1831: fp@1831: #include "soe_request.h" fp@1831: fp@1831: /*****************************************************************************/ fp@1831: fp@1831: /** Default timeout in ms to wait for SoE responses. fp@1831: */ fp@1831: #define EC_SOE_REQUEST_RESPONSE_TIMEOUT 1000 fp@1831: fp@1831: /*****************************************************************************/ fp@1831: fp@1831: void ec_soe_request_clear_data(ec_soe_request_t *); fp@1831: fp@1831: /*****************************************************************************/ fp@1831: fp@1831: /** SoE request constructor. fp@1831: */ fp@1831: void ec_soe_request_init( fp@1831: ec_soe_request_t *req /**< SoE request. */ fp@1831: ) fp@1831: { fp@1952: req->drive_no = 0x00; fp@1952: req->idn = 0x0000; fp@1944: req->al_state = EC_AL_STATE_INIT; fp@1831: req->data = NULL; fp@1831: req->mem_size = 0; fp@1831: req->data_size = 0; fp@1831: req->dir = EC_DIR_INVALID; fp@1831: req->state = EC_INT_REQUEST_INIT; fp@1831: req->jiffies_sent = 0U; fp@1831: req->error_code = 0x0000; fp@1831: } fp@1831: fp@1831: /*****************************************************************************/ fp@1831: fp@1831: /** SoE request destructor. fp@1831: */ fp@1831: void ec_soe_request_clear( fp@1831: ec_soe_request_t *req /**< SoE request. */ fp@1831: ) fp@1831: { fp@1831: ec_soe_request_clear_data(req); fp@1831: } fp@1831: fp@1831: /*****************************************************************************/ fp@1831: fp@1843: /** Copy another SoE request. fp@1843: */ fp@1843: int ec_soe_request_copy( fp@1843: ec_soe_request_t *req, /**< SoE request. */ fp@1843: const ec_soe_request_t *other /**< Other SoE request to copy from. */ fp@1843: ) fp@1843: { fp@1952: req->drive_no = other->drive_no; fp@1843: req->idn = other->idn; fp@1944: req->al_state = other->al_state; fp@1843: return ec_soe_request_copy_data(req, other->data, other->data_size); fp@1843: } fp@1843: fp@1843: /*****************************************************************************/ fp@1843: fp@1952: /** Set drive number. fp@1952: */ fp@1952: void ec_soe_request_set_drive_no( fp@1952: ec_soe_request_t *req, /**< SoE request. */ fp@1952: uint8_t drive_no /** Drive Number. */ fp@1952: ) fp@1952: { fp@1952: req->drive_no = drive_no; fp@1952: } fp@1952: fp@1952: /*****************************************************************************/ fp@1952: fp@1831: /** Set IDN. fp@1831: */ fp@1831: void ec_soe_request_set_idn( fp@1831: ec_soe_request_t *req, /**< SoE request. */ fp@1831: uint16_t idn /** IDN. */ fp@1831: ) fp@1831: { fp@1831: req->idn = idn; fp@1831: } fp@1831: fp@1831: /*****************************************************************************/ fp@1831: fp@1831: /** Free allocated memory. fp@1831: */ fp@1831: void ec_soe_request_clear_data( fp@1831: ec_soe_request_t *req /**< SoE request. */ fp@1831: ) fp@1831: { fp@1831: if (req->data) { fp@1831: kfree(req->data); fp@1831: req->data = NULL; fp@1831: } fp@1831: fp@1831: req->mem_size = 0; fp@1831: req->data_size = 0; fp@1831: } fp@1831: fp@1831: /*****************************************************************************/ fp@1831: fp@1831: /** Pre-allocates the data memory. fp@1831: * fp@1831: * If the \a mem_size is already bigger than \a size, nothing is done. fp@1831: * fp@1831: * \return 0 on success, otherwise -ENOMEM. fp@1831: */ fp@1831: int ec_soe_request_alloc( fp@1831: ec_soe_request_t *req, /**< SoE request. */ fp@1831: size_t size /**< Data size to allocate. */ fp@1831: ) fp@1831: { fp@1831: if (size <= req->mem_size) fp@1831: return 0; fp@1831: fp@1831: ec_soe_request_clear_data(req); fp@1831: fp@1831: if (!(req->data = (uint8_t *) kmalloc(size, GFP_KERNEL))) { fp@1831: EC_ERR("Failed to allocate %zu bytes of SoE memory.\n", size); fp@1831: return -ENOMEM; fp@1831: } fp@1831: fp@1831: req->mem_size = size; fp@1831: req->data_size = 0; fp@1831: return 0; fp@1831: } fp@1831: fp@1831: /*****************************************************************************/ fp@1831: fp@1831: /** Copies SoE data from an external source. fp@1831: * fp@1831: * If the \a mem_size is to small, new memory is allocated. fp@1831: * fp@1831: * \retval 0 Success. fp@1831: * \retval <0 Error code. fp@1831: */ fp@1831: int ec_soe_request_copy_data( fp@1831: ec_soe_request_t *req, /**< SoE request. */ fp@1831: const uint8_t *source, /**< Source data. */ fp@1831: size_t size /**< Number of bytes in \a source. */ fp@1831: ) fp@1831: { fp@1831: int ret = ec_soe_request_alloc(req, size); fp@1831: if (ret < 0) fp@1831: return ret; fp@1831: fp@1831: memcpy(req->data, source, size); fp@1831: req->data_size = size; fp@1831: return 0; fp@1831: } fp@1831: fp@1831: /*****************************************************************************/ fp@1831: fp@1864: /** Copies SoE data from an external source. fp@1864: * fp@1864: * If the \a mem_size is to small, new memory is allocated. fp@1864: * fp@1864: * \retval 0 Success. fp@1864: * \retval <0 Error code. fp@1864: */ fp@1864: int ec_soe_request_append_data( fp@1864: ec_soe_request_t *req, /**< SoE request. */ fp@1864: const uint8_t *source, /**< Source data. */ fp@1864: size_t size /**< Number of bytes in \a source. */ fp@1864: ) fp@1864: { fp@1864: if (req->data_size + size > req->mem_size) { fp@1864: size_t new_size = req->mem_size ? req->mem_size * 2 : size; fp@1864: uint8_t *new_data = (uint8_t *) kmalloc(new_size, GFP_KERNEL); fp@1864: if (!new_data) { fp@1864: EC_ERR("Failed to allocate %zu bytes of SoE memory.\n", fp@1864: new_size); fp@1864: return -ENOMEM; fp@1864: } fp@1864: memcpy(new_data, req->data, req->data_size); fp@1864: kfree(req->data); fp@1864: req->data = new_data; fp@1864: req->mem_size = new_size; fp@1864: } fp@1864: fp@1864: memcpy(req->data + req->data_size, source, size); fp@1864: req->data_size += size; fp@1864: return 0; fp@1864: } fp@1864: fp@1864: /*****************************************************************************/ fp@1864: fp@1907: /** Request a read operation. fp@1907: */ fp@1907: void ec_soe_request_read( fp@1907: ec_soe_request_t *req /**< SoE request. */ fp@1907: ) fp@1831: { fp@1831: req->dir = EC_DIR_INPUT; fp@1831: req->state = EC_INT_REQUEST_QUEUED; fp@1831: req->error_code = 0x0000; fp@1831: } fp@1831: fp@1831: /*****************************************************************************/ fp@1831: fp@1907: /** Request a write operation. fp@1907: */ fp@1907: void ec_soe_request_write( fp@1907: ec_soe_request_t *req /**< SoE request. */ fp@1907: ) fp@1831: { fp@1831: req->dir = EC_DIR_OUTPUT; fp@1831: req->state = EC_INT_REQUEST_QUEUED; fp@1831: req->error_code = 0x0000; fp@1831: } fp@1831: fp@1831: /*****************************************************************************/