master/fsm_foe.c
changeset 2589 2b9c78543663
parent 2259 5538f60ea32c
child 2591 23b360e4a530
--- a/master/fsm_foe.c	Thu Sep 06 14:21:02 2012 +0200
+++ b/master/fsm_foe.c	Mon Nov 03 15:20:05 2014 +0100
@@ -3,6 +3,7 @@
  *  $Id$
  *
  *  Copyright (C) 2008  Olav Zarges, imc Messsysteme GmbH
+ *                2013  Florian Pose <fp@igh-essen.com>
  *
  *  This file is part of the IgH EtherCAT Master.
  *
@@ -27,10 +28,9 @@
  *
  *****************************************************************************/
 
-/**
-   \file
-   EtherCAT FoE state machines.
-*/
+/** \file
+ * EtherCAT FoE state machines.
+ */
 
 /*****************************************************************************/
 
@@ -74,44 +74,42 @@
 
 /*****************************************************************************/
 
-int ec_foe_prepare_data_send(ec_fsm_foe_t *);
-int ec_foe_prepare_wrq_send(ec_fsm_foe_t *);
-int ec_foe_prepare_rrq_send(ec_fsm_foe_t *);
-int ec_foe_prepare_send_ack(ec_fsm_foe_t *);
+int ec_foe_prepare_data_send(ec_fsm_foe_t *, ec_datagram_t *);
+int ec_foe_prepare_wrq_send(ec_fsm_foe_t *, ec_datagram_t *);
+int ec_foe_prepare_rrq_send(ec_fsm_foe_t *, ec_datagram_t *);
+int ec_foe_prepare_send_ack(ec_fsm_foe_t *, ec_datagram_t *);
 
 void ec_foe_set_tx_error(ec_fsm_foe_t *, uint32_t);
 void ec_foe_set_rx_error(ec_fsm_foe_t *, uint32_t);
 
-void ec_fsm_foe_write(ec_fsm_foe_t *);
-void ec_fsm_foe_read(ec_fsm_foe_t *);
-void ec_fsm_foe_end(ec_fsm_foe_t *);
-void ec_fsm_foe_error(ec_fsm_foe_t *);
-
-void ec_fsm_foe_state_wrq_sent(ec_fsm_foe_t *);
-void ec_fsm_foe_state_rrq_sent(ec_fsm_foe_t *);
-
-void ec_fsm_foe_state_ack_check(ec_fsm_foe_t *);
-void ec_fsm_foe_state_ack_read(ec_fsm_foe_t *);
-
-void ec_fsm_foe_state_data_sent(ec_fsm_foe_t *);
-
-void ec_fsm_foe_state_data_check(ec_fsm_foe_t *);
-void ec_fsm_foe_state_data_read(ec_fsm_foe_t *);
-void ec_fsm_foe_state_sent_ack(ec_fsm_foe_t *);
-
-void ec_fsm_foe_write_start(ec_fsm_foe_t *);
-void ec_fsm_foe_read_start(ec_fsm_foe_t *);
+void ec_fsm_foe_end(ec_fsm_foe_t *, ec_datagram_t *);
+void ec_fsm_foe_error(ec_fsm_foe_t *, ec_datagram_t *);
+
+void ec_fsm_foe_state_wrq_sent(ec_fsm_foe_t *, ec_datagram_t *);
+void ec_fsm_foe_state_rrq_sent(ec_fsm_foe_t *, ec_datagram_t *);
+
+void ec_fsm_foe_state_ack_check(ec_fsm_foe_t *, ec_datagram_t *);
+void ec_fsm_foe_state_ack_read(ec_fsm_foe_t *, ec_datagram_t *);
+
+void ec_fsm_foe_state_data_sent(ec_fsm_foe_t *, ec_datagram_t *);
+
+void ec_fsm_foe_state_data_check(ec_fsm_foe_t *, ec_datagram_t *);
+void ec_fsm_foe_state_data_read(ec_fsm_foe_t *, ec_datagram_t *);
+void ec_fsm_foe_state_sent_ack(ec_fsm_foe_t *, ec_datagram_t *);
+
+void ec_fsm_foe_write_start(ec_fsm_foe_t *, ec_datagram_t *);
+void ec_fsm_foe_read_start(ec_fsm_foe_t *, ec_datagram_t *);
 
 /*****************************************************************************/
 
 /** Constructor.
  */
-void ec_fsm_foe_init(ec_fsm_foe_t *fsm, /**< finite state machine */
-                     ec_mailbox_t *mbox /**< mailbox */
-                     )
+void ec_fsm_foe_init(
+        ec_fsm_foe_t *fsm /**< finite state machine */
+        )
 {
     fsm->state = NULL;
-    fsm->mbox  = mbox;
+    fsm->datagram = NULL;
 }
 
 /*****************************************************************************/
@@ -125,13 +123,36 @@
 /*****************************************************************************/
 
 /** Executes the current state of the state machine.
- * \return false, if state machine has terminated
- */
-int ec_fsm_foe_exec(ec_fsm_foe_t *fsm /**< finite state machine */)
-{
-    fsm->state(fsm);
-
-    return fsm->state != ec_fsm_foe_end && fsm->state != ec_fsm_foe_error;
+ *
+ * \return 1, if the datagram was used, else 0.
+ */
+int ec_fsm_foe_exec(
+        ec_fsm_foe_t *fsm, /**< finite state machine */
+        ec_datagram_t *datagram /**< Datagram to use. */
+        )
+{
+    int datagram_used = 0;
+
+    if (fsm->datagram &&
+            (fsm->datagram->state == EC_DATAGRAM_INIT ||
+             fsm->datagram->state == EC_DATAGRAM_QUEUED ||
+             fsm->datagram->state == EC_DATAGRAM_SENT)) {
+        // datagram not received yet
+        return datagram_used;
+    }
+
+    fsm->state(fsm, datagram);
+
+    datagram_used =
+        fsm->state != ec_fsm_foe_end && fsm->state != ec_fsm_foe_error;
+
+    if (datagram_used) {
+        fsm->datagram = datagram;
+    } else {
+        fsm->datagram = NULL;
+    }
+
+    return datagram_used;
 }
 
 /*****************************************************************************/
@@ -139,7 +160,7 @@
 /** Returns, if the state machine terminated with success.
  * \return non-zero if successful.
  */
-int ec_fsm_foe_success(ec_fsm_foe_t *fsm /**< Finite state machine */)
+int ec_fsm_foe_success(const ec_fsm_foe_t *fsm /**< Finite state machine */)
 {
     return fsm->state == ec_fsm_foe_end;
 }
@@ -156,11 +177,25 @@
 {
     fsm->slave = slave;
     fsm->request = request;
+
     if (request->dir == EC_DIR_OUTPUT) {
-        fsm->state = ec_fsm_foe_write;
+        fsm->tx_buffer = fsm->request->buffer;
+        fsm->tx_buffer_size = fsm->request->data_size;
+        fsm->tx_buffer_offset = 0;
+
+        fsm->tx_filename = fsm->request->file_name;
+        fsm->tx_filename_len = strlen(fsm->tx_filename);
+
+        fsm->state = ec_fsm_foe_write_start;
     }
     else {
-        fsm->state = ec_fsm_foe_read;
+        fsm->rx_buffer = fsm->request->buffer;
+        fsm->rx_buffer_size = fsm->request->buffer_size;
+
+        fsm->rx_filename = fsm->request->file_name;
+        fsm->rx_filename_len = strlen(fsm->rx_filename);
+
+        fsm->state = ec_fsm_foe_read_start;
     }
 }
 
@@ -168,10 +203,13 @@
 
 /** State: ERROR.
  */
-void ec_fsm_foe_error(ec_fsm_foe_t *fsm /**< finite state machine */)
-{
-#ifdef DEBUG_FOE
-    printk("ec_fsm_foe_error()\n");
+void ec_fsm_foe_error(
+        ec_fsm_foe_t *fsm, /**< finite state machine */
+        ec_datagram_t *datagram /**< Datagram to use. */
+        )
+{
+#ifdef DEBUG_FOE
+    EC_SLAVE_DBG(fsm->slave, 0, "%s()\n", __func__);
 #endif
 }
 
@@ -179,18 +217,26 @@
 
 /** State: END.
  */
-void ec_fsm_foe_end(ec_fsm_foe_t *fsm /**< finite state machine */)
-{
-#ifdef DEBUG_FOE
-    printk("ec_fsm_foe_end\n");
+void ec_fsm_foe_end(
+        ec_fsm_foe_t *fsm, /**< finite state machine */
+        ec_datagram_t *datagram /**< Datagram to use. */
+        )
+{
+#ifdef DEBUG_FOE
+    EC_SLAVE_DBG(fsm->slave, 0, "%s()\n", __func__);
 #endif
 }
 
 /*****************************************************************************/
 
 /** Sends a file or the next fragment.
- */
-int ec_foe_prepare_data_send(ec_fsm_foe_t *fsm)
+ *
+ * \return Zero on success, otherwise a negative error code.
+ */
+int ec_foe_prepare_data_send(
+        ec_fsm_foe_t *fsm, /**< Finite state machine. */
+        ec_datagram_t *datagram /**< Datagram to use. */
+        )
 {
     size_t remaining_size, current_size;
     uint8_t *data;
@@ -207,13 +253,14 @@
     }
 
     data = ec_slave_mbox_prepare_send(fsm->slave,
-            fsm->mbox, EC_MBOX_TYPE_FILEACCESS,
+            datagram, EC_MBOX_TYPE_FILEACCESS,
             current_size + EC_FOE_HEADER_SIZE);
-    if (IS_ERR(data))
+    if (IS_ERR(data)) {
         return -1;
-
-    EC_WRITE_U8 ( data, EC_FOE_OPCODE_DATA );    // OpCode = DataBlock req.
-    EC_WRITE_U32( data + 2, fsm->tx_packet_no ); // PacketNo, Password
+    }
+
+    EC_WRITE_U16(data, EC_FOE_OPCODE_DATA);    // OpCode = DataBlock req.
+    EC_WRITE_U32(data + 2, fsm->tx_packet_no); // PacketNo, Password
 
     memcpy(data + EC_FOE_HEADER_SIZE,
             fsm->tx_buffer + fsm->tx_buffer_offset, current_size);
@@ -225,8 +272,13 @@
 /*****************************************************************************/
 
 /** Prepare a write request (WRQ) with filename
- */
-int ec_foe_prepare_wrq_send(ec_fsm_foe_t *fsm)
+ *
+ * \return Zero on success, otherwise a negative error code.
+ */
+int ec_foe_prepare_wrq_send(
+        ec_fsm_foe_t *fsm, /**< Finite state machine. */
+        ec_datagram_t *datagram /**< Datagram to use. */
+        )
 {
     size_t current_size;
     uint8_t *data;
@@ -238,10 +290,11 @@
 
     current_size = fsm->tx_filename_len;
 
-    data = ec_slave_mbox_prepare_send(fsm->slave, fsm->mbox,
+    data = ec_slave_mbox_prepare_send(fsm->slave, datagram,
             EC_MBOX_TYPE_FILEACCESS, current_size + EC_FOE_HEADER_SIZE);
-    if (IS_ERR(data))
+    if (IS_ERR(data)) {
         return -1;
+    }
 
     EC_WRITE_U16( data, EC_FOE_OPCODE_WRQ); // fsm write request
     EC_WRITE_U32( data + 2, fsm->tx_packet_no );
@@ -253,27 +306,12 @@
 
 /*****************************************************************************/
 
-/** Start a write operation.
- */
-void ec_fsm_foe_write(
-        ec_fsm_foe_t *fsm /**< FoE statemachine. */
-        )
-{
-    fsm->tx_buffer = fsm->request->buffer;
-    fsm->tx_buffer_size = fsm->request->data_size;
-    fsm->tx_buffer_offset = 0;
-
-    fsm->tx_filename = fsm->request->file_name;
-    fsm->tx_filename_len = strlen(fsm->tx_filename);
-
-    fsm->state = ec_fsm_foe_write_start;
-}
-
-/*****************************************************************************/
-
 /** Initializes the FoE write state machine.
  */
-void ec_fsm_foe_write_start(ec_fsm_foe_t *fsm /**< finite state machine */)
+void ec_fsm_foe_write_start(
+        ec_fsm_foe_t *fsm, /**< finite state machine */
+        ec_datagram_t *datagram /**< Datagram to use. */
+        )
 {
     ec_slave_t *slave = fsm->slave;
 
@@ -283,7 +321,7 @@
     fsm->tx_last_packet = 0;
 
 #ifdef DEBUG_FOE
-    printk("ec_fsm_foe_write_start()\n");
+    EC_SLAVE_DBG(fsm->slave, 0, "%s()\n", __func__);
 #endif
 
     if (!(slave->sii.mailbox_protocols & EC_MBOX_FOE)) {
@@ -292,7 +330,7 @@
         return;
     }
 
-    if (ec_foe_prepare_wrq_send(fsm)) {
+    if (ec_foe_prepare_wrq_send(fsm, datagram)) {
         ec_foe_set_tx_error(fsm, FOE_PROT_ERROR);
         return;
     }
@@ -305,49 +343,48 @@
 /** Check for acknowledge.
  */
 void ec_fsm_foe_state_ack_check(
-        ec_fsm_foe_t *fsm /**< FoE statemachine. */
-        )
-{
-    ec_mailbox_t *mbox = fsm->mbox;
-    ec_datagram_t *datagram = mbox->datagram;
+        ec_fsm_foe_t *fsm, /**< FoE statemachine. */
+        ec_datagram_t *datagram /**< Datagram to use. */
+        )
+{
     ec_slave_t *slave = fsm->slave;
 
 #ifdef DEBUG_FOE
-    printk("ec_fsm_foe_ack_check()\n");
-#endif
-
-    if (!ec_mbox_is_datagram_state(mbox, EC_DATAGRAM_RECEIVED)) {
+    EC_SLAVE_DBG(fsm->slave, 0, "%s()\n", __func__);
+#endif
+
+    if (fsm->datagram->state != EC_DATAGRAM_RECEIVED) {
         ec_foe_set_rx_error(fsm, FOE_RECEIVE_ERROR);
         EC_SLAVE_ERR(slave, "Failed to receive FoE mailbox check datagram: ");
-        ec_datagram_print_state(datagram);
-        return;
-    }
-
-    if (!ec_mbox_is_datagram_wc(mbox, 1)) {
-        // slave did not put anything in the mailbox yet
+        ec_datagram_print_state(fsm->datagram);
+        return;
+    }
+
+    if (fsm->datagram->working_counter != 1) {
         ec_foe_set_rx_error(fsm, FOE_WC_ERROR);
         EC_SLAVE_ERR(slave, "Reception of FoE mailbox check datagram"
                 " failed: ");
-        ec_datagram_print_wc_error(datagram);
-        return;
-    }
-
-    if (!ec_slave_mbox_check(mbox)) {
-        unsigned long diff_ms =
-            (datagram->jiffies_received - fsm->jiffies_start) * 1000 / HZ;
+        ec_datagram_print_wc_error(fsm->datagram);
+        return;
+    }
+
+    if (!ec_slave_mbox_check(fsm->datagram)) {
+        // slave did not put anything in the mailbox yet
+        unsigned long diff_ms = (fsm->datagram->jiffies_received -
+                fsm->jiffies_start) * 1000 / HZ;
         if (diff_ms >= EC_FSM_FOE_TIMEOUT) {
             ec_foe_set_tx_error(fsm, FOE_TIMEOUT_ERROR);
             EC_SLAVE_ERR(slave, "Timeout while waiting for ack response.\n");
             return;
         }
 
-        ec_slave_mbox_prepare_check(slave, mbox); // can not fail.
+        ec_slave_mbox_prepare_check(slave, datagram); // can not fail.
         fsm->retries = EC_FSM_RETRIES;
         return;
     }
 
     // Fetch response
-    ec_slave_mbox_prepare_fetch(slave, mbox); // can not fail.
+    ec_slave_mbox_prepare_fetch(slave, datagram); // can not fail.
 
     fsm->retries = EC_FSM_RETRIES;
     fsm->state = ec_fsm_foe_state_ack_read;
@@ -358,36 +395,35 @@
 /** Acknowledge a read operation.
  */
 void ec_fsm_foe_state_ack_read(
-        ec_fsm_foe_t *fsm /**< FoE statemachine. */
-        )
-{
-    ec_mailbox_t *mbox = fsm->mbox;
-    ec_datagram_t *datagram = mbox->datagram;
+        ec_fsm_foe_t *fsm, /**< FoE statemachine. */
+        ec_datagram_t *datagram /**< Datagram to use. */
+        )
+{
     ec_slave_t *slave = fsm->slave;
     uint8_t *data, mbox_prot;
     uint8_t opCode;
     size_t rec_size;
 
 #ifdef DEBUG_FOE
-    printk("ec_fsm_foe_ack_read()\n");
-#endif
-
-    if (!ec_mbox_is_datagram_state(mbox, EC_DATAGRAM_RECEIVED)) {
+    EC_SLAVE_DBG(fsm->slave, 0, "%s()\n", __func__);
+#endif
+
+    if (fsm->datagram->state != EC_DATAGRAM_RECEIVED) {
         ec_foe_set_rx_error(fsm, FOE_RECEIVE_ERROR);
         EC_SLAVE_ERR(slave, "Failed to receive FoE ack response datagram: ");
-        ec_datagram_print_state(datagram);
-        return;
-    }
-
-    if (!ec_mbox_is_datagram_wc(mbox, 1)) {
+        ec_datagram_print_state(fsm->datagram);
+        return;
+    }
+
+    if (fsm->datagram->working_counter != 1) {
         ec_foe_set_rx_error(fsm, FOE_WC_ERROR);
         EC_SLAVE_ERR(slave, "Reception of FoE ack response failed: ");
-        ec_datagram_print_wc_error(datagram);
-        return;
-    }
-
-    if (!(data = ec_slave_mbox_fetch(fsm->slave, fsm->mbox,
-                    &mbox_prot, &rec_size))) {
+        ec_datagram_print_wc_error(fsm->datagram);
+        return;
+    }
+
+    data = ec_slave_mbox_fetch(slave, fsm->datagram, &mbox_prot, &rec_size);
+    if (IS_ERR(data)) {
         ec_foe_set_tx_error(fsm, FOE_PROT_ERROR);
         return;
     }
@@ -403,7 +439,7 @@
 
     if (opCode == EC_FOE_OPCODE_BUSY) {
         // slave not ready
-        if (ec_foe_prepare_data_send(fsm)) {
+        if (ec_foe_prepare_data_send(fsm, datagram)) {
             ec_foe_set_tx_error(fsm, FOE_PROT_ERROR);
             EC_SLAVE_ERR(slave, "Slave is busy.\n");
             return;
@@ -421,7 +457,7 @@
             return;
         }
 
-        if (ec_foe_prepare_data_send(fsm)) {
+        if (ec_foe_prepare_data_send(fsm, datagram)) {
             ec_foe_set_tx_error(fsm, FOE_PROT_ERROR);
             return;
         }
@@ -439,35 +475,34 @@
  * fragment, if necessary.
  */
 void ec_fsm_foe_state_wrq_sent(
-        ec_fsm_foe_t *fsm /**< FoE statemachine. */
-        )
-{
-    ec_mailbox_t *mbox = fsm->mbox;
-    ec_datagram_t *datagram = mbox->datagram;
+        ec_fsm_foe_t *fsm, /**< FoE statemachine. */
+        ec_datagram_t *datagram /**< Datagram to use. */
+        )
+{
     ec_slave_t *slave = fsm->slave;
 
 #ifdef DEBUG_FOE
-    printk("ec_foe_state_sent_wrq()\n");
-#endif
-
-    if (!ec_mbox_is_datagram_state(mbox, EC_DATAGRAM_RECEIVED)) {
+    EC_SLAVE_DBG(fsm->slave, 0, "%s()\n", __func__);
+#endif
+
+    if (fsm->datagram->state != EC_DATAGRAM_RECEIVED) {
         ec_foe_set_rx_error(fsm, FOE_RECEIVE_ERROR);
         EC_SLAVE_ERR(slave, "Failed to send FoE WRQ: ");
-        ec_datagram_print_state(datagram);
-        return;
-    }
-
-    if (!ec_mbox_is_datagram_wc(mbox, 1)) {
+        ec_datagram_print_state(fsm->datagram);
+        return;
+    }
+
+    if (fsm->datagram->working_counter != 1) {
         // slave did not put anything in the mailbox yet
         ec_foe_set_rx_error(fsm, FOE_WC_ERROR);
         EC_SLAVE_ERR(slave, "Reception of FoE WRQ failed: ");
-        ec_datagram_print_wc_error(datagram);
-        return;
-    }
-
-    fsm->jiffies_start = datagram->jiffies_sent;
-
-    ec_slave_mbox_prepare_check(fsm->slave, fsm->mbox); // can not fail.
+        ec_datagram_print_wc_error(fsm->datagram);
+        return;
+    }
+
+    fsm->jiffies_start = fsm->datagram->jiffies_sent;
+
+    ec_slave_mbox_prepare_check(slave, datagram); // can not fail.
 
     fsm->retries = EC_FSM_RETRIES;
     fsm->state = ec_fsm_foe_state_ack_check;
@@ -481,32 +516,31 @@
  * fragment, if necessary.
  */
 void ec_fsm_foe_state_data_sent(
-        ec_fsm_foe_t *fsm /**< Foe statemachine. */
-        )
-{
-    ec_mailbox_t *mbox = fsm->mbox;
-    ec_datagram_t *datagram = mbox->datagram;
+        ec_fsm_foe_t *fsm, /**< Foe statemachine. */
+        ec_datagram_t *datagram /**< Datagram to use. */
+        )
+{
     ec_slave_t *slave = fsm->slave;
 
 #ifdef DEBUG_FOE
-    printk("ec_fsm_foe_state_data_sent()\n");
-#endif
-
-    if (!ec_mbox_is_datagram_state(mbox, EC_DATAGRAM_RECEIVED)) {
+    EC_SLAVE_DBG(fsm->slave, 0, "%s()\n", __func__);
+#endif
+
+    if (fsm->datagram->state != EC_DATAGRAM_RECEIVED) {
         ec_foe_set_tx_error(fsm, FOE_RECEIVE_ERROR);
         EC_SLAVE_ERR(slave, "Failed to receive FoE ack response datagram: ");
-        ec_datagram_print_state(datagram);
-        return;
-    }
-
-    if (!ec_mbox_is_datagram_wc(mbox, 1)) {
+        ec_datagram_print_state(fsm->datagram);
+        return;
+    }
+
+    if (fsm->datagram->working_counter != 1) {
         ec_foe_set_tx_error(fsm, FOE_WC_ERROR);
         EC_SLAVE_ERR(slave, "Reception of FoE data send failed: ");
-        ec_datagram_print_wc_error(datagram);
-        return;
-    }
-
-    ec_slave_mbox_prepare_check(slave, mbox);
+        ec_datagram_print_wc_error(fsm->datagram);
+        return;
+    }
+
+    ec_slave_mbox_prepare_check(slave, datagram);
     fsm->jiffies_start = jiffies;
     fsm->retries = EC_FSM_RETRIES;
     fsm->state = ec_fsm_foe_state_ack_check;
@@ -515,18 +549,24 @@
 /*****************************************************************************/
 
 /** Prepare a read request (RRQ) with filename
- */
-int ec_foe_prepare_rrq_send(ec_fsm_foe_t *fsm)
+ *
+ * \return Zero on success, otherwise a negative error code.
+ */
+int ec_foe_prepare_rrq_send(
+        ec_fsm_foe_t *fsm, /**< Finite state machine. */
+        ec_datagram_t *datagram /**< Datagram to use. */
+        )
 {
     size_t current_size;
     uint8_t *data;
 
     current_size = fsm->rx_filename_len;
 
-    data = ec_slave_mbox_prepare_send(fsm->slave, fsm->mbox,
+    data = ec_slave_mbox_prepare_send(fsm->slave, datagram,
             EC_MBOX_TYPE_FILEACCESS, current_size + EC_FOE_HEADER_SIZE);
-    if (IS_ERR(data))
+    if (IS_ERR(data)) {
         return -1;
+    }
 
     EC_WRITE_U16(data, EC_FOE_OPCODE_RRQ); // fsm read request
     EC_WRITE_U32(data + 2, 0x00000000); // no passwd
@@ -543,20 +583,24 @@
 /*****************************************************************************/
 
 /** Prepare to send an acknowledge.
+ *
+ * \return Zero on success, otherwise a negative error code.
  */
 int ec_foe_prepare_send_ack(
-        ec_fsm_foe_t *foe /**< FoE statemachine. */
+        ec_fsm_foe_t *fsm, /**< FoE statemachine. */
+        ec_datagram_t *datagram /**< Datagram to use. */
         )
 {
     uint8_t *data;
 
-    data = ec_slave_mbox_prepare_send(foe->slave, foe->mbox,
+    data = ec_slave_mbox_prepare_send(fsm->slave, datagram,
             EC_MBOX_TYPE_FILEACCESS, EC_FOE_HEADER_SIZE);
-    if (IS_ERR(data))
+    if (IS_ERR(data)) {
         return -1;
+    }
 
     EC_WRITE_U16(data, EC_FOE_OPCODE_ACK);
-    EC_WRITE_U32(data + 2, foe->rx_expected_packet_no);
+    EC_WRITE_U32(data + 2, fsm->rx_expected_packet_no);
 
     return 0;
 }
@@ -565,39 +609,38 @@
 
 /** State: RRQ SENT.
  *
- * Checks is the previous transmit datagram succeded and sends the next
+ * Checks is the previous transmit datagram succeeded and sends the next
  * fragment, if necessary.
  */
 void ec_fsm_foe_state_rrq_sent(
-        ec_fsm_foe_t *fsm /**< FoE statemachine. */
-        )
-{
-    ec_mailbox_t *mbox = fsm->mbox;
-    ec_datagram_t *datagram = mbox->datagram;
+        ec_fsm_foe_t *fsm, /**< FoE statemachine. */
+        ec_datagram_t *datagram /**< Datagram to use. */
+        )
+{
     ec_slave_t *slave = fsm->slave;
 
 #ifdef DEBUG_FOE
-    printk("ec_foe_state_rrq_sent()\n");
-#endif
-
-    if (!ec_mbox_is_datagram_state(mbox, EC_DATAGRAM_RECEIVED)) {
+    EC_SLAVE_DBG(fsm->slave, 0, "%s()\n", __func__);
+#endif
+
+    if (fsm->datagram->state != EC_DATAGRAM_RECEIVED) {
         ec_foe_set_rx_error(fsm, FOE_RECEIVE_ERROR);
         EC_SLAVE_ERR(slave, "Failed to send FoE RRQ: ");
-        ec_datagram_print_state(datagram);
-        return;
-    }
-
-    if (!ec_mbox_is_datagram_wc(mbox, 1)) {
+        ec_datagram_print_state(fsm->datagram);
+        return;
+    }
+
+    if (fsm->datagram->working_counter != 1) {
         // slave did not put anything in the mailbox yet
         ec_foe_set_rx_error(fsm, FOE_WC_ERROR);
         EC_SLAVE_ERR(slave, "Reception of FoE RRQ failed: ");
-        ec_datagram_print_wc_error(datagram);
-        return;
-    }
-
-    fsm->jiffies_start = datagram->jiffies_sent;
-
-    ec_slave_mbox_prepare_check(fsm->slave, fsm->mbox); // can not fail.
+        ec_datagram_print_wc_error(fsm->datagram);
+        return;
+    }
+
+    fsm->jiffies_start = fsm->datagram->jiffies_sent;
+
+    ec_slave_mbox_prepare_check(slave, datagram); // can not fail.
 
     fsm->retries = EC_FSM_RETRIES;
     fsm->state = ec_fsm_foe_state_data_check;
@@ -605,26 +648,11 @@
 
 /*****************************************************************************/
 
-/** Start a read operation.
- */
-void ec_fsm_foe_read(
-        ec_fsm_foe_t *fsm /**< FoE state machine. */
-        )
-{
-    fsm->state = ec_fsm_foe_read_start;
-    fsm->rx_filename = fsm->request->file_name;
-    fsm->rx_filename_len = strlen(fsm->rx_filename);
-
-    fsm->rx_buffer = fsm->request->buffer;
-    fsm->rx_buffer_size = fsm->request->buffer_size;
-}
-
-/*****************************************************************************/
-
 /** Starting state for read operations.
  */
 void ec_fsm_foe_read_start(
-        ec_fsm_foe_t *fsm /**< FoE statemachine. */
+        ec_fsm_foe_t *fsm, /**< FoE statemachine. */
+        ec_datagram_t *datagram /**< Datagram to use. */
         )
 {
     ec_slave_t *slave = fsm->slave;
@@ -634,7 +662,7 @@
     fsm->rx_last_packet = 0;
 
 #ifdef DEBUG_FOE
-    printk("ec_fsm_foe_read_start()\n");
+    EC_SLAVE_DBG(fsm->slave, 0, "%s()\n", __func__);
 #endif
 
     if (!(slave->sii.mailbox_protocols & EC_MBOX_FOE)) {
@@ -643,7 +671,7 @@
         return;
     }
 
-    if (ec_foe_prepare_rrq_send(fsm)) {
+    if (ec_foe_prepare_rrq_send(fsm, datagram)) {
         ec_foe_set_rx_error(fsm, FOE_PROT_ERROR);
         return;
     }
@@ -656,51 +684,49 @@
 /** Check for data.
  */
 void ec_fsm_foe_state_data_check(
-        ec_fsm_foe_t *fsm /**< FoE statemachine. */
-        )
-{
-    ec_mailbox_t *mbox = fsm->mbox;
-    ec_datagram_t *datagram = mbox->datagram;
+        ec_fsm_foe_t *fsm, /**< FoE statemachine. */
+        ec_datagram_t *datagram /**< Datagram to use. */
+        )
+{
     ec_slave_t *slave = fsm->slave;
 
 #ifdef DEBUG_FOE
-    printk("ec_fsm_foe_state_data_check()\n");
-#endif
-
-    if (!ec_mbox_is_datagram_state(mbox, EC_DATAGRAM_RECEIVED)) {
+    EC_SLAVE_DBG(fsm->slave, 0, "%s()\n", __func__);
+#endif
+
+    if (fsm->datagram->state != EC_DATAGRAM_RECEIVED) {
         ec_foe_set_rx_error(fsm, FOE_RECEIVE_ERROR);
         EC_SLAVE_ERR(slave, "Failed to send FoE DATA READ: ");
-        ec_datagram_print_state(datagram);
-        return;
-    }
-
-    if (!ec_mbox_is_datagram_wc(mbox, 1)) {
+        ec_datagram_print_state(fsm->datagram);
+        return;
+    }
+
+    if (fsm->datagram->working_counter != 1) {
         ec_foe_set_rx_error(fsm, FOE_WC_ERROR);
         EC_SLAVE_ERR(slave, "Reception of FoE DATA READ: ");
-        ec_datagram_print_wc_error(datagram);
-        return;
-    }
-
-    if (!ec_slave_mbox_check(mbox)) {
-        unsigned long diff_ms =
-            (datagram->jiffies_received - fsm->jiffies_start) * 1000 / HZ;
+        ec_datagram_print_wc_error(fsm->datagram);
+        return;
+    }
+
+    if (!ec_slave_mbox_check(fsm->datagram)) {
+        unsigned long diff_ms = (fsm->datagram->jiffies_received -
+                fsm->jiffies_start) * 1000 / HZ;
         if (diff_ms >= EC_FSM_FOE_TIMEOUT) {
             ec_foe_set_tx_error(fsm, FOE_TIMEOUT_ERROR);
             EC_SLAVE_ERR(slave, "Timeout while waiting for ack response.\n");
             return;
         }
 
-        ec_slave_mbox_prepare_check(slave, mbox); // can not fail.
+        ec_slave_mbox_prepare_check(slave, datagram); // can not fail.
         fsm->retries = EC_FSM_RETRIES;
         return;
     }
 
     // Fetch response
-    ec_slave_mbox_prepare_fetch(slave, mbox); // can not fail.
+    ec_slave_mbox_prepare_fetch(slave, datagram); // can not fail.
 
     fsm->retries = EC_FSM_RETRIES;
     fsm->state = ec_fsm_foe_state_data_read;
-
 }
 
 /*****************************************************************************/
@@ -708,35 +734,35 @@
 /** Start reading data.
  */
 void ec_fsm_foe_state_data_read(
-        ec_fsm_foe_t *fsm /**< FoE statemachine. */
+        ec_fsm_foe_t *fsm, /**< FoE statemachine. */
+        ec_datagram_t *datagram /**< Datagram to use. */
         )
 {
     size_t rec_size;
     uint8_t *data, opCode, packet_no, mbox_prot;
 
-    ec_mailbox_t *mbox = fsm->mbox;
-    ec_datagram_t *datagram = mbox->datagram;
     ec_slave_t *slave = fsm->slave;
 
 #ifdef DEBUG_FOE
-    printk("ec_fsm_foe_state_data_read()\n");
-#endif
-
-    if (!ec_mbox_is_datagram_state(mbox, EC_DATAGRAM_RECEIVED)) {
+    EC_SLAVE_DBG(fsm->slave, 0, "%s()\n", __func__);
+#endif
+
+    if (fsm->datagram->state != EC_DATAGRAM_RECEIVED) {
         ec_foe_set_rx_error(fsm, FOE_RECEIVE_ERROR);
         EC_SLAVE_ERR(slave, "Failed to receive FoE DATA READ datagram: ");
-        ec_datagram_print_state(datagram);
-        return;
-    }
-
-    if (!ec_mbox_is_datagram_wc(mbox, 1)) {
+        ec_datagram_print_state(fsm->datagram);
+        return;
+    }
+
+    if (fsm->datagram->working_counter != 1) {
         ec_foe_set_rx_error(fsm, FOE_WC_ERROR);
         EC_SLAVE_ERR(slave, "Reception of FoE DATA READ failed: ");
-        ec_datagram_print_wc_error(datagram);
-        return;
-    }
-
-    if (!(data = ec_slave_mbox_fetch(slave, mbox, &mbox_prot, &rec_size))) {
+        ec_datagram_print_wc_error(fsm->datagram);
+        return;
+    }
+
+    data = ec_slave_mbox_fetch(slave, fsm->datagram, &mbox_prot, &rec_size);
+    if (IS_ERR(data)) {
         ec_foe_set_rx_error(fsm, FOE_MBOX_FETCH_ERROR);
         return;
     }
@@ -751,7 +777,7 @@
     opCode = EC_READ_U8(data);
 
     if (opCode == EC_FOE_OPCODE_BUSY) {
-        if (ec_foe_prepare_send_ack(fsm)) {
+        if (ec_foe_prepare_send_ack(fsm, datagram)) {
             ec_foe_set_rx_error(fsm, FOE_PROT_ERROR);
         }
         return;
@@ -795,7 +821,7 @@
 
     fsm->rx_last_packet =
         (rec_size + EC_MBOX_HEADER_SIZE + EC_FOE_HEADER_SIZE
-         != fsm->slave->configured_rx_mailbox_size);
+         != slave->configured_rx_mailbox_size);
 
     if (fsm->rx_last_packet ||
             (slave->configured_rx_mailbox_size - EC_MBOX_HEADER_SIZE
@@ -804,9 +830,9 @@
         // either it was the last packet or a new packet will fit into the
         // delivered buffer
 #ifdef DEBUG_FOE
-        printk ("last_packet=true\n");
-#endif
-        if (ec_foe_prepare_send_ack(fsm)) {
+        EC_SLAVE_DBG(fsm->slave, 0, "last_packet=true\n");
+#endif
+        if (ec_foe_prepare_send_ack(fsm, datagram)) {
             ec_foe_set_rx_error(fsm, FOE_RX_DATA_ACK_ERROR);
             return;
         }
@@ -816,13 +842,12 @@
     else {
         // no more data fits into the delivered buffer
         // ... wait for new read request
-        printk ("ERROR: data doesn't fit in receive buffer\n");
-        printk ("       rx_buffer_size  = %d\n", fsm->rx_buffer_size);
-        printk ("       rx_buffer_offset= %d\n", fsm->rx_buffer_offset);
-        printk ("       rec_size        = %zd\n", rec_size);
-        printk ("       rx_mailbox_size = %d\n",
-                slave->configured_rx_mailbox_size);
-        printk ("       rx_last_packet  = %d\n", fsm->rx_last_packet);
+        EC_SLAVE_ERR(slave, "Data do not fit in receive buffer!\n");
+        printk("  rx_buffer_size = %d\n", fsm->rx_buffer_size);
+        printk("rx_buffer_offset = %d\n", fsm->rx_buffer_offset);
+        printk("        rec_size = %zd\n", rec_size);
+        printk(" rx_mailbox_size = %d\n", slave->configured_rx_mailbox_size);
+        printk("  rx_last_packet = %d\n", fsm->rx_last_packet);
         fsm->request->result = FOE_READY;
     }
 }
@@ -832,35 +857,34 @@
 /** Sent an acknowledge.
  */
 void ec_fsm_foe_state_sent_ack(
-        ec_fsm_foe_t *fsm /**< FoE statemachine. */
-        )
-{
-    ec_mailbox_t *mbox = fsm->mbox;
-    ec_datagram_t *datagram = mbox->datagram;
+        ec_fsm_foe_t *fsm, /**< FoE statemachine. */
+        ec_datagram_t *datagram /**< Datagram to use. */
+        )
+{
     ec_slave_t *slave = fsm->slave;
 
 #ifdef DEBUG_FOE
-    printk("ec_foe_state_sent_ack()\n");
-#endif
-
-    if (!ec_mbox_is_datagram_state(mbox, EC_DATAGRAM_RECEIVED)) {
+    EC_SLAVE_DBG(fsm->slave, 0, "%s()\n", __func__);
+#endif
+
+    if (fsm->datagram->state != EC_DATAGRAM_RECEIVED) {
         ec_foe_set_rx_error(fsm, FOE_RECEIVE_ERROR);
         EC_SLAVE_ERR(slave, "Failed to send FoE ACK: ");
-        ec_datagram_print_state(datagram);
-        return;
-    }
-
-    if (!ec_mbox_is_datagram_wc(mbox, 1)) {
+        ec_datagram_print_state(fsm->datagram);
+        return;
+    }
+
+    if (fsm->datagram->working_counter != 1) {
         // slave did not put anything into the mailbox yet
         ec_foe_set_rx_error(fsm, FOE_WC_ERROR);
         EC_SLAVE_ERR(slave, "Reception of FoE ACK failed: ");
-        ec_datagram_print_wc_error(datagram);
-        return;
-    }
-
-    fsm->jiffies_start = datagram->jiffies_sent;
-
-    ec_slave_mbox_prepare_check(fsm->slave, fsm->mbox); // can not fail.
+        ec_datagram_print_wc_error(fsm->datagram);
+        return;
+    }
+
+    fsm->jiffies_start = fsm->datagram->jiffies_sent;
+
+    ec_slave_mbox_prepare_check(slave, datagram); // can not fail.
 
     if (fsm->rx_last_packet) {
         fsm->rx_expected_packet_no = 0;