master/fsm_soe.c
changeset 1980 a89e2bedf004
parent 1905 5abe24872083
child 1921 d9cf40facbc4
--- a/master/fsm_soe.c	Fri Mar 19 13:27:08 2010 +0100
+++ b/master/fsm_soe.c	Thu Apr 29 14:05:15 2010 +0200
@@ -45,16 +45,21 @@
  */
 #define EC_MBOX_TYPE_SOE 0x05
 
-#define EC_SOE_OPCODE_READ_REQUEST   0x01
-#define EC_SOE_OPCODE_READ_RESPONSE  0x02
-#define EC_SOE_OPCODE_WRITE_REQUEST  0x03
-#define EC_SOE_OPCODE_WRITE_RESPONSE 0x04
-
-#define EC_SOE_READ_REQUEST_SIZE   0x04
-#define EC_SOE_READ_RESPONSE_SIZE  0x04
-#define EC_SOE_WRITE_REQUEST_SIZE  0x04
-#define EC_SOE_WRITE_RESPONSE_SIZE 0x04
-
+/** SoE operations
+ */
+enum ec_soe_opcodes {
+    OPCODE_READ_REQUEST   = 0x01, /**< Read request. */
+    OPCODE_READ_RESPONSE  = 0x02, /**< Read response. */
+    OPCODE_WRITE_REQUEST  = 0x03, /**< Write request. */
+    OPCODE_WRITE_RESPONSE = 0x04  /**< Write response. */
+};
+
+/** Size of all SoE headers.
+ */
+#define EC_SOE_SIZE 0x04
+
+/** SoE response timeout [ms].
+ */
 #define EC_SOE_RESPONSE_TIMEOUT 1000
 
 /*****************************************************************************/
@@ -74,12 +79,35 @@
 
 /*****************************************************************************/
 
+extern const ec_code_msg_t soe_error_codes[];
+
+/*****************************************************************************/
+
+/** Outputs an SoE error code.
+*/
+void ec_print_soe_error(uint16_t error_code)
+{
+    const ec_code_msg_t *error_msg;
+
+    for (error_msg = soe_error_codes; error_msg->code; error_msg++) {
+        if (error_msg->code == error_code) {
+            EC_ERR("SoE error 0x%04X: \"%s\".\n",
+                   error_msg->code, error_msg->message);
+            return;
+        }
+    }
+
+    EC_ERR("Unknown SoE error 0x%04X.\n", error_code);
+}
+
+/*****************************************************************************/
+
 /** Constructor.
  */
 void ec_fsm_soe_init(
-		ec_fsm_soe_t *fsm, /**< finite state machine */
-		ec_datagram_t *datagram /**< datagram */
-		)
+        ec_fsm_soe_t *fsm, /**< finite state machine */
+        ec_datagram_t *datagram /**< datagram */
+        )
 {
     fsm->state = NULL;
     fsm->datagram = datagram;
@@ -90,8 +118,8 @@
 /** Destructor.
  */
 void ec_fsm_soe_clear(
-		ec_fsm_soe_t *fsm /**< finite state machine */
-		)
+        ec_fsm_soe_t *fsm /**< finite state machine */
+        )
 {
 }
 
@@ -109,9 +137,9 @@
     fsm->request = request;
     if (request->dir == EC_DIR_OUTPUT) {
         fsm->state = ec_fsm_soe_write_start;
-	} else {
+    } else {
         fsm->state = ec_fsm_soe_read_start;
-	}
+    }
 }
 
 /*****************************************************************************/
@@ -140,6 +168,26 @@
     return fsm->state == ec_fsm_soe_end;
 }
 
+/*****************************************************************************/
+
+/** Output information about a failed SoE transfer.
+ */
+void ec_fsm_soe_print_error(ec_fsm_soe_t *fsm /**< Finite state machine */)
+{
+    ec_soe_request_t *request = fsm->request;
+
+    EC_ERR("");
+
+    if (request->dir == EC_DIR_OUTPUT) {
+        printk("Writing");
+    } else {
+        printk("Reading");
+    }
+
+    printk(" IDN 0x%04X failed on slave %u.\n",
+            request->idn, fsm->slave->ring_position);
+}
+
 /******************************************************************************
  * SoE read state machine
  *****************************************************************************/
@@ -159,25 +207,27 @@
                request->idn, slave->ring_position);
 
     if (!(slave->sii.mailbox_protocols & EC_MBOX_SOE)) {
-        EC_ERR("Slave %u does not support SoE!\n", slave->ring_position);
-        fsm->state = ec_fsm_soe_error;
+        EC_ERR("Slave does not support SoE!\n");
+        fsm->state = ec_fsm_soe_error;
+        ec_fsm_soe_print_error(fsm);
         return;
     }
 
     data = ec_slave_mbox_prepare_send(slave, datagram, EC_MBOX_TYPE_SOE,
-			EC_SOE_READ_REQUEST_SIZE);
+            EC_SOE_SIZE);
     if (IS_ERR(data)) {
         fsm->state = ec_fsm_soe_error;
-        return;
-    }
-
-    EC_WRITE_U8(data, EC_SOE_OPCODE_READ_REQUEST);
+        ec_fsm_soe_print_error(fsm);
+        return;
+    }
+
+    EC_WRITE_U8(data, OPCODE_READ_REQUEST);
     EC_WRITE_U8(data + 1, 1 << 6); // request value
     EC_WRITE_U16(data + 2, request->idn);
 
     if (master->debug_level) {
         EC_DBG("SCC read request:\n");
-        ec_print_data(data, EC_SOE_READ_REQUEST_SIZE);
+        ec_print_data(data, EC_SOE_SIZE);
     }
 
     fsm->request->data_size = 0;
@@ -201,9 +251,9 @@
 
     if (datagram->state != EC_DATAGRAM_RECEIVED) {
         fsm->state = ec_fsm_soe_error;
-        EC_ERR("Failed to receive SoE read request for slave %u: ",
-               slave->ring_position);
+        EC_ERR("Failed to receive SoE read request: ");
         ec_datagram_print_state(datagram);
+        ec_fsm_soe_print_error(fsm);
         return;
     }
 
@@ -217,11 +267,10 @@
             }
         }
         fsm->state = ec_fsm_soe_error;
-        EC_ERR("Reception of SoE read request for IDN 0x%04x failed"
-                " after %u ms on slave %u: ",
-                fsm->request->idn, (u32) diff_ms,
-                fsm->slave->ring_position);
+        EC_ERR("Reception of SoE read request failed after %u ms: ",
+                (u32) diff_ms);
         ec_datagram_print_wc_error(datagram);
+        ec_fsm_soe_print_error(fsm);
         return;
     }
 
@@ -245,17 +294,17 @@
 
     if (datagram->state != EC_DATAGRAM_RECEIVED) {
         fsm->state = ec_fsm_soe_error;
-        EC_ERR("Failed to receive SoE mailbox check datagram from slave %u: ",
-               slave->ring_position);
+        EC_ERR("Failed to receive SoE mailbox check datagram: ");
         ec_datagram_print_state(datagram);
+        ec_fsm_soe_print_error(fsm);
         return;
     }
 
     if (datagram->working_counter != 1) {
         fsm->state = ec_fsm_soe_error;
-        EC_ERR("Reception of SoE mailbox check datagram failed on slave %u: ",
-				slave->ring_position);
+        EC_ERR("Reception of SoE mailbox check datagram failed: ");
         ec_datagram_print_wc_error(datagram);
+        ec_fsm_soe_print_error(fsm);
         return;
     }
 
@@ -264,9 +313,9 @@
             (datagram->jiffies_received - fsm->jiffies_start) * 1000 / HZ;
         if (diff_ms >= EC_SOE_RESPONSE_TIMEOUT) {
             fsm->state = ec_fsm_soe_error;
-            EC_ERR("Timeout after %u ms while waiting for IDN 0x%04x"
-                    " read response on slave %u.\n", (u32) diff_ms,
-                    fsm->request->idn, slave->ring_position);
+            EC_ERR("Timeout after %u ms while waiting for read response.\n",
+                    (u32) diff_ms);
+            ec_fsm_soe_print_error(fsm);
             return;
         }
 
@@ -300,23 +349,24 @@
 
     if (datagram->state != EC_DATAGRAM_RECEIVED) {
         fsm->state = ec_fsm_soe_error;
-        EC_ERR("Failed to receive SoE read response datagram for"
-               " slave %u: ", slave->ring_position);
+        EC_ERR("Failed to receive SoE read response datagram: ");
         ec_datagram_print_state(datagram);
+        ec_fsm_soe_print_error(fsm);
         return;
     }
 
     if (datagram->working_counter != 1) {
         fsm->state = ec_fsm_soe_error;
-        EC_ERR("Reception of SoE read response failed on slave %u: ",
-                slave->ring_position);
+        EC_ERR("Reception of SoE read response failed: ");
         ec_datagram_print_wc_error(datagram);
+        ec_fsm_soe_print_error(fsm);
         return;
     }
 
     data = ec_slave_mbox_fetch(slave, datagram, &mbox_prot, &rec_size);
     if (IS_ERR(data)) {
         fsm->state = ec_fsm_soe_error;
+        ec_fsm_soe_print_error(fsm);
         return;
     }
 
@@ -327,53 +377,59 @@
 
     if (mbox_prot != EC_MBOX_TYPE_SOE) {
         fsm->state = ec_fsm_soe_error;
-        EC_WARN("Received mailbox protocol 0x%02X as response.\n", mbox_prot);
-        return;
-    }
-
-    if (rec_size < EC_SOE_READ_RESPONSE_SIZE) {
-        fsm->state = ec_fsm_soe_error;
-        EC_ERR("Received currupted SoE read response (%zu bytes)!\n",
-				rec_size);
+        EC_ERR("Received mailbox protocol 0x%02X as response.\n", mbox_prot);
+        ec_fsm_soe_print_error(fsm);
+        return;
+    }
+
+    if (rec_size < EC_SOE_SIZE) {
+        fsm->state = ec_fsm_soe_error;
+        EC_ERR("Received currupted SoE read response"
+                " (%zu bytes)!\n", rec_size);
         ec_print_data(data, rec_size);
+        ec_fsm_soe_print_error(fsm);
         return;
     }
 
     header = EC_READ_U8(data);
-	opcode = header & 0x7;
+    opcode = header & 0x7;
     incomplete = (header >> 3) & 1;
-	error_flag = (header >> 4) & 1;
-
-    if (opcode != EC_SOE_OPCODE_READ_RESPONSE) {
+    error_flag = (header >> 4) & 1;
+
+    if (opcode != OPCODE_READ_RESPONSE) {
         EC_ERR("Received no read response (opcode %x).\n", opcode);
         ec_print_data(data, rec_size);
-        fsm->state = ec_fsm_soe_error;
-        return;
-    }
-
-	if (error_flag) {
-		req->error_code = EC_READ_U16(data + rec_size - 2);
-		EC_ERR("Received error response: 0x%04x.\n",
-				req->error_code);
-        fsm->state = ec_fsm_soe_error;
-        return;
-	} else {
-		req->error_code = 0x0000;
-	}
-
-	value_included = (EC_READ_U8(data + 1) >> 6) & 1;
-	if (!value_included) {
-		EC_ERR("No value included!\n");
-		fsm->state = ec_fsm_soe_error;
-		return;
-	}
-
-	data_size = rec_size - EC_SOE_READ_RESPONSE_SIZE;
-	if (ec_soe_request_append_data(req,
-                data + EC_SOE_READ_RESPONSE_SIZE, data_size)) {
-		fsm->state = ec_fsm_soe_error;
-		return;
-	}
+        ec_fsm_soe_print_error(fsm);
+        fsm->state = ec_fsm_soe_error;
+        return;
+    }
+
+    if (error_flag) {
+        req->error_code = EC_READ_U16(data + rec_size - 2);
+        EC_ERR("Received error response:\n");
+        ec_print_soe_error(req->error_code);
+        ec_fsm_soe_print_error(fsm);
+        fsm->state = ec_fsm_soe_error;
+        return;
+    } else {
+        req->error_code = 0x0000;
+    }
+
+    value_included = (EC_READ_U8(data + 1) >> 6) & 1;
+    if (!value_included) {
+        EC_ERR("No value included!\n");
+        ec_fsm_soe_print_error(fsm);
+        fsm->state = ec_fsm_soe_error;
+        return;
+    }
+
+    data_size = rec_size - EC_SOE_SIZE;
+    if (ec_soe_request_append_data(req,
+                data + EC_SOE_SIZE, data_size)) {
+        fsm->state = ec_fsm_soe_error;
+        ec_fsm_soe_print_error(fsm);
+        return;
+    }
 
     if (incomplete) {
         if (master->debug_level) {
@@ -412,11 +468,12 @@
     size_t header_size, max_fragment_size, remaining_size, fragment_size;
     uint16_t fragments_left;
 
-    header_size = EC_MBOX_HEADER_SIZE + EC_SOE_WRITE_REQUEST_SIZE;
+    header_size = EC_MBOX_HEADER_SIZE + EC_SOE_SIZE;
     if (slave->configured_rx_mailbox_size <= header_size) {
         EC_ERR("Mailbox size (%u) too small for SoE write.\n",
                 slave->configured_rx_mailbox_size);
         fsm->state = ec_fsm_soe_error;
+        ec_fsm_soe_print_error(fsm);
         return;
     }
 
@@ -430,21 +487,22 @@
     }
 
     data = ec_slave_mbox_prepare_send(slave, datagram, EC_MBOX_TYPE_SOE,
-			EC_SOE_WRITE_REQUEST_SIZE + fragment_size);
+            EC_SOE_SIZE + fragment_size);
     if (IS_ERR(data)) {
         fsm->state = ec_fsm_soe_error;
-        return;
-    }
-
-    EC_WRITE_U8(data, EC_SOE_OPCODE_WRITE_REQUEST | incomplete << 3);
+        ec_fsm_soe_print_error(fsm);
+        return;
+    }
+
+    EC_WRITE_U8(data, OPCODE_WRITE_REQUEST | incomplete << 3);
     EC_WRITE_U8(data + 1, 1 << 6); // only value included
     EC_WRITE_U16(data + 2, incomplete ? fragments_left : req->idn);
-	memcpy(data + 4, req->data + fsm->offset, fragment_size);
+    memcpy(data + 4, req->data + fsm->offset, fragment_size);
     fsm->offset += fragment_size;
 
     if (master->debug_level) {
         EC_DBG("SCC write request:\n");
-        ec_print_data(data, EC_SOE_WRITE_REQUEST_SIZE + fragment_size);
+        ec_print_data(data, EC_SOE_SIZE + fragment_size);
     }
 
     req->jiffies_sent = jiffies;
@@ -467,8 +525,9 @@
                req->idn, req->data_size, slave->ring_position);
 
     if (!(slave->sii.mailbox_protocols & EC_MBOX_SOE)) {
-        EC_ERR("Slave %u does not support SoE!\n", slave->ring_position);
-        fsm->state = ec_fsm_soe_error;
+        EC_ERR("Slave does not support SoE!\n");
+        fsm->state = ec_fsm_soe_error;
+        ec_fsm_soe_print_error(fsm);
         return;
     }
 
@@ -491,9 +550,9 @@
 
     if (datagram->state != EC_DATAGRAM_RECEIVED) {
         fsm->state = ec_fsm_soe_error;
-        EC_ERR("Failed to receive SoE write request for slave %u: ",
-               slave->ring_position);
+        EC_ERR("Failed to receive SoE write request: ");
         ec_datagram_print_state(datagram);
+        ec_fsm_soe_print_error(fsm);
         return;
     }
 
@@ -507,11 +566,10 @@
             }
         }
         fsm->state = ec_fsm_soe_error;
-        EC_ERR("Reception of SoE write request for IDN 0x%04x failed"
-                " after %u ms on slave %u: ",
-                fsm->request->idn, (u32) diff_ms,
-                fsm->slave->ring_position);
+        EC_ERR("Reception of SoE write request failed after %u ms: ",
+                (u32) diff_ms);
         ec_datagram_print_wc_error(datagram);
+        ec_fsm_soe_print_error(fsm);
         return;
     }
 
@@ -537,17 +595,17 @@
 
     if (datagram->state != EC_DATAGRAM_RECEIVED) {
         fsm->state = ec_fsm_soe_error;
-        EC_ERR("Failed to receive SoE write request datagram from slave %u: ",
-               slave->ring_position);
+        EC_ERR("Failed to receive SoE write request datagram: ");
         ec_datagram_print_state(datagram);
+        ec_fsm_soe_print_error(fsm);
         return;
     }
 
     if (datagram->working_counter != 1) {
         fsm->state = ec_fsm_soe_error;
-        EC_ERR("Reception of SoE write request datagram failed on slave %u: ",
-				slave->ring_position);
+        EC_ERR("Reception of SoE write request datagram: ");
         ec_datagram_print_wc_error(datagram);
+        ec_fsm_soe_print_error(fsm);
         return;
     }
 
@@ -559,9 +617,9 @@
                 (datagram->jiffies_received - fsm->jiffies_start) * 1000 / HZ;
             if (diff_ms >= EC_SOE_RESPONSE_TIMEOUT) {
                 fsm->state = ec_fsm_soe_error;
-                EC_ERR("Timeout after %u ms while waiting for IDN 0x%04x"
-                        " write response on slave %u.\n", (u32) diff_ms,
-                        fsm->request->idn, slave->ring_position);
+                EC_ERR("Timeout after %u ms while waiting"
+                        " for write response.\n", (u32) diff_ms);
+                ec_fsm_soe_print_error(fsm);
                 return;
             }
 
@@ -588,7 +646,7 @@
     ec_master_t *master = slave->master;
     ec_soe_request_t *req = fsm->request;
     uint8_t *data, mbox_prot, opcode, error_flag;
-	uint16_t idn;
+    uint16_t idn;
     size_t rec_size;
 
     if (datagram->state == EC_DATAGRAM_TIMED_OUT && fsm->retries--)
@@ -596,23 +654,24 @@
 
     if (datagram->state != EC_DATAGRAM_RECEIVED) {
         fsm->state = ec_fsm_soe_error;
-        EC_ERR("Failed to receive SoE write response datagram for"
-               " slave %u: ", slave->ring_position);
+        EC_ERR("Failed to receive SoE write response datagram: ");
         ec_datagram_print_state(datagram);
+        ec_fsm_soe_print_error(fsm);
         return;
     }
 
     if (datagram->working_counter != 1) {
         fsm->state = ec_fsm_soe_error;
-        EC_ERR("Reception of SoE write response failed on slave %u: ",
-                slave->ring_position);
+        EC_ERR("Reception of SoE write response failed: ");
         ec_datagram_print_wc_error(datagram);
+        ec_fsm_soe_print_error(fsm);
         return;
     }
 
     data = ec_slave_mbox_fetch(slave, datagram, &mbox_prot, &rec_size);
     if (IS_ERR(data)) {
         fsm->state = ec_fsm_soe_error;
+        ec_fsm_soe_print_error(fsm);
         return;
     }
 
@@ -623,50 +682,55 @@
 
     if (mbox_prot != EC_MBOX_TYPE_SOE) {
         fsm->state = ec_fsm_soe_error;
-        EC_WARN("Received mailbox protocol 0x%02X as response.\n", mbox_prot);
-        return;
-    }
-
-    if (rec_size < EC_SOE_WRITE_RESPONSE_SIZE) {
+        EC_ERR("Received mailbox protocol 0x%02X as response.\n", mbox_prot);
+        ec_fsm_soe_print_error(fsm);
+        return;
+    }
+
+    if (rec_size < EC_SOE_SIZE) {
         fsm->state = ec_fsm_soe_error;
         EC_ERR("Received currupted SoE write response (%zu bytes)!\n",
-				rec_size);
+                rec_size);
         ec_print_data(data, rec_size);
-        return;
-    }
-
-	opcode = EC_READ_U8(data) & 0x7;
-    if (opcode != EC_SOE_OPCODE_WRITE_RESPONSE) {
+        ec_fsm_soe_print_error(fsm);
+        return;
+    }
+
+    opcode = EC_READ_U8(data) & 0x7;
+    if (opcode != OPCODE_WRITE_RESPONSE) {
         EC_ERR("Received no write response (opcode %x).\n", opcode);
         ec_print_data(data, rec_size);
-        fsm->state = ec_fsm_soe_error;
-        return;
-    }
-
-	idn = EC_READ_U16(data + 2);
-	if (idn != req->idn) {
-		EC_ERR("Received response for wrong IDN 0x%04x.\n", idn);
+        ec_fsm_soe_print_error(fsm);
+        fsm->state = ec_fsm_soe_error;
+        return;
+    }
+
+    idn = EC_READ_U16(data + 2);
+    if (idn != req->idn) {
+        EC_ERR("Received response for wrong IDN 0x%04x.\n", idn);
         ec_print_data(data, rec_size);
-        fsm->state = ec_fsm_soe_error;
-		return;
-	}
-
-	error_flag = (EC_READ_U8(data) >> 4) & 1;
-	if (error_flag) {
-		if (rec_size < EC_SOE_WRITE_RESPONSE_SIZE + 2) {
-			EC_ERR("Received corrupted error response - error flag set,"
-					" but received size is %zu.\n", rec_size);
-		} else {
-			req->error_code = EC_READ_U16(data + EC_SOE_WRITE_RESPONSE_SIZE);
-			EC_ERR("Received error response: 0x%04x.\n",
-					req->error_code);
-		}
-		ec_print_data(data, rec_size);
-		fsm->state = ec_fsm_soe_error;
-        return;
-	} else {
-		req->error_code = 0x0000;
-	}
+        ec_fsm_soe_print_error(fsm);
+        fsm->state = ec_fsm_soe_error;
+        return;
+    }
+
+    error_flag = (EC_READ_U8(data) >> 4) & 1;
+    if (error_flag) {
+        if (rec_size < EC_SOE_SIZE + 2) {
+            EC_ERR("Received corrupted error response - error flag set,"
+                    " but received size is %zu.\n", rec_size);
+        } else {
+            req->error_code = EC_READ_U16(data + EC_SOE_SIZE);
+            EC_ERR("Received error response:\n");
+            ec_print_soe_error(req->error_code);
+        }
+        ec_print_data(data, rec_size);
+        ec_fsm_soe_print_error(fsm);
+        fsm->state = ec_fsm_soe_error;
+        return;
+    } else {
+        req->error_code = 0x0000;
+    }
 
     fsm->state = ec_fsm_soe_end; // success
 }