Added VoE handler.
--- a/examples/mini/mini.c Wed Aug 27 16:04:18 2008 +0000
+++ b/examples/mini/mini.c Mon Sep 01 14:17:18 2008 +0000
@@ -48,6 +48,7 @@
#define EL3152_ALT_PDOS 0
#define EXTERNAL_MEMORY 1
#define SDO_ACCESS 0
+#define VOE_ACCESS 0
#define PFX "ec_mini: "
@@ -184,6 +185,10 @@
static ec_sdo_request_t *sdo;
#endif
+#if VOE_ACCESS
+static ec_voe_handler_t *voe;
+#endif
+
/*****************************************************************************/
void check_domain1_state(void)
@@ -249,18 +254,18 @@
void read_sdo(void)
{
switch (ecrt_sdo_request_state(sdo)) {
- case EC_SDO_REQUEST_UNUSED: // request was not used yet
+ case EC_REQUEST_UNUSED: // request was not used yet
ecrt_sdo_request_read(sdo); // trigger first read
break;
- case EC_SDO_REQUEST_BUSY:
+ case EC_REQUEST_BUSY:
printk(KERN_INFO PFX "Still busy...\n");
break;
- case EC_SDO_REQUEST_SUCCESS:
+ case EC_REQUEST_SUCCESS:
printk(KERN_INFO PFX "Sdo value: 0x%04X\n",
EC_READ_U16(ecrt_sdo_request_data(sdo)));
ecrt_sdo_request_read(sdo); // trigger next read
break;
- case EC_SDO_REQUEST_ERROR:
+ case EC_REQUEST_ERROR:
printk(KERN_INFO PFX "Failed to read Sdo!\n");
ecrt_sdo_request_read(sdo); // retry reading
break;
@@ -270,6 +275,31 @@
/*****************************************************************************/
+#if VOE_ACCESS
+void read_voe(void)
+{
+ switch (ecrt_voe_handler_execute(voe)) {
+ case EC_REQUEST_UNUSED:
+ ecrt_voe_handler_read(voe); // trigger first read
+ break;
+ case EC_REQUEST_BUSY:
+ printk(KERN_INFO PFX "VoE read still busy...\n");
+ break;
+ case EC_REQUEST_SUCCESS:
+ printk(KERN_INFO PFX "VoE received.\n");
+ // get data via ecrt_voe_handler_data(voe)
+ ecrt_voe_handler_read(voe); // trigger next read
+ break;
+ case EC_REQUEST_ERROR:
+ printk(KERN_INFO PFX "Failed to read VoE data!\n");
+ ecrt_voe_handler_read(voe); // retry reading
+ break;
+ }
+}
+#endif
+
+/*****************************************************************************/
+
void cyclic_task(unsigned long data)
{
// receive process data
@@ -299,6 +329,10 @@
// read process data Sdo
read_sdo();
#endif
+
+#if VOE_ACCESS
+ read_voe();
+#endif
}
// write process data
@@ -401,6 +435,14 @@
ecrt_sdo_request_timeout(sdo, 500); // ms
#endif
+#if VOE_ACCESS
+ printk(KERN_INFO PFX "Creating VoE handlers...\n");
+ if (!(voe = ecrt_slave_config_create_voe_handler(sc_ana_in, 1000))) {
+ printk(KERN_ERR PFX "Failed to create VoE handler.\n");
+ goto out_release_master;
+ }
+#endif
+
printk(KERN_INFO PFX "Registering Pdo entries...\n");
if (ecrt_domain_reg_pdo_entry_list(domain1, domain1_regs)) {
printk(KERN_ERR PFX "Pdo entry registration failed!\n");
--- a/include/ecrt.h Wed Aug 27 16:04:18 2008 +0000
+++ b/include/ecrt.h Mon Sep 01 14:17:18 2008 +0000
@@ -113,7 +113,7 @@
/** EtherCAT realtime interface minor version number.
*/
-#define ECRT_VER_MINOR 4
+#define ECRT_VER_MINOR 5
/** EtherCAT realtime interface version word generator.
*/
@@ -151,6 +151,9 @@
struct ec_sdo_request;
typedef struct ec_sdo_request ec_sdo_request_t; /**< \see ec_sdo_request. */
+struct ec_voe_handler;
+typedef struct ec_voe_handler ec_voe_handler_t; /**< \see ec_voe_handler. */
+
/*****************************************************************************/
/** Master state.
@@ -305,16 +308,17 @@
/*****************************************************************************/
-/** Sdo request state.
- *
- * This is used as return type of ecrt_sdo_request_state().
+/** Request state.
+ *
+ * This is used as return type for ecrt_sdo_request_state() and
+ * ecrt_voe_handler_state().
*/
typedef enum {
- EC_SDO_REQUEST_UNUSED, /**< Not requested. */
- EC_SDO_REQUEST_BUSY, /**< Request is being processed. */
- EC_SDO_REQUEST_SUCCESS, /**< Request was processed successfully. */
- EC_SDO_REQUEST_ERROR, /**< Request processing failed. */
-} ec_sdo_request_state_t;
+ EC_REQUEST_UNUSED, /**< Not requested. */
+ EC_REQUEST_BUSY, /**< Request is being processed. */
+ EC_REQUEST_SUCCESS, /**< Request was processed successfully. */
+ EC_REQUEST_ERROR, /**< Request processing failed. */
+} ec_request_state_t;
/******************************************************************************
* Global functions
@@ -727,6 +731,17 @@
size_t size /**< Data size to reserve. */
);
+/** Create an VoE handler to exchange vendor-specific data during realtime
+ * operation.
+ *
+ * The created VoE handler object is freed automatically when the master is
+ * released.
+ */
+ec_voe_handler_t *ecrt_slave_config_create_voe_handler(
+ ec_slave_config_t *sc, /**< Slave configuration. */
+ size_t size /**< Data size to reserve. */
+ );
+
/** Outputs the state of the slave configuration.
*
* Stores the state information in the given \a state structure.
@@ -878,7 +893,7 @@
*
* \return Request state.
*/
-ec_sdo_request_state_t ecrt_sdo_request_state(
+ec_request_state_t ecrt_sdo_request_state(
const ec_sdo_request_t *req /**< Sdo request. */
);
@@ -904,6 +919,73 @@
ec_sdo_request_t *req /**< Sdo request. */
);
+/*****************************************************************************
+ * VoE handler methods.
+ ****************************************************************************/
+
+/** Access to the VoE handler's data.
+ *
+ * This function returns a pointer to the handler's internal memory.
+ *
+ * - After a read operation was successful, the memory contains the received
+ * data. The size of the received data can be determined via
+ * ecrt_voe_handler_data_size().
+ * - Before a write operation is triggered, the data have to be written to
+ * the internal memory. Be sure, that the data fit into the memory. The
+ * memory size is a parameter of ecrt_slave_config_create_voe_handler().
+ *
+ * \return Pointer to the internal memory.
+ */
+uint8_t *ecrt_voe_handler_data(
+ ec_voe_handler_t *voe /**< VoE handler. */
+ );
+
+/** Returns the current data size.
+ *
+ * When the VoE handler is created, the data size is set to the size of the
+ * reserved memory. At a write operation, the data size is set to the number
+ * of bytes to write. After a read operation the size is set to the size of
+ * the read data. The size is not modified in any other situation.
+ *
+ * \return Data size in bytes.
+ */
+size_t ecrt_voe_handler_data_size(
+ const ec_voe_handler_t *voe /**< VoE handler. */
+ );
+
+/** Start a VoE write operation.
+ *
+ * After this function has been called, the ecrt_voe_handler_execute() method
+ * must be called in every bus cycle as long as it returns EC_REQUEST_BUSY.
+ */
+void ecrt_voe_handler_write(
+ ec_voe_handler_t *voe, /**< VoE handler. */
+ size_t size /**< Number of bytes to write. */
+ );
+
+/** Start a VoE read operation.
+ *
+ * After this function has been called, the ecrt_voe_handler_execute() method
+ * must be called in every bus cycle as long as it returns EC_REQUEST_BUSY.
+ *
+ * On success, the size of the read data can be determined via
+ * ecrt_voe_handler_data_size().
+ */
+void ecrt_voe_handler_read(
+ ec_voe_handler_t *voe /**< VoE handler. */
+ );
+
+/** Execute the handler.
+ *
+ * This method executes the VoE handler. It has to be called in every bus cycle
+ * as long as it returns EC_REQUEST_BUSY.
+ *
+ * \return Handler state.
+ */
+ec_request_state_t ecrt_voe_handler_execute(
+ ec_voe_handler_t *voe /**< VoE handler. */
+ );
+
/******************************************************************************
* Bitwise read/write macros
*****************************************************************************/
--- a/master/Kbuild.in Wed Aug 27 16:04:18 2008 +0000
+++ b/master/Kbuild.in Mon Sep 01 14:17:18 2008 +0000
@@ -61,7 +61,8 @@
slave.o \
slave_config.o \
sync.o \
- sync_config.o
+ sync_config.o \
+ voe_handler.o
ifeq (@ENABLE_EOE@,1)
ec_master-objs += ethernet.o
--- a/master/Makefile.am Wed Aug 27 16:04:18 2008 +0000
+++ b/master/Makefile.am Mon Sep 01 14:17:18 2008 +0000
@@ -64,7 +64,8 @@
slave.c slave.h \
slave_config.c slave_config.h \
sync.c sync.h \
- sync_config.c sync_config.h
+ sync_config.c sync_config.h \
+ voe_handler.c voe_handler.h
BUILT_SOURCES = \
Kbuild
--- a/master/cdev.c Wed Aug 27 16:04:18 2008 +0000
+++ b/master/cdev.c Mon Sep 01 14:17:18 2008 +0000
@@ -726,10 +726,10 @@
// wait for processing through FSM
if (wait_event_interruptible(master->sdo_queue,
- request.req.state != EC_REQUEST_QUEUED)) {
+ request.req.state != EC_INT_REQUEST_QUEUED)) {
// interrupted by signal
down(&master->master_sem);
- if (request.req.state == EC_REQUEST_QUEUED) {
+ if (request.req.state == EC_INT_REQUEST_QUEUED) {
list_del(&request.req.list);
up(&master->master_sem);
ec_sdo_request_clear(&request.req);
@@ -740,11 +740,11 @@
}
// wait until master FSM has finished processing
- wait_event(master->sdo_queue, request.req.state != EC_REQUEST_BUSY);
+ wait_event(master->sdo_queue, request.req.state != EC_INT_REQUEST_BUSY);
data.abort_code = request.req.abort_code;
- if (request.req.state != EC_REQUEST_SUCCESS) {
+ if (request.req.state != EC_INT_REQUEST_SUCCESS) {
data.data_size = 0;
retval = -EIO;
} else {
@@ -828,10 +828,10 @@
// wait for processing through FSM
if (wait_event_interruptible(master->sdo_queue,
- request.req.state != EC_REQUEST_QUEUED)) {
+ request.req.state != EC_INT_REQUEST_QUEUED)) {
// interrupted by signal
down(&master->master_sem);
- if (request.req.state == EC_REQUEST_QUEUED) {
+ if (request.req.state == EC_INT_REQUEST_QUEUED) {
list_del(&request.req.list);
up(&master->master_sem);
ec_sdo_request_clear(&request.req);
@@ -842,11 +842,11 @@
}
// wait until master FSM has finished processing
- wait_event(master->sdo_queue, request.req.state != EC_REQUEST_BUSY);
+ wait_event(master->sdo_queue, request.req.state != EC_INT_REQUEST_BUSY);
data.abort_code = request.req.abort_code;
- retval = request.req.state == EC_REQUEST_SUCCESS ? 0 : -EIO;
+ retval = request.req.state == EC_INT_REQUEST_SUCCESS ? 0 : -EIO;
if (__copy_to_user((void __user *) arg, &data, sizeof(data))) {
retval = -EFAULT;
@@ -954,7 +954,7 @@
request.words = words;
request.offset = data.offset;
request.nwords = data.nwords;
- request.state = EC_REQUEST_QUEUED;
+ request.state = EC_INT_REQUEST_QUEUED;
// schedule SII write request.
list_add_tail(&request.list, &master->sii_requests);
@@ -963,10 +963,10 @@
// wait for processing through FSM
if (wait_event_interruptible(master->sii_queue,
- request.state != EC_REQUEST_QUEUED)) {
+ request.state != EC_INT_REQUEST_QUEUED)) {
// interrupted by signal
down(&master->master_sem);
- if (request.state == EC_REQUEST_QUEUED) {
+ if (request.state == EC_INT_REQUEST_QUEUED) {
// abort request
list_del(&request.list);
up(&master->master_sem);
@@ -977,11 +977,11 @@
}
// wait until master FSM has finished processing
- wait_event(master->sii_queue, request.state != EC_REQUEST_BUSY);
+ wait_event(master->sii_queue, request.state != EC_INT_REQUEST_BUSY);
kfree(words);
- return request.state == EC_REQUEST_SUCCESS ? 0 : -EIO;
+ return request.state == EC_INT_REQUEST_SUCCESS ? 0 : -EIO;
}
/*****************************************************************************/
@@ -1027,7 +1027,7 @@
request.data = contents;
request.offset = data.offset;
request.length = data.length;
- request.state = EC_REQUEST_QUEUED;
+ request.state = EC_INT_REQUEST_QUEUED;
// schedule request.
list_add_tail(&request.list, &master->phy_requests);
@@ -1036,10 +1036,10 @@
// wait for processing through FSM
if (wait_event_interruptible(master->phy_queue,
- request.state != EC_REQUEST_QUEUED)) {
+ request.state != EC_INT_REQUEST_QUEUED)) {
// interrupted by signal
down(&master->master_sem);
- if (request.state == EC_REQUEST_QUEUED) {
+ if (request.state == EC_INT_REQUEST_QUEUED) {
// abort request
list_del(&request.list);
up(&master->master_sem);
@@ -1050,15 +1050,15 @@
}
// wait until master FSM has finished processing
- wait_event(master->phy_queue, request.state != EC_REQUEST_BUSY);
-
- if (request.state == EC_REQUEST_SUCCESS) {
+ wait_event(master->phy_queue, request.state != EC_INT_REQUEST_BUSY);
+
+ if (request.state == EC_INT_REQUEST_SUCCESS) {
if (copy_to_user((void __user *) data.data, contents, data.length))
return -EFAULT;
}
kfree(contents);
- return request.state == EC_REQUEST_SUCCESS ? 0 : -EIO;
+ return request.state == EC_INT_REQUEST_SUCCESS ? 0 : -EIO;
}
/*****************************************************************************/
@@ -1110,7 +1110,7 @@
request.data = contents;
request.offset = data.offset;
request.length = data.length;
- request.state = EC_REQUEST_QUEUED;
+ request.state = EC_INT_REQUEST_QUEUED;
// schedule request.
list_add_tail(&request.list, &master->phy_requests);
@@ -1119,10 +1119,10 @@
// wait for processing through FSM
if (wait_event_interruptible(master->phy_queue,
- request.state != EC_REQUEST_QUEUED)) {
+ request.state != EC_INT_REQUEST_QUEUED)) {
// interrupted by signal
down(&master->master_sem);
- if (request.state == EC_REQUEST_QUEUED) {
+ if (request.state == EC_INT_REQUEST_QUEUED) {
// abort request
list_del(&request.list);
up(&master->master_sem);
@@ -1133,11 +1133,11 @@
}
// wait until master FSM has finished processing
- wait_event(master->phy_queue, request.state != EC_REQUEST_BUSY);
+ wait_event(master->phy_queue, request.state != EC_INT_REQUEST_BUSY);
kfree(contents);
- return request.state == EC_REQUEST_SUCCESS ? 0 : -EIO;
+ return request.state == EC_INT_REQUEST_SUCCESS ? 0 : -EIO;
}
/*****************************************************************************/
--- a/master/cdev.h Wed Aug 27 16:04:18 2008 +0000
+++ b/master/cdev.h Mon Sep 01 14:17:18 2008 +0000
@@ -45,7 +45,6 @@
#include <linux/cdev.h>
#include "globals.h"
-#include "../include/ecrt.h"
/*****************************************************************************/
--- a/master/device.h Wed Aug 27 16:04:18 2008 +0000
+++ b/master/device.h Mon Sep 01 14:17:18 2008 +0000
@@ -43,7 +43,6 @@
#include <linux/interrupt.h>
-#include "../include/ecrt.h"
#include "../devices/ecdev.h"
#include "globals.h"
--- a/master/ethernet.c Wed Aug 27 16:04:18 2008 +0000
+++ b/master/ethernet.c Mon Sep 01 14:17:18 2008 +0000
@@ -41,7 +41,6 @@
#include <linux/netdevice.h>
#include <linux/etherdevice.h>
-#include "../include/ecrt.h"
#include "globals.h"
#include "master.h"
#include "slave.h"
--- a/master/ethernet.h Wed Aug 27 16:04:18 2008 +0000
+++ b/master/ethernet.h Mon Sep 01 14:17:18 2008 +0000
@@ -41,7 +41,6 @@
#include <linux/list.h>
#include <linux/netdevice.h>
-#include "../include/ecrt.h"
#include "globals.h"
#include "slave.h"
#include "datagram.h"
--- a/master/fmmu_config.h Wed Aug 27 16:04:18 2008 +0000
+++ b/master/fmmu_config.h Mon Sep 01 14:17:18 2008 +0000
@@ -40,8 +40,6 @@
#ifndef __EC_FMMU_CONFIG_H__
#define __EC_FMMU_CONFIG_H__
-#include "../include/ecrt.h"
-
#include "globals.h"
#include "sync.h"
--- a/master/fsm_change.h Wed Aug 27 16:04:18 2008 +0000
+++ b/master/fsm_change.h Mon Sep 01 14:17:18 2008 +0000
@@ -42,7 +42,6 @@
#define __EC_FSM_CHANGE_H__
#include "globals.h"
-#include "../include/ecrt.h"
#include "datagram.h"
#include "slave.h"
--- a/master/fsm_coe.h Wed Aug 27 16:04:18 2008 +0000
+++ b/master/fsm_coe.h Mon Sep 01 14:17:18 2008 +0000
@@ -42,7 +42,6 @@
#define __EC_FSM_COE_H__
#include "globals.h"
-#include "../include/ecrt.h"
#include "datagram.h"
#include "slave.h"
#include "sdo.h"
--- a/master/fsm_master.c Wed Aug 27 16:04:18 2008 +0000
+++ b/master/fsm_master.c Mon Sep 01 14:17:18 2008 +0000
@@ -305,7 +305,7 @@
request = list_entry(master->sii_requests.next,
ec_sii_write_request_t, list);
list_del_init(&request->list); // dequeue
- request->state = EC_REQUEST_BUSY;
+ request->state = EC_INT_REQUEST_BUSY;
// found pending SII write operation. execute it!
if (master->debug_level)
@@ -345,7 +345,7 @@
request = list_entry(master->phy_requests.next,
ec_phy_request_t, list);
list_del_init(&request->list); // dequeue
- request->state = EC_REQUEST_BUSY;
+ request->state = EC_INT_REQUEST_BUSY;
// found pending request; process it!
if (master->debug_level)
@@ -360,7 +360,7 @@
if (request->length > fsm->datagram->mem_size) {
EC_ERR("Request length (%u) exceeds maximum datagram size (%u)!\n",
request->length, fsm->datagram->mem_size);
- request->state = EC_REQUEST_FAILURE;
+ request->state = EC_INT_REQUEST_FAILURE;
wake_up(&master->phy_queue);
continue;
}
@@ -398,10 +398,10 @@
if (!slave->config)
continue;
list_for_each_entry(req, &slave->config->sdo_requests, list) {
- if (req->state == EC_REQUEST_QUEUED) {
+ if (req->state == EC_INT_REQUEST_QUEUED) {
if (ec_sdo_request_timed_out(req)) {
- req->state = EC_REQUEST_FAILURE;
+ req->state = EC_INT_REQUEST_FAILURE;
if (master->debug_level)
EC_DBG("Sdo request for slave %u timed out...\n",
slave->ring_position);
@@ -409,11 +409,11 @@
}
if (slave->current_state == EC_SLAVE_STATE_INIT) {
- req->state = EC_REQUEST_FAILURE;
+ req->state = EC_INT_REQUEST_FAILURE;
continue;
}
- req->state = EC_REQUEST_BUSY;
+ req->state = EC_INT_REQUEST_BUSY;
if (master->debug_level)
EC_DBG("Processing Sdo request for slave %u...\n",
slave->ring_position);
@@ -438,13 +438,13 @@
request = list_entry(master->slave_sdo_requests.next,
ec_master_sdo_request_t, list);
list_del_init(&request->list); // dequeue
- request->req.state = EC_REQUEST_BUSY;
+ request->req.state = EC_INT_REQUEST_BUSY;
slave = request->slave;
if (slave->current_state == EC_SLAVE_STATE_INIT) {
EC_ERR("Discarding Sdo request, slave %u is in INIT.\n",
slave->ring_position);
- request->req.state = EC_REQUEST_FAILURE;
+ request->req.state = EC_INT_REQUEST_FAILURE;
wake_up(&master->sdo_queue);
continue;
}
@@ -812,7 +812,7 @@
if (!ec_fsm_sii_success(&fsm->fsm_sii)) {
EC_ERR("Failed to write SII data to slave %u.\n",
slave->ring_position);
- request->state = EC_REQUEST_FAILURE;
+ request->state = EC_INT_REQUEST_FAILURE;
wake_up(&master->sii_queue);
ec_fsm_master_restart(fsm);
return;
@@ -839,7 +839,7 @@
}
// TODO: Evaluate other SII contents!
- request->state = EC_REQUEST_SUCCESS;
+ request->state = EC_INT_REQUEST_SUCCESS;
wake_up(&master->sii_queue);
// check for another SII write request
@@ -898,14 +898,14 @@
if (!ec_fsm_coe_success(&fsm->fsm_coe)) {
EC_DBG("Failed to process Sdo request for slave %u.\n",
fsm->slave->ring_position);
- request->state = EC_REQUEST_FAILURE;
+ request->state = EC_INT_REQUEST_FAILURE;
wake_up(&master->sdo_queue);
ec_fsm_master_restart(fsm);
return;
}
// Sdo request finished
- request->state = EC_REQUEST_SUCCESS;
+ request->state = EC_INT_REQUEST_SUCCESS;
wake_up(&master->sdo_queue);
if (master->debug_level)
@@ -934,7 +934,7 @@
if (datagram->state != EC_DATAGRAM_RECEIVED) {
EC_ERR("Failed to receive phy request datagram (state %u).\n",
datagram->state);
- request->state = EC_REQUEST_FAILURE;
+ request->state = EC_INT_REQUEST_FAILURE;
wake_up(&master->phy_queue);
ec_fsm_master_restart(fsm);
return;
@@ -947,7 +947,7 @@
if (!request->data) {
EC_ERR("Failed to allocate %u bytes of memory for phy request.\n",
request->length);
- request->state = EC_REQUEST_FAILURE;
+ request->state = EC_INT_REQUEST_FAILURE;
wake_up(&master->phy_queue);
ec_fsm_master_restart(fsm);
return;
@@ -955,7 +955,7 @@
memcpy(request->data, datagram->data, request->length);
}
- request->state = EC_REQUEST_SUCCESS;
+ request->state = EC_INT_REQUEST_SUCCESS;
wake_up(&master->phy_queue);
// check for another PHY request
--- a/master/fsm_master.h Wed Aug 27 16:04:18 2008 +0000
+++ b/master/fsm_master.h Mon Sep 01 14:17:18 2008 +0000
@@ -41,8 +41,6 @@
#ifndef __EC_FSM_MASTER_H__
#define __EC_FSM_MASTER_H__
-#include "../include/ecrt.h"
-
#include "globals.h"
#include "datagram.h"
#include "sdo_request.h"
@@ -60,7 +58,7 @@
uint16_t offset; /**< SII word offset. */
size_t nwords; /**< Number of words. */
const uint16_t *words; /**< Pointer to the data words. */
- ec_request_state_t state; /**< State of the request. */
+ ec_internal_request_state_t state; /**< State of the request. */
} ec_sii_write_request_t;
/*****************************************************************************/
@@ -74,7 +72,7 @@
uint16_t offset; /**< Physical memory offset. */
size_t length; /**< Number of bytes. */
uint8_t *data;
- ec_request_state_t state; /**< State of the request. */
+ ec_internal_request_state_t state; /**< State of the request. */
} ec_phy_request_t;
/*****************************************************************************/
--- a/master/fsm_pdo.h Wed Aug 27 16:04:18 2008 +0000
+++ b/master/fsm_pdo.h Mon Sep 01 14:17:18 2008 +0000
@@ -41,8 +41,6 @@
#ifndef __EC_FSM_PDO_H__
#define __EC_FSM_PDO_H__
-#include "../include/ecrt.h"
-
#include "globals.h"
#include "datagram.h"
#include "fsm_coe.h"
--- a/master/fsm_pdo_entry.h Wed Aug 27 16:04:18 2008 +0000
+++ b/master/fsm_pdo_entry.h Mon Sep 01 14:17:18 2008 +0000
@@ -41,7 +41,6 @@
#define __EC_FSM_PDO_ENTRY_H__
#include "globals.h"
-#include "../include/ecrt.h"
#include "datagram.h"
#include "fsm_coe.h"
--- a/master/fsm_sii.h Wed Aug 27 16:04:18 2008 +0000
+++ b/master/fsm_sii.h Mon Sep 01 14:17:18 2008 +0000
@@ -42,7 +42,6 @@
#define __EC_FSM_SII_H__
#include "globals.h"
-#include "../include/ecrt.h"
#include "datagram.h"
#include "slave.h"
--- a/master/fsm_slave_config.h Wed Aug 27 16:04:18 2008 +0000
+++ b/master/fsm_slave_config.h Mon Sep 01 14:17:18 2008 +0000
@@ -41,8 +41,6 @@
#ifndef __EC_FSM_SLAVE_CONFIG_H__
#define __EC_FSM_SLAVE_CONFIG_H__
-#include "../include/ecrt.h"
-
#include "globals.h"
#include "slave.h"
#include "datagram.h"
--- a/master/fsm_slave_scan.h Wed Aug 27 16:04:18 2008 +0000
+++ b/master/fsm_slave_scan.h Mon Sep 01 14:17:18 2008 +0000
@@ -41,8 +41,6 @@
#ifndef __EC_FSM_SLAVE_SCAN_H__
#define __EC_FSM_SLAVE_SCAN_H__
-#include "../include/ecrt.h"
-
#include "globals.h"
#include "datagram.h"
#include "slave.h"
--- a/master/globals.h Wed Aug 27 16:04:18 2008 +0000
+++ b/master/globals.h Mon Sep 01 14:17:18 2008 +0000
@@ -43,6 +43,7 @@
#include <linux/types.h>
#include "../globals.h"
+#include "../include/ecrt.h"
/******************************************************************************
* EtherCAT master
@@ -253,12 +254,16 @@
* state_table in master/sdo_request.c.
*/
typedef enum {
- EC_REQUEST_INIT,
- EC_REQUEST_QUEUED,
- EC_REQUEST_BUSY,
- EC_REQUEST_SUCCESS,
- EC_REQUEST_FAILURE
-} ec_request_state_t;
+ EC_INT_REQUEST_INIT,
+ EC_INT_REQUEST_QUEUED,
+ EC_INT_REQUEST_BUSY,
+ EC_INT_REQUEST_SUCCESS,
+ EC_INT_REQUEST_FAILURE
+} ec_internal_request_state_t;
+
+/*****************************************************************************/
+
+extern const ec_request_state_t ec_request_state_translation_table[];
/*****************************************************************************/
--- a/master/master.c Wed Aug 27 16:04:18 2008 +0000
+++ b/master/master.c Mon Sep 01 14:17:18 2008 +0000
@@ -46,7 +46,6 @@
#include <linux/device.h>
#include <linux/version.h>
-#include "../include/ecrt.h"
#include "globals.h"
#include "slave.h"
#include "slave_config.h"
--- a/master/module.c Wed Aug 27 16:04:18 2008 +0000
+++ b/master/module.c Mon Sep 01 14:17:18 2008 +0000
@@ -545,6 +545,20 @@
/*****************************************************************************/
+/** Global request state type translation table.
+ *
+ * Translates an internal request state to an external one.
+ */
+const ec_request_state_t ec_request_state_translation_table[] = {
+ EC_REQUEST_UNUSED, // EC_INT_REQUEST_INIT,
+ EC_REQUEST_BUSY, // EC_INT_REQUEST_QUEUED,
+ EC_REQUEST_BUSY, // EC_INT_REQUEST_BUSY,
+ EC_REQUEST_SUCCESS, // EC_INT_REQUEST_SUCCESS,
+ EC_REQUEST_ERROR // EC_INT_REQUEST_FAILURE
+};
+
+/*****************************************************************************/
+
/** \cond */
module_init(ec_init_module);
--- a/master/pdo.h Wed Aug 27 16:04:18 2008 +0000
+++ b/master/pdo.h Mon Sep 01 14:17:18 2008 +0000
@@ -43,8 +43,6 @@
#include <linux/list.h>
-#include "../include/ecrt.h"
-
#include "globals.h"
#include "pdo_entry.h"
--- a/master/pdo_entry.h Wed Aug 27 16:04:18 2008 +0000
+++ b/master/pdo_entry.h Mon Sep 01 14:17:18 2008 +0000
@@ -43,8 +43,6 @@
#include <linux/list.h>
-#include "../include/ecrt.h"
-
#include "globals.h"
/*****************************************************************************/
--- a/master/pdo_list.h Wed Aug 27 16:04:18 2008 +0000
+++ b/master/pdo_list.h Mon Sep 01 14:17:18 2008 +0000
@@ -43,8 +43,6 @@
#include <linux/list.h>
-#include "../include/ecrt.h"
-
#include "globals.h"
#include "pdo.h"
--- a/master/sdo_request.c Wed Aug 27 16:04:18 2008 +0000
+++ b/master/sdo_request.c Mon Sep 01 14:17:18 2008 +0000
@@ -54,18 +54,6 @@
/*****************************************************************************/
-/** State type translation table.
- */
-static const ec_sdo_request_state_t state_translation_table[] = {
- EC_SDO_REQUEST_UNUSED, // EC_REQUEST_INIT,
- EC_SDO_REQUEST_BUSY, // EC_REQUEST_QUEUED,
- EC_SDO_REQUEST_BUSY, // EC_REQUEST_BUSY,
- EC_SDO_REQUEST_SUCCESS, // EC_REQUEST_SUCCESS,
- EC_SDO_REQUEST_ERROR // EC_REQUEST_FAILURE
-};
-
-/*****************************************************************************/
-
/** Sdo request constructor.
*/
void ec_sdo_request_init(
@@ -78,7 +66,7 @@
req->dir = EC_DIR_INVALID;
req->issue_timeout = 0; // no timeout
req->response_timeout = EC_SDO_REQUEST_RESPONSE_TIMEOUT;
- req->state = EC_REQUEST_INIT;
+ req->state = EC_INT_REQUEST_INIT;
req->abort_code = 0x00000000;
}
@@ -207,9 +195,9 @@
/*****************************************************************************/
-ec_sdo_request_state_t ecrt_sdo_request_state(const ec_sdo_request_t *req)
-{
- return state_translation_table[req->state];
+ec_request_state_t ecrt_sdo_request_state(const ec_sdo_request_t *req)
+{
+ return ec_request_state_translation_table[req->state];
}
/*****************************************************************************/
@@ -217,7 +205,7 @@
void ecrt_sdo_request_read(ec_sdo_request_t *req)
{
req->dir = EC_DIR_INPUT;
- req->state = EC_REQUEST_QUEUED;
+ req->state = EC_INT_REQUEST_QUEUED;
req->abort_code = 0x00000000;
req->jiffies_start = jiffies;
}
@@ -227,7 +215,7 @@
void ecrt_sdo_request_write(ec_sdo_request_t *req)
{
req->dir = EC_DIR_OUTPUT;
- req->state = EC_REQUEST_QUEUED;
+ req->state = EC_INT_REQUEST_QUEUED;
req->abort_code = 0x00000000;
req->jiffies_start = jiffies;
}
--- a/master/sdo_request.h Wed Aug 27 16:04:18 2008 +0000
+++ b/master/sdo_request.h Mon Sep 01 14:17:18 2008 +0000
@@ -43,8 +43,6 @@
#include <linux/list.h>
-#include "../include/ecrt.h"
-
#include "globals.h"
/*****************************************************************************/
@@ -65,7 +63,7 @@
ec_direction_t dir; /**< Direction. EC_DIR_OUTPUT means downloading to
the slave, EC_DIR_INPUT means uploading from the
slave. */
- ec_request_state_t state; /**< Sdo request state. */
+ ec_internal_request_state_t state; /**< Sdo request state. */
unsigned long jiffies_start; /**< Jiffies, when the request was issued. */
unsigned long jiffies_sent; /**< Jiffies, when the upload/download
request was sent. */
--- a/master/slave.h Wed Aug 27 16:04:18 2008 +0000
+++ b/master/slave.h Mon Sep 01 14:17:18 2008 +0000
@@ -44,8 +44,6 @@
#include <linux/list.h>
#include <linux/kobject.h>
-#include "../include/ecrt.h"
-
#include "globals.h"
#include "datagram.h"
#include "pdo.h"
--- a/master/slave_config.c Wed Aug 27 16:04:18 2008 +0000
+++ b/master/slave_config.c Mon Sep 01 14:17:18 2008 +0000
@@ -42,6 +42,7 @@
#include "globals.h"
#include "master.h"
+#include "voe_handler.h"
#include "slave_config.h"
@@ -75,6 +76,7 @@
INIT_LIST_HEAD(&sc->sdo_configs);
INIT_LIST_HEAD(&sc->sdo_requests);
+ INIT_LIST_HEAD(&sc->voe_handlers);
sc->used_fmmus = 0;
}
@@ -91,6 +93,7 @@
{
unsigned int i;
ec_sdo_request_t *req, *next_req;
+ ec_voe_handler_t *voe, *next_voe;
ec_slave_config_detach(sc);
@@ -111,6 +114,13 @@
ec_sdo_request_clear(req);
kfree(req);
}
+
+ // free all VoE handlers
+ list_for_each_entry_safe(voe, next_voe, &sc->voe_handlers, list) {
+ list_del(&voe->list);
+ ec_voe_handler_clear(voe);
+ kfree(voe);
+ }
}
/*****************************************************************************/
@@ -742,6 +752,35 @@
/*****************************************************************************/
+ec_voe_handler_t *ecrt_slave_config_create_voe_handler(ec_slave_config_t *sc,
+ size_t size)
+{
+ ec_voe_handler_t *voe;
+
+ if (sc->master->debug_level)
+ EC_DBG("ecrt_slave_config_create_voe_handler(sc = 0x%x, size = %u)\n",
+ (u32) sc, size);
+
+ if (!(voe = (ec_voe_handler_t *)
+ kmalloc(sizeof(ec_voe_handler_t), GFP_KERNEL))) {
+ EC_ERR("Failed to allocate Sdo request memory!\n");
+ return NULL;
+ }
+
+ if (ec_voe_handler_init(voe, sc, size)) {
+ kfree(voe);
+ return NULL;
+ }
+
+ down(&sc->master->master_sem);
+ list_add_tail(&voe->list, &sc->voe_handlers);
+ up(&sc->master->master_sem);
+
+ return voe;
+}
+
+/*****************************************************************************/
+
void ecrt_slave_config_state(const ec_slave_config_t *sc,
ec_slave_config_state_t *state)
{
--- a/master/slave_config.h Wed Aug 27 16:04:18 2008 +0000
+++ b/master/slave_config.h Mon Sep 01 14:17:18 2008 +0000
@@ -43,8 +43,6 @@
#include <linux/list.h>
-#include "../include/ecrt.h"
-
#include "globals.h"
#include "slave.h"
#include "sync_config.h"
@@ -74,7 +72,7 @@
struct list_head sdo_configs; /**< List of Sdo configurations. */
struct list_head sdo_requests; /**< List of Sdo requests. */
-
+ struct list_head voe_handlers; /**< List of VoE handlers. */
};
/*****************************************************************************/
--- a/master/sync.h Wed Aug 27 16:04:18 2008 +0000
+++ b/master/sync.h Mon Sep 01 14:17:18 2008 +0000
@@ -40,8 +40,6 @@
#ifndef __EC_SYNC_H__
#define __EC_SYNC_H__
-#include "../include/ecrt.h"
-
#include "globals.h"
#include "pdo_list.h"
--- a/master/sync_config.h Wed Aug 27 16:04:18 2008 +0000
+++ b/master/sync_config.h Mon Sep 01 14:17:18 2008 +0000
@@ -40,8 +40,6 @@
#ifndef __EC_SYNC_CONFIG_H__
#define __EC_SYNC_CONFIG_H__
-#include "../include/ecrt.h"
-
#include "globals.h"
#include "pdo_list.h"
--- /dev/null Thu Jan 01 00:00:00 1970 +0000
+++ b/master/voe_handler.c Mon Sep 01 14:17:18 2008 +0000
@@ -0,0 +1,386 @@
+/******************************************************************************
+ *
+ * $Id$
+ *
+ * Copyright (C) 2006 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
+ * as published by the Free Software Foundation; either version 2 of the
+ * License, or (at your option) any later version.
+ *
+ * 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 right to use EtherCAT Technology is granted and comes free of
+ * charge under condition of compatibility of product made by
+ * Licensee. People intending to distribute/sell products based on the
+ * code, have to sign an agreement to guarantee that products using
+ * software based on IgH EtherCAT master stay compatible with the actual
+ * EtherCAT specification (which are released themselves as an open
+ * standard) as the (only) precondition to have the right to use EtherCAT
+ * Technology, IP and trade marks.
+ *
+ *****************************************************************************/
+
+/** \file
+ * Vendor-specific-over-EtherCAT protocol handler functions.
+ */
+
+/*****************************************************************************/
+
+#include <linux/module.h>
+
+#include "master.h"
+#include "slave_config.h"
+#include "mailbox.h"
+#include "voe_handler.h"
+
+/** VoE response timeout in [ms].
+ */
+#define EC_VOE_RESPONSE_TIMEOUT 500
+
+/*****************************************************************************/
+
+void ec_voe_handler_clear_data(ec_voe_handler_t *);
+
+void ec_voe_handler_state_write_start(ec_voe_handler_t *);
+void ec_voe_handler_state_write_response(ec_voe_handler_t *);
+
+void ec_voe_handler_state_read_start(ec_voe_handler_t *);
+void ec_voe_handler_state_read_check(ec_voe_handler_t *);
+void ec_voe_handler_state_read_response(ec_voe_handler_t *);
+
+void ec_voe_handler_state_end(ec_voe_handler_t *);
+void ec_voe_handler_state_error(ec_voe_handler_t *);
+
+/*****************************************************************************/
+
+/** VoE handler constructor.
+ */
+int ec_voe_handler_init(
+ ec_voe_handler_t *voe, /**< VoE handler. */
+ ec_slave_config_t *sc, /**< Parent slave configuration. */
+ size_t size /**< Size of memory to reserve. */
+ )
+{
+ voe->config = sc;
+ voe->data_size = 0;
+ voe->dir = EC_DIR_INVALID;
+ voe->state = ec_voe_handler_state_error;
+ voe->request_state = EC_INT_REQUEST_INIT;
+
+ ec_datagram_init(&voe->datagram);
+ if (ec_datagram_prealloc(&voe->datagram, size + 6))
+ return -1;
+
+ return 0;
+}
+
+/*****************************************************************************/
+
+/** VoE handler destructor.
+ */
+void ec_voe_handler_clear(
+ ec_voe_handler_t *voe /**< VoE handler. */
+ )
+{
+ ec_datagram_clear(&voe->datagram);
+}
+
+/*****************************************************************************
+ * Application interface.
+ ****************************************************************************/
+
+uint8_t *ecrt_voe_handler_data(ec_voe_handler_t *voe)
+{
+ return voe->datagram.data + 6;
+}
+
+/*****************************************************************************/
+
+size_t ecrt_voe_handler_data_size(const ec_voe_handler_t *voe)
+{
+ return voe->data_size;
+}
+
+/*****************************************************************************/
+
+void ecrt_voe_handler_read(ec_voe_handler_t *voe)
+{
+ voe->dir = EC_DIR_INPUT;
+ voe->state = ec_voe_handler_state_read_start;
+ voe->request_state = EC_INT_REQUEST_QUEUED;
+}
+
+/*****************************************************************************/
+
+void ecrt_voe_handler_write(ec_voe_handler_t *voe, size_t size)
+{
+ voe->dir = EC_DIR_OUTPUT;
+ voe->datagram.data_size = size + 6;
+ voe->state = ec_voe_handler_state_write_start;
+ voe->request_state = EC_INT_REQUEST_QUEUED;
+}
+
+/*****************************************************************************/
+
+ec_request_state_t ecrt_voe_handler_execute(ec_voe_handler_t *voe)
+{
+ if (voe->config->slave) {
+ voe->state(voe);
+ if (voe->request_state == EC_REQUEST_BUSY)
+ ec_master_queue_datagram(voe->config->master, &voe->datagram);
+ } else {
+ voe->state = ec_voe_handler_state_error;
+ voe->request_state = EC_INT_REQUEST_FAILURE;
+ }
+
+ return ec_request_state_translation_table[voe->request_state];
+}
+
+/******************************************************************************
+ * State functions.
+ *****************************************************************************/
+
+void ec_voe_handler_state_write_start(ec_voe_handler_t *voe)
+{
+ ec_slave_t *slave = voe->config->slave;
+ uint8_t *data;
+
+ if (slave->master->debug_level) {
+ EC_DBG("Writing %u bytes of VoE data to slave %u.\n",
+ voe->data_size, slave->ring_position);
+ ec_print_data(ecrt_voe_handler_data(voe), voe->data_size);
+ }
+
+ if (!(slave->sii.mailbox_protocols & EC_MBOX_VOE)) {
+ EC_ERR("Slave %u does not support VoE!\n", slave->ring_position);
+ voe->state = ec_voe_handler_state_error;
+ voe->request_state = EC_INT_REQUEST_FAILURE;
+ return;
+ }
+
+ if (!(data = ec_slave_mbox_prepare_send(
+ slave, &voe->datagram, 0x01, voe->data_size))) {
+ voe->state = ec_voe_handler_state_error;
+ voe->request_state = EC_INT_REQUEST_FAILURE;
+ return;
+ }
+
+ voe->retries = EC_FSM_RETRIES;
+ voe->jiffies_start = jiffies;
+ voe->state = ec_voe_handler_state_write_response;
+}
+
+/*****************************************************************************/
+
+void ec_voe_handler_state_write_response(ec_voe_handler_t *voe)
+{
+ ec_datagram_t *datagram = &voe->datagram;
+ ec_slave_t *slave = voe->config->slave;
+
+ if (datagram->state == EC_DATAGRAM_TIMED_OUT && voe->retries--)
+ return;
+
+ if (datagram->state != EC_DATAGRAM_RECEIVED) {
+ voe->state = ec_voe_handler_state_error;
+ voe->request_state = EC_INT_REQUEST_FAILURE;
+ EC_ERR("Failed to receive VoE write request datagram for"
+ " slave %u (datagram state %u).\n",
+ slave->ring_position, datagram->state);
+ return;
+ }
+
+ if (datagram->working_counter != 1) {
+ if (!datagram->working_counter) {
+ unsigned long diff_ms =
+ (jiffies - voe->jiffies_start) * 1000 / HZ;
+ if (diff_ms < EC_VOE_RESPONSE_TIMEOUT) {
+ if (slave->master->debug_level) {
+ EC_DBG("Slave %u did not respond to VoE write request. "
+ "Retrying after %u ms...\n",
+ slave->ring_position, (u32) diff_ms);
+ }
+ // no response; send request datagram again
+ return;
+ }
+ }
+ voe->state = ec_voe_handler_state_error;
+ voe->request_state = EC_INT_REQUEST_FAILURE;
+ EC_ERR("Reception of VoE write request failed on slave %u: ",
+ slave->ring_position);
+ ec_datagram_print_wc_error(datagram);
+ return;
+ }
+
+ if (voe->config->master->debug_level)
+ EC_DBG("VoE write request successful.\n");
+
+ voe->request_state = EC_INT_REQUEST_SUCCESS;
+ voe->state = ec_voe_handler_state_end;
+}
+
+/*****************************************************************************/
+
+void ec_voe_handler_state_read_start(ec_voe_handler_t *voe)
+{
+ ec_datagram_t *datagram = &voe->datagram;
+ ec_slave_t *slave = voe->config->slave;
+
+ if (slave->master->debug_level)
+ EC_DBG("Reading VoE data to slave %u.\n", slave->ring_position);
+
+ if (!(slave->sii.mailbox_protocols & EC_MBOX_VOE)) {
+ EC_ERR("Slave %u does not support VoE!\n", slave->ring_position);
+ voe->state = ec_voe_handler_state_error;
+ voe->request_state = EC_INT_REQUEST_FAILURE;
+ return;
+ }
+
+ ec_slave_mbox_prepare_check(slave, datagram); // can not fail.
+
+ voe->jiffies_start = jiffies;
+ voe->retries = EC_FSM_RETRIES;
+ voe->state = ec_voe_handler_state_read_check;
+}
+
+/*****************************************************************************/
+
+void ec_voe_handler_state_read_check(ec_voe_handler_t *voe)
+{
+ ec_datagram_t *datagram = &voe->datagram;
+ ec_slave_t *slave = voe->config->slave;
+
+ if (datagram->state == EC_DATAGRAM_TIMED_OUT && voe->retries--)
+ return;
+
+ if (datagram->state != EC_DATAGRAM_RECEIVED) {
+ voe->state = ec_voe_handler_state_error;
+ voe->request_state = EC_INT_REQUEST_FAILURE;
+ EC_ERR("Failed to receive VoE mailbox check datagram from slave %u"
+ " (datagram state %u).\n",
+ slave->ring_position, datagram->state);
+ return;
+ }
+
+ if (datagram->working_counter != 1) {
+ voe->state = ec_voe_handler_state_error;
+ voe->request_state = EC_INT_REQUEST_FAILURE;
+ EC_ERR("Reception of VoE mailbox check"
+ " datagram failed on slave %u: ", slave->ring_position);
+ ec_datagram_print_wc_error(datagram);
+ return;
+ }
+
+ if (!ec_slave_mbox_check(datagram)) {
+ unsigned long diff_ms =
+ (datagram->jiffies_received - voe->jiffies_start) * 1000 / HZ;
+ if (diff_ms >= EC_VOE_RESPONSE_TIMEOUT) {
+ voe->state = ec_voe_handler_state_error;
+ voe->request_state = EC_INT_REQUEST_FAILURE;
+ EC_ERR("Timeout while waiting for VoE data on "
+ "slave %u.\n", slave->ring_position);
+ return;
+ }
+
+ ec_slave_mbox_prepare_check(slave, datagram); // can not fail.
+ voe->retries = EC_FSM_RETRIES;
+ return;
+ }
+
+ // Fetch response
+ ec_slave_mbox_prepare_fetch(slave, datagram); // can not fail.
+ voe->retries = EC_FSM_RETRIES;
+ voe->state = ec_voe_handler_state_read_response;
+}
+
+/*****************************************************************************/
+
+void ec_voe_handler_state_read_response(ec_voe_handler_t *voe)
+{
+ ec_datagram_t *datagram = &voe->datagram;
+ ec_slave_t *slave = voe->config->slave;
+ ec_master_t *master = voe->config->master;
+ uint8_t *data, mbox_prot;
+ size_t rec_size;
+
+ if (datagram->state == EC_DATAGRAM_TIMED_OUT && voe->retries--)
+ return;
+
+ if (datagram->state != EC_DATAGRAM_RECEIVED) {
+ voe->state = ec_voe_handler_state_error;
+ voe->request_state = EC_INT_REQUEST_FAILURE;
+ EC_ERR("Failed to receive VoE read datagram for"
+ " slave %u (datagram state %u).\n",
+ slave->ring_position, datagram->state);
+ return;
+ }
+
+ if (datagram->working_counter != 1) {
+ voe->state = ec_voe_handler_state_error;
+ voe->request_state = EC_INT_REQUEST_FAILURE;
+ EC_ERR("Reception of VoE read response failed on slave %u: ",
+ slave->ring_position);
+ ec_datagram_print_wc_error(datagram);
+ return;
+ }
+
+ if (!(data = ec_slave_mbox_fetch(slave, datagram,
+ &mbox_prot, &rec_size))) {
+ voe->state = ec_voe_handler_state_error;
+ voe->request_state = EC_INT_REQUEST_FAILURE;
+ return;
+ }
+
+ if (mbox_prot != 0x01) { // VoE
+ voe->state = ec_voe_handler_state_error;
+ voe->request_state = EC_INT_REQUEST_FAILURE;
+ EC_WARN("Received mailbox protocol 0x%02X as response.\n", mbox_prot);
+ ec_print_data(data, rec_size);
+ return;
+ }
+
+ if (master->debug_level) {
+ EC_DBG("VoE data:\n");
+ ec_print_data(data, rec_size);
+ }
+
+ voe->data_size = rec_size;
+ voe->request_state = EC_INT_REQUEST_SUCCESS;
+ voe->state = ec_voe_handler_state_end; // success
+}
+
+/*****************************************************************************/
+
+void ec_voe_handler_state_end(ec_voe_handler_t *voe)
+{
+}
+
+/*****************************************************************************/
+
+void ec_voe_handler_state_error(ec_voe_handler_t *voe)
+{
+}
+
+/*****************************************************************************/
+
+/** \cond */
+
+EXPORT_SYMBOL(ecrt_voe_handler_data);
+EXPORT_SYMBOL(ecrt_voe_handler_data_size);
+EXPORT_SYMBOL(ecrt_voe_handler_read);
+EXPORT_SYMBOL(ecrt_voe_handler_write);
+EXPORT_SYMBOL(ecrt_voe_handler_execute);
+
+/** \endcond */
+
+/*****************************************************************************/
--- /dev/null Thu Jan 01 00:00:00 1970 +0000
+++ b/master/voe_handler.h Mon Sep 01 14:17:18 2008 +0000
@@ -0,0 +1,74 @@
+/******************************************************************************
+ *
+ * $Id$
+ *
+ * Copyright (C) 2006 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
+ * as published by the Free Software Foundation; either version 2 of the
+ * License, or (at your option) any later version.
+ *
+ * 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 right to use EtherCAT Technology is granted and comes free of
+ * charge under condition of compatibility of product made by
+ * Licensee. People intending to distribute/sell products based on the
+ * code, have to sign an agreement to guarantee that products using
+ * software based on IgH EtherCAT master stay compatible with the actual
+ * EtherCAT specification (which are released themselves as an open
+ * standard) as the (only) precondition to have the right to use EtherCAT
+ * Technology, IP and trade marks.
+ *
+ *****************************************************************************/
+
+/**
+ \file
+ Vendor-specific-over-EtherCAT protocol handler.
+*/
+
+/*****************************************************************************/
+
+#ifndef __EC_VOE_HANDLER_H__
+#define __EC_VOE_HANDLER_H__
+
+#include <linux/list.h>
+
+#include "globals.h"
+#include "datagram.h"
+
+/*****************************************************************************/
+
+/** Vendor-specific-over-EtherCAT handler.
+ */
+struct ec_voe_handler {
+ struct list_head list; /**< List item. */
+ ec_slave_config_t *config; /**< Parent slave configuration. */
+ ec_datagram_t datagram; /**< State machine datagram. */
+ size_t data_size; /**< Size of Sdo data. */
+ ec_direction_t dir; /**< Direction. EC_DIR_OUTPUT means writing to
+ the slave, EC_DIR_INPUT means reading from the
+ slave. */
+ void (*state)(ec_voe_handler_t *); /**< State function */
+ ec_internal_request_state_t request_state; /**< Handler state. */
+ unsigned int retries; /**< retries upon datagram timeout */
+ unsigned long jiffies_start; /**< Timestamp for timeout calculation. */
+};
+
+/*****************************************************************************/
+
+int ec_voe_handler_init(ec_voe_handler_t *, ec_slave_config_t *, size_t);
+void ec_voe_handler_clear(ec_voe_handler_t *);
+
+/*****************************************************************************/
+
+#endif