IgH EtherCAT Master  1.6.0-rc1
fsm_foe.c
Go to the documentation of this file.
1 /******************************************************************************
2  *
3  * $Id$
4  *
5  * Copyright (C) 2008 Olav Zarges, imc Messsysteme GmbH
6  * 2013 Florian Pose <fp@igh-essen.com>
7  *
8  * This file is part of the IgH EtherCAT Master.
9  *
10  * The IgH EtherCAT Master is free software; you can redistribute it and/or
11  * modify it under the terms of the GNU General Public License version 2, as
12  * published by the Free Software Foundation.
13  *
14  * The IgH EtherCAT Master is distributed in the hope that it will be useful,
15  * but WITHOUT ANY WARRANTY; without even the implied warranty of
16  * MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the GNU General
17  * Public License for more details.
18  *
19  * You should have received a copy of the GNU General Public License along
20  * with the IgH EtherCAT Master; if not, write to the Free Software
21  * Foundation, Inc., 51 Franklin St, Fifth Floor, Boston, MA 02110-1301 USA
22  *
23  * ---
24  *
25  * The license mentioned above concerns the source code only. Using the
26  * EtherCAT technology and brand is only permitted in compliance with the
27  * industrial property and similar rights of Beckhoff Automation GmbH.
28  *
29  *****************************************************************************/
30 
35 /*****************************************************************************/
36 
37 #include "globals.h"
38 #include "master.h"
39 #include "mailbox.h"
40 #include "fsm_foe.h"
41 #include "foe.h"
42 
43 /*****************************************************************************/
44 
48 #define EC_FSM_FOE_TIMEOUT_JIFFIES (3 * HZ)
49 
52 #define EC_FOE_HEADER_SIZE 6
53 // uint8_t OpCode
54 // uint8_t reserved
55 // uint32_t PacketNo, Password, ErrorCode
56 
57 //#define DEBUG_FOE
58 
59 /*****************************************************************************/
60 
63 enum {
70 };
71 
72 /*****************************************************************************/
73 
78 
79 void ec_foe_set_tx_error(ec_fsm_foe_t *, uint32_t);
80 void ec_foe_set_rx_error(ec_fsm_foe_t *, uint32_t);
81 
84 
87 
91 
93 
98 
101 
102 /*****************************************************************************/
103 
107  ec_fsm_foe_t *fsm
108  )
109 {
110  fsm->state = NULL;
111  fsm->datagram = NULL;
112 }
113 
114 /*****************************************************************************/
115 
119 {
120 }
121 
122 /*****************************************************************************/
123 
129  ec_fsm_foe_t *fsm,
130  ec_datagram_t *datagram
131  )
132 {
133  if (fsm->state == ec_fsm_foe_end || fsm->state == ec_fsm_foe_error)
134  return 0;
135 
136  if (fsm->datagram &&
137  (fsm->datagram->state == EC_DATAGRAM_INIT ||
138  fsm->datagram->state == EC_DATAGRAM_QUEUED ||
139  fsm->datagram->state == EC_DATAGRAM_SENT)) {
140  // datagram not received yet
141  if (datagram != fsm->datagram)
142  datagram->state = EC_DATAGRAM_INVALID;
143  return 1;
144  }
145 
146  fsm->state(fsm, datagram);
147 
148  if (fsm->state == ec_fsm_foe_end || fsm->state == ec_fsm_foe_error) {
149  fsm->datagram = NULL;
150  return 0;
151  }
152 
153  fsm->datagram = datagram;
154  return 1;
155 }
156 
157 /*****************************************************************************/
158 
163 {
164  return fsm->state == ec_fsm_foe_end;
165 }
166 
167 /*****************************************************************************/
168 
172  ec_fsm_foe_t *fsm,
173  ec_slave_t *slave,
174  ec_foe_request_t *request
175  )
176 {
177  fsm->slave = slave;
178  fsm->request = request;
179 
180  if (request->dir == EC_DIR_OUTPUT) {
181  fsm->tx_buffer = fsm->request->buffer;
182  fsm->tx_buffer_size = fsm->request->data_size;
183  fsm->tx_buffer_offset = 0;
184 
185  fsm->tx_filename = fsm->request->file_name;
186  fsm->tx_filename_len = strlen(fsm->tx_filename);
187 
189  }
190  else {
191  fsm->rx_buffer = fsm->request->buffer;
192  fsm->rx_buffer_size = fsm->request->buffer_size;
193 
194  fsm->rx_filename = fsm->request->file_name;
195  fsm->rx_filename_len = strlen(fsm->rx_filename);
196 
198  }
199 }
200 
201 /*****************************************************************************/
202 
206  ec_fsm_foe_t *fsm,
207  ec_datagram_t *datagram
208  )
209 {
210 #ifdef DEBUG_FOE
211  EC_SLAVE_DBG(fsm->slave, 0, "%s()\n", __func__);
212 #endif
213 }
214 
215 /*****************************************************************************/
216 
220  ec_fsm_foe_t *fsm,
221  ec_datagram_t *datagram
222  )
223 {
224 #ifdef DEBUG_FOE
225  EC_SLAVE_DBG(fsm->slave, 0, "%s()\n", __func__);
226 #endif
227 }
228 
229 /*****************************************************************************/
230 
236  ec_fsm_foe_t *fsm,
237  ec_datagram_t *datagram
238  )
239 {
240  size_t remaining_size, current_size;
241  uint8_t *data;
242 
243  remaining_size = fsm->tx_buffer_size - fsm->tx_buffer_offset;
244 
245  if (remaining_size < fsm->slave->configured_tx_mailbox_size
247  current_size = remaining_size;
248  fsm->tx_last_packet = 1;
249  } else {
250  current_size = fsm->slave->configured_tx_mailbox_size
252  }
253 
254  data = ec_slave_mbox_prepare_send(fsm->slave,
255  datagram, EC_MBOX_TYPE_FOE, current_size + EC_FOE_HEADER_SIZE);
256  if (IS_ERR(data)) {
257  return -1;
258  }
259 
260  EC_WRITE_U16(data, EC_FOE_OPCODE_DATA); // OpCode = DataBlock req.
261  EC_WRITE_U32(data + 2, fsm->tx_packet_no); // PacketNo, Password
262 #ifdef DEBUG_FOE
263  EC_SLAVE_DBG(fsm->slave, 0, "sending opcode %u packet %u\n",
265 #endif
266 
267  memcpy(data + EC_FOE_HEADER_SIZE,
268  fsm->tx_buffer + fsm->tx_buffer_offset, current_size);
269  fsm->tx_current_size = current_size;
270 
271  return 0;
272 }
273 
274 /*****************************************************************************/
275 
281  ec_fsm_foe_t *fsm,
282  ec_datagram_t *datagram
283  )
284 {
285  size_t current_size;
286  uint8_t *data;
287 
288  fsm->tx_buffer_offset = 0;
289  fsm->tx_current_size = 0;
290  fsm->tx_packet_no = 0;
291  fsm->tx_last_packet = 0;
292 
293  current_size = fsm->tx_filename_len;
294 
295  data = ec_slave_mbox_prepare_send(fsm->slave, datagram,
296  EC_MBOX_TYPE_FOE, current_size + EC_FOE_HEADER_SIZE);
297  if (IS_ERR(data)) {
298  return -1;
299  }
300 
301  EC_WRITE_U16( data, EC_FOE_OPCODE_WRQ); // fsm write request
302  EC_WRITE_U32( data + 2, fsm->request->password );
303 #ifdef DEBUG_FOE
304  EC_SLAVE_DBG(fsm->slave, 0, "sending opcode %u packet %u\n",
306 #endif
307 
308  memcpy(data + EC_FOE_HEADER_SIZE, fsm->tx_filename, current_size);
309 
310  return 0;
311 }
312 
313 /*****************************************************************************/
314 
318  ec_fsm_foe_t *fsm,
319  ec_datagram_t *datagram
320  )
321 {
322  ec_slave_t *slave = fsm->slave;
323 
324  fsm->tx_buffer_offset = 0;
325  fsm->tx_current_size = 0;
326  fsm->tx_packet_no = 0;
327  fsm->tx_last_packet = 0;
328 
329 #ifdef DEBUG_FOE
330  EC_SLAVE_DBG(fsm->slave, 0, "%s()\n", __func__);
331 #endif
332 
333  if (!(slave->sii.mailbox_protocols & EC_MBOX_FOE)) {
335  EC_SLAVE_ERR(slave, "Slave does not support FoE!\n");
336  return;
337  }
338 
339  if (ec_foe_prepare_wrq_send(fsm, datagram)) {
341  return;
342  }
343 
345 }
346 
347 /*****************************************************************************/
348 
352  ec_fsm_foe_t *fsm,
353  ec_datagram_t *datagram
354  )
355 {
356  ec_slave_t *slave = fsm->slave;
357 
358 #ifdef DEBUG_FOE
359  EC_SLAVE_DBG(fsm->slave, 0, "%s()\n", __func__);
360 #endif
361 
362  if (fsm->datagram->state != EC_DATAGRAM_RECEIVED) {
365  EC_SLAVE_ERR(slave, "Failed to receive FoE mailbox check datagram: ");
367  return;
368  }
369 
370  if (fsm->datagram->working_counter != 1) {
373  EC_SLAVE_ERR(slave, "Reception of FoE mailbox check datagram"
374  " failed: ");
376  return;
377  }
378 
379  if (!ec_slave_mbox_check(fsm->datagram)) {
380  // slave did not put anything in the mailbox yet
381 
382  // check that data is not already received by another read request
383  if (slave->mbox_foe_data.payload_size > 0) {
386  fsm->state(fsm, datagram);
387  return;
388  }
389 
390  if (time_after(fsm->datagram->jiffies_received,
394  EC_SLAVE_ERR(slave, "Timeout while waiting for ack response.\n");
395  return;
396  }
397 
398  ec_slave_mbox_prepare_check(slave, datagram); // can not fail.
399  fsm->retries = EC_FSM_RETRIES;
400  return;
401  }
402 
403  // Fetch response
404  ec_slave_mbox_prepare_fetch(slave, datagram); // can not fail.
405 
406  fsm->retries = EC_FSM_RETRIES;
408 }
409 
410 /*****************************************************************************/
411 
415  ec_fsm_foe_t *fsm,
416  ec_datagram_t *datagram
417  )
418 {
419  ec_slave_t *slave = fsm->slave;
420 
421 #ifdef DEBUG_FOE
422  EC_SLAVE_DBG(fsm->slave, 0, "%s()\n", __func__);
423 #endif
424 
425  if (fsm->datagram->state != EC_DATAGRAM_RECEIVED) {
428  EC_SLAVE_ERR(slave, "Failed to receive FoE ack response datagram: ");
430  return;
431  }
432 
433  if (fsm->datagram->working_counter != 1) {
434  // only an error if data has not already been read by another read request
435  if (slave->mbox_foe_data.payload_size == 0) {
438  EC_SLAVE_ERR(slave, "Reception of FoE ack response failed: ");
440  return;
441  }
442  }
445  fsm->state(fsm, datagram);
446 }
447 
448 /*****************************************************************************/
449 
453  ec_fsm_foe_t *fsm,
454  ec_datagram_t *datagram
455  )
456 {
457  ec_slave_t *slave = fsm->slave;
458  uint8_t *data, mbox_prot;
459  uint8_t opCode;
460  size_t rec_size;
461 
462  // process the data available or initiate a new mailbox read check
463  if (slave->mbox_foe_data.payload_size > 0) {
464  slave->mbox_foe_data.payload_size = 0;
465  } else {
466  // initiate a new mailbox read check if required data is not available
467  if (ec_read_mbox_locked(slave)) {
468  // await current read request and mark the datagram as invalid
469  datagram->state = EC_DATAGRAM_INVALID;
470  } else {
471  ec_slave_mbox_prepare_check(slave, datagram); // can not fail.
473  }
474  return;
475  }
476 
477  data = ec_slave_mbox_fetch(slave, &slave->mbox_foe_data, &mbox_prot, &rec_size);
478  if (IS_ERR(data)) {
480  return;
481  }
482 
483  if (mbox_prot != EC_MBOX_TYPE_FOE) {
485  EC_SLAVE_ERR(slave, "Received mailbox protocol 0x%02X as response.\n",
486  mbox_prot);
487  return;
488  }
489 
490  opCode = EC_READ_U8(data);
491 #ifdef DEBUG_FOE
492  EC_SLAVE_DBG(fsm->slave, 0, "received opcode %u\n", opCode);
493 #endif
494 
495  if (opCode == EC_FOE_OPCODE_BUSY) {
496  // slave not ready
497  if (ec_foe_prepare_data_send(fsm, datagram)) {
499  EC_SLAVE_ERR(slave, "Slave is busy.\n");
500  return;
501  }
503  return;
504  }
505 
506  if (opCode == EC_FOE_OPCODE_ERR) {
507  fsm->request->error_code = EC_READ_U32(data + 2);
508  EC_SLAVE_ERR(slave, "Received FoE Error Request (code 0x%08x).\n",
509  fsm->request->error_code);
510  if (rec_size > 6 && data[6]) {
511  uint8_t text[256];
512  strncpy(text, data + 6, min(rec_size - 6, sizeof(text)));
513  text[sizeof(text)-1] = 0;
514  EC_SLAVE_ERR(slave, "FoE Error Text: %s\n", text);
515  }
517  return;
518  }
519 
520  if (opCode == EC_FOE_OPCODE_ACK) {
521  fsm->tx_packet_no++;
522  fsm->tx_buffer_offset += fsm->tx_current_size;
523 
524  if (fsm->tx_last_packet) {
525  fsm->state = ec_fsm_foe_end;
526  return;
527  }
528 
529  if (ec_foe_prepare_data_send(fsm, datagram)) {
531  return;
532  }
534  return;
535  }
537 }
538 
539 /*****************************************************************************/
540 
547  ec_fsm_foe_t *fsm,
548  ec_datagram_t *datagram
549  )
550 {
551  ec_slave_t *slave = fsm->slave;
552 
553 #ifdef DEBUG_FOE
554  EC_SLAVE_DBG(fsm->slave, 0, "%s()\n", __func__);
555 #endif
556 
557  if (fsm->datagram->state != EC_DATAGRAM_RECEIVED) {
559  EC_SLAVE_ERR(slave, "Failed to send FoE WRQ: ");
561  return;
562  }
563 
564  if (fsm->datagram->working_counter != 1) {
565  // slave did not put anything in the mailbox yet
567  EC_SLAVE_ERR(slave, "Reception of FoE WRQ failed: ");
569  return;
570  }
571 
572  fsm->jiffies_start = fsm->datagram->jiffies_sent;
573 
574  // mailbox read check is skipped if a read request is already ongoing
575  if (ec_read_mbox_locked(slave)) {
577  // the datagram is not used and marked as invalid
578  datagram->state = EC_DATAGRAM_INVALID;
579  } else {
580  ec_slave_mbox_prepare_check(slave, datagram); // can not fail.
581  fsm->retries = EC_FSM_RETRIES;
583  }
584 }
585 
586 /*****************************************************************************/
587 
594  ec_fsm_foe_t *fsm,
595  ec_datagram_t *datagram
596  )
597 {
598  ec_slave_t *slave = fsm->slave;
599 
600 #ifdef DEBUG_FOE
601  EC_SLAVE_DBG(fsm->slave, 0, "%s()\n", __func__);
602 #endif
603 
604  if (fsm->datagram->state != EC_DATAGRAM_RECEIVED) {
606  EC_SLAVE_ERR(slave, "Failed to receive FoE ack response datagram: ");
608  return;
609  }
610 
611  if (fsm->datagram->working_counter != 1) {
613  EC_SLAVE_ERR(slave, "Reception of FoE data send failed: ");
615  return;
616  }
617 
618  fsm->jiffies_start = jiffies;
619 
620  // mailbox read check is skipped if a read request is already ongoing
621  if (ec_read_mbox_locked(slave)) {
623  // the datagram is not used and marked as invalid
624  datagram->state = EC_DATAGRAM_INVALID;
625  } else {
626  ec_slave_mbox_prepare_check(slave, datagram);
627  fsm->retries = EC_FSM_RETRIES;
629  }
630 }
631 
632 /*****************************************************************************/
633 
639  ec_fsm_foe_t *fsm,
640  ec_datagram_t *datagram
641  )
642 {
643  size_t current_size;
644  uint8_t *data;
645 
646  current_size = fsm->rx_filename_len;
647 
648  data = ec_slave_mbox_prepare_send(fsm->slave, datagram,
649  EC_MBOX_TYPE_FOE, current_size + EC_FOE_HEADER_SIZE);
650  if (IS_ERR(data)) {
651  return -1;
652  }
653 
654  EC_WRITE_U16(data, EC_FOE_OPCODE_RRQ); // fsm read request
655  EC_WRITE_U32(data + 2, fsm->request->password);
656  memcpy(data + EC_FOE_HEADER_SIZE, fsm->rx_filename, current_size);
657 #ifdef DEBUG_FOE
658  EC_SLAVE_DBG(fsm->slave, 0, "sending opcode %u\n", EC_FOE_OPCODE_RRQ);
659 #endif
660 
661  if (fsm->slave->master->debug_level) {
662  EC_SLAVE_DBG(fsm->slave, 1, "FoE Read Request:\n");
663  ec_print_data(data, current_size + EC_FOE_HEADER_SIZE);
664  }
665 
666  return 0;
667 }
668 
669 /*****************************************************************************/
670 
676  ec_fsm_foe_t *fsm,
677  ec_datagram_t *datagram
678  )
679 {
680  uint8_t *data;
681 
682  data = ec_slave_mbox_prepare_send(fsm->slave, datagram,
683  EC_MBOX_TYPE_FOE, EC_FOE_HEADER_SIZE);
684  if (IS_ERR(data)) {
685  return -1;
686  }
687 
689  EC_WRITE_U32(data + 2, fsm->rx_expected_packet_no);
690 #ifdef DEBUG_FOE
691  EC_SLAVE_DBG(fsm->slave, 0, "sending opcode %u packet %u\n",
693 #endif
694 
695  return 0;
696 }
697 
698 /*****************************************************************************/
699 
706  ec_fsm_foe_t *fsm,
707  ec_datagram_t *datagram
708  )
709 {
710  ec_slave_t *slave = fsm->slave;
711 
712 #ifdef DEBUG_FOE
713  EC_SLAVE_DBG(fsm->slave, 0, "%s()\n", __func__);
714 #endif
715 
716  if (fsm->datagram->state != EC_DATAGRAM_RECEIVED) {
719  EC_SLAVE_ERR(slave, "Failed to send FoE RRQ: ");
721  return;
722  }
723 
724  if (fsm->datagram->working_counter != 1) {
725  // slave did not put anything in the mailbox yet
728  EC_SLAVE_ERR(slave, "Reception of FoE RRQ failed: ");
730  return;
731  }
732 
733  fsm->jiffies_start = fsm->datagram->jiffies_sent;
734 
735  // mailbox read check is skipped if a read request is already ongoing
736  if (ec_read_mbox_locked(slave)) {
738  // the datagram is not used and marked as invalid
739  datagram->state = EC_DATAGRAM_INVALID;
740  } else {
741  ec_slave_mbox_prepare_check(slave, datagram); // can not fail.
742  fsm->retries = EC_FSM_RETRIES;
744  }
745 }
746 
747 /*****************************************************************************/
748 
752  ec_fsm_foe_t *fsm,
753  ec_datagram_t *datagram
754  )
755 {
756  ec_slave_t *slave = fsm->slave;
757 
758  fsm->rx_buffer_offset = 0;
759  fsm->rx_expected_packet_no = 1;
760  fsm->rx_last_packet = 0;
761 
762 #ifdef DEBUG_FOE
763  EC_SLAVE_DBG(fsm->slave, 0, "%s()\n", __func__);
764 #endif
765 
766  if (!(slave->sii.mailbox_protocols & EC_MBOX_FOE)) {
768  EC_SLAVE_ERR(slave, "Slave does not support FoE!\n");
769  return;
770  }
771 
772  if (ec_foe_prepare_rrq_send(fsm, datagram)) {
774  return;
775  }
776 
778 }
779 
780 /*****************************************************************************/
781 
785  ec_fsm_foe_t *fsm,
786  ec_datagram_t *datagram
787  )
788 {
789  ec_slave_t *slave = fsm->slave;
790 
791 #ifdef DEBUG_FOE
792  EC_SLAVE_DBG(fsm->slave, 0, "%s()\n", __func__);
793 #endif
794 
795  if (fsm->datagram->state != EC_DATAGRAM_RECEIVED) {
798  EC_SLAVE_ERR(slave, "Failed to send FoE DATA READ: ");
800  return;
801  }
802 
803  if (fsm->datagram->working_counter != 1) {
806  EC_SLAVE_ERR(slave, "Reception of FoE DATA READ: ");
808  return;
809  }
810 
811  if (!ec_slave_mbox_check(fsm->datagram)) {
812  // check that data is not already received by another read request
813  if (slave->mbox_foe_data.payload_size > 0) {
816  fsm->state(fsm, datagram);
817  return;
818  }
819 
820  if (time_after(fsm->datagram->jiffies_received,
824  EC_SLAVE_ERR(slave, "Timeout while waiting for ack response.\n");
825  return;
826  }
827 
828  ec_slave_mbox_prepare_check(slave, datagram); // can not fail.
829  fsm->retries = EC_FSM_RETRIES;
830  return;
831  }
832 
833  // Fetch response
834  ec_slave_mbox_prepare_fetch(slave, datagram); // can not fail.
835 
836  fsm->retries = EC_FSM_RETRIES;
838 }
839 
840 /*****************************************************************************/
841 
845  ec_fsm_foe_t *fsm,
846  ec_datagram_t *datagram
847  )
848 {
849  ec_slave_t *slave = fsm->slave;
850 
851 #ifdef DEBUG_FOE
852  EC_SLAVE_DBG(fsm->slave, 0, "%s()\n", __func__);
853 #endif
854 
855  if (fsm->datagram->state != EC_DATAGRAM_RECEIVED) {
858  EC_SLAVE_ERR(slave, "Failed to receive FoE DATA READ datagram: ");
860  return;
861  }
862 
863  if (fsm->datagram->working_counter != 1) {
864  // only an error if data has not already been read by another read request
865  if (slave->mbox_foe_data.payload_size == 0) {
868  EC_SLAVE_ERR(slave, "Reception of FoE DATA READ failed: ");
870  return;
871  }
872  }
875  fsm->state(fsm, datagram);
876 }
877 
878 /*****************************************************************************/
879 
883  ec_fsm_foe_t *fsm,
884  ec_datagram_t *datagram
885  )
886 {
887  ec_slave_t *slave = fsm->slave;
888  size_t rec_size;
889  uint8_t *data, opCode, packet_no, mbox_prot;
890 
891  // process the data available or initiate a new mailbox read check
892  if (slave->mbox_foe_data.payload_size > 0) {
893  slave->mbox_foe_data.payload_size = 0;
894  } else {
895  // initiate a new mailbox read check if required data is not available
896  if (ec_read_mbox_locked(slave)) {
897  // await current read request and mark the datagram as invalid
898  datagram->state = EC_DATAGRAM_INVALID;
899  } else {
900  ec_slave_mbox_prepare_check(slave, datagram); // can not fail.
902  }
903  return;
904  }
905 
906  data = ec_slave_mbox_fetch(slave, &slave->mbox_foe_data, &mbox_prot, &rec_size);
907  if (IS_ERR(data)) {
909  return;
910  }
911 
912  if (mbox_prot != EC_MBOX_TYPE_FOE) {
913  EC_SLAVE_ERR(slave, "Received mailbox protocol 0x%02X as response.\n",
914  mbox_prot);
916  return;
917  }
918 
919  opCode = EC_READ_U8(data);
920 #ifdef DEBUG_FOE
921  EC_SLAVE_DBG(fsm->slave, 0, "received opcode %u\n", opCode);
922 #endif
923 
924  if (opCode == EC_FOE_OPCODE_BUSY) {
925  fsm->rx_expected_packet_no--;
926  if (ec_foe_prepare_send_ack(fsm, datagram)) {
928  } else {
930  }
931 #ifdef DEBUG_FOE
932  EC_SLAVE_DBG(fsm->slave, 0, "%s() busy. Next pkt %u\n", __func__,
933  fsm->rx_expected_packet_no);
934 #endif
935  return;
936  }
937 
938  if (opCode == EC_FOE_OPCODE_ERR) {
939  fsm->request->error_code = EC_READ_U32(data + 2);
940  EC_SLAVE_ERR(slave, "Received FoE Error Request (code 0x%08x).\n",
941  fsm->request->error_code);
942  if (rec_size > 6 && data[6]) {
943  uint8_t text[256];
944  strncpy(text, data + 6, min(rec_size - 6, sizeof(text)));
945  text[sizeof(text)-1] = 0;
946  EC_SLAVE_ERR(slave, "FoE Error Text: %s\n", text);
947  }
949  return;
950  }
951 
952  if (opCode != EC_FOE_OPCODE_DATA) {
953  EC_SLAVE_ERR(slave, "Received OPCODE %x, expected %x.\n",
954  opCode, EC_FOE_OPCODE_DATA);
955  fsm->request->error_code = 0x00000000;
957  return;
958  }
959 
960  packet_no = EC_READ_U32(data + 2);
961  if (packet_no != fsm->rx_expected_packet_no) {
962  EC_SLAVE_ERR(slave, "Received packet number %u, expected %u.\n",
963  packet_no, fsm->rx_expected_packet_no);
965  return;
966  }
967 
968  rec_size -= EC_FOE_HEADER_SIZE;
969 
970  if (fsm->rx_buffer_size >= fsm->rx_buffer_offset + rec_size) {
971  memcpy(fsm->rx_buffer + fsm->rx_buffer_offset,
972  data + EC_FOE_HEADER_SIZE, rec_size);
973  fsm->rx_buffer_offset += rec_size;
974  }
975 
976  fsm->rx_last_packet =
978  != slave->configured_rx_mailbox_size);
979 
980  if (fsm->rx_last_packet ||
983  <= fsm->rx_buffer_size) {
984  // either it was the last packet or a new packet will fit into the
985  // delivered buffer
986 #ifdef DEBUG_FOE
987  EC_SLAVE_DBG(fsm->slave, 0, "last_packet=true\n");
988 #endif
989  if (ec_foe_prepare_send_ack(fsm, datagram)) {
991  return;
992  }
993 
995  }
996  else {
997  // no more data fits into the delivered buffer
998  // ... wait for new read request
999  EC_SLAVE_ERR(slave, "Data do not fit in receive buffer!\n");
1000  printk(KERN_CONT " rx_buffer_size = %d\n", fsm->rx_buffer_size);
1001  printk(KERN_CONT "rx_buffer_offset = %d\n", fsm->rx_buffer_offset);
1002  printk(KERN_CONT " rec_size = %zd\n", rec_size);
1003  printk(KERN_CONT " rx_mailbox_size = %d\n",
1005  printk(KERN_CONT " rx_last_packet = %d\n", fsm->rx_last_packet);
1006  fsm->request->result = FOE_READY;
1007  }
1008 }
1009 
1010 /*****************************************************************************/
1011 
1015  ec_fsm_foe_t *fsm,
1016  ec_datagram_t *datagram
1017  )
1018 {
1019  ec_slave_t *slave = fsm->slave;
1020 
1021 #ifdef DEBUG_FOE
1022  EC_SLAVE_DBG(fsm->slave, 0, "%s()\n", __func__);
1023 #endif
1024 
1025  if (fsm->datagram->state != EC_DATAGRAM_RECEIVED) {
1027  EC_SLAVE_ERR(slave, "Failed to send FoE ACK: ");
1029  return;
1030  }
1031 
1032  if (fsm->datagram->working_counter != 1) {
1033  // slave did not put anything into the mailbox yet
1035  EC_SLAVE_ERR(slave, "Reception of FoE ACK failed: ");
1037  return;
1038  }
1039 
1040  fsm->jiffies_start = fsm->datagram->jiffies_sent;
1041 
1042  if (fsm->rx_last_packet) {
1043  fsm->rx_expected_packet_no = 0;
1044  fsm->request->data_size = fsm->rx_buffer_offset;
1045  fsm->state = ec_fsm_foe_end;
1046  }
1047  else {
1048  fsm->rx_expected_packet_no++;
1049 
1050  // mailbox read check is skipped if a read request is already ongoing
1051  if (ec_read_mbox_locked(slave)) {
1053  // the datagram is not used and marked as invalid
1054  datagram->state = EC_DATAGRAM_INVALID;
1055  } else {
1056  ec_slave_mbox_prepare_check(slave, datagram); // can not fail.
1057  fsm->retries = EC_FSM_RETRIES;
1059  }
1060  }
1061 }
1062 
1063 /*****************************************************************************/
1064 
1068  ec_fsm_foe_t *fsm,
1069  uint32_t errorcode
1070  )
1071 {
1072  fsm->request->result = errorcode;
1073  fsm->state = ec_fsm_foe_error;
1074 }
1075 
1076 /*****************************************************************************/
1077 
1081  ec_fsm_foe_t *fsm,
1082  uint32_t errorcode
1083  )
1084 {
1085  fsm->request->result = errorcode;
1086  fsm->state = ec_fsm_foe_error;
1087 }
1088 
1089 /*****************************************************************************/
uint8_t * tx_filename
Name of file to transmit.
Definition: fsm_foe.h:70
#define EC_FSM_RETRIES
Number of state machine retries on datagram timeout.
Definition: globals.h:47
Receive error.
Definition: foe.h:46
ec_slave_t * slave
Slave the FSM runs on.
Definition: fsm_foe.h:54
uint8_t * rx_buffer
Buffer for received data.
Definition: fsm_foe.h:73
uint8_t * ec_slave_mbox_prepare_send(const ec_slave_t *slave, ec_datagram_t *datagram, uint8_t type, size_t size)
Prepares a mailbox-send datagram.
Definition: mailbox.c:51
unsigned long jiffies_sent
Jiffies, when the datagram was sent.
Definition: datagram.h:105
void ec_fsm_foe_state_ack_read(ec_fsm_foe_t *, ec_datagram_t *)
Acknowledge a read operation.
Definition: fsm_foe.c:414
ec_sii_t sii
Extracted SII data.
Definition: slave.h:246
Error fetching data from mailbox.
Definition: foe.h:55
int ec_fsm_foe_success(const ec_fsm_foe_t *fsm)
Returns, if the state machine terminated with success.
Definition: fsm_foe.c:162
ec_direction_t dir
Direction.
Definition: foe_request.h:60
uint16_t configured_tx_mailbox_size
Configured send mailbox size.
Definition: slave.h:224
void ec_fsm_foe_clear(ec_fsm_foe_t *fsm)
Destructor.
Definition: fsm_foe.c:118
int ec_foe_prepare_data_send(ec_fsm_foe_t *, ec_datagram_t *)
Sends a file or the next fragment.
Definition: fsm_foe.c:235
#define EC_SLAVE_DBG(slave, level, fmt, args...)
Convenience macro for printing slave-specific debug messages to syslog.
Definition: slave.h:107
Working counter error.
Definition: foe.h:45
uint32_t tx_packet_no
FoE packet number.
Definition: fsm_foe.h:68
unsigned long jiffies_start
FoE timestamp.
Definition: fsm_foe.h:59
Read request.
Definition: fsm_foe.c:64
void ec_fsm_foe_error(ec_fsm_foe_t *, ec_datagram_t *)
State: ERROR.
Definition: fsm_foe.c:205
ec_mbox_data_t mbox_foe_data
Received mailbox data for FoE.
Definition: slave.h:269
Packet number error.
Definition: foe.h:49
int ec_slave_mbox_prepare_fetch(const ec_slave_t *slave, ec_datagram_t *datagram)
Prepares a datagram to fetch mailbox data.
Definition: mailbox.c:128
EtherCAT datagram.
Definition: datagram.h:88
void ec_fsm_foe_state_data_check(ec_fsm_foe_t *, ec_datagram_t *)
Check for data.
Definition: fsm_foe.c:784
uint8_t * tx_buffer
Buffer with data to transmit.
Definition: fsm_foe.h:64
uint32_t tx_buffer_offset
Offset of data to tranmit next.
Definition: fsm_foe.h:66
#define EC_FOE_HEADER_SIZE
Size of the FoE header.
Definition: fsm_foe.c:52
uint8_t * ec_slave_mbox_fetch(const ec_slave_t *slave, ec_mbox_data_t *response_data, uint8_t *type, size_t *size)
Processes received mailbox data.
Definition: mailbox.c:166
int ec_foe_prepare_send_ack(ec_fsm_foe_t *, ec_datagram_t *)
Prepare to send an acknowledge.
Definition: fsm_foe.c:675
uint16_t working_counter
Working counter.
Definition: datagram.h:100
void ec_fsm_foe_transfer(ec_fsm_foe_t *fsm, ec_slave_t *slave, ec_foe_request_t *request)
Prepares an FoE transfer.
Definition: fsm_foe.c:171
void ec_fsm_foe_state_wrq_sent(ec_fsm_foe_t *, ec_datagram_t *)
State: WRQ SENT.
Definition: fsm_foe.c:546
uint32_t tx_filename_len
Lenth of transmit file name.
Definition: fsm_foe.h:71
uint32_t rx_filename_len
Length of the receive file name.
Definition: fsm_foe.h:79
Sent (still in the queue).
Definition: datagram.h:77
uint32_t result
FoE request abort code.
Definition: foe_request.h:69
void ec_fsm_foe_state_data_read_data(ec_fsm_foe_t *, ec_datagram_t *)
Process a read data operation.
Definition: fsm_foe.c:882
void ec_foe_set_rx_error(ec_fsm_foe_t *, uint32_t)
Set an error code and go to the receive error state.
Definition: fsm_foe.c:1080
Global definitions and macros.
EtherCAT master structure.
Initial state of a new datagram.
Definition: datagram.h:75
EtherCAT slave.
Definition: slave.h:199
size_t buffer_size
Size of FoE data memory.
Definition: foe_request.h:53
void ec_fsm_foe_end(ec_fsm_foe_t *, ec_datagram_t *)
State: END.
Definition: fsm_foe.c:219
uint32_t tx_last_packet
Current packet is last one to send.
Definition: fsm_foe.h:67
OpCode error.
Definition: foe.h:50
void ec_fsm_foe_init(ec_fsm_foe_t *fsm)
Constructor.
Definition: fsm_foe.c:106
ec_datagram_state_t state
State.
Definition: datagram.h:101
#define EC_WRITE_U32(DATA, VAL)
Write a 32-bit unsigned value to EtherCAT data.
Definition: ecrt.h:2372
uint8_t * buffer
Pointer to FoE data.
Definition: foe_request.h:52
uint32_t rx_expected_packet_no
Expected receive packet number.
Definition: fsm_foe.h:76
uint16_t mailbox_protocols
Supported mailbox protocols.
Definition: slave.h:170
Error acknowledging received data.
Definition: foe.h:53
unsigned int debug_level
Master debug level.
Definition: master.h:285
#define EC_SLAVE_ERR(slave, fmt, args...)
Convenience macro for printing slave-specific errors to syslog.
Definition: slave.h:77
void ec_datagram_print_wc_error(const ec_datagram_t *datagram)
Evaluates the working counter of a single-cast datagram.
Definition: datagram.c:606
void ec_fsm_foe_state_ack_check(ec_fsm_foe_t *, ec_datagram_t *)
Check for acknowledge.
Definition: fsm_foe.c:351
uint32_t rx_buffer_size
Size of receive buffer.
Definition: fsm_foe.h:74
#define EC_WRITE_U16(DATA, VAL)
Write a 16-bit unsigned value to EtherCAT data.
Definition: ecrt.h:2355
#define EC_READ_U32(DATA)
Read a 32-bit unsigned value from EtherCAT data.
Definition: ecrt.h:2266
void ec_fsm_foe_read_start(ec_fsm_foe_t *, ec_datagram_t *)
Starting state for read operations.
Definition: fsm_foe.c:751
Timeout error.
Definition: foe.h:51
ec_master_t * master
Master owning the slave.
Definition: slave.h:201
int ec_read_mbox_locked(ec_slave_t *slave)
Return the current mailbox lock status and lock it if not locked.
Definition: slave.c:203
uint32_t tx_buffer_size
Size of data to transmit.
Definition: fsm_foe.h:65
void ec_fsm_foe_state_data_read(ec_fsm_foe_t *, ec_datagram_t *)
Start reading data.
Definition: fsm_foe.c:844
FoE defines.
#define EC_MBOX_HEADER_SIZE
Mailbox header size.
Definition: globals.h:89
size_t data_size
Size of FoE data.
Definition: foe_request.h:54
void ec_fsm_foe_write_start(ec_fsm_foe_t *, ec_datagram_t *)
Initializes the FoE write state machine.
Definition: fsm_foe.c:317
uint32_t rx_last_packet
Current packet is the last to receive.
Definition: fsm_foe.h:77
void ec_print_data(const uint8_t *, size_t)
Outputs frame contents for debugging purposes.
Definition: module.c:345
void ec_read_mbox_lock_clear(ec_slave_t *slave)
Clears the mailbox lock.
Definition: slave.c:190
uint8_t * file_name
Pointer to the filename.
Definition: foe_request.h:67
void ec_fsm_foe_state_rrq_sent(ec_fsm_foe_t *, ec_datagram_t *)
State: RRQ SENT.
Definition: fsm_foe.c:705
unsigned int retries
Retries upon datagram timeout.
Definition: fsm_foe.h:55
FoE request.
Definition: foe_request.h:50
int ec_slave_mbox_prepare_check(const ec_slave_t *slave, ec_datagram_t *datagram)
Prepares a datagram for checking the mailbox state.
Definition: mailbox.c:97
Protocol error.
Definition: foe.h:47
ec_datagram_t * datagram
Datagram used in previous step.
Definition: fsm_foe.h:58
int ec_fsm_foe_exec(ec_fsm_foe_t *fsm, ec_datagram_t *datagram)
Executes the current state of the state machine.
Definition: fsm_foe.c:128
void ec_datagram_print_state(const ec_datagram_t *datagram)
Prints the state of a datagram.
Definition: datagram.c:566
Mailbox functionality.
Acknowledge.
Definition: fsm_foe.c:67
ec_foe_request_t * request
FoE request.
Definition: fsm_foe.h:61
Queued for sending.
Definition: datagram.h:76
void ec_foe_set_tx_error(ec_fsm_foe_t *, uint32_t)
Set an error code and go to the send error state.
Definition: fsm_foe.c:1067
Ready.
Definition: foe.h:43
uint16_t configured_rx_mailbox_size
Configured receive mailbox size.
Definition: slave.h:220
void(* state)(ec_fsm_foe_t *, ec_datagram_t *)
FoE state function.
Definition: fsm_foe.h:57
Mailbox protocol error.
Definition: foe.h:57
int ec_foe_prepare_rrq_send(ec_fsm_foe_t *, ec_datagram_t *)
Prepare a read request (RRQ) with filename.
Definition: fsm_foe.c:638
void ec_fsm_foe_state_data_sent(ec_fsm_foe_t *, ec_datagram_t *)
State: WRQ SENT.
Definition: fsm_foe.c:593
int ec_foe_prepare_wrq_send(ec_fsm_foe_t *, ec_datagram_t *)
Prepare a write request (WRQ) with filename.
Definition: fsm_foe.c:280
#define EC_READ_U8(DATA)
Read an 8-bit unsigned value from EtherCAT data.
Definition: ecrt.h:2234
uint8_t * rx_filename
Name of the file to receive.
Definition: fsm_foe.h:78
uint32_t error_code
Error code from an FoE Error Request.
Definition: foe_request.h:70
#define EC_FSM_FOE_TIMEOUT_JIFFIES
Maximum time in jiffies to wait for responses when reading out the dictionary.
Definition: fsm_foe.c:48
Unused and should not be queued (dequeued).
Definition: datagram.h:81
void ec_fsm_foe_state_ack_read_data(ec_fsm_foe_t *, ec_datagram_t *)
Process a read operation.
Definition: fsm_foe.c:452
uint32_t password
Password needed for FoE.
Definition: foe_request.h:68
Acknowledge error.
Definition: foe.h:54
Values written by the master.
Definition: ecrt.h:437
Received (dequeued).
Definition: datagram.h:78
void ec_fsm_foe_state_sent_ack(ec_fsm_foe_t *, ec_datagram_t *)
Sent an acknowledge.
Definition: fsm_foe.c:1014
uint32_t tx_current_size
Size of current packet to send.
Definition: fsm_foe.h:69
File-Access over EtherCAT.
Definition: globals.h:153
Write request.
Definition: fsm_foe.c:65
EtherCAT FoE state machines.
unsigned long jiffies_received
Jiffies, when the datagram was received.
Definition: datagram.h:110
size_t payload_size
Size of the mailbox response payload data.
Definition: datagram.h:125
int ec_slave_mbox_check(const ec_datagram_t *datagram)
Processes a mailbox state checking datagram.
Definition: mailbox.c:116
Finite state machines for the CANopen-over-EtherCAT protocol.
Definition: fsm_foe.h:53
uint32_t rx_buffer_offset
Offset in receive buffer.
Definition: fsm_foe.h:75