Added API for querying CoE emergency requests.
--- 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
--- 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)
{
--- 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 \
--- 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 \
--- /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 <linux/slab.h>
+
+#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;
+}
+
+/*****************************************************************************/
--- /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
--- 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));
--- 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;
--- 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;
--- 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);
--- 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. */
};
/*****************************************************************************/