fp@1335: /****************************************************************************** fp@1335: * fp@1335: * $Id$ fp@1335: * fp@1335: * Copyright (C) 2008 Olav Zarges, imc Meßsysteme GmbH fp@1335: * fp@1335: * This file is part of the IgH EtherCAT Master. fp@1335: * fp@1335: * The IgH EtherCAT Master is free software; you can redistribute it fp@1335: * and/or modify it under the terms of the GNU General Public License fp@1335: * as published by the Free Software Foundation; either version 2 of the fp@1335: * License, or (at your option) any later version. fp@1335: * fp@1335: * The IgH EtherCAT Master is distributed in the hope that it will be fp@1335: * useful, but WITHOUT ANY WARRANTY; without even the implied warranty of fp@1335: * MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the fp@1335: * GNU General Public License for more details. fp@1335: * fp@1335: * You should have received a copy of the GNU General Public License fp@1335: * along with the IgH EtherCAT Master; if not, write to the Free Software fp@1335: * Foundation, Inc., 51 Franklin St, Fifth Floor, Boston, MA 02110-1301 USA fp@1335: * fp@1335: * The right to use EtherCAT Technology is granted and comes free of fp@1335: * charge under condition of compatibility of product made by fp@1335: * Licensee. People intending to distribute/sell products based on the fp@1335: * code, have to sign an agreement to guarantee that products using fp@1335: * software based on IgH EtherCAT master stay compatible with the actual fp@1335: * EtherCAT specification (which are released themselves as an open fp@1335: * standard) as the (only) precondition to have the right to use EtherCAT fp@1335: * Technology, IP and trade marks. fp@1335: * fp@1335: *****************************************************************************/ fp@1335: fp@1335: /** \file fp@1335: * File-over-EtherCAT request functions. fp@1335: */ fp@1335: fp@1335: /*****************************************************************************/ fp@1335: fp@1335: #include fp@1335: #include fp@1335: fp@1335: #include "foe_request.h" fp@1336: #include "foe.h" fp@1335: fp@1335: /*****************************************************************************/ fp@1335: fp@1335: /** Default timeout in ms to wait for FoE transfer responses. fp@1335: */ fp@1335: #define EC_FOE_REQUEST_RESPONSE_TIMEOUT 3000 fp@1335: fp@1335: /*****************************************************************************/ fp@1335: fp@1335: void ec_foe_request_clear_data(ec_foe_request_t *); fp@1335: fp@1335: /*****************************************************************************/ fp@1335: fp@1335: /** FoE request constructor. fp@1335: */ fp@1335: void ec_foe_request_init( fp@1335: ec_foe_request_t *req, /**< FoE request. */ fp@1335: uint8_t* file_name /** filename */) fp@1335: { fp@1335: req->buffer = NULL; fp@1335: req->file_name = file_name; fp@1335: req->buffer_size = 0; fp@1335: req->data_size = 0; fp@1335: req->dir = EC_DIR_INVALID; fp@1335: req->issue_timeout = 0; // no timeout fp@1335: req->response_timeout = EC_FOE_REQUEST_RESPONSE_TIMEOUT; fp@1335: req->state = EC_INT_REQUEST_INIT; fp@1336: req->result = FOE_BUSY; fp@1336: req->error_code = 0x00000000; fp@1335: } fp@1335: fp@1335: /*****************************************************************************/ fp@1335: fp@1335: /** FoE request destructor. fp@1335: */ fp@1335: void ec_foe_request_clear( fp@1335: ec_foe_request_t *req /**< FoE request. */ fp@1335: ) fp@1335: { fp@1335: ec_foe_request_clear_data(req); fp@1335: } fp@1335: fp@1335: /*****************************************************************************/ fp@1335: fp@1335: /** FoE request destructor. fp@1335: */ fp@1335: void ec_foe_request_clear_data( fp@1335: ec_foe_request_t *req /**< FoE request. */ fp@1335: ) fp@1335: { fp@1335: if (req->buffer) { fp@1335: kfree(req->buffer); fp@1335: req->buffer = NULL; fp@1335: } fp@1335: fp@1335: req->buffer_size = 0; fp@1335: req->data_size = 0; fp@1335: } fp@1335: fp@1335: /*****************************************************************************/ fp@1335: fp@1335: /** Pre-allocates the data memory. fp@1335: * fp@1335: * If the \a buffer_size is already bigger than \a size, nothing is done. fp@1335: */ fp@1335: int ec_foe_request_alloc( fp@1335: ec_foe_request_t *req, /**< FoE request. */ fp@1335: size_t size /**< Data size to allocate. */ fp@1335: ) fp@1335: { fp@1335: if (size <= req->buffer_size) fp@1335: return 0; fp@1335: fp@1335: ec_foe_request_clear_data(req); fp@1335: fp@1335: if (!(req->buffer = (uint8_t *) kmalloc(size, GFP_KERNEL))) { fp@1335: EC_ERR("Failed to allocate %u bytes of FoE memory.\n", size); fp@1335: return -1; fp@1335: } fp@1335: fp@1335: req->buffer_size = size; fp@1335: req->data_size = 0; fp@1335: return 0; fp@1335: } fp@1335: fp@1335: /*****************************************************************************/ fp@1335: fp@1335: /** Copies FoE data from an external source. fp@1335: * fp@1335: * If the \a buffer_size is to small, new memory is allocated. fp@1335: */ fp@1335: int ec_foe_request_copy_data( fp@1335: ec_foe_request_t *req, /**< FoE request. */ fp@1335: const uint8_t *source, /**< Source data. */ fp@1335: size_t size /**< Number of bytes in \a source. */ fp@1335: ) fp@1335: { fp@1335: if (ec_foe_request_alloc(req, size)) fp@1335: return -1; fp@1335: fp@1335: memcpy(req->buffer, source, size); fp@1335: req->data_size = size; fp@1335: return 0; fp@1335: } fp@1335: fp@1335: /*****************************************************************************/ fp@1335: fp@1335: /** Checks, if the timeout was exceeded. fp@1335: * fp@1335: * \return non-zero if the timeout was exceeded, else zero. fp@1335: */ fp@1335: int ec_foe_request_timed_out(const ec_foe_request_t *req /**< FoE request. */) fp@1335: { fp@1335: return req->issue_timeout fp@1335: && jiffies - req->jiffies_start > HZ * req->issue_timeout / 1000; fp@1335: } fp@1335: fp@1335: /*****************************************************************************/ fp@1335: fp@1335: void ec_foe_request_timeout(ec_foe_request_t *req, uint32_t timeout) fp@1335: { fp@1335: req->issue_timeout = timeout; fp@1335: } fp@1335: fp@1335: /*****************************************************************************/ fp@1335: fp@1335: uint8_t *ec_foe_request_data(ec_foe_request_t *req) fp@1335: { fp@1335: return req->buffer; fp@1335: } fp@1335: fp@1335: /*****************************************************************************/ fp@1335: fp@1335: size_t ec_foe_request_data_size(const ec_foe_request_t *req) fp@1335: { fp@1335: return req->data_size; fp@1335: } fp@1335: fp@1335: /*****************************************************************************/ fp@1335: fp@1335: void ec_foe_request_read(ec_foe_request_t *req) fp@1335: { fp@1335: req->dir = EC_DIR_INPUT; fp@1335: req->state = EC_INT_REQUEST_QUEUED; fp@1336: req->result = FOE_BUSY; fp@1335: req->jiffies_start = jiffies; fp@1335: } fp@1335: fp@1335: /*****************************************************************************/ fp@1335: fp@1335: void ec_foe_request_write(ec_foe_request_t *req) fp@1335: { fp@1335: req->dir = EC_DIR_OUTPUT; fp@1335: req->state = EC_INT_REQUEST_QUEUED; fp@1336: req->result = FOE_BUSY; fp@1335: req->jiffies_start = jiffies; fp@1335: } fp@1335: fp@1335: /*****************************************************************************/