Improved FoE. 1.4-foe
authorFlorian Pose <fp@igh-essen.com>
Mon, 19 Jan 2009 12:36:18 +0000
branch1.4-foe
changeset 1708 fae3a1759126
parent 1707 11ec009e145d
child 1709 63e4bc918640
Improved FoE.
master/cdev.c
master/foe.h
master/foe_request.c
master/foe_request.h
master/fsm_foe.c
master/fsm_master.c
master/ioctl.h
tool/CommandFoeRead.cpp
tool/CommandFoeWrite.cpp
tool/FoeCommand.cpp
tool/FoeCommand.h
--- a/master/cdev.c	Mon Jan 19 10:18:41 2009 +0000
+++ b/master/cdev.c	Mon Jan 19 12:36:18 2009 +0000
@@ -1228,6 +1228,11 @@
 
     up(&master->master_sem);
 
+    if (master->debug_level) {
+        EC_DBG("Scheduled FoE read request on slave %u.\n",
+                request.slave->ring_position);
+    }
+
     // wait for processing through FSM
     if (wait_event_interruptible(master->foe_queue,
                 request.req.state != EC_REQUEST_QUEUED)) {
@@ -1246,11 +1251,12 @@
     // wait until master FSM has finished processing
     wait_event(master->foe_queue, request.req.state != EC_REQUEST_BUSY);
 
-    data.abort_code = request.req.abort_code;
+    data.result = request.req.result;
+    data.error_code = request.req.error_code;
 
 	if (master->debug_level) {
-		EC_DBG("%d bytes read via FoE (abort_code = 0x%x).\n",
-				request.req.data_size, request.req.abort_code);
+		EC_DBG("Read %d bytes via FoE (result = 0x%x).\n",
+				request.req.data_size, request.req.result);
 	}
 
     if (request.req.state != EC_REQUEST_SUCCESS) {
@@ -1275,7 +1281,12 @@
         retval = -EFAULT;
     }
 
+    if (master->debug_level)
+        EC_DBG("FoE read request finished on slave %u.\n",
+                request.slave->ring_position);
+
     ec_foe_request_clear(&request.req);
+
     return retval;
 }
 
@@ -1350,7 +1361,8 @@
     // wait until master FSM has finished processing
     wait_event(master->foe_queue, request.req.state != EC_REQUEST_BUSY);
 
-    data.abort_code = request.req.abort_code;
+    data.result = request.req.result;
+    data.error_code = request.req.error_code;
 
     retval = request.req.state == EC_REQUEST_SUCCESS ? 0 : -EIO;
 
--- a/master/foe.h	Mon Jan 19 10:18:41 2009 +0000
+++ b/master/foe.h	Mon Jan 19 12:36:18 2009 +0000
@@ -38,7 +38,7 @@
     FOE_PROT_ERROR         = 5,
     FOE_NODATA_ERROR       = 6,
     FOE_PACKETNO_ERROR     = 7,
-    FOE_OPMODE_ERROR       = 8,
+    FOE_OPCODE_ERROR       = 8,
     FOE_TIMEOUT_ERROR      = 9,
     FOE_SEND_RX_DATA_ERROR = 10,
     FOE_RX_DATA_ACK_ERROR  = 11,
--- a/master/foe_request.c	Mon Jan 19 10:18:41 2009 +0000
+++ b/master/foe_request.c	Mon Jan 19 12:36:18 2009 +0000
@@ -1,6 +1,6 @@
 /******************************************************************************
  *
- *  $Id:$
+ *  $Id$
  *
  *  Copyright (C) 2008  Olav Zarges, imc Meßsysteme GmbH
  *
@@ -41,6 +41,7 @@
 #include <linux/jiffies.h>
 
 #include "foe_request.h"
+#include "foe.h"
 
 /*****************************************************************************/
 
@@ -68,7 +69,8 @@
     req->issue_timeout = 0; // no timeout
     req->response_timeout = EC_FOE_REQUEST_RESPONSE_TIMEOUT;
     req->state = EC_REQUEST_INIT;
-    req->abort_code = 0x00000000;
+    req->result = FOE_BUSY;
+    req->error_code = 0x00000000;
 }
 
 /*****************************************************************************/
@@ -184,7 +186,7 @@
 {
     req->dir = EC_DIR_INPUT;
     req->state = EC_REQUEST_QUEUED;
-    req->abort_code = 0x00000000;
+    req->result = FOE_BUSY;
     req->jiffies_start = jiffies;
 }
 
@@ -194,7 +196,7 @@
 {
     req->dir = EC_DIR_OUTPUT;
     req->state = EC_REQUEST_QUEUED;
-    req->abort_code = 0x00000000;
+    req->result = FOE_BUSY;
     req->jiffies_start = jiffies;
 }
 
--- a/master/foe_request.h	Mon Jan 19 10:18:41 2009 +0000
+++ b/master/foe_request.h	Mon Jan 19 12:36:18 2009 +0000
@@ -1,6 +1,6 @@
 /******************************************************************************
  *
- *  $Id:$
+ *  $Id$
  *
  *  Copyright (C) 2008  Olav Zarges, imc Meßsysteme GmbH
  *
@@ -68,7 +68,8 @@
     unsigned long jiffies_sent; /**< Jiffies, when the upload/download
                                      request was sent. */
     uint8_t *file_name; /**< Pointer to the filename. */
-    uint32_t abort_code; /**< FoE request abort code. Zero on success. */
+    uint32_t result; /**< FoE request abort code. Zero on success. */
+    uint32_t error_code; /**< Error code from an FoE Error Request. */
 } ec_foe_request_t;
 
 /*****************************************************************************/
--- a/master/fsm_foe.c	Mon Jan 19 10:18:41 2009 +0000
+++ b/master/fsm_foe.c	Mon Jan 19 12:36:18 2009 +0000
@@ -1,6 +1,6 @@
 /******************************************************************************
  *
- *  $Id:$
+ *  $Id$
  *
  *  Copyright (C) 2008  Olav Zarges, imc Meßsysteme GmbH
  *
@@ -52,6 +52,8 @@
 
 #define EC_MBOX_TYPE_FILEACCESS 0x04
 
+#define myDEBUG
+
 /*****************************************************************************/
 
 int		ec_foe_prepare_data_send( ec_fsm_foe_t * );
@@ -188,18 +190,18 @@
 // uint8_t	Counter:4
 
 #define	EC_FOE_HEADER_SIZE		6
-// uint8_t	OpMode
+// uint8_t	OpCode
 // uint8_t	reserved
 // uint32_t	PacketNo, Password, ErrorCode
 
 enum {
-	EC_FOE_OPMODE_RRQ  = 1,
-	EC_FOE_OPMODE_WRQ  = 2,
-	EC_FOE_OPMODE_DATA = 3,
-	EC_FOE_OPMODE_ACK  = 4,
-	EC_FOE_OPMODE_ERR  = 5,
-	EC_FOE_OPMODE_BUSY = 6
-} ec_foe_opmode_t;
+	EC_FOE_OPCODE_RRQ  = 1,
+	EC_FOE_OPCODE_WRQ  = 2,
+	EC_FOE_OPCODE_DATA = 3,
+	EC_FOE_OPCODE_ACK  = 4,
+	EC_FOE_OPCODE_ERR  = 5,
+	EC_FOE_OPCODE_BUSY = 6
+} ec_foe_opcode_t;
 
 /*****************************************************************************/
 /**
@@ -224,7 +226,7 @@
     		EC_MBOX_TYPE_FILEACCESS, current_size + EC_FOE_HEADER_SIZE)))
         return -1;
 
-    EC_WRITE_U8 ( data, EC_FOE_OPMODE_DATA ); 		// OpMode = DataBlock req.
+    EC_WRITE_U8 ( 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);
@@ -254,7 +256,7 @@
     		EC_MBOX_TYPE_FILEACCESS, current_size + EC_FOE_HEADER_SIZE)))
         return -1;
 
-    EC_WRITE_U16( data, EC_FOE_OPMODE_WRQ); // fsm write request
+    EC_WRITE_U16( data, EC_FOE_OPCODE_WRQ); // fsm write request
     EC_WRITE_U32( data + 2, fsm->tx_packet_no );
 
     memcpy(data + EC_FOE_HEADER_SIZE, fsm->tx_filename, current_size);
@@ -375,7 +377,7 @@
     ec_datagram_t *datagram = fsm->datagram;
     ec_slave_t *slave = fsm->slave;
     uint8_t *data, mbox_prot;
-    uint16_t opMode;
+    uint8_t opCode;
     size_t rec_size;
 
 #ifdef	myDEBUG
@@ -408,9 +410,9 @@
         return;
     }
 
-    opMode = EC_READ_U16(data);
-
-    if ( opMode == EC_FOE_OPMODE_BUSY ) {
+    opCode = EC_READ_U8(data);
+
+    if (opCode == EC_FOE_OPCODE_BUSY) {
     	// slave ist noch nicht bereit
         if (ec_foe_prepare_data_send(fsm)) {
         	ec_foe_set_tx_error(fsm, FOE_PROT_ERROR);
@@ -421,7 +423,7 @@
         return;
     }
 
-    if ( opMode == EC_FOE_OPMODE_ACK ) {
+    if (opCode == EC_FOE_OPCODE_ACK) {
         fsm->tx_packet_no++;
         fsm->tx_buffer_offset += fsm->tx_current_size;
 
@@ -530,11 +532,15 @@
     		EC_MBOX_TYPE_FILEACCESS, current_size + EC_FOE_HEADER_SIZE)))
         return -1;
 
-    EC_WRITE_U16( data, EC_FOE_OPMODE_RRQ); // fsm read request
-    EC_WRITE_U32( data + 2, 0 );
-
+    EC_WRITE_U16(data, EC_FOE_OPCODE_RRQ); // fsm read request
+    EC_WRITE_U32(data + 2, 0x00000000); // no passwd
     memcpy(data + EC_FOE_HEADER_SIZE, fsm->rx_filename, current_size);
 
+    if (fsm->slave->master->debug_level) {
+        EC_DBG("FoE Read Request:\n");
+        ec_print_data(data, current_size + EC_FOE_HEADER_SIZE);
+    }
+
     return 0;
 }
 
@@ -548,7 +554,7 @@
     		EC_MBOX_TYPE_FILEACCESS, EC_FOE_HEADER_SIZE)))
         return -1;
 
-    EC_WRITE_U16( data, EC_FOE_OPMODE_ACK);
+    EC_WRITE_U16( data, EC_FOE_OPCODE_ACK);
     EC_WRITE_U32( data + 2, foe->rx_expected_packet_no  );
 
     return 0;
@@ -698,7 +704,7 @@
 
 void ec_fsm_foe_state_data_read ( ec_fsm_foe_t *fsm ) {
     size_t 	rec_size;
-    uint8_t *data, opMode, packet_no, mbox_prot;
+    uint8_t *data, opCode, packet_no, mbox_prot;
 
     ec_datagram_t *datagram = fsm->datagram;
     ec_slave_t *slave = fsm->slave;
@@ -706,6 +712,7 @@
 #ifdef	myDEBUG
 	printk("ec_fsm_foe_state_data_read()\n");
 #endif
+
     if (datagram->state != EC_DATAGRAM_RECEIVED) {
     	ec_foe_set_rx_error(fsm, FOE_RECEIVE_ERROR);
         EC_ERR("Failed to receive FoE DATA READ datagram for"
@@ -733,37 +740,59 @@
         return;
     }
 
-    opMode = EC_READ_U16(data);
-
-    if (opMode == EC_FOE_OPMODE_BUSY) {
+    opCode = EC_READ_U8(data);
+
+    if (opCode == EC_FOE_OPCODE_BUSY) {
         if (ec_foe_prepare_send_ack(fsm)) {
             ec_foe_set_rx_error(fsm, FOE_PROT_ERROR);
         }
         return;
     }
 
-    if (opMode != EC_FOE_OPMODE_DATA) {
-        ec_foe_set_rx_error(fsm, FOE_OPMODE_ERROR);
+    if (opCode == EC_FOE_OPCODE_ERR) {
+        fsm->request->error_code = EC_READ_U32(data + 2);
+        EC_ERR("Received FoE Error Request (code %08x) on slave %u.\n",
+                fsm->request->error_code, slave->ring_position);
+        if (rec_size > 6) {
+            uint8_t text[1024];
+            strncpy(text, data + 6, min(rec_size - 6, sizeof(text)));
+            EC_ERR("FoE Error Text: %s\n", text);
+        }
+        ec_foe_set_rx_error(fsm, FOE_OPCODE_ERROR);
+        return;
+    }
+
+    if (opCode != EC_FOE_OPCODE_DATA) {
+        EC_ERR("Received OPCODE %x, expected %x on slave %u.\n",
+                opCode, EC_FOE_OPCODE_DATA, slave->ring_position);
+        fsm->request->error_code = 0x00000000;
+        ec_foe_set_rx_error(fsm, FOE_OPCODE_ERROR);
         return;
     }
 
     packet_no = EC_READ_U16(data + 2);
     if (packet_no != fsm->rx_expected_packet_no) {
+        EC_ERR("Received unexpected packet number on slave %u.\n",
+                slave->ring_position);
         ec_foe_set_rx_error(fsm, FOE_PACKETNO_ERROR);
         return;
     }
 
     rec_size -= EC_FOE_HEADER_SIZE;
 
-    if ( fsm->rx_buffer_size >= fsm->rx_buffer_offset + rec_size ) {
-        memcpy ( fsm->rx_buffer + fsm->rx_buffer_offset, data + EC_FOE_HEADER_SIZE, rec_size );
+    if (fsm->rx_buffer_size >= fsm->rx_buffer_offset + rec_size) {
+        memcpy(fsm->rx_buffer + fsm->rx_buffer_offset,
+                data + EC_FOE_HEADER_SIZE, rec_size);
         fsm->rx_buffer_offset += rec_size;
     }
 
-    fsm->rx_last_packet = (rec_size + EC_MBOX_HEADER_SIZE + EC_FOE_HEADER_SIZE != fsm->slave->sii.rx_mailbox_size);
+    fsm->rx_last_packet =
+        (rec_size + EC_MBOX_HEADER_SIZE + EC_FOE_HEADER_SIZE
+         != fsm->slave->sii.rx_mailbox_size);
 
     if (fsm->rx_last_packet ||
-    	slave->sii.rx_mailbox_size - EC_MBOX_HEADER_SIZE - EC_FOE_HEADER_SIZE  + fsm->rx_buffer_offset <= fsm->rx_buffer_size) {
+    	(slave->sii.rx_mailbox_size - EC_MBOX_HEADER_SIZE
+         - EC_FOE_HEADER_SIZE + fsm->rx_buffer_offset) <= fsm->rx_buffer_size) {
     	// either it was the last packet or a new packet will fit into the delivered buffer
 #ifdef	myDEBUG
     	printk ("last_packet=true\n");
@@ -776,8 +805,8 @@
 	    fsm->state = ec_fsm_foe_state_sent_ack;
     }
     else {
-    	// no more data fits into the deliverd buffer
-    	// ... wait for new read request (an den Treiber)
+    	// 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);
@@ -785,7 +814,7 @@
     	printk ("       rx_mailbox_size = %d\n", slave->sii.rx_mailbox_size);
     	printk ("       rx_last_packet  = %d\n", fsm->rx_last_packet);
 //    	fsm->state = ec_fsm_state_wait_next_read;
-    	fsm->request->abort_code = FOE_READY;
+    	fsm->request->result = FOE_READY;
     }
 }
 
@@ -834,17 +863,19 @@
 
 /*****************************************************************************/
 
-void ec_foe_set_tx_error( ec_fsm_foe_t *fsm, uint32_t errorcode ) {
+void ec_foe_set_tx_error(ec_fsm_foe_t *fsm, uint32_t errorcode)
+{
 	fsm->tx_errors++;
-	fsm->request->abort_code = errorcode;
+	fsm->request->result = errorcode;
 	fsm->state = ec_fsm_foe_error;
 }
 
 /*****************************************************************************/
 
-void ec_foe_set_rx_error( ec_fsm_foe_t *fsm, uint32_t errorcode ) {
+void ec_foe_set_rx_error(ec_fsm_foe_t *fsm, uint32_t errorcode)
+{
 	fsm->rx_errors++;
-	fsm->request->abort_code = errorcode;
+	fsm->request->result = errorcode;
 	fsm->state = ec_fsm_foe_error;
 }
 
--- a/master/fsm_master.c	Mon Jan 19 10:18:41 2009 +0000
+++ b/master/fsm_master.c	Mon Jan 19 12:36:18 2009 +0000
@@ -436,17 +436,14 @@
         request->req.state = EC_REQUEST_BUSY;
         slave = request->slave;
 
-        EC_DBG("---- Master read command from queue ----\n");
-        // found pending FOE write operation. execute it!
         if (master->debug_level)
-            EC_DBG("Writing FOE data to slave %u...\n",
-                    request->slave->ring_position);
+            EC_DBG("Processing FoE request for slave %u.\n",
+                    slave->ring_position);
 
         fsm->foe_request = &request->req;
         fsm->slave = slave;
         fsm->state = ec_fsm_master_state_foe_request;
         ec_fsm_foe_transfer(&fsm->fsm_foe, slave, &request->req);
-        //(&fsm->fsm_foe, request->slave, request->offset, request->words);
         ec_fsm_foe_exec(&fsm->fsm_foe);
         return 1;
     }
@@ -471,6 +468,10 @@
     if (ec_fsm_master_action_process_sdo(fsm))
         return;
 
+    // Check for pending FoE requests
+    if (ec_fsm_master_action_process_foe(fsm))
+        return;
+
     // check, if slaves have an SDO dictionary to read out.
     for (slave = master->slaves;
             slave < master->slaves + master->slave_count;
@@ -850,10 +851,11 @@
     ec_foe_request_t *request = fsm->foe_request;
     ec_slave_t *slave = fsm->slave;
 
-    if (ec_fsm_foe_exec(&fsm->fsm_foe)) return;
+    if (ec_fsm_foe_exec(&fsm->fsm_foe))
+        return;
 
     if (!ec_fsm_foe_success(&fsm->fsm_foe)) {
-        EC_ERR("Failed to handle FOE request to slave %u.\n",
+        EC_ERR("Failed to handle FoE request to slave %u.\n",
                 slave->ring_position);
         request->state = EC_REQUEST_FAILURE;
         wake_up(&master->foe_queue);
@@ -861,10 +863,10 @@
         return;
     }
 
-    // finished writing FOE
+    // finished transferring FoE
     if (master->debug_level)
-        EC_DBG("Finished writing %u words of FOE data to slave %u.\n",
-                request->data_size, slave->ring_position);
+        EC_DBG("Successfully transferred %u bytes of FoE data from/to"
+                " slave %u.\n", request->data_size, slave->ring_position);
 
     request->state = EC_REQUEST_SUCCESS;
     wake_up(&master->foe_queue);
--- a/master/ioctl.h	Mon Jan 19 10:18:41 2009 +0000
+++ b/master/ioctl.h	Mon Jan 19 12:36:18 2009 +0000
@@ -353,7 +353,8 @@
 
     // outputs
     uint32_t data_size;
-    uint32_t abort_code;
+    uint32_t result;
+    uint32_t error_code;
     char file_name[32];
 } ec_ioctl_slave_foe_t;
 
--- a/tool/CommandFoeRead.cpp	Mon Jan 19 10:18:41 2009 +0000
+++ b/tool/CommandFoeRead.cpp	Mon Jan 19 12:36:18 2009 +0000
@@ -1,6 +1,6 @@
 /*****************************************************************************
  *
- * $Id:$
+ * $Id$
  *
  ****************************************************************************/
 
@@ -10,6 +10,7 @@
 
 #include "CommandFoeRead.h"
 #include "byteorder.h"
+#include "foe.h"
 
 /*****************************************************************************/
 
@@ -83,7 +84,19 @@
 		m.readFoe(&data);
 	} catch (MasterDeviceException &e) {
         delete [] data.buffer;
-		throw e;
+        if (data.result) {
+            if (data.result == FOE_OPCODE_ERROR) {
+                err << "FoE read aborted with error code 0x"
+                    << setw(8) << setfill('0') << hex << data.error_code
+                    << ": " << errorText(data.error_code);
+            } else {
+                err << "Failed to write via FoE: "
+                    << resultText(data.result);
+            }
+            throwCommandException(err);
+        } else {
+            throw e;
+        }
 	}
 
     // TODO --output-file
--- a/tool/CommandFoeWrite.cpp	Mon Jan 19 10:18:41 2009 +0000
+++ b/tool/CommandFoeWrite.cpp	Mon Jan 19 12:36:18 2009 +0000
@@ -1,6 +1,6 @@
 /*****************************************************************************
  *
- * $Id:$
+ * $Id$
  *
  ****************************************************************************/
 
@@ -13,6 +13,7 @@
 
 #include "CommandFoeWrite.h"
 #include "byteorder.h"
+#include "foe.h"
 
 /*****************************************************************************/
 
@@ -120,9 +121,15 @@
     } catch (MasterDeviceException &e) {
         if (data.buffer_size)
             delete [] data.buffer;
-        if (data.abort_code) {
-            err << "Failed to write via FoE: "
-                << errorString(data.abort_code);
+        if (data.result) {
+            if (data.result == FOE_OPCODE_ERROR) {
+                err << "FoE write aborted with error code 0x"
+                    << setw(8) << setfill('0') << hex << data.error_code
+                    << ": " << errorText(data.error_code);
+            } else {
+                err << "Failed to write via FoE: "
+                    << resultText(data.result);
+            }
             throwCommandException(err);
         } else {
             throw e;
--- a/tool/FoeCommand.cpp	Mon Jan 19 10:18:41 2009 +0000
+++ b/tool/FoeCommand.cpp	Mon Jan 19 12:36:18 2009 +0000
@@ -16,9 +16,9 @@
 
 /****************************************************************************/
 
-std::string FoeCommand::errorString(int abort_code)
+std::string FoeCommand::resultText(int result)
 {
-	switch (abort_code) {
+	switch (result) {
 		case FOE_BUSY:
 			return "FOE_BUSY";
 		case FOE_READY:
@@ -35,8 +35,8 @@
 			return "FOE_NODATA_ERROR";
 		case FOE_PACKETNO_ERROR:
 			return "FOE_PACKETNO_ERROR";
-		case FOE_OPMODE_ERROR:
-			return "FOE_OPMODE_ERROR";
+		case FOE_OPCODE_ERROR:
+			return "FOE_OPCODE_ERROR";
 		case FOE_TIMEOUT_ERROR:
 			return "FOE_TIMEOUT_ERROR";
 		case FOE_SEND_RX_DATA_ERROR:
@@ -57,3 +57,35 @@
 }
 
 /****************************************************************************/
+
+std::string FoeCommand::errorText(int errorCode)
+{
+	switch (errorCode) {
+        case 0x00008001:
+            return "Not found.";
+        case 0x00008002:
+            return "Access denied.";
+        case 0x00008003:
+            return "Disk full.";
+        case 0x00008004:
+            return "Illegal.";
+        case 0x00008005:
+            return "Packet number wrong.";
+        case 0x00008006:
+            return "Already exists.";
+        case 0x00008007:
+            return "No user.";
+        case 0x00008008:
+            return "Bootstrap only.";
+        case 0x00008009:
+            return "Not Bootstrap.";
+        case 0x0000800a:
+            return "No rights.";
+        case 0x0000800b:
+            return "Program Error.";
+		default:
+			return "Unknown error code";
+	}
+}
+
+/****************************************************************************/
--- a/tool/FoeCommand.h	Mon Jan 19 10:18:41 2009 +0000
+++ b/tool/FoeCommand.h	Mon Jan 19 12:36:18 2009 +0000
@@ -18,7 +18,8 @@
         FoeCommand(const string &, const string &);
 
     protected:
-		static std::string errorString(int);
+		static std::string resultText(int);
+		static std::string errorText(int);
 };
 
 /****************************************************************************/