MERGE -r908:HEAD svn://yak/vol/projekte/msr_messen_steuern_regeln/ethercat/rep/trunk (1.3.1 changes) stable-1.3
authorFlorian Pose <fp@igh-essen.com>
Thu, 13 Sep 2007 11:08:46 +0000
branchstable-1.3
changeset 1745 07fd94c5119d
parent 1744 7bc131b92039
child 1746 72e7507b3f1b
MERGE -r908:HEAD svn://yak/vol/projekte/msr_messen_steuern_regeln/ethercat/rep/trunk (1.3.1 changes)
Makefile.am
NEWS
README.EoE
TODO
configure.ac
documentation/graphs/Makefile
documentation/graphs/fsm_master.dot
include/ecdb.h
include/ecrt.h
master/Kbuild
master/datagram.c
master/datagram.h
master/domain.c
master/ethernet.c
master/ethernet.h
master/fsm_change.c
master/fsm_coe.c
master/fsm_master.c
master/fsm_sii.c
master/fsm_slave.c
master/globals.h
master/master.c
master/master.h
script/Makefile.am
script/ifup-eoe.sh
script/init.d/ethercat
--- a/Makefile.am	Fri Aug 10 15:27:08 2007 +0000
+++ b/Makefile.am	Thu Sep 13 11:08:46 2007 +0000
@@ -39,7 +39,8 @@
 	Doxyfile \
 	FEATURES \
 	globals.h \
-	Kbuild
+	Kbuild \
+	README.EoE
 
 modules:
 	$(MAKE) -C "$(LINUX_SOURCE_DIR)" M="@abs_srcdir@" modules
--- a/NEWS	Fri Aug 10 15:27:08 2007 +0000
+++ b/NEWS	Thu Sep 13 11:08:46 2007 +0000
@@ -4,17 +4,33 @@
 
 -------------------------------------------------------------------------------
 
+Changes in version 1.3.1:
+
+* Improved EoE handling: Avoided skipping of datagrams and release lock
+  while processing.
+* Added some statistics to the datagram structure.
+* Master state machine clears all station addresses with a broadcast datagram
+  before setting them.
+* Added --enable-eoe conditional.
+* Minor extensions of the master info file.
+* Improved handling of unexpected working counters.
+* Create network interfaces for EoE devices with alias as eoeXaY.
+* Fixed problems on big-endian systems.
+* Added documentation on how to set up an EoE network.
+
+-------------------------------------------------------------------------------
+
 Changes in version 1.3.0:
 
-* Added Intel PRO/1000 gigabit ethernet driver (e1000).
-* Added testing version of Intel PRO/100 ethernet driver (e100).
-* Added testing version of NVIDIA nForce ethernet driver (forcedeth).
+* Added Intel PRO/1000 Gigabit Ethernet driver (e1000).
+* Added testing version of Intel PRO/100 Ethernet driver (e100).
+* Added testing version of NVIDIA nForce Ethernet driver (forcedeth).
 * Removed "ec_eoeif_count" master module parameter. EoE handlers are created
   dynamically instead.
 * Added "main" and "backup" parameters to master module to hand over the
   MAC addresses of the devices to wait for. This made the ec_device_index
-  parameter of the ethernet drivers obsolete. The broadcast MAC address means,
-  that the master accepts the first device offered by any ethernet driver.
+  parameter of the Ethernet drivers obsolete. The broadcast MAC address means,
+  that the master accepts the first device offered by any Ethernet driver.
 * Changed format of sysconfig file and accordingly adjusted functionality
   of the init script to handle the above MAC address lists.
 * Realtime interface changes:
@@ -48,7 +64,7 @@
   state machine.
 * Master state machine scheduled with timeout if idle, otherwise is executed
   as fast as possible (with schedule()).
-* Added dummy module for simulation purpuses.
+* Added dummy module for simulation purposes.
 * Limited infinite EEPROM reading, if 0xffff limiter word is missing.
 * Init script works now properly on non-SUSE distros (no rc.status dependency
   any more).
@@ -58,7 +74,7 @@
 
 Changes in version 1.2.0:
 
-* Serveral fixes of bugs and stability issues. Master should now run fine
+* Several fixes of bugs and stability issues. Master should now run fine
   with kernels 2.6.17 to 2.6.19.
 * Realtime interface changes:
   - Re-introduced ecrt_domain_queue() to allow datagram queuing apart
@@ -93,7 +109,7 @@
 * Device modules for kernel 2.6.17.
 * SDO configurations available in Sysfs.
 * FMMU configurations cleared when going to INIT.
-* Slave-specific logs only at debug level 1 (for large busses).
+* Slave-specific logs only at debug level 1 (for large buses).
 * Slave flags (error, online) available in Sysfs.
 * Acknowledging of spontaneous state changes in master FSMs.
 * ecrt_master_deactivate() deprecated.
--- /dev/null	Thu Jan 01 00:00:00 1970 +0000
+++ b/README.EoE	Thu Sep 13 11:08:46 2007 +0000
@@ -0,0 +1,24 @@
+-------------------------------------------------------------------------------
+
+$Id$
+
+This file shall give additional information on how to set up a network
+environment with Ethernet-over-EtherCAT devices.
+
+A virtual network interface will appear for every EoE-capable slave. The
+interface naming scheme is eoeXsY, where X is the master index and Y is the
+slave's ring position. Please provide a network configuration file for any of
+these interfaces. On SUSE systems, these can look like the following:
+
+/etc/sysconfig/network/ifcfg-eoe0s14:
+IPADDRESS=10.0.0.14/8
+STARTMODE=auto
+
+This will tell the ifupd to configure and open the device after it appears.
+
+If the interfaces shall be part of a network bridge, the IPADDRESS line is not
+necessary. Instead, copy the file script/ifup-eoe.sh to your systems if-up.d
+directory (on SUSE, this is /etc/sysconfig/network/if-up.d), and customize the
+included variables.
+
+-------------------------------------------------------------------------------
--- a/TODO	Fri Aug 10 15:27:08 2007 +0000
+++ b/TODO	Thu Sep 13 11:08:46 2007 +0000
@@ -13,12 +13,13 @@
   - Redundancy with 2 network adapters.
   - Mailbox handler
   - Support slaves, that don't support the LRW datagram, only LRD/LWR.
+  - PDO reading in IDLE mode.
+  - Replace Sysfs interface with cdev and user space program.
 
 * Smaller issues:
   - Clear sync managers in INIT.
   - Simplify FSMs with <state>_enter() functions.
   - Output intermediate results during lsec.
-  - State change FSM: Follow spontaneous state changes.
   - Read out CRC counters.
   - Calculate expected working counter for domains.
   - Optimize alignment of process data.
--- a/configure.ac	Fri Aug 10 15:27:08 2007 +0000
+++ b/configure.ac	Thu Sep 13 11:08:46 2007 +0000
@@ -3,7 +3,7 @@
 #------------------------------------------------------------------------------
 
 AC_PREREQ(2.59)
-AC_INIT([ethercat],[1.3.0],[fp@igh-essen.com])
+AC_INIT([ethercat],[1.3.1],[fp@igh-essen.com])
 AC_CONFIG_AUX_DIR([autoconf])
 AM_INIT_AUTOMAKE([-Wall -Werror dist-bzip2])
 AC_PREFIX_DEFAULT([/opt/etherlab])
@@ -414,6 +414,31 @@
 AM_CONDITIONAL(ENABLE_DUMMY, test "x$dummy" = "x1")
 
 #------------------------------------------------------------------------------
+# Ethernet-over-EtherCAT support
+#------------------------------------------------------------------------------
+
+AC_ARG_ENABLE([eoe],
+    AS_HELP_STRING([--enable-eoe],
+                   [Enable EoE support (default: yes)]),
+    [
+        case "${enableval}" in
+            yes) eoe=1
+                ;;
+            no) eoe=0
+                ;;
+            *) AC_MSG_ERROR([Invalid value for --enable-eoe])
+                ;;
+        esac
+    ],
+    [eoe=1]
+)
+
+if test "x${eoe}" = "x1"; then
+    AC_DEFINE([EC_EOE], [1], [EoE support enabled])
+fi
+AM_CONDITIONAL(ENABLE_EOE, test "x$eoe" = "x1")
+
+#------------------------------------------------------------------------------
 
 # Create config.kbuild
 
@@ -433,6 +458,7 @@
 MSR_DIR := "${msrdir}"
 ENABLE_DEBUG_IF := ${dbg}
 ENABLE_DUMMY := ${dummy}
+ENABLE_EOE := ${eoe}
 EOF
 
 #------------------------------------------------------------------------------
--- a/documentation/graphs/Makefile	Fri Aug 10 15:27:08 2007 +0000
+++ b/documentation/graphs/Makefile	Thu Sep 13 11:08:46 2007 +0000
@@ -4,7 +4,7 @@
 #
 #-----------------------------------------------------------------------------
 
-GRAPHS := fsm_slave_conf.ps fsm_pdo_mapping.ps
+GRAPHS := fsm_slave_conf.ps fsm_pdo_mapping.ps fsm_master.ps
 
 all: $(GRAPHS)
 
--- /dev/null	Thu Jan 01 00:00:00 1970 +0000
+++ b/documentation/graphs/fsm_master.dot	Thu Sep 13 11:08:46 2007 +0000
@@ -0,0 +1,79 @@
+digraph master {
+    size="7,9"
+    center=1
+	ratio=fill
+
+    action_process_eeprom [shape=point,label=""]
+    action_process_sdo [shape=point,label=""]
+    action_configure [shape=point,label=""]
+    action_next_slave_state [shape=point,label=""]
+    action_process_states [shape=point,label=""]
+    action_addresses [shape=point,label=""]
+
+    start -> broadcast [weight=10]
+
+    //broadcast -> error
+    broadcast -> end
+    broadcast -> clear_addresses
+    broadcast -> read_states [weight=10]
+
+    action_process_eeprom -> write_eeprom
+
+    action_process_sdo -> sdo_request
+
+    action_configure -> configure_slave
+
+    action_next_slave_state -> read_states
+    action_next_slave_state -> validate_vendor
+    action_next_slave_state -> action_process_states
+
+    action_process_states -> action_configure
+    action_process_states -> action_process_sdo
+    action_process_states -> action_process_eeprom
+    action_process_states -> sdodict
+    action_process_states -> end
+
+    //read_states -> error
+    read_states -> action_next_slave_state
+    read_states -> acknowledge
+
+    //acknowledge -> error
+    acknowledge -> action_next_slave_state
+
+    //validate_vendor -> error
+    validate_vendor -> validate_product
+
+    action_addresses -> end
+    action_addresses -> rewrite_addresses
+
+    //validate_product -> error
+    validate_product -> validate_vendor
+    validate_product -> action_addresses
+
+    //rewrite_addresses -> error
+    rewrite_addresses -> end
+    rewrite_addresses -> action_addresses
+
+    //clear_addresses -> error
+    clear_addresses -> scan_slaves
+
+    scan_slaves -> scan_slaves
+    scan_slaves -> end
+
+    configure_slave -> action_configure
+    configure_slave -> end
+
+    //write_eeprom -> error
+    write_eeprom -> end
+
+    //sdodict -> error
+    sdodict -> end
+
+    //sdo_request -> error
+    sdo_request -> action_process_sdo
+    sdo_request -> end
+
+    //error -> start
+
+    //end -> start
+}
--- a/include/ecdb.h	Fri Aug 10 15:27:08 2007 +0000
+++ b/include/ecdb.h	Thu Sep 13 11:08:46 2007 +0000
@@ -34,6 +34,10 @@
 /**
    \file
    EtherCAT Slave Database.
+
+   \warn Please do not create any dependencies to this file! It may be changed
+   between releases. Provide a copy, if you want to use it in foreign
+   projects.
 */
 
 /*****************************************************************************/
@@ -51,10 +55,16 @@
 #define Beckhoff_EL1004_PDO_Inputs 0x3101, 1
 #define Beckhoff_EL1004_Inputs Beckhoff_EL1004, Beckhoff_EL1004_PDO_Inputs
 
+#define Beckhoff_EL1004v2_PDO_Inputs 0x6000, 1
+#define Beckhoff_EL1004v2_Inputs Beckhoff_EL1004, Beckhoff_EL1004v2_PDO_Inputs
+
 #define Beckhoff_EL1014 0x00000002, 0x03F63052
 #define Beckhoff_EL1014_PDO_Inputs 0x3101, 1
 #define Beckhoff_EL1014_Inputs Beckhoff_EL1014, Beckhoff_EL1014_PDO_Inputs 
 
+#define Beckhoff_EL1014v2_PDO_Inputs 0x6000, 1
+#define Beckhoff_EL1014v2_Inputs Beckhoff_EL1014, Beckhoff_EL1014v2_PDO_Inputs
+
 #define Beckhoff_EL2004 0x00000002, 0x07D43052
 #define Beckhoff_EL2004_PDO_Outputs 0x3001, 1
 #define Beckhoff_EL2004_Outputs Beckhoff_EL2004, Beckhoff_EL2004_PDO_Outputs 
--- a/include/ecrt.h	Fri Aug 10 15:27:08 2007 +0000
+++ b/include/ecrt.h	Thu Sep 13 11:08:46 2007 +0000
@@ -325,7 +325,7 @@
 #define EC_WRITE_U32(DATA, VAL) \
     do { \
         *((uint32_t *) (DATA)) = (uint32_t) (VAL); \
-        cpu_to_le16s(DATA); \
+        cpu_to_le32s(DATA); \
     } while (0)
 
 /**
--- a/master/Kbuild	Fri Aug 10 15:27:08 2007 +0000
+++ b/master/Kbuild	Thu Sep 13 11:08:46 2007 +0000
@@ -36,9 +36,12 @@
 obj-m := ec_master.o
 
 ec_master-objs := module.o master.o device.o pdo.o sync.o fmmu.o slave.o \
-    datagram.o domain.o mailbox.o canopen.o ethernet.o fsm_sii.o fsm_change.o \
+    datagram.o domain.o mailbox.o canopen.o fsm_sii.o fsm_change.o \
     fsm_coe.o fsm_mapping.o fsm_slave.o fsm_master.o
 
+ifeq ($(ENABLE_EOE),1)
+	ec_master-objs += ethernet.o
+endif
 ifeq ($(ENABLE_DEBUG_IF),1)
 	ec_master-objs += debug.o
 endif
--- a/master/datagram.c	Fri Aug 10 15:27:08 2007 +0000
+++ b/master/datagram.c	Thu Sep 13 11:08:46 2007 +0000
@@ -71,7 +71,7 @@
 {
     INIT_LIST_HEAD(&datagram->queue); // mark as unqueued
     datagram->type = EC_DATAGRAM_NONE;
-    datagram->address.logical = 0x00000000;
+    memset(datagram->address, 0x00, EC_ADDR_LEN);
     datagram->data = NULL;
     datagram->mem_size = 0;
     datagram->data_size = 0;
@@ -82,6 +82,9 @@
     datagram->jiffies_sent = 0;
     datagram->cycles_received = 0;
     datagram->jiffies_received = 0;
+    datagram->skip_count = 0;
+    datagram->stats_output_jiffies = 0;
+    datagram->name[0] = 0x00;
 }
 
 /*****************************************************************************/
@@ -147,8 +150,8 @@
 
     EC_FUNC_HEADER;
     datagram->type = EC_DATAGRAM_NPRD;
-    datagram->address.physical.slave = node_address;
-    datagram->address.physical.mem = offset;
+    EC_WRITE_U16(datagram->address, node_address);
+    EC_WRITE_U16(datagram->address + 2, offset);
     EC_FUNC_FOOTER;
 }
 
@@ -175,8 +178,8 @@
 
     EC_FUNC_HEADER;
     datagram->type = EC_DATAGRAM_NPWR;
-    datagram->address.physical.slave = node_address;
-    datagram->address.physical.mem = offset;
+    EC_WRITE_U16(datagram->address, node_address);
+    EC_WRITE_U16(datagram->address + 2, offset);
     EC_FUNC_FOOTER;
 }
 
@@ -200,8 +203,8 @@
 {
     EC_FUNC_HEADER;
     datagram->type = EC_DATAGRAM_APRD;
-    datagram->address.physical.slave = (int16_t) ring_position * (-1);
-    datagram->address.physical.mem = offset;
+    EC_WRITE_S16(datagram->address, (int16_t) ring_position * (-1));
+    EC_WRITE_U16(datagram->address + 2, offset);
     EC_FUNC_FOOTER;
 }
 
@@ -225,8 +228,8 @@
 {
     EC_FUNC_HEADER;
     datagram->type = EC_DATAGRAM_APWR;
-    datagram->address.physical.slave = (int16_t) ring_position * (-1);
-    datagram->address.physical.mem = offset;
+    EC_WRITE_S16(datagram->address, (int16_t) ring_position * (-1));
+    EC_WRITE_U16(datagram->address + 2, offset);
     EC_FUNC_FOOTER;
 }
 
@@ -248,8 +251,8 @@
 {
     EC_FUNC_HEADER;
     datagram->type = EC_DATAGRAM_BRD;
-    datagram->address.physical.slave = 0x0000;
-    datagram->address.physical.mem = offset;
+    EC_WRITE_U16(datagram->address, 0x0000);
+    EC_WRITE_U16(datagram->address + 2, offset);
     EC_FUNC_FOOTER;
 }
 
@@ -271,8 +274,8 @@
 {
     EC_FUNC_HEADER;
     datagram->type = EC_DATAGRAM_BWR;
-    datagram->address.physical.slave = 0x0000;
-    datagram->address.physical.mem = offset;
+    EC_WRITE_U16(datagram->address, 0x0000);
+    EC_WRITE_U16(datagram->address + 2, offset);
     EC_FUNC_FOOTER;
 }
 
@@ -294,8 +297,51 @@
 {
     EC_FUNC_HEADER;
     datagram->type = EC_DATAGRAM_LRW;
-    datagram->address.logical = offset;
-    EC_FUNC_FOOTER;
-}
-
-/*****************************************************************************/
+    EC_WRITE_U32(datagram->address, offset);
+    EC_FUNC_FOOTER;
+}
+
+/*****************************************************************************/
+
+/**
+ * Evaluates the working counter of a single-cast datagram.
+ * Outputs an error message.
+ */
+
+void ec_datagram_print_wc_error(
+        const ec_datagram_t *datagram
+        )
+{
+    if (datagram->working_counter == 0)
+        printk("No response.");
+    else if (datagram->working_counter > 1)
+        printk("%u slaves responded!", datagram->working_counter);
+    else
+        printk("Success.");
+    printk("\n");
+}
+
+/*****************************************************************************/
+
+/**
+ * Outputs datagram statistics at most every second.
+ */
+
+void ec_datagram_output_stats(
+        ec_datagram_t *datagram
+        )
+{
+    if (jiffies - datagram->stats_output_jiffies < HZ) {
+        datagram->stats_output_jiffies = jiffies;
+    
+        if (unlikely(datagram->skip_count)) {
+            EC_WARN("Datagram %x (%s) was SKIPPED %u time%s.\n",
+                    (unsigned int) datagram, datagram->name,
+                    datagram->skip_count,
+                    datagram->skip_count == 1 ? "" : "s");
+            datagram->skip_count = 0;
+        }
+    }
+}
+
+/*****************************************************************************/
--- a/master/datagram.h	Fri Aug 10 15:27:08 2007 +0000
+++ b/master/datagram.h	Thu Sep 13 11:08:46 2007 +0000
@@ -49,6 +49,11 @@
 
 /*****************************************************************************/
 
+/** size of the datagram description string */
+#define EC_DATAGRAM_NAME_SIZE 20
+
+/*****************************************************************************/
+
 /**
    EtherCAT datagram type.
 */
@@ -84,28 +89,6 @@
 /*****************************************************************************/
 
 /**
-   EtherCAT address.
-*/
-
-typedef union
-{
-    /**
-     * Physical address.
-     */
-    struct
-    {
-        uint16_t slave; /**< configured or autoincrement address */
-        uint16_t mem; /**< physical memory address */
-    }
-    physical;
-
-    uint32_t logical; /**< logical address */
-}
-ec_address_t;
-
-/*****************************************************************************/
-
-/**
    EtherCAT datagram.
 */
 
@@ -115,7 +98,7 @@
     struct list_head queue; /**< master datagram queue item */
     struct list_head sent; /**< master list item for sent datagrams */
     ec_datagram_type_t type; /**< datagram type (APRD, BWR, etc) */
-    ec_address_t address; /**< recipient address */
+    uint8_t address[EC_ADDR_LEN]; /**< recipient address */
     uint8_t *data; /**< datagram data */
     size_t mem_size; /**< datagram \a data memory size */
     size_t data_size; /**< size of the data in \a data */
@@ -125,7 +108,10 @@
     cycles_t cycles_sent; /**< time, the datagram was sent */
     unsigned long jiffies_sent; /**< jiffies, when the datagram was sent */
     cycles_t cycles_received; /**< time, when the datagram was received */
-    unsigned long jiffies_received; /**< jiffies, when the datagram was rec. */
+    unsigned long jiffies_received; /**< jiffies the datagram was received */
+    unsigned int skip_count; /**< number of requeues when not yet received */
+    unsigned long stats_output_jiffies; /**< last statistics output */
+    char name[EC_DATAGRAM_NAME_SIZE]; /**< description of the datagram */
 }
 ec_datagram_t;
 
@@ -143,6 +129,9 @@
 int ec_datagram_bwr(ec_datagram_t *, uint16_t, size_t);
 int ec_datagram_lrw(ec_datagram_t *, uint32_t, size_t);
 
+void ec_datagram_print_wc_error(const ec_datagram_t *);
+void ec_datagram_output_stats(ec_datagram_t *datagram);
+
 /*****************************************************************************/
 
 #endif
--- a/master/domain.c	Fri Aug 10 15:27:08 2007 +0000
+++ b/master/domain.c	Thu Sep 13 11:08:46 2007 +0000
@@ -269,6 +269,8 @@
     }
 
     ec_datagram_init(datagram);
+    snprintf(datagram->name, EC_DATAGRAM_NAME_SIZE,
+            "domain%u-%u", domain->index, offset);
 
     if (ec_datagram_lrw(datagram, offset, data_size)) {
         kfree(datagram);
@@ -298,7 +300,7 @@
     ec_fmmu_t *fmmu;
     unsigned int i, j, datagram_count;
     uint32_t pdo_off, pdo_off_datagram;
-    uint32_t datagram_offset;
+    uint32_t datagram_offset, log_addr;
     size_t datagram_data_size, sync_size;
     ec_datagram_t *datagram;
 
@@ -350,8 +352,9 @@
                 pdo_off = fmmu->logical_start_address + data_reg->sync_offset;
                 // search datagram
                 list_for_each_entry(datagram, &domain->datagrams, list) {
-                    pdo_off_datagram = pdo_off - datagram->address.logical;
-                    if (pdo_off >= datagram->address.logical &&
+                    log_addr = EC_READ_U32(datagram->address);
+                    pdo_off_datagram = pdo_off - log_addr;
+                    if (pdo_off >= log_addr &&
                         pdo_off_datagram < datagram->mem_size) {
                         *data_reg->data_ptr = datagram->data +
                             pdo_off_datagram;
@@ -546,6 +549,7 @@
     working_counter_sum = 0;
     domain->state = 0;
     list_for_each_entry(datagram, &domain->datagrams, list) {
+        ec_datagram_output_stats(datagram);
         if (datagram->state == EC_DATAGRAM_RECEIVED) {
             working_counter_sum += datagram->working_counter;
         }
--- a/master/ethernet.c	Fri Aug 10 15:27:08 2007 +0000
+++ b/master/ethernet.c	Thu Sep 13 11:08:46 2007 +0000
@@ -94,11 +94,12 @@
 {
     ec_eoe_t **priv;
     int result, i;
-    char name[20];
+    char name[EC_DATAGRAM_NAME_SIZE];
 
     eoe->slave = slave;
 
     ec_datagram_init(&eoe->datagram);
+    eoe->queue_datagram = 0;
     eoe->state = ec_eoe_state_rx_start;
     eoe->opened = 0;
     eoe->rx_skb = NULL;
@@ -117,12 +118,20 @@
     eoe->tx_rate = 0;
     eoe->rate_jiffies = 0;
 
-    /* device name eoe<MASTER>s<SLAVE>, because system tools don't like
-     * hyphens etc. in interface names. */
-    sprintf(name, "eoe%us%u", slave->master->index, slave->ring_position);
+    /* device name eoe<MASTER>[as]<SLAVE>, because networking scripts don't
+     * like hyphens etc. in interface names. */
+    if (slave->sii_alias) {
+        snprintf(name, EC_DATAGRAM_NAME_SIZE,
+                "eoe%ua%u", slave->master->index, slave->sii_alias);
+    } else {
+        snprintf(name, EC_DATAGRAM_NAME_SIZE,
+                "eoe%us%u", slave->master->index, slave->ring_position);
+    }
+
+    snprintf(eoe->datagram.name, EC_DATAGRAM_NAME_SIZE, name);
 
     if (!(eoe->dev = alloc_netdev(sizeof(ec_eoe_t *), name, ether_setup))) {
-        EC_ERR("Unable to allocate net_device for EoE handler!\n");
+        EC_ERR("Unable to allocate net_device %s for EoE handler!\n", name);
         goto out_return;
     }
 
@@ -275,7 +284,7 @@
                             (eoe->tx_frame_number & 0x0F) << 12));
 
     memcpy(data + 4, eoe->tx_frame->skb->data + eoe->tx_offset, current_size);
-    ec_master_queue_datagram(eoe->slave->master, &eoe->datagram);
+    eoe->queue_datagram = 1;
 
     eoe->tx_offset += current_size;
     eoe->tx_fragment_number++;
@@ -292,6 +301,10 @@
 {
     if (!eoe->opened) return;
 
+    // if the datagram was not sent, or is not yet received, skip this cycle
+    if (eoe->queue_datagram || eoe->datagram.state == EC_DATAGRAM_SENT)
+        return;
+
     // call state function
     eoe->state(eoe);
 
@@ -303,6 +316,22 @@
         eoe->tx_counter = 0;
         eoe->rate_jiffies = jiffies;
     }
+
+    ec_datagram_output_stats(&eoe->datagram);
+}
+
+/*****************************************************************************/
+
+/**
+ * Queues the datagram, if necessary.
+ */
+
+void ec_eoe_queue(ec_eoe_t *eoe /**< EoE handler */)
+{
+   if (eoe->queue_datagram) {
+       ec_master_queue_datagram(eoe->slave->master, &eoe->datagram);
+       eoe->queue_datagram = 0;
+   }
 }
 
 /*****************************************************************************/
@@ -334,7 +363,7 @@
         return;
 
     ec_slave_mbox_prepare_check(eoe->slave, &eoe->datagram);
-    ec_master_queue_datagram(eoe->slave->master, &eoe->datagram);
+    eoe->queue_datagram = 1;
     eoe->state = ec_eoe_state_rx_check;
 }
 
@@ -360,7 +389,7 @@
     }
 
     ec_slave_mbox_prepare_fetch(eoe->slave, &eoe->datagram);
-    ec_master_queue_datagram(eoe->slave->master, &eoe->datagram);
+    eoe->queue_datagram = 1;
     eoe->state = ec_eoe_state_rx_fetch;
 }
 
--- a/master/ethernet.h	Fri Aug 10 15:27:08 2007 +0000
+++ b/master/ethernet.h	Thu Sep 13 11:08:46 2007 +0000
@@ -74,6 +74,7 @@
     struct list_head list; /**< list item */
     ec_slave_t *slave; /**< pointer to the corresponding slave */
     ec_datagram_t datagram; /**< datagram */
+    unsigned int queue_datagram; /**< the datagram is ready for queuing */
     void (*state)(ec_eoe_t *); /**< state function for the state machine */
     struct net_device *dev; /**< net_device for virtual ethernet device */
     struct net_device_stats stats; /**< device statistics */
@@ -102,6 +103,7 @@
 int ec_eoe_init(ec_eoe_t *, ec_slave_t *);
 void ec_eoe_clear(ec_eoe_t *);
 void ec_eoe_run(ec_eoe_t *);
+void ec_eoe_queue(ec_eoe_t *);
 int ec_eoe_is_open(const ec_eoe_t *);
 
 /*****************************************************************************/
--- a/master/fsm_change.c	Fri Aug 10 15:27:08 2007 +0000
+++ b/master/fsm_change.c	Thu Sep 13 11:08:46 2007 +0000
@@ -190,13 +190,14 @@
         fsm->jiffies_start = datagram->jiffies_sent;
     }
 
-    if (datagram->working_counter != 1) {
+    if (datagram->working_counter == 0) {
         if (datagram->jiffies_received - fsm->jiffies_start >= 3 * HZ) {
             char state_str[EC_STATE_STRING_SIZE];
             ec_state_string(fsm->requested_state, state_str);
             fsm->state = ec_fsm_change_state_error;
-            EC_ERR("Failed to set state %s on slave %i: Slave did not"
-                   " respond.\n", state_str, fsm->slave->ring_position);
+            EC_ERR("Failed to set state %s on slave %i: ",
+                    state_str, fsm->slave->ring_position);
+            ec_datagram_print_wc_error(datagram);
             return;
         }
 
@@ -207,6 +208,16 @@
         return;
     }
 
+    if (unlikely(datagram->working_counter > 1)) {
+        char state_str[EC_STATE_STRING_SIZE];
+        ec_state_string(fsm->requested_state, state_str);
+        fsm->state = ec_fsm_change_state_error;
+        EC_ERR("Failed to set state %s on slave %i: ",
+                state_str, fsm->slave->ring_position);
+        ec_datagram_print_wc_error(datagram);
+        return;
+    }
+
     fsm->take_time = 1;
 
     // read AL status from slave
@@ -242,8 +253,9 @@
         char req_state[EC_STATE_STRING_SIZE];
         ec_state_string(fsm->requested_state, req_state);
         fsm->state = ec_fsm_change_state_error;
-        EC_ERR("Failed to check state %s on slave %i.\n",
+        EC_ERR("Failed to check state %s on slave %i: ",
                req_state, slave->ring_position);
+        ec_datagram_print_wc_error(datagram);
         return;
     }
 
@@ -372,7 +384,8 @@
     }
 
     if (datagram->working_counter != 1) {
-        EC_WARN("Reception of AL status code datagram failed.\n");
+        EC_WARN("Reception of AL status code datagram failed: ");
+        ec_datagram_print_wc_error(datagram);
     }
     else {
         if ((code = EC_READ_U16(datagram->data))) {
@@ -433,8 +446,9 @@
 
     if (datagram->working_counter != 1) {
         fsm->state = ec_fsm_change_state_error;
-        EC_ERR("Reception of state ack datagram failed - slave %i did not"
-               " respond.\n", slave->ring_position);
+        EC_ERR("Reception of state ack datagram failed on slave %i: ",
+                slave->ring_position);
+        ec_datagram_print_wc_error(datagram);
         return;
     }
 
@@ -471,8 +485,9 @@
 
     if (datagram->working_counter != 1) {
         fsm->state = ec_fsm_change_state_error;
-        EC_ERR("Reception of state ack check datagram failed - slave %i did"
-               " not respond.\n", slave->ring_position);
+        EC_ERR("Reception of state ack check datagram failed on slave %i: ",
+                slave->ring_position);
+        ec_datagram_print_wc_error(datagram);
         return;
     }
 
--- a/master/fsm_coe.c	Fri Aug 10 15:27:08 2007 +0000
+++ b/master/fsm_coe.c	Thu Sep 13 11:08:46 2007 +0000
@@ -289,8 +289,9 @@
 
     if (datagram->working_counter != 1) {
         fsm->state = ec_fsm_coe_error;
-        EC_ERR("Reception of CoE dictionary request failed - slave %i did"
-               " not respond.\n", slave->ring_position);
+        EC_ERR("Reception of CoE dictionary request failed on slave %i: ",
+                slave->ring_position);
+        ec_datagram_print_wc_error(datagram);
         return;
     }
 
@@ -325,9 +326,9 @@
 
     if (datagram->working_counter != 1) {
         fsm->state = ec_fsm_coe_error;
-        EC_ERR("Reception of CoE mailbox check datagram failed - slave %i did"
-               " not respond.\n",
+        EC_ERR("Reception of CoE mailbox check datagram failed on slave %i: ",
                slave->ring_position);
+        ec_datagram_print_wc_error(datagram);
         return;
     }
 
@@ -381,8 +382,9 @@
 
     if (datagram->working_counter != 1) {
         fsm->state = ec_fsm_coe_error;
-        EC_ERR("Reception of CoE dictionary response failed - slave %i did"
-               " not respond.\n", slave->ring_position);
+        EC_ERR("Reception of CoE dictionary response failed on slave %i: ",
+                slave->ring_position);
+        ec_datagram_print_wc_error(datagram);
         return;
     }
 
@@ -506,8 +508,9 @@
 
     if (datagram->working_counter != 1) {
         fsm->state = ec_fsm_coe_error;
-        EC_ERR("Reception of CoE SDO description request failed - slave %i did"
-               " not respond.\n", slave->ring_position);
+        EC_ERR("Reception of CoE SDO description"
+                " request failed on slave %i: ", slave->ring_position);
+        ec_datagram_print_wc_error(datagram);
         return;
     }
 
@@ -542,8 +545,9 @@
 
     if (datagram->working_counter != 1) {
         fsm->state = ec_fsm_coe_error;
-        EC_ERR("Reception of CoE mailbox check datagram failed - slave %i did"
-               " not respond.\n", slave->ring_position);
+        EC_ERR("Reception of CoE mailbox check"
+                " datagram failed on slave %i: ", slave->ring_position);
+        ec_datagram_print_wc_error(datagram);
         return;
     }
 
@@ -596,8 +600,9 @@
 
     if (datagram->working_counter != 1) {
         fsm->state = ec_fsm_coe_error;
-        EC_ERR("Reception of CoE SDO description response failed - slave %i"
-               " did not respond.\n", slave->ring_position);
+        EC_ERR("Reception of CoE SDO description"
+                " response failed on slave %i: ", slave->ring_position);
+        ec_datagram_print_wc_error(datagram);
         return;
     }
 
@@ -709,8 +714,9 @@
 
     if (datagram->working_counter != 1) {
         fsm->state = ec_fsm_coe_error;
-        EC_ERR("Reception of CoE SDO entry request failed - slave %i did"
-               " not respond.\n", slave->ring_position);
+        EC_ERR("Reception of CoE SDO entry request failed on slave %i: ",
+                slave->ring_position);
+        ec_datagram_print_wc_error(datagram);
         return;
     }
 
@@ -746,8 +752,9 @@
 
     if (datagram->working_counter != 1) {
         fsm->state = ec_fsm_coe_error;
-        EC_ERR("Reception of CoE mailbox check datagram failed - slave %i did"
-               " not respond.\n", slave->ring_position);
+        EC_ERR("Reception of CoE mailbox check"
+                " datagram failed on slave %i: ", slave->ring_position);
+        ec_datagram_print_wc_error(datagram);
         return;
     }
 
@@ -801,8 +808,9 @@
 
     if (datagram->working_counter != 1) {
         fsm->state = ec_fsm_coe_error;
-        EC_ERR("Reception of CoE SDO description response failed - slave %i"
-               " did not respond.\n", slave->ring_position);
+        EC_ERR("Reception of CoE SDO description"
+                " response failed on slave %i: ", slave->ring_position);
+        ec_datagram_print_wc_error(datagram);
         return;
     }
 
@@ -991,8 +999,9 @@
 
     if (datagram->working_counter != 1) {
         fsm->state = ec_fsm_coe_error;
-        EC_ERR("Reception of CoE download request failed - slave %i did not"
-               " respond.\n", slave->ring_position);
+        EC_ERR("Reception of CoE download request failed on slave %i: ",
+                slave->ring_position);
+        ec_datagram_print_wc_error(datagram);
         return;
     }
 
@@ -1027,8 +1036,9 @@
 
     if (datagram->working_counter != 1) {
         fsm->state = ec_fsm_coe_error;
-        EC_ERR("Reception of CoE mailbox check datagram failed - slave %i did"
-               " not respond.\n", slave->ring_position);
+        EC_ERR("Reception of CoE mailbox check"
+                " datagram failed on slave %i: ", slave->ring_position);
+        ec_datagram_print_wc_error(datagram);
         return;
     }
 
@@ -1080,8 +1090,9 @@
 
     if (datagram->working_counter != 1) {
         fsm->state = ec_fsm_coe_error;
-        EC_ERR("Reception of CoE download response failed - slave %i did not"
-               " respond.\n", slave->ring_position);
+        EC_ERR("Reception of CoE download response failed on slave %i: ",
+                slave->ring_position);
+        ec_datagram_print_wc_error(datagram);
         return;
     }
 
@@ -1200,8 +1211,9 @@
 
     if (datagram->working_counter != 1) {
         fsm->state = ec_fsm_coe_error;
-        EC_ERR("Reception of CoE upload request failed - slave %i did not"
-               " respond.\n", slave->ring_position);
+        EC_ERR("Reception of CoE upload request failed on slave %i: ",
+                slave->ring_position);
+        ec_datagram_print_wc_error(datagram);
         return;
     }
 
@@ -1236,8 +1248,9 @@
 
     if (datagram->working_counter != 1) {
         fsm->state = ec_fsm_coe_error;
-        EC_ERR("Reception of CoE mailbox check datagram failed - slave %i did"
-               " not respond.\n", slave->ring_position);
+        EC_ERR("Reception of CoE mailbox check"
+                " datagram failed on slave %i: ", slave->ring_position);
+        ec_datagram_print_wc_error(datagram);
         return;
     }
 
@@ -1294,8 +1307,9 @@
 
     if (datagram->working_counter != 1) {
         fsm->state = ec_fsm_coe_error;
-        EC_ERR("Reception of CoE upload response failed - slave %i did not"
-               " respond.\n", slave->ring_position);
+        EC_ERR("Reception of CoE upload response failed on slave %i: ",
+                slave->ring_position);
+        ec_datagram_print_wc_error(datagram);
         return;
     }
 
@@ -1439,8 +1453,9 @@
 
     if (datagram->working_counter != 1) {
         fsm->state = ec_fsm_coe_error;
-        EC_ERR("Reception of CoE upload segment request failed - slave %i did"
-               " not respond.\n", slave->ring_position);
+        EC_ERR("Reception of CoE upload segment"
+                " request failed on slave %i: ", slave->ring_position);
+        ec_datagram_print_wc_error(datagram);
         return;
     }
 
@@ -1475,8 +1490,9 @@
 
     if (datagram->working_counter != 1) {
         fsm->state = ec_fsm_coe_error;
-        EC_ERR("Reception of CoE mailbox check datagram failed - slave %i did"
-               " not respond.\n", slave->ring_position);
+        EC_ERR("Reception of CoE mailbox check"
+                " datagram failed on slave %i: ", slave->ring_position);
+        ec_datagram_print_wc_error(datagram);
         return;
     }
 
@@ -1533,8 +1549,9 @@
 
     if (datagram->working_counter != 1) {
         fsm->state = ec_fsm_coe_error;
-        EC_ERR("Reception of CoE upload segment response failed - slave %i"
-               " did not respond.\n", slave->ring_position);
+        EC_ERR("Reception of CoE upload segment"
+                " response failed on slave %i: ", slave->ring_position);
+        ec_datagram_print_wc_error(datagram);
         return;
     }
 
--- a/master/fsm_master.c	Fri Aug 10 15:27:08 2007 +0000
+++ b/master/fsm_master.c	Thu Sep 13 11:08:46 2007 +0000
@@ -41,7 +41,9 @@
 #include "globals.h"
 #include "master.h"
 #include "mailbox.h"
+#ifdef EC_EOE
 #include "ethernet.h"
+#endif
 #include "fsm_master.h"
 
 /*****************************************************************************/
@@ -54,6 +56,7 @@
 void ec_fsm_master_state_validate_product(ec_fsm_master_t *);
 void ec_fsm_master_state_rewrite_addresses(ec_fsm_master_t *);
 void ec_fsm_master_state_configure_slave(ec_fsm_master_t *);
+void ec_fsm_master_state_clear_addresses(ec_fsm_master_t *);
 void ec_fsm_master_state_scan_slaves(ec_fsm_master_t *);
 void ec_fsm_master_state_write_eeprom(ec_fsm_master_t *);
 void ec_fsm_master_state_sdodict(ec_fsm_master_t *);
@@ -238,8 +241,10 @@
             fsm->idle = 0;
             fsm->scan_jiffies = jiffies;
 
+#ifdef EC_EOE
             ec_master_eoe_stop(master);
             ec_master_clear_eoe_handlers(master);
+#endif
             ec_master_destroy_slaves(master);
 
             master->slave_count = datagram->working_counter;
@@ -276,13 +281,13 @@
                 list_add_tail(&slave->list, &master->slaves);
             }
 
-            EC_INFO("Scanning bus.\n");
-
-            // begin scanning of slaves
-            fsm->slave = list_entry(master->slaves.next, ec_slave_t, list);
-            fsm->state = ec_fsm_master_state_scan_slaves;
-            ec_fsm_slave_start_scan(&fsm->fsm_slave, fsm->slave);
-            ec_fsm_slave_exec(&fsm->fsm_slave); // execute immediately
+            if (master->debug_level)
+                EC_DBG("Clearing station addresses...\n");
+
+            ec_datagram_bwr(datagram, 0x0010, 2);
+            EC_WRITE_U16(datagram->data, 0x0000);
+            fsm->retries = EC_FSM_RETRIES;
+            fsm->state = ec_fsm_master_state_clear_addresses;
             return;
         }
     }
@@ -587,18 +592,21 @@
 
     if (datagram->state != EC_DATAGRAM_RECEIVED) {
         EC_ERR("Failed to receive AL state datagram for slave %i"
-                " (datagram state %i)\n", slave->ring_position, datagram->state);
+                " (datagram state %i)\n",
+                slave->ring_position, datagram->state);
         fsm->state = ec_fsm_master_state_error;
         return;
     }
 
     // did the slave not respond to its station address?
-    if (datagram->working_counter != 1) {
+    if (datagram->working_counter == 0) {
         ec_slave_set_online_state(slave, EC_SLAVE_OFFLINE);
         ec_fsm_master_action_next_slave_state(fsm);
         return;
     }
 
+    // FIXME what to to on multiple response?
+
     // slave responded
     ec_slave_set_state(slave, EC_READ_U8(datagram->data)); // set app state first
     ec_slave_set_online_state(slave, EC_SLAVE_ONLINE);
@@ -774,8 +782,9 @@
     }
 
     if (datagram->working_counter != 1) {
-        EC_ERR("Failed to write station address - slave %i did not respond.\n",
+        EC_ERR("Failed to write station address of slave %i: ",
                slave->ring_position);
+        ec_datagram_print_wc_error(datagram);
         fsm->state = ec_fsm_master_state_error;
         return;
     }
@@ -794,6 +803,43 @@
 /*****************************************************************************/
 
 /**
+ * Master state: CLEAR ADDRESSES.
+ */
+
+void ec_fsm_master_state_clear_addresses(
+        ec_fsm_master_t *fsm /**< master state machine */
+        )
+{
+    ec_master_t *master = fsm->master;
+    ec_datagram_t *datagram = fsm->datagram;
+
+    if (datagram->state == EC_DATAGRAM_TIMED_OUT && fsm->retries--)
+        return;
+
+    if (datagram->state != EC_DATAGRAM_RECEIVED) {
+        EC_ERR("Failed to receive address clearing datagram (state %i).\n",
+                datagram->state);
+        fsm->state = ec_fsm_master_state_error;
+        return;
+    }
+
+    if (datagram->working_counter != master->slave_count) {
+        EC_WARN("Failed to clear all station addresses: Cleared %u of %u",
+                datagram->working_counter, master->slave_count);
+    }
+
+    EC_INFO("Scanning bus.\n");
+
+    // begin scanning of slaves
+    fsm->slave = list_entry(master->slaves.next, ec_slave_t, list);
+    fsm->state = ec_fsm_master_state_scan_slaves;
+    ec_fsm_slave_start_scan(&fsm->fsm_slave, fsm->slave);
+    ec_fsm_slave_exec(&fsm->fsm_slave); // execute immediately
+}
+
+/*****************************************************************************/
+
+/**
  * Master state: SCAN SLAVES.
  * Executes the sub-statemachine for the scanning of a slave.
  */
@@ -808,6 +854,7 @@
     if (ec_fsm_slave_exec(&fsm->fsm_slave)) // execute slave state machine
         return;
 
+#ifdef EC_EOE
     if (slave->sii_mailbox_protocols & EC_MBOX_EOE) {
         // create EoE handler for this slave
         ec_eoe_t *eoe;
@@ -824,6 +871,7 @@
             list_add_tail(&eoe->list, &master->eoe_handlers);
         }
     }
+#endif
 
     // another slave to fetch?
     if (slave->list.next != &master->slaves) {
@@ -836,8 +884,10 @@
     EC_INFO("Bus scanning completed in %u ms.\n",
             (u32) (jiffies - fsm->scan_jiffies) * 1000 / HZ);
 
+#ifdef EC_EOE
     // check if EoE processing has to be started
     ec_master_eoe_start(master);
+#endif
 
     master->scan_state = EC_REQUEST_COMPLETE;
     wake_up_interruptible(&master->scan_queue);
--- a/master/fsm_sii.c	Fri Aug 10 15:27:08 2007 +0000
+++ b/master/fsm_sii.c	Thu Sep 13 11:08:46 2007 +0000
@@ -196,8 +196,9 @@
 
     if (datagram->working_counter != 1) {
         fsm->state = ec_fsm_sii_error;
-        EC_ERR("Reception of SII read datagram failed - slave %i did not"
-               " respond.\n", fsm->slave->ring_position);
+        EC_ERR("Reception of SII read datagram failed on slave %i: ",
+                fsm->slave->ring_position);
+        ec_datagram_print_wc_error(datagram);
         return;
     }
 
@@ -242,8 +243,9 @@
 
     if (datagram->working_counter != 1) {
         fsm->state = ec_fsm_sii_error;
-        EC_ERR("Reception of SII check/fetch datagram failed - slave %i did"
-               " not respond\n", fsm->slave->ring_position);
+        EC_ERR("Reception of SII check/fetch datagram failed on slave %i: ",
+                fsm->slave->ring_position);
+        ec_datagram_print_wc_error(datagram);
         return;
     }
 
@@ -338,8 +340,9 @@
 
     if (datagram->working_counter != 1) {
         fsm->state = ec_fsm_sii_error;
-        EC_ERR("Reception of SII write datagram failed - slave %i did not"
-               " respond.\n", fsm->slave->ring_position);
+        EC_ERR("Reception of SII write datagram failed on slave %i: ",
+                fsm->slave->ring_position);
+        ec_datagram_print_wc_error(datagram);
         return;
     }
 
@@ -375,8 +378,9 @@
 
     if (datagram->working_counter != 1) {
         fsm->state = ec_fsm_sii_error;
-        EC_ERR("Reception of SII write check datagram failed - slave %i did"
-               " not respond.\n", fsm->slave->ring_position);
+        EC_ERR("Reception of SII write check datagram failed on slave %i: ",
+                fsm->slave->ring_position);
+        ec_datagram_print_wc_error(datagram);
         return;
     }
 
--- a/master/fsm_slave.c	Fri Aug 10 15:27:08 2007 +0000
+++ b/master/fsm_slave.c	Thu Sep 13 11:08:46 2007 +0000
@@ -226,8 +226,9 @@
     if (datagram->working_counter != 1) {
         fsm->slave->error_flag = 1;
         fsm->state = ec_fsm_slave_state_error;
-        EC_ERR("Failed to write station address - slave %i did not respond.\n",
+        EC_ERR("Failed to write station address on slave %i: ",
                fsm->slave->ring_position);
+        ec_datagram_print_wc_error(datagram);
         return;
     }
 
@@ -243,7 +244,9 @@
    Slave scan state: STATE.
 */
 
-void ec_fsm_slave_scan_state_state(ec_fsm_slave_t *fsm /**< slave state machine */)
+void ec_fsm_slave_scan_state_state(
+        ec_fsm_slave_t *fsm /**< slave state machine */
+        )
 {
     ec_datagram_t *datagram = fsm->datagram;
     ec_slave_t *slave = fsm->slave;
@@ -262,8 +265,9 @@
     if (datagram->working_counter != 1) {
         fsm->slave->error_flag = 1;
         fsm->state = ec_fsm_slave_state_error;
-        EC_ERR("Failed to read AL state - slave %i did not respond.\n",
+        EC_ERR("Failed to read AL state of slave %i: ",
                fsm->slave->ring_position);
+        ec_datagram_print_wc_error(datagram);
         return;
     }
 
@@ -306,8 +310,9 @@
     if (datagram->working_counter != 1) {
         fsm->slave->error_flag = 1;
         fsm->state = ec_fsm_slave_state_error;
-        EC_ERR("Failed to read base data - slave %i did not respond.\n",
+        EC_ERR("Failed to read base data from slave %i: ",
                slave->ring_position);
+        ec_datagram_print_wc_error(datagram);
         return;
     }
 
@@ -352,8 +357,9 @@
     if (datagram->working_counter != 1) {
         fsm->slave->error_flag = 1;
         fsm->state = ec_fsm_slave_state_error;
-        EC_ERR("Failed to read DL status - slave %i did not respond.\n",
+        EC_ERR("Failed to read DL status from slave %i: ",
                slave->ring_position);
+        ec_datagram_print_wc_error(datagram);
         return;
     }
 
@@ -644,8 +650,9 @@
     if (datagram->working_counter != 1) {
         fsm->slave->error_flag = 1;
         fsm->state = ec_fsm_slave_state_error;
-        EC_ERR("Failed to clear FMMUs - slave %i did not respond.\n",
+        EC_ERR("Failed to clear FMMUs of slave %i: ",
                fsm->slave->ring_position);
+        ec_datagram_print_wc_error(datagram);
         return;
     }
 
@@ -726,8 +733,9 @@
     if (datagram->working_counter != 1) {
         slave->error_flag = 1;
         fsm->state = ec_fsm_slave_state_error;
-        EC_ERR("Failed to set sync managers - slave %i did not respond.\n",
+        EC_ERR("Failed to set sync managers of slave %i: ",
                slave->ring_position);
+        ec_datagram_print_wc_error(datagram);
         return;
     }
 
@@ -941,8 +949,9 @@
     if (datagram->working_counter != 1) {
         slave->error_flag = 1;
         fsm->state = ec_fsm_slave_state_error;
-        EC_ERR("Failed to set process data sync managers - slave %i did not"
-               " respond.\n", slave->ring_position);
+        EC_ERR("Failed to set process data sync managers of slave %i: ",
+                slave->ring_position);
+        ec_datagram_print_wc_error(datagram);
         return;
     }
 
@@ -1002,8 +1011,9 @@
     if (datagram->working_counter != 1) {
         slave->error_flag = 1;
         fsm->state = ec_fsm_slave_state_error;
-        EC_ERR("Failed to set FMMUs - slave %i did not respond.\n",
+        EC_ERR("Failed to set FMMUs of slave %i: ",
                slave->ring_position);
+        ec_datagram_print_wc_error(datagram);
         return;
     }
 
--- a/master/globals.h	Fri Aug 10 15:27:08 2007 +0000
+++ b/master/globals.h	Thu Sep 13 11:08:46 2007 +0000
@@ -81,6 +81,9 @@
 /** size of an EtherCAT datagram footer */
 #define EC_DATAGRAM_FOOTER_SIZE 2
 
+/** size of the EtherCAT address field */
+#define EC_ADDR_LEN 4
+
 /** resulting maximum data size of a single datagram in a frame */
 #define EC_MAX_DATA_SIZE (ETH_DATA_LEN - EC_FRAME_HEADER_SIZE \
                           - EC_DATAGRAM_HEADER_SIZE - EC_DATAGRAM_FOOTER_SIZE)
--- a/master/master.c	Fri Aug 10 15:27:08 2007 +0000
+++ b/master/master.c	Thu Sep 13 11:08:46 2007 +0000
@@ -50,7 +50,9 @@
 #include "slave.h"
 #include "device.h"
 #include "datagram.h"
+#ifdef EC_EOE
 #include "ethernet.h"
+#endif
 
 /*****************************************************************************/
 
@@ -58,9 +60,10 @@
 void ec_master_sync_io(ec_master_t *);
 static int ec_master_idle_thread(ec_master_t *);
 static int ec_master_operation_thread(ec_master_t *);
+#ifdef EC_EOE
 void ec_master_eoe_run(unsigned long);
+#endif
 void ec_master_check_sdo(unsigned long);
-int ec_master_measure_bus_time(ec_master_t *);
 ssize_t ec_show_master_attribute(struct kobject *, struct attribute *, char *);
 ssize_t ec_store_master_attribute(struct kobject *, struct attribute *,
                                   const char *, size_t);
@@ -139,15 +142,17 @@
 
     master->stats.timeouts = 0;
     master->stats.corrupted = 0;
-    master->stats.skipped = 0;
     master->stats.unmatched = 0;
     master->stats.output_jiffies = 0;
 
     for (i = 0; i < HZ; i++) {
         master->idle_cycle_times[i] = 0;
+#ifdef EC_EOE
         master->eoe_cycle_times[i] = 0;
+#endif
     }
     master->idle_cycle_time_pos = 0;
+#ifdef EC_EOE
     master->eoe_cycle_time_pos = 0;
 
     init_timer(&master->eoe_timer);
@@ -155,6 +160,7 @@
     master->eoe_timer.data = (unsigned long) master;
     master->eoe_running = 0;
     INIT_LIST_HEAD(&master->eoe_handlers);
+#endif
 
     master->internal_lock = SPIN_LOCK_UNLOCKED;
     master->request_cb = NULL;
@@ -178,6 +184,7 @@
 
     // init state machine datagram
     ec_datagram_init(&master->fsm_datagram);
+    snprintf(master->fsm_datagram.name, EC_DATAGRAM_NAME_SIZE, "master-fsm");
     if (ec_datagram_prealloc(&master->fsm_datagram, EC_MAX_DATA_SIZE)) {
         EC_ERR("Failed to allocate FSM datagram.\n");
         goto out_clear_backup;
@@ -228,7 +235,9 @@
         ec_master_t *master /**< EtherCAT master */
         )
 {
+#ifdef EC_EOE
     ec_master_clear_eoe_handlers(master);
+#endif
     ec_master_destroy_slaves(master);
     ec_master_destroy_domains(master);
     ec_fsm_master_clear(&master->fsm);
@@ -243,6 +252,7 @@
 
 /*****************************************************************************/
 
+#ifdef EC_EOE
 /**
  * Clear and free all EoE handlers.
  */
@@ -259,6 +269,7 @@
         kfree(eoe);
     }
 }
+#endif
 
 /*****************************************************************************/
 
@@ -394,7 +405,9 @@
 {
     master->mode = EC_MASTER_MODE_ORPHANED;
     
+#ifdef EC_EOE
     ec_master_eoe_stop(master);
+#endif
     ec_master_thread_stop(master);
     ec_master_destroy_slaves(master);
 }
@@ -408,7 +421,9 @@
 int ec_master_enter_operation_mode(ec_master_t *master /**< EtherCAT master */)
 {
     ec_slave_t *slave;
+#ifdef EC_EOE
     ec_eoe_t *eoe;
+#endif
 
     down(&master->config_sem);
     master->allow_config = 0; // temporarily disable slave configuration
@@ -442,11 +457,13 @@
     list_for_each_entry(slave, &master->slaves, list) {
         ec_slave_request_state(slave, EC_SLAVE_STATE_PREOP);
     }
+#ifdef EC_EOE
     // ... but set EoE slaves to OP
     list_for_each_entry(eoe, &master->eoe_handlers, list) {
         if (ec_eoe_is_open(eoe))
             ec_slave_request_state(eoe->slave, EC_SLAVE_STATE_OP);
     }
+#endif
 
     if (master->debug_level)
         EC_DBG("Switching to operation mode.\n");
@@ -475,11 +492,15 @@
                                     /**< EtherCAT master */)
 {
     ec_slave_t *slave;
+#ifdef EC_EOE
     ec_eoe_t *eoe;
+#endif
 
     master->mode = EC_MASTER_MODE_IDLE;
 
+#ifdef EC_EOE
     ec_master_eoe_stop(master);
+#endif
     ec_master_thread_stop(master);
     
     master->request_cb = ec_master_request_cb;
@@ -491,17 +512,21 @@
         ec_slave_reset(slave);
         ec_slave_request_state(slave, EC_SLAVE_STATE_PREOP);
     }
+#ifdef EC_EOE
     // ... but leave EoE slaves in OP
     list_for_each_entry(eoe, &master->eoe_handlers, list) {
         if (ec_eoe_is_open(eoe))
             ec_slave_request_state(eoe->slave, EC_SLAVE_STATE_OP);
     }
+#endif
 
     ec_master_destroy_domains(master);
     
     if (ec_master_thread_start(master, ec_master_idle_thread))
         EC_WARN("Failed to restart master thread!\n");
+#ifdef EC_EOE
     ec_master_eoe_start(master);
+#endif
 
     master->allow_scan = 1;
     master->allow_config = 1;
@@ -522,10 +547,9 @@
     // check, if the datagram is already queued
     list_for_each_entry(queued_datagram, &master->datagram_queue, queue) {
         if (queued_datagram == datagram) {
-            master->stats.skipped++;
+            datagram->skip_count++;
             if (master->debug_level)
                 EC_DBG("skipping datagram %x.\n", (unsigned int) datagram);
-            ec_master_output_stats(master);
             datagram->state = EC_DATAGRAM_QUEUED;
             return;
         }
@@ -592,7 +616,7 @@
             // EtherCAT datagram header
             EC_WRITE_U8 (cur_data,     datagram->type);
             EC_WRITE_U8 (cur_data + 1, datagram->index);
-            EC_WRITE_U32(cur_data + 2, datagram->address.logical);
+            memcpy(cur_data + 2, datagram->address, EC_ADDR_LEN);
             EC_WRITE_U16(cur_data + 6, datagram->data_size & 0x7FF);
             EC_WRITE_U16(cur_data + 8, 0x0000);
             follows_word = cur_data + 6;
@@ -772,11 +796,6 @@
                     master->stats.corrupted == 1 ? "" : "s");
             master->stats.corrupted = 0;
         }
-        if (master->stats.skipped) {
-            EC_WARN("%i datagram%s SKIPPED!\n", master->stats.skipped,
-                    master->stats.skipped == 1 ? "" : "s");
-            master->stats.skipped = 0;
-        }
         if (master->stats.unmatched) {
             EC_WARN("%i datagram%s UNMATCHED!\n", master->stats.unmatched,
                     master->stats.unmatched == 1 ? "" : "s");
@@ -800,6 +819,7 @@
 
     while (!signal_pending(current)) {
         cycles_start = get_cycles();
+        ec_datagram_output_stats(&master->fsm_datagram);
 
         if (ec_fsm_master_running(&master->fsm)) { // datagram on the way
             // receive
@@ -856,6 +876,7 @@
     allow_signal(SIGTERM);
 
     while (!signal_pending(current)) {
+        ec_datagram_output_stats(&master->fsm_datagram);
         if (master->injection_seq_rt != master->injection_seq_fsm ||
                 master->fsm_datagram.state == EC_DATAGRAM_SENT ||
                 master->fsm_datagram.state == EC_DATAGRAM_QUEUED)
@@ -941,7 +962,9 @@
                        )
 {
     off_t off = 0;
+#ifdef EC_EOE
     ec_eoe_t *eoe;
+#endif
     uint32_t cur, sum, min, max, pos, i;
 
     off += sprintf(buffer + off, "\nMode: ");
@@ -959,6 +982,10 @@
 
     off += sprintf(buffer + off, "\nSlaves: %i\n",
                    master->slave_count);
+    off += sprintf(buffer + off, "Status: %s\n",
+                   master->fsm.tainted ? "TAINTED" : "sane");
+    off += sprintf(buffer + off, "PDO slaves: %s\n",
+                   master->pdo_slaves_offline ? "INCOMPLETE" : "online");
 
     off += sprintf(buffer + off, "\nDevices:\n");
     
@@ -986,6 +1013,7 @@
     off += sprintf(buffer + off, "  Idle cycle: %u / %u.%u / %u\n",
                    min, sum / HZ, (sum * 100 / HZ) % 100, max);
 
+#ifdef EC_EOE
     sum = 0;
     min = 0xFFFFFFFF;
     max = 0;
@@ -1006,6 +1034,7 @@
                        eoe->dev->name, eoe->rx_rate, eoe->tx_rate,
                        ((eoe->rx_rate + eoe->tx_rate) / 8 + 512) / 1024);
     }
+#endif
 
     off += sprintf(buffer + off, "\n");
 
@@ -1075,6 +1104,7 @@
 
 /*****************************************************************************/
 
+#ifdef EC_EOE
 /**
    Starts Ethernet-over-EtherCAT processing on demand.
 */
@@ -1141,11 +1171,11 @@
     if (none_open)
         goto queue_timer;
 
+    // receive datagrams
     if (master->request_cb(master->cb_data)) goto queue_timer;
-
-    // receive datagrams
     cycles_start = get_cycles();
     ecrt_master_receive(master);
+    master->release_cb(master->cb_data);
 
     // actual EoE processing
     list_for_each_entry(eoe, &master->eoe_handlers, list) {
@@ -1153,11 +1183,16 @@
     }
 
     // send datagrams
+    if (master->request_cb(master->cb_data)) {
+        goto queue_timer;
+    }
+    list_for_each_entry(eoe, &master->eoe_handlers, list) {
+        ec_eoe_queue(eoe);
+    }
     ecrt_master_send(master);
+    master->release_cb(master->cb_data);
     cycles_end = get_cycles();
 
-    master->release_cb(master->cb_data);
-
     master->eoe_cycle_times[master->eoe_cycle_time_pos]
         = (u32) (cycles_end - cycles_start) * 1000 / cpu_khz;
     master->eoe_cycle_time_pos++;
@@ -1166,72 +1201,10 @@
  queue_timer:
     restart_jiffies = HZ / EC_EOE_FREQUENCY;
     if (!restart_jiffies) restart_jiffies = 1;
-    master->eoe_timer.expires += restart_jiffies;
+    master->eoe_timer.expires = jiffies + restart_jiffies;
     add_timer(&master->eoe_timer);
 }
-
-/*****************************************************************************/
-
-/**
-   Measures the time, a frame is on the bus.
-   \return 0 in case of success, else < 0
-*/
-
-int ec_master_measure_bus_time(ec_master_t *master)
-{
-    ec_datagram_t datagram;
-    uint32_t cur, sum, min, max, i;
-
-    ec_datagram_init(&datagram);
-
-    if (ec_datagram_brd(&datagram, 0x0130, 2)) {
-        EC_ERR("Failed to allocate datagram for bus time measuring.\n");
-        ec_datagram_clear(&datagram);
-        return -1;
-    }
-
-    ecrt_master_receive(master);
-
-    sum = 0;
-    min = 0xFFFFFFFF;
-    max = 0;
-
-    for (i = 0; i < 100; i++) {
-        ec_master_queue_datagram(master, &datagram);
-        ecrt_master_send(master);
-
-        while (1) {
-            ecrt_master_receive(master);
-
-            if (datagram.state == EC_DATAGRAM_RECEIVED) {
-                break;
-            }
-            else if (datagram.state == EC_DATAGRAM_ERROR) {
-                EC_WARN("Failed to measure bus time.\n");
-                goto error;
-            }
-            else if (datagram.state == EC_DATAGRAM_TIMED_OUT) {
-                EC_WARN("Timeout while measuring bus time.\n");
-                goto error;
-            }
-        }
-
-        cur = (unsigned int) (datagram.cycles_received
-                              - datagram.cycles_sent) * 1000 / cpu_khz;
-        sum += cur;
-        if (cur > max) max = cur;
-        if (cur < min) min = cur;
-    }
-
-    EC_DBG("Bus time is (min/avg/max) %u / %u.%u / %u us.\n",
-           min, sum / 100, sum % 100, max);
-    ec_datagram_clear(&datagram);
-    return 0;
-
-  error:
-    ec_datagram_clear(&datagram);
-    return -1;
-}
+#endif
 
 /*****************************************************************************/
 
@@ -1431,7 +1404,9 @@
     }
     
     // restart EoE process and master thread with new locking
+#ifdef EC_EOE
     ec_master_eoe_stop(master);
+#endif
     ec_master_thread_stop(master);
 
     ec_master_prepare(master); // prepare asynchronous IO
@@ -1449,7 +1424,9 @@
         EC_ERR("Failed to start master thread!\n");
         return -1;
     }
+#ifdef EC_EOE
     ec_master_eoe_start(master);
+#endif
     return 0;
 }
 
--- a/master/master.h	Fri Aug 10 15:27:08 2007 +0000
+++ b/master/master.h	Thu Sep 13 11:08:46 2007 +0000
@@ -75,8 +75,6 @@
 {
     unsigned int timeouts; /**< datagram timeouts */
     unsigned int corrupted; /**< corrupted frames */
-    unsigned int skipped; /**< skipped datagrams (the ones that were
-                             requeued when not yet received) */
     unsigned int unmatched; /**< unmatched datagrams (received, but not
                                queued any longer) */
     unsigned long output_jiffies; /**< time of last output */
@@ -145,11 +143,13 @@
     uint32_t idle_cycle_times[HZ]; /**< Idle cycle times ring */
     unsigned int idle_cycle_time_pos; /**< time ring buffer position */
 
+#ifdef EC_EOE
     struct timer_list eoe_timer; /**< EoE timer object */
     unsigned int eoe_running; /**< non-zero, if EoE processing is active. */
     struct list_head eoe_handlers; /**< Ethernet-over-EtherCAT handlers */
     uint32_t eoe_cycle_times[HZ]; /**< EoE cycle times ring */
     unsigned int eoe_cycle_time_pos; /**< time ring buffer position */
+#endif
 
     spinlock_t internal_lock; /**< spinlock used in idle mode */
     int (*request_cb)(void *); /**< lock request callback */
@@ -185,9 +185,11 @@
 int ec_master_enter_operation_mode(ec_master_t *);
 void ec_master_leave_operation_mode(ec_master_t *);
 
+#ifdef EC_EOE
 // EoE
 void ec_master_eoe_start(ec_master_t *);
 void ec_master_eoe_stop(ec_master_t *);
+#endif
 
 // datagram IO
 void ec_master_receive_datagrams(ec_master_t *, const uint8_t *, size_t);
@@ -195,7 +197,9 @@
 
 // misc.
 void ec_master_output_stats(ec_master_t *);
+#ifdef EC_EOE
 void ec_master_clear_eoe_handlers(ec_master_t *);
+#endif
 void ec_master_destroy_slaves(ec_master_t *);
 
 /*****************************************************************************/
--- a/script/Makefile.am	Fri Aug 10 15:27:08 2007 +0000
+++ b/script/Makefile.am	Thu Sep 13 11:08:46 2007 +0000
@@ -39,6 +39,6 @@
 
 bin_SCRIPTS = lsec
 
-EXTRA_DIST = lsec
+EXTRA_DIST = lsec ifup-eoe.sh
 
 #------------------------------------------------------------------------------
--- /dev/null	Thu Jan 01 00:00:00 1970 +0000
+++ b/script/ifup-eoe.sh	Thu Sep 13 11:08:46 2007 +0000
@@ -0,0 +1,64 @@
+#!/bin/bash
+
+#------------------------------------------------------------------------------
+#
+#  $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.
+#
+#------------------------------------------------------------------------------
+
+# this ifup.d script adds special network interfaces to a network bridge
+
+CFGNAME=${1}
+IFNAME=${2}
+
+# customize here
+BRNAME="eoebr0"
+INTERFACES=""
+BRCTL="/sbin/brctl"
+LOGGER="logger -t ifup-eoe"
+
+# if the current interface in the list of interfaces to bridge?
+if ! echo ${INTERFACES} | grep -qw ${IFNAME}; then
+    exit 0;
+fi
+
+# does the EoE bridge already exist?
+if ! ${BRCTL} show | grep -q "^${BRNAME}"; then
+	${LOGGER} Creating ${BRNAME}
+	${BRCTL} addbr ${BRNAME} # create it
+fi
+
+${LOGGER} Adding ${IFNAME} to ${BRNAME}
+ip link set ${IFNAME} down
+ip addr flush dev ${IFNAME}
+${BRCTL} addif ${BRNAME} ${IFNAME}
+ip link set ${IFNAME} up
+
+#------------------------------------------------------------------------------
--- a/script/init.d/ethercat	Fri Aug 10 15:27:08 2007 +0000
+++ b/script/init.d/ethercat	Thu Sep 13 11:08:46 2007 +0000
@@ -102,6 +102,7 @@
 {
     if [ -r /etc/rc.status ]; then
         rc_failed
+        rc_status -v
         rc_exit
     else
         echo " failed"
@@ -111,6 +112,20 @@
 
 #------------------------------------------------------------------------------
 
+function exit_dead()
+{
+    if [ -r /etc/rc.status ]; then
+        rc_failed
+        rc_status -v
+        rc_exit
+    else
+        echo " dead"
+        exit 1
+    fi
+}
+
+#------------------------------------------------------------------------------
+
 function parse_mac_address()
 {
     if [ -z "${1}" ]; then
@@ -228,7 +243,7 @@
     if [ ${MASTERS_RUNNING} -eq 0 -a ${MASTERS_IDLE} -eq 0 ]; then
         exit_running
     else
-        exit_fail
+        exit_dead
     fi
     ;;