# HG changeset patch # User Florian Pose # Date 1352208224 -3600 # Node ID 9c3e629a220cd823e3364d8bc6ae10fcd35ac41a # Parent 7b8078c1ad36771a476b778b4170849f23b942af Added API for querying CoE emergency requests. diff -r 7b8078c1ad36 -r 9c3e629a220c include/ecrt.h --- a/include/ecrt.h Tue Nov 06 11:49:55 2012 +0100 +++ b/include/ecrt.h Tue Nov 06 14:23:44 2012 +0100 @@ -48,6 +48,10 @@ * redundancy features. * - Added ecrt_sdo_request_index() to change SDO index and subindex after * handler creation. + * - Added interface for retrieving CoE emergency messages, i. e. + * ecrt_slave_config_emerg_size(), ecrt_slave_config_emerg_pop(), + * ecrt_slave_config_emerg_clear(), ecrt_slave_config_emerg_overruns() and + * the defines EC_HAVE_EMERGENCY and EC_COE_EMERGENCY_MSG_SIZE. * * Changes in version 1.5: * @@ -140,6 +144,12 @@ */ #define EC_HAVE_REDUNDANCY +/** Defined, if the CoE emergency ring feature is available. + * + * I. e. if the ecrt_slave_config_emerg_*() methods are available. + */ +#define EC_HAVE_EMERGENCY + /*****************************************************************************/ /** End of list marker. @@ -172,6 +182,12 @@ #define EC_TIMEVAL2NANO(TV) \ (((TV).tv_sec - 946684800ULL) * 1000000000ULL + (TV).tv_usec * 1000ULL) +/** Size of a CoE emergency message in byte. + * + * \see ecrt_slave_config_emerg_pop(). + */ +#define EC_COE_EMERGENCY_MSG_SIZE 8 + /****************************************************************************** * Data types *****************************************************************************/ @@ -1283,6 +1299,55 @@ size_t size /**< Size of the \a data. */ ); +/** Set the size of the CoE emergency ring buffer. + * + * The initial size is zero, so all messages will be dropped. This method can + * be called even after master activation, but it will clear the ring buffer! + * + * \return 0 on success, or negative error code. + */ +int ecrt_slave_config_emerg_size( + ec_slave_config_t *sc, /**< Slave configuration. */ + size_t elements /**< Number of records of the CoE emergency ring. */ + ); + +/** Read and remove one record from the CoE emergency ring buffer. + * + * A record consists of 8 bytes: + * + * Byte 0-1: Error code (little endian) + * Byte 2: Error register + * Byte 3-7: Data + * + * \return 0 on success (record popped), or negative error code (i. e. + * -ENOENT, if ring is empty). + */ +int ecrt_slave_config_emerg_pop( + ec_slave_config_t *sc, /**< Slave configuration. */ + uint8_t *target /**< Pointer to target memory (at least + EC_COE_EMERGENCY_MSG_SIZE bytes). */ + ); + +/** Clears CoE emergency ring buffer and the overrun counter. + * + * \return 0 on success, or negative error code. + */ +int ecrt_slave_config_emerg_clear( + ec_slave_config_t *sc /**< Slave configuration. */ + ); + +/** Read the number of CoE emergency overruns. + * + * The overrun counter will be incremented when a CoE emergency message could + * not be stored in the ring buffer and had to be dropped. Call + * ecrt_slave_config_emerg_clear() to reset the counter. + * + * \return Number of overruns since last clear, or negative error code. + */ +int ecrt_slave_config_emerg_overruns( + ec_slave_config_t *sc /**< Slave configuration. */ + ); + /** Create an SDO request to exchange SDOs during realtime operation. * * The created SDO request object is freed automatically when the master is diff -r 7b8078c1ad36 -r 9c3e629a220c lib/slave_config.c --- a/lib/slave_config.c Tue Nov 06 11:49:55 2012 +0100 +++ b/lib/slave_config.c Tue Nov 06 14:23:44 2012 +0100 @@ -403,6 +403,84 @@ /*****************************************************************************/ +int ecrt_slave_config_emerg_size(ec_slave_config_t *sc, size_t elements) +{ + ec_ioctl_sc_emerg_t io; + int ret; + + io.config_index = sc->index; + io.size = elements; + + ret = ioctl(sc->master->fd, EC_IOCTL_SC_EMERG_SIZE, &io); + if (EC_IOCTL_IS_ERROR(ret)) { + fprintf(stderr, "Failed to set emergency ring size: %s\n", + strerror(EC_IOCTL_ERRNO(ret))); + return -EC_IOCTL_ERRNO(ret); + } + + return 0; +} + +/*****************************************************************************/ + +int ecrt_slave_config_emerg_pop(ec_slave_config_t *sc, uint8_t *target) +{ + ec_ioctl_sc_emerg_t io; + int ret; + + io.config_index = sc->index; + io.target = target; + + ret = ioctl(sc->master->fd, EC_IOCTL_SC_EMERG_POP, &io); + if (EC_IOCTL_IS_ERROR(ret)) { + fprintf(stderr, "Failed to get emergency message: %s\n", + strerror(EC_IOCTL_ERRNO(ret))); + return -EC_IOCTL_ERRNO(ret); + } + + return 0; +} + +/*****************************************************************************/ + +int ecrt_slave_config_emerg_clear(ec_slave_config_t *sc) +{ + ec_ioctl_sc_emerg_t io; + int ret; + + io.config_index = sc->index; + + ret = ioctl(sc->master->fd, EC_IOCTL_SC_EMERG_CLEAR, &io); + if (EC_IOCTL_IS_ERROR(ret)) { + fprintf(stderr, "Failed to clear emergency ring: %s\n", + strerror(EC_IOCTL_ERRNO(ret))); + return -EC_IOCTL_ERRNO(ret); + } + + return 0; +} + +/*****************************************************************************/ + +int ecrt_slave_config_emerg_overruns(ec_slave_config_t *sc) +{ + ec_ioctl_sc_emerg_t io; + int ret; + + io.config_index = sc->index; + + ret = ioctl(sc->master->fd, EC_IOCTL_SC_EMERG_OVERRUNS, &io); + if (EC_IOCTL_IS_ERROR(ret)) { + fprintf(stderr, "Failed to get emergency overruns: %s\n", + strerror(EC_IOCTL_ERRNO(ret))); + return -EC_IOCTL_ERRNO(ret); + } + + return io.overruns; +} + +/*****************************************************************************/ + void ec_slave_config_add_sdo_request(ec_slave_config_t *sc, ec_sdo_request_t *req) { diff -r 7b8078c1ad36 -r 9c3e629a220c master/Kbuild.in --- a/master/Kbuild.in Tue Nov 06 11:49:55 2012 +0100 +++ b/master/Kbuild.in Tue Nov 06 14:23:44 2012 +0100 @@ -35,6 +35,7 @@ ec_master-objs := \ cdev.o \ + coe_emerg_ring.o \ datagram.o \ datagram_pair.o \ device.o \ diff -r 7b8078c1ad36 -r 9c3e629a220c master/Makefile.am --- a/master/Makefile.am Tue Nov 06 11:49:55 2012 +0100 +++ b/master/Makefile.am Tue Nov 06 14:23:44 2012 +0100 @@ -30,6 +30,7 @@ # using HEADERS to enable tags target noinst_HEADERS = \ cdev.c cdev.h \ + coe_emerg_ring.c coe_emerg_ring.h \ datagram.c datagram.h \ datagram_pair.c datagram_pair.h \ debug.c debug.h \ diff -r 7b8078c1ad36 -r 9c3e629a220c master/coe_emerg_ring.c --- /dev/null Thu Jan 01 00:00:00 1970 +0000 +++ b/master/coe_emerg_ring.c Tue Nov 06 14:23:44 2012 +0100 @@ -0,0 +1,170 @@ +/****************************************************************************** + * + * $Id$ + * + * Copyright (C) 2012 Florian Pose, Ingenieurgemeinschaft IgH + * + * This file is part of the IgH EtherCAT Master. + * + * The IgH EtherCAT Master is free software; you can redistribute it and/or + * modify it under the terms of the GNU General Public License version 2, as + * published by the Free Software Foundation. + * + * The IgH EtherCAT Master is distributed in the hope that it will be useful, + * but WITHOUT ANY WARRANTY; without even the implied warranty of + * MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the GNU General + * Public License for more details. + * + * You should have received a copy of the GNU General Public License along + * with the IgH EtherCAT Master; if not, write to the Free Software + * Foundation, Inc., 51 Franklin St, Fifth Floor, Boston, MA 02110-1301 USA + * + * --- + * + * The license mentioned above concerns the source code only. Using the + * EtherCAT technology and brand is only permitted in compliance with the + * industrial property and similar rights of Beckhoff Automation GmbH. + * + * vim: expandtab + * + *****************************************************************************/ + +/** + \file + EtherCAT CoE emergency ring buffer methods. +*/ + +/*****************************************************************************/ + +#include + +#include "coe_emerg_ring.h" + +/*****************************************************************************/ + +/** Emergency ring buffer constructor. + */ +void ec_coe_emerg_ring_init( + ec_coe_emerg_ring_t *ring, /**< Emergency ring. */ + ec_slave_config_t *sc /**< Slave configuration. */ + ) +{ + ring->sc = sc; + ring->msgs = NULL; + ring->size = 0; + ring->read_index = 0; + ring->write_index = 0; + ring->overruns = 0; +} + +/*****************************************************************************/ + +/** Emergency ring buffer destructor. + */ +void ec_coe_emerg_ring_clear( + ec_coe_emerg_ring_t *ring /**< Emergency ring. */ + ) +{ + if (ring->msgs) { + kfree(ring->msgs); + } +} + +/*****************************************************************************/ + +/** Set the ring size. + */ +int ec_coe_emerg_ring_size( + ec_coe_emerg_ring_t *ring, /**< Emergency ring. */ + size_t size /**< Maximum number of messages in the ring. */ + ) +{ + ring->size = 0; + + if (size < 0) { + size = 0; + } + + ring->read_index = ring->write_index = 0; + + if (ring->msgs) { + kfree(ring->msgs); + } + ring->msgs = NULL; + + if (size == 0) { + return 0; + } + + ring->msgs = kmalloc(sizeof(ec_coe_emerg_msg_t) * (size + 1), GFP_KERNEL); + if (!ring->msgs) { + return -ENOMEM; + } + + ring->size = size; + return 0; +} + +/*****************************************************************************/ + +/** Add a new emergency message. + */ +void ec_coe_emerg_ring_push( + ec_coe_emerg_ring_t *ring, /**< Emergency ring. */ + const u8 *msg /**< Emergency message. */ + ) +{ + if (!ring->size || + (ring->write_index + 1) % (ring->size + 1) == ring->read_index) { + ring->overruns++; + return; + } + + memcpy(ring->msgs[ring->write_index].data, msg, + EC_COE_EMERGENCY_MSG_SIZE); + ring->write_index = (ring->write_index + 1) % (ring->size + 1); +} + +/*****************************************************************************/ + +/** Remove an emergency message from the ring. + */ +int ec_coe_emerg_ring_pop( + ec_coe_emerg_ring_t *ring, /**< Emergency ring. */ + u8 *msg /**< Memory to store the emergency message. */ + ) +{ + if (ring->read_index == ring->write_index) { + return -ENOENT; + } + + memcpy(msg, ring->msgs[ring->read_index].data, EC_COE_EMERGENCY_MSG_SIZE); + ring->read_index = (ring->read_index + 1) % (ring->size + 1); + return 0; +} + +/*****************************************************************************/ + +/** Clear the ring. + */ +int ec_coe_emerg_ring_clear_ring( + ec_coe_emerg_ring_t *ring /**< Emergency ring. */ + ) +{ + ring->read_index = ring->write_index; + ring->overruns = 0; + return 0; +} + +/*****************************************************************************/ + +/** Read the number of overruns. + */ +int ec_coe_emerg_ring_overruns( + ec_coe_emerg_ring_t *ring /**< Emergency ring. */ + ) +{ + return ring->overruns; +} + +/*****************************************************************************/ diff -r 7b8078c1ad36 -r 9c3e629a220c master/coe_emerg_ring.h --- /dev/null Thu Jan 01 00:00:00 1970 +0000 +++ b/master/coe_emerg_ring.h Tue Nov 06 14:23:44 2012 +0100 @@ -0,0 +1,78 @@ +/****************************************************************************** + * + * $Id$ + * + * Copyright (C) 2012 Florian Pose, Ingenieurgemeinschaft IgH + * + * This file is part of the IgH EtherCAT Master. + * + * The IgH EtherCAT Master is free software; you can redistribute it and/or + * modify it under the terms of the GNU General Public License version 2, as + * published by the Free Software Foundation. + * + * The IgH EtherCAT Master is distributed in the hope that it will be useful, + * but WITHOUT ANY WARRANTY; without even the implied warranty of + * MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the GNU General + * Public License for more details. + * + * You should have received a copy of the GNU General Public License along + * with the IgH EtherCAT Master; if not, write to the Free Software + * Foundation, Inc., 51 Franklin St, Fifth Floor, Boston, MA 02110-1301 USA + * + * --- + * + * The license mentioned above concerns the source code only. Using the + * EtherCAT technology and brand is only permitted in compliance with the + * industrial property and similar rights of Beckhoff Automation GmbH. + * + *****************************************************************************/ + +/** + \file + EtherCAT CoE emergency ring buffer structure. +*/ + +/*****************************************************************************/ + +#ifndef __EC_COE_EMERG_RING_H__ +#define __EC_COE_EMERG_RING_H__ + +#include "globals.h" + +/*****************************************************************************/ + +/** EtherCAT CoE emergency message record. + */ +typedef struct { + u8 data[EC_COE_EMERGENCY_MSG_SIZE]; +} ec_coe_emerg_msg_t; + +/*****************************************************************************/ + +/** EtherCAT CoE emergency ring buffer. + */ +typedef struct { + ec_slave_config_t *sc; /**< Slave configuration owning the ring. */ + + ec_coe_emerg_msg_t *msgs; + size_t size; + + unsigned int read_index; + unsigned int write_index; + unsigned int overruns; +} ec_coe_emerg_ring_t; + +/*****************************************************************************/ + +void ec_coe_emerg_ring_init(ec_coe_emerg_ring_t *, ec_slave_config_t *); +void ec_coe_emerg_ring_clear(ec_coe_emerg_ring_t *); + +int ec_coe_emerg_ring_size(ec_coe_emerg_ring_t *, size_t); +void ec_coe_emerg_ring_push(ec_coe_emerg_ring_t *, const u8 *); +int ec_coe_emerg_ring_pop(ec_coe_emerg_ring_t *, u8 *); +int ec_coe_emerg_ring_clear_ring(ec_coe_emerg_ring_t *); +int ec_coe_emerg_ring_overruns(ec_coe_emerg_ring_t *); + +/*****************************************************************************/ + +#endif diff -r 7b8078c1ad36 -r 9c3e629a220c master/fsm_coe.c --- a/master/fsm_coe.c Tue Nov 06 11:49:55 2012 +0100 +++ b/master/fsm_coe.c Tue Nov 06 14:23:44 2012 +0100 @@ -38,6 +38,7 @@ #include "master.h" #include "mailbox.h" #include "fsm_coe.h" +#include "slave_config.h" /*****************************************************************************/ @@ -269,6 +270,13 @@ return 1; } + { + ec_slave_config_t *sc = fsm->slave->config; + if (sc) { + ec_coe_emerg_ring_push(&sc->emerg_ring, data + 2); + } + } + EC_SLAVE_WARN(fsm->slave, "CoE Emergency Request received:\n" "Error code 0x%04X, Error register 0x%02X, data:\n", EC_READ_U16(data + 2), EC_READ_U8(data + 4)); diff -r 7b8078c1ad36 -r 9c3e629a220c master/ioctl.c --- a/master/ioctl.c Tue Nov 06 11:49:55 2012 +0100 +++ b/master/ioctl.c Tue Nov 06 14:23:44 2012 +0100 @@ -2276,6 +2276,169 @@ /*****************************************************************************/ +/** Set the emergency ring buffer size. + */ +static int ec_ioctl_sc_emerg_size( + ec_master_t *master, /**< EtherCAT master. */ + void *arg, /**< ioctl() argument. */ + ec_ioctl_context_t *ctx /**< Private data structure of file handle. */ + ) +{ + ec_ioctl_sc_emerg_t io; + ec_slave_config_t *sc; + int ret; + + if (unlikely(!ctx->requested)) + return -EPERM; + + if (copy_from_user(&io, (void __user *) arg, sizeof(io))) + return -EFAULT; + + if (down_interruptible(&master->master_sem)) { + return -EINTR; + } + + if (!(sc = ec_master_get_config(master, io.config_index))) { + up(&master->master_sem); + return -ENOENT; + } + + ret = ecrt_slave_config_emerg_size(sc, io.size); + + up(&master->master_sem); + + return ret; +} + +/*****************************************************************************/ + +/** Get an emergency message from the ring. + */ +static int ec_ioctl_sc_emerg_pop( + ec_master_t *master, /**< EtherCAT master. */ + void *arg, /**< ioctl() argument. */ + ec_ioctl_context_t *ctx /**< Private data structure of file handle. */ + ) +{ + ec_ioctl_sc_emerg_t io; + ec_slave_config_t *sc; + u8 msg[EC_COE_EMERGENCY_MSG_SIZE]; + int ret; + + if (unlikely(!ctx->requested)) + return -EPERM; + + if (copy_from_user(&io, (void __user *) arg, sizeof(io))) + return -EFAULT; + + if (down_interruptible(&master->master_sem)) { + return -EINTR; + } + + if (!(sc = ec_master_get_config(master, io.config_index))) { + up(&master->master_sem); + return -ENOENT; + } + + ret = ecrt_slave_config_emerg_pop(sc, msg); + + up(&master->master_sem); + + if (ret < 0) { + return ret; + } + + if (copy_to_user((void __user *) io.target, msg, sizeof(msg))) { + return -EFAULT; + } + + return ret; +} + +/*****************************************************************************/ + +/** Clear the emergency ring. + */ +static int ec_ioctl_sc_emerg_clear( + ec_master_t *master, /**< EtherCAT master. */ + void *arg, /**< ioctl() argument. */ + ec_ioctl_context_t *ctx /**< Private data structure of file handle. */ + ) +{ + ec_ioctl_sc_emerg_t io; + ec_slave_config_t *sc; + int ret; + + if (unlikely(!ctx->requested)) + return -EPERM; + + if (copy_from_user(&io, (void __user *) arg, sizeof(io))) + return -EFAULT; + + if (down_interruptible(&master->master_sem)) { + return -EINTR; + } + + if (!(sc = ec_master_get_config(master, io.config_index))) { + up(&master->master_sem); + return -ENOENT; + } + + ret = ecrt_slave_config_emerg_clear(sc); + + up(&master->master_sem); + + return ret; +} + +/*****************************************************************************/ + +/** Get the number of emergency overruns. + */ +static int ec_ioctl_sc_emerg_overruns( + ec_master_t *master, /**< EtherCAT master. */ + void *arg, /**< ioctl() argument. */ + ec_ioctl_context_t *ctx /**< Private data structure of file handle. */ + ) +{ + ec_ioctl_sc_emerg_t io; + ec_slave_config_t *sc; + int ret; + + if (unlikely(!ctx->requested)) + return -EPERM; + + if (copy_from_user(&io, (void __user *) arg, sizeof(io))) + return -EFAULT; + + if (down_interruptible(&master->master_sem)) { + return -EINTR; + } + + if (!(sc = ec_master_get_config(master, io.config_index))) { + up(&master->master_sem); + return -ENOENT; + } + + ret = ecrt_slave_config_emerg_overruns(sc); + + up(&master->master_sem); + + if (ret < 0) { + return ret; + } + + io.overruns = ret; + + if (copy_to_user((void __user *) arg, &io, sizeof(io))) { + return -EFAULT; + } + + return 0; +} + +/*****************************************************************************/ + /** Create an SDO request. */ static int ec_ioctl_sc_create_sdo_request( @@ -3678,6 +3841,34 @@ } ret = ec_ioctl_sc_sdo(master, arg, ctx); break; + case EC_IOCTL_SC_EMERG_SIZE: + if (!ctx->writable) { + ret = -EPERM; + break; + } + ret = ec_ioctl_sc_emerg_size(master, arg, ctx); + break; + case EC_IOCTL_SC_EMERG_POP: + if (!ctx->writable) { + ret = -EPERM; + break; + } + ret = ec_ioctl_sc_emerg_pop(master, arg, ctx); + break; + case EC_IOCTL_SC_EMERG_CLEAR: + if (!ctx->writable) { + ret = -EPERM; + break; + } + ret = ec_ioctl_sc_emerg_clear(master, arg, ctx); + break; + case EC_IOCTL_SC_EMERG_OVERRUNS: + if (!ctx->writable) { + ret = -EPERM; + break; + } + ret = ec_ioctl_sc_emerg_overruns(master, arg, ctx); + break; case EC_IOCTL_SC_SDO_REQUEST: if (!ctx->writable) { ret = -EPERM; diff -r 7b8078c1ad36 -r 9c3e629a220c master/ioctl.h --- a/master/ioctl.h Tue Nov 06 11:49:55 2012 +0100 +++ b/master/ioctl.h Tue Nov 06 14:23:44 2012 +0100 @@ -56,7 +56,7 @@ * * Increment this when changing the ioctl interface! */ -#define EC_IOCTL_VERSION_MAGIC 20 +#define EC_IOCTL_VERSION_MAGIC 21 // Command-line tool #define EC_IOCTL_MODULE EC_IOR(0x00, ec_ioctl_module_t) @@ -117,28 +117,32 @@ #define EC_IOCTL_SC_REG_PDO_ENTRY EC_IOWR(0x33, ec_ioctl_reg_pdo_entry_t) #define EC_IOCTL_SC_DC EC_IOW(0x34, ec_ioctl_config_t) #define EC_IOCTL_SC_SDO EC_IOW(0x35, ec_ioctl_sc_sdo_t) -#define EC_IOCTL_SC_SDO_REQUEST EC_IOWR(0x36, ec_ioctl_sdo_request_t) -#define EC_IOCTL_SC_VOE EC_IOWR(0x37, ec_ioctl_voe_t) -#define EC_IOCTL_SC_STATE EC_IOWR(0x38, ec_ioctl_sc_state_t) -#define EC_IOCTL_SC_IDN EC_IOW(0x39, ec_ioctl_sc_idn_t) -#define EC_IOCTL_DOMAIN_OFFSET EC_IO(0x3a) -#define EC_IOCTL_DOMAIN_PROCESS EC_IO(0x3b) -#define EC_IOCTL_DOMAIN_QUEUE EC_IO(0x3c) -#define EC_IOCTL_DOMAIN_STATE EC_IOWR(0x3d, ec_ioctl_domain_state_t) -#define EC_IOCTL_SDO_REQUEST_INDEX EC_IOWR(0x3e, ec_ioctl_sdo_request_t) -#define EC_IOCTL_SDO_REQUEST_TIMEOUT EC_IOWR(0x3f, ec_ioctl_sdo_request_t) -#define EC_IOCTL_SDO_REQUEST_STATE EC_IOWR(0x40, ec_ioctl_sdo_request_t) -#define EC_IOCTL_SDO_REQUEST_READ EC_IOWR(0x41, ec_ioctl_sdo_request_t) -#define EC_IOCTL_SDO_REQUEST_WRITE EC_IOWR(0x42, ec_ioctl_sdo_request_t) -#define EC_IOCTL_SDO_REQUEST_DATA EC_IOWR(0x43, ec_ioctl_sdo_request_t) -#define EC_IOCTL_VOE_SEND_HEADER EC_IOW(0x44, ec_ioctl_voe_t) -#define EC_IOCTL_VOE_REC_HEADER EC_IOWR(0x45, ec_ioctl_voe_t) -#define EC_IOCTL_VOE_READ EC_IOW(0x46, ec_ioctl_voe_t) -#define EC_IOCTL_VOE_READ_NOSYNC EC_IOW(0x47, ec_ioctl_voe_t) -#define EC_IOCTL_VOE_WRITE EC_IOWR(0x48, ec_ioctl_voe_t) -#define EC_IOCTL_VOE_EXEC EC_IOWR(0x49, ec_ioctl_voe_t) -#define EC_IOCTL_VOE_DATA EC_IOWR(0x4a, ec_ioctl_voe_t) -#define EC_IOCTL_SET_SEND_INTERVAL EC_IOW(0x4b, size_t) +#define EC_IOCTL_SC_EMERG_SIZE EC_IOW(0x36, ec_ioctl_sc_emerg_t) +#define EC_IOCTL_SC_EMERG_POP EC_IOWR(0x37, ec_ioctl_sc_emerg_t) +#define EC_IOCTL_SC_EMERG_CLEAR EC_IOW(0x38, ec_ioctl_sc_emerg_t) +#define EC_IOCTL_SC_EMERG_OVERRUNS EC_IOWR(0x39, ec_ioctl_sc_emerg_t) +#define EC_IOCTL_SC_SDO_REQUEST EC_IOWR(0x3a, ec_ioctl_sdo_request_t) +#define EC_IOCTL_SC_VOE EC_IOWR(0x3b, ec_ioctl_voe_t) +#define EC_IOCTL_SC_STATE EC_IOWR(0x3c, ec_ioctl_sc_state_t) +#define EC_IOCTL_SC_IDN EC_IOW(0x3d, ec_ioctl_sc_idn_t) +#define EC_IOCTL_DOMAIN_OFFSET EC_IO(0x3e) +#define EC_IOCTL_DOMAIN_PROCESS EC_IO(0x3f) +#define EC_IOCTL_DOMAIN_QUEUE EC_IO(0x40) +#define EC_IOCTL_DOMAIN_STATE EC_IOWR(0x41, ec_ioctl_domain_state_t) +#define EC_IOCTL_SDO_REQUEST_INDEX EC_IOWR(0x42, ec_ioctl_sdo_request_t) +#define EC_IOCTL_SDO_REQUEST_TIMEOUT EC_IOWR(0x43, ec_ioctl_sdo_request_t) +#define EC_IOCTL_SDO_REQUEST_STATE EC_IOWR(0x44, ec_ioctl_sdo_request_t) +#define EC_IOCTL_SDO_REQUEST_READ EC_IOWR(0x45, ec_ioctl_sdo_request_t) +#define EC_IOCTL_SDO_REQUEST_WRITE EC_IOWR(0x46, ec_ioctl_sdo_request_t) +#define EC_IOCTL_SDO_REQUEST_DATA EC_IOWR(0x47, ec_ioctl_sdo_request_t) +#define EC_IOCTL_VOE_SEND_HEADER EC_IOW(0x48, ec_ioctl_voe_t) +#define EC_IOCTL_VOE_REC_HEADER EC_IOWR(0x49, ec_ioctl_voe_t) +#define EC_IOCTL_VOE_READ EC_IOW(0x4a, ec_ioctl_voe_t) +#define EC_IOCTL_VOE_READ_NOSYNC EC_IOW(0x4b, ec_ioctl_voe_t) +#define EC_IOCTL_VOE_WRITE EC_IOWR(0x4c, ec_ioctl_voe_t) +#define EC_IOCTL_VOE_EXEC EC_IOWR(0x4d, ec_ioctl_voe_t) +#define EC_IOCTL_VOE_DATA EC_IOWR(0x4e, ec_ioctl_voe_t) +#define EC_IOCTL_SET_SEND_INTERVAL EC_IOW(0x4f, size_t) /*****************************************************************************/ @@ -622,6 +626,18 @@ typedef struct { // inputs uint32_t config_index; + size_t size; + uint8_t *target; + + // outputs + int32_t overruns; +} ec_ioctl_sc_emerg_t; + +/*****************************************************************************/ + +typedef struct { + // inputs + uint32_t config_index; // outputs ec_slave_config_state_t *state; diff -r 7b8078c1ad36 -r 9c3e629a220c master/slave_config.c --- a/master/slave_config.c Tue Nov 06 11:49:55 2012 +0100 +++ b/master/slave_config.c Tue Nov 06 14:23:44 2012 +0100 @@ -88,6 +88,8 @@ INIT_LIST_HEAD(&sc->sdo_requests); INIT_LIST_HEAD(&sc->voe_handlers); INIT_LIST_HEAD(&sc->soe_configs); + + ec_coe_emerg_ring_init(&sc->emerg_ring, sc); } /*****************************************************************************/ @@ -138,6 +140,8 @@ ec_soe_request_clear(soe); kfree(soe); } + + ec_coe_emerg_ring_clear(&sc->emerg_ring); } /*****************************************************************************/ @@ -881,6 +885,34 @@ /*****************************************************************************/ +int ecrt_slave_config_emerg_size(ec_slave_config_t *sc, size_t elements) +{ + return ec_coe_emerg_ring_size(&sc->emerg_ring, elements); +} + +/*****************************************************************************/ + +int ecrt_slave_config_emerg_pop(ec_slave_config_t *sc, uint8_t *target) +{ + return ec_coe_emerg_ring_pop(&sc->emerg_ring, target); +} + +/*****************************************************************************/ + +int ecrt_slave_config_emerg_clear(ec_slave_config_t *sc) +{ + return ec_coe_emerg_ring_clear_ring(&sc->emerg_ring); +} + +/*****************************************************************************/ + +int ecrt_slave_config_emerg_overruns(ec_slave_config_t *sc) +{ + return ec_coe_emerg_ring_overruns(&sc->emerg_ring); +} + +/*****************************************************************************/ + /** Same as ecrt_slave_config_create_sdo_request(), but with ERR_PTR() return * value. */ @@ -1063,6 +1095,10 @@ EXPORT_SYMBOL(ecrt_slave_config_sdo16); EXPORT_SYMBOL(ecrt_slave_config_sdo32); EXPORT_SYMBOL(ecrt_slave_config_complete_sdo); +EXPORT_SYMBOL(ecrt_slave_config_emerg_size); +EXPORT_SYMBOL(ecrt_slave_config_emerg_pop); +EXPORT_SYMBOL(ecrt_slave_config_emerg_clear); +EXPORT_SYMBOL(ecrt_slave_config_emerg_overruns); EXPORT_SYMBOL(ecrt_slave_config_create_sdo_request); EXPORT_SYMBOL(ecrt_slave_config_create_voe_handler); EXPORT_SYMBOL(ecrt_slave_config_state); diff -r 7b8078c1ad36 -r 9c3e629a220c master/slave_config.h --- a/master/slave_config.h Tue Nov 06 11:49:55 2012 +0100 +++ b/master/slave_config.h Tue Nov 06 14:23:44 2012 +0100 @@ -43,6 +43,7 @@ #include "slave.h" #include "sync_config.h" #include "fmmu_config.h" +#include "coe_emerg_ring.h" /*****************************************************************************/ @@ -141,6 +142,8 @@ struct list_head sdo_requests; /**< List of SDO requests. */ struct list_head voe_handlers; /**< List of VoE handlers. */ struct list_head soe_configs; /**< List of SoE configurations. */ + + ec_coe_emerg_ring_t emerg_ring; /**< CoE emergency ring buffer. */ }; /*****************************************************************************/