IgH EtherCAT Master  1.5.2
fsm_slave_scan.c
Go to the documentation of this file.
1 /******************************************************************************
2  *
3  * $Id$
4  *
5  * Copyright (C) 2006-2008 Florian Pose, Ingenieurgemeinschaft IgH
6  *
7  * This file is part of the IgH EtherCAT Master.
8  *
9  * The IgH EtherCAT Master is free software; you can redistribute it and/or
10  * modify it under the terms of the GNU General Public License version 2, as
11  * published by the Free Software Foundation.
12  *
13  * The IgH EtherCAT Master is distributed in the hope that it will be useful,
14  * but WITHOUT ANY WARRANTY; without even the implied warranty of
15  * MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the GNU General
16  * Public License for more details.
17  *
18  * You should have received a copy of the GNU General Public License along
19  * with the IgH EtherCAT Master; if not, write to the Free Software
20  * Foundation, Inc., 51 Franklin St, Fifth Floor, Boston, MA 02110-1301 USA
21  *
22  * ---
23  *
24  * The license mentioned above concerns the source code only. Using the
25  * EtherCAT technology and brand is only permitted in compliance with the
26  * industrial property and similar rights of Beckhoff Automation GmbH.
27  *
28  *****************************************************************************/
29 
35 /*****************************************************************************/
36 
37 #include "globals.h"
38 #include "master.h"
39 #include "mailbox.h"
40 #include "sii_firmware.h"
41 #include "slave_config.h"
42 
43 #include "fsm_slave_scan.h"
44 
52 #define SCAN_RETRY_TIME 100
53 
54 /*****************************************************************************/
55 
63 #ifdef EC_SII_ASSIGN
65 #endif
66 #ifdef EC_SII_CACHE
68 #endif
69 #ifdef EC_SII_OVERRIDE
70 void ec_fsm_slave_scan_state_sii_device(ec_fsm_slave_scan_t *, ec_datagram_t *);
71 void ec_fsm_slave_scan_state_sii_request(ec_fsm_slave_scan_t *, ec_datagram_t *);
72 #endif
77 #ifdef EC_REGALIAS
78 void ec_fsm_slave_scan_state_regalias(ec_fsm_slave_scan_t *, ec_datagram_t *);
79 #endif
83 
88 
90 #ifdef EC_REGALIAS
91 void ec_fsm_slave_scan_enter_regalias(ec_fsm_slave_scan_t *, ec_datagram_t *);
92 #endif
93 #ifdef EC_SII_CACHE
95 #endif
96 #ifdef EC_SII_OVERRIDE
97 void ec_fsm_slave_scan_enter_sii_request(ec_fsm_slave_scan_t *, ec_datagram_t *);
98 #endif
104 
105 /*****************************************************************************/
106 
110  ec_fsm_slave_scan_t *fsm,
111  ec_slave_t *slave,
112  ec_fsm_slave_config_t *fsm_slave_config,
114  ec_fsm_pdo_t *fsm_pdo
115  )
116 {
117  fsm->slave = slave;
118  fsm->datagram = NULL;
119  fsm->fsm_slave_config = fsm_slave_config;
120  fsm->fsm_pdo = fsm_pdo;
121 
122  // init sub state machines
123  ec_fsm_sii_init(&fsm->fsm_sii);
124 }
125 
126 /*****************************************************************************/
127 
131 {
132  // clear sub state machines
133  ec_fsm_sii_clear(&fsm->fsm_sii);
134 }
135 
136 /*****************************************************************************/
137 
143  ec_fsm_slave_scan_t *fsm
144  )
145 {
148 }
149 
150 /*****************************************************************************/
151 
157 {
158  return fsm->state != ec_fsm_slave_scan_state_end
160 }
161 
162 /*****************************************************************************/
163 
172  ec_fsm_slave_scan_t *fsm,
173  ec_datagram_t *datagram
174  )
175 {
176  if (!ec_fsm_slave_scan_running(fsm))
177  return 0;
178 
179  fsm->state(fsm, datagram);
180 
181  if (!ec_fsm_slave_scan_running(fsm)) {
182  fsm->datagram = NULL;
183  return 0;
184  }
185 
186  fsm->datagram = datagram;
187  return 1;
188 }
189 
190 /*****************************************************************************/
191 
197 {
198  return fsm->state == ec_fsm_slave_scan_state_end;
199 }
200 
201 /******************************************************************************
202  * slave scan state machine
203  *****************************************************************************/
204 
212  ec_fsm_slave_scan_t *fsm,
213  ec_datagram_t *datagram
214  )
215 {
216  // write station address
217  ec_datagram_apwr(datagram, fsm->slave->ring_position, 0x0010, 2);
218  EC_WRITE_U16(datagram->data, fsm->slave->station_address);
219  fsm->retries = EC_FSM_RETRIES;
221 }
222 
223 /*****************************************************************************/
224 
230  ec_fsm_slave_scan_t *fsm,
231  ec_datagram_t *datagram
232  )
233 {
234  if (fsm->datagram->state == EC_DATAGRAM_TIMED_OUT && fsm->retries--) {
235  ec_datagram_repeat(datagram, fsm->datagram);
236  return;
237  }
238 
239  if (fsm->datagram->state != EC_DATAGRAM_RECEIVED) {
241  EC_SLAVE_ERR(fsm->slave,
242  "Failed to receive station address datagram: ");
244  return;
245  }
246 
247  if (fsm->datagram->working_counter != 1) {
248  fsm->slave->error_flag = 1;
250  EC_SLAVE_ERR(fsm->slave, "Failed to write station address: ");
252  return;
253  }
254 
255  // Read AL state
256  ec_datagram_fprd(datagram, fsm->slave->station_address, 0x0130, 2);
257  ec_datagram_zero(datagram);
258  fsm->retries = EC_FSM_RETRIES;
260 }
261 
262 /*****************************************************************************/
263 
269  ec_fsm_slave_scan_t *fsm,
270  ec_datagram_t *datagram
271  )
272 {
273  ec_slave_t *slave = fsm->slave;
274 
275  if (fsm->datagram->state == EC_DATAGRAM_TIMED_OUT && fsm->retries--) {
276  ec_datagram_repeat(datagram, fsm->datagram);
277  return;
278  }
279 
280  if (fsm->datagram->state != EC_DATAGRAM_RECEIVED) {
282  EC_SLAVE_ERR(slave, "Failed to receive AL state datagram: ");
284  return;
285  }
286 
287  if (fsm->datagram->working_counter != 1) {
288  fsm->slave->error_flag = 1;
290  EC_SLAVE_ERR(slave, "Failed to read AL state: ");
292  return;
293  }
294 
295  slave->current_state = EC_READ_U8(fsm->datagram->data);
296  if (slave->current_state & EC_SLAVE_STATE_ACK_ERR) {
297  char state_str[EC_STATE_STRING_SIZE];
298  ec_state_string(slave->current_state, state_str, 0);
299  EC_SLAVE_WARN(slave, "Slave has state error bit set (%s)!\n",
300  state_str);
301  }
302 
303  // read base data
304  ec_datagram_fprd(datagram, fsm->slave->station_address, 0x0000, 12);
305  ec_datagram_zero(datagram);
306  fsm->retries = EC_FSM_RETRIES;
308 }
309 
310 /*****************************************************************************/
311 
315  ec_fsm_slave_scan_t *fsm,
316  ec_datagram_t *datagram
317  )
318 {
319  ec_slave_t *slave = fsm->slave;
320  u8 octet;
321  int i;
322 
323  if (fsm->datagram->state == EC_DATAGRAM_TIMED_OUT && fsm->retries--) {
324  ec_datagram_repeat(datagram, fsm->datagram);
325  return;
326  }
327 
328  if (fsm->datagram->state != EC_DATAGRAM_RECEIVED) {
330  EC_SLAVE_ERR(slave, "Failed to receive base data datagram: ");
332  return;
333  }
334 
335  if (fsm->datagram->working_counter != 1) {
336  fsm->slave->error_flag = 1;
338  EC_SLAVE_ERR(slave, "Failed to read base data: ");
340  return;
341  }
342 
343  slave->base_type = EC_READ_U8 (fsm->datagram->data);
344  slave->base_revision = EC_READ_U8 (fsm->datagram->data + 1);
345  slave->base_build = EC_READ_U16(fsm->datagram->data + 2);
346 
347  slave->base_fmmu_count = EC_READ_U8 (fsm->datagram->data + 4);
348  if (slave->base_fmmu_count > EC_MAX_FMMUS) {
349  EC_SLAVE_WARN(slave, "Slave has more FMMUs (%u) than the master can"
350  " handle (%u).\n", slave->base_fmmu_count, EC_MAX_FMMUS);
351  slave->base_fmmu_count = EC_MAX_FMMUS;
352  }
353 
354  slave->base_sync_count = EC_READ_U8(fsm->datagram->data + 5);
355  if (slave->base_sync_count > EC_MAX_SYNC_MANAGERS) {
356  EC_SLAVE_WARN(slave, "Slave provides more sync managers (%u)"
357  " than the master can handle (%u).\n",
360  }
361 
362  octet = EC_READ_U8(fsm->datagram->data + 7);
363  for (i = 0; i < EC_MAX_PORTS; i++) {
364  slave->ports[i].desc = (octet >> (2 * i)) & 0x03;
365  }
366 
367  octet = EC_READ_U8(fsm->datagram->data + 8);
368  slave->base_fmmu_bit_operation = octet & 0x01;
369  slave->base_dc_supported = (octet >> 2) & 0x01;
370  slave->base_dc_range = ((octet >> 3) & 0x01) ? EC_DC_64 : EC_DC_32;
371 
372  if (slave->base_dc_supported) {
373  // read DC capabilities
374  ec_datagram_fprd(datagram, slave->station_address, 0x0910,
375  slave->base_dc_range == EC_DC_64 ? 8 : 4);
376  ec_datagram_zero(datagram);
377  fsm->retries = EC_FSM_RETRIES;
379  } else {
380  ec_fsm_slave_scan_enter_datalink(fsm, datagram);
381  }
382 }
383 
384 /*****************************************************************************/
385 
391  ec_fsm_slave_scan_t *fsm,
392  ec_datagram_t *datagram
393  )
394 {
395  ec_slave_t *slave = fsm->slave;
396 
397  if (fsm->datagram->state == EC_DATAGRAM_TIMED_OUT && fsm->retries--) {
398  ec_datagram_repeat(datagram, fsm->datagram);
399  return;
400  }
401 
402  if (fsm->datagram->state != EC_DATAGRAM_RECEIVED) {
404  EC_SLAVE_ERR(slave, "Failed to receive system time datagram: ");
406  return;
407  }
408 
409  if (fsm->datagram->working_counter == 1) {
410  slave->has_dc_system_time = 1;
411  EC_SLAVE_DBG(slave, 1, "Slave has the System Time register.\n");
412  } else if (fsm->datagram->working_counter == 0) {
413  EC_SLAVE_DBG(slave, 1, "Slave has no System Time register; delay "
414  "measurement only.\n");
415  } else {
416  fsm->slave->error_flag = 1;
418  EC_SLAVE_ERR(slave, "Failed to determine, if system time register is "
419  "supported: ");
421  return;
422  }
423 
424  // read DC port receive times
425  ec_datagram_fprd(datagram, slave->station_address, 0x0900, 16);
426  ec_datagram_zero(datagram);
427  fsm->retries = EC_FSM_RETRIES;
429 }
430 
431 /*****************************************************************************/
432 
438  ec_fsm_slave_scan_t *fsm,
439  ec_datagram_t *datagram
440  )
441 {
442  ec_slave_t *slave = fsm->slave;
443  int i;
444 
445  if (fsm->datagram->state == EC_DATAGRAM_TIMED_OUT && fsm->retries--) {
446  ec_datagram_repeat(datagram, fsm->datagram);
447  return;
448  }
449 
450  if (fsm->datagram->state != EC_DATAGRAM_RECEIVED) {
452  EC_SLAVE_ERR(slave, "Failed to receive system time datagram: ");
454  return;
455  }
456 
457  if (fsm->datagram->working_counter != 1) {
458  fsm->slave->error_flag = 1;
460  EC_SLAVE_ERR(slave, "Failed to get DC receive times: ");
462  return;
463  }
464 
465  for (i = 0; i < EC_MAX_PORTS; i++) {
466  u32 new_time = EC_READ_U32(fsm->datagram->data + 4 * i);
467  if (new_time == slave->ports[i].receive_time) {
468  // time has not changed since initial scan; this port has not
469  // processed the broadcast timing datagram. this can occur
470  // in certain redundancy scenarios. it can also occur if the
471  // port is closed, so at this stage we can't tell if it's an issue.
472  slave->ports[i].link.bypassed = 1;
473  }
474  slave->ports[i].receive_time = new_time;
475  }
476 
477  ec_fsm_slave_scan_enter_datalink(fsm, datagram);
478 }
479 
480 /*****************************************************************************/
481 
487  ec_fsm_slave_scan_t *fsm,
488  ec_datagram_t *datagram
489  )
490 {
491  ec_slave_t *slave = fsm->slave;
492 
493  // read data link status
494  ec_datagram_fprd(datagram, slave->station_address, 0x0110, 2);
495  ec_datagram_zero(datagram);
496  fsm->retries = EC_FSM_RETRIES;
498 }
499 
500 #ifdef EC_SII_CACHE
501 /*****************************************************************************/
502 
506  ec_fsm_slave_scan_t *fsm,
507  ec_datagram_t *datagram
508  )
509 {
510  // Start fetching SII serial number
512  ec_fsm_sii_read(&fsm->fsm_sii, fsm->slave, fsm->sii_offset,
515  fsm->state(fsm, datagram); // execute state immediately
516 }
517 #endif
518 
519 /*****************************************************************************/
520 
524  ec_fsm_slave_scan_t *fsm,
525  ec_datagram_t *datagram
526  )
527 {
528  ec_sii_image_t *sii_image;
529  ec_slave_t *slave = fsm->slave;
530 
531 #ifdef EC_SII_CACHE
532  unsigned int i = 0;
533  unsigned int found = 0;
534 
535  if ((slave->effective_alias != 0) || (slave->effective_serial_number != 0)) {
536  list_for_each_entry(sii_image, &slave->master->sii_images, list) {
537  // Check if slave match a stored SII image with alias, serial number,
538  // vendor id and product code.
539  if ((slave->effective_alias != 0) &&
540  (slave->effective_alias == sii_image->sii.alias) &&
541  (slave->effective_revision_number == sii_image->sii.revision_number)) {
542  EC_SLAVE_DBG(slave, 1, "Slave can re-use SII image data stored."
543  " Identified by alias %u.\n", (uint32_t)slave->effective_alias);
544  found = 1;
545  break;
546  }
547  else if ((slave->effective_vendor_id == sii_image->sii.vendor_id) &&
548  (slave->effective_product_code == sii_image->sii.product_code) &&
549  (slave->effective_revision_number == sii_image->sii.revision_number) &&
550  (slave->effective_serial_number == sii_image->sii.serial_number)) {
551  EC_SLAVE_DBG(slave, 1, "Slave can re-use SII image data stored."
552  " Identified by vendor id 0x%08x,"
553  " product code 0x%08x, revision 0x%08x and serial 0x%08x.\n",
554  slave->effective_vendor_id,
555  slave->effective_product_code,
557  slave->effective_serial_number);
558  found = 1;
559  break;
560  }
561  }
562  }
563  else {
564  EC_SLAVE_DBG(slave, 1, "Slave cannot be uniquely identified."
565  " SII image data cannot be re-used!\n");
566  }
567 
568  if (found) {
569  // Update slave references lost during slave initialization
570  slave->effective_vendor_id = sii_image->sii.vendor_id;
571  slave->effective_product_code = sii_image->sii.product_code;
572  slave->effective_revision_number = sii_image->sii.revision_number;
573  slave->effective_serial_number = sii_image->sii.serial_number;
574  slave->sii_image = sii_image;
575  for (i = 0; i < slave->sii_image->sii.sync_count; i++) {
576  slave->sii_image->sii.syncs[i].slave = slave;
577  }
578  // The SII image data is already available and we can enter PREOP
579 #ifdef EC_REGALIAS
580  ec_fsm_slave_scan_enter_regalias(fsm, datagram);
581 #else
582  if (slave->sii_image->sii.mailbox_protocols & EC_MBOX_COE) {
583  ec_fsm_slave_scan_enter_preop(fsm, datagram);
584  } else {
586  }
587 #endif
588  }
589  else
590 #endif
591  {
592  EC_MASTER_DBG(slave->master, 1, "Creating slave SII image for %u\n",
593  fsm->slave->ring_position);
594 
595  if (!(sii_image = (ec_sii_image_t *) kmalloc(sizeof(ec_sii_image_t),
596  GFP_KERNEL))) {
598  EC_MASTER_ERR(fsm->slave->master, "Failed to allocate memory"
599  " for slave SII image.\n");
600  return;
601  }
602  // Initialize SII image data
603  ec_slave_sii_image_init(sii_image);
604  // Attach SII image to the slave
605  slave->sii_image = sii_image;
606  // Store the SII image for later re-use
607  list_add_tail(&sii_image->list, &slave->master->sii_images);
608 
609  ec_fsm_slave_scan_enter_sii_size(fsm, datagram);
610  }
611 }
612 
613 /*****************************************************************************/
614 
618  ec_fsm_slave_scan_t *fsm,
619  ec_datagram_t *datagram
620  )
621 {
622  ec_slave_t *slave = fsm->slave;
623 
624 #ifdef EC_SII_OVERRIDE
625  if (!slave->vendor_words) {
626  if (!(slave->vendor_words =
627  (uint16_t *) kmalloc(32, GFP_KERNEL))) {
628  EC_SLAVE_ERR(slave, "Failed to allocate 16 words of SII data.\n");
629  slave->error_flag = 1;
631  return;
632  }
633  }
634 
635  // Start fetching device identity
636  fsm->sii_offset = 0;
637  fsm->state = ec_fsm_slave_scan_state_sii_device;
638 #else
639  // Start fetching SII size
640  fsm->sii_offset = EC_FIRST_SII_CATEGORY_OFFSET; // first category header
642 #endif
643 
644  ec_fsm_sii_read(&fsm->fsm_sii, slave, fsm->sii_offset,
646 
647  fsm->state(fsm, datagram); // execute state immediately
648 }
649 
650 /*****************************************************************************/
651 
652 #ifdef EC_SII_ASSIGN
653 
657  ec_fsm_slave_scan_t *fsm,
658  ec_datagram_t *datagram
659  )
660 {
661  ec_slave_t *slave = fsm->slave;
662 
663  EC_SLAVE_DBG(slave, 1, "Assigning SII access to EtherCAT.\n");
664 
665  // assign SII to ECAT
666  ec_datagram_fpwr(datagram, slave->station_address, 0x0500, 1);
667  EC_WRITE_U8(datagram->data, 0x00); // EtherCAT
668  fsm->retries = EC_FSM_RETRIES;
670 }
671 
672 #endif
673 
674 /*****************************************************************************/
675 
681  ec_fsm_slave_scan_t *fsm,
682  ec_datagram_t *datagram
683  )
684 {
685  ec_slave_t *slave = fsm->slave;
686 
687  if (fsm->datagram->state == EC_DATAGRAM_TIMED_OUT && fsm->retries--) {
688  ec_datagram_repeat(datagram, fsm->datagram);
689  return;
690  }
691 
692  if (fsm->datagram->state != EC_DATAGRAM_RECEIVED) {
694  EC_SLAVE_ERR(slave, "Failed to receive DL status datagram: ");
696  return;
697  }
698 
699  if (fsm->datagram->working_counter != 1) {
700  fsm->slave->error_flag = 1;
702  EC_SLAVE_ERR(slave, "Failed to read DL status: ");
704  return;
705  }
706 
708 
709 #ifdef EC_SII_ASSIGN
710  ec_fsm_slave_scan_enter_assign_sii(fsm, datagram);
711 #elif defined(EC_SII_CACHE)
713 #else
714  ec_fsm_slave_scan_enter_attach_sii(fsm, datagram);
715 #endif
716 }
717 
718 /*****************************************************************************/
719 
720 #ifdef EC_SII_ASSIGN
721 
727  ec_fsm_slave_scan_t *fsm,
728  ec_datagram_t *datagram
729  )
730 {
731  ec_slave_t *slave = fsm->slave;
732 
733  if (fsm->datagram->state == EC_DATAGRAM_TIMED_OUT && fsm->retries--) {
734  ec_datagram_repeat(datagram, fsm->datagram);
735  return;
736  }
737 
738  if (fsm->datagram->state != EC_DATAGRAM_RECEIVED) {
739  EC_SLAVE_WARN(slave, "Failed to receive SII assignment datagram: ");
741  // Try to go on, probably assignment is correct
742  goto continue_with_sii_size;
743  }
744 
745  if (fsm->datagram->working_counter != 1) {
746  EC_SLAVE_WARN(slave, "Failed to assign SII to EtherCAT: ");
748  // Try to go on, probably assignment is correct
749  }
750 
751 continue_with_sii_size:
752 #ifdef EC_SII_CACHE
754 #else
755  ec_fsm_slave_scan_enter_attach_sii(fsm, datagram);
756 #endif
757 }
758 
759 #endif
760 
761 #ifdef EC_SII_CACHE
762 /*****************************************************************************/
763 
769  ec_fsm_slave_scan_t *fsm,
770  ec_datagram_t *datagram
771  )
772 {
773  ec_slave_t *slave = fsm->slave;
774 
775  while (1) {
776  if (ec_fsm_sii_exec(&fsm->fsm_sii, datagram))
777  return;
778 
779  if (!ec_fsm_sii_success(&fsm->fsm_sii)) {
780  EC_SLAVE_ERR(slave, "Failed to determine SII identity\n");
781  if (fsm->scan_retries--) {
783  } else {
784  fsm->slave->error_flag = 1;
786  }
787  return;
788  }
789 
790  switch (fsm->sii_offset) {
791  case EC_ALIAS_SII_OFFSET:
792  slave->effective_alias = EC_READ_U16(fsm->fsm_sii.value);
793  EC_SLAVE_DBG(slave, 1, "Alias: %u\n",
794  (uint32_t)slave->effective_alias);
795  if (slave->effective_alias) {
797  } else {
799  }
800  break;
803  EC_SLAVE_DBG(slave, 1, "Serial Number: 0x%08x\n",
804  slave->effective_serial_number);
805  if (!slave->effective_serial_number) {
806  ec_fsm_slave_scan_enter_attach_sii(fsm, datagram);
807  return;
808  }
810  break;
813  EC_SLAVE_DBG(slave, 1, "Vendor ID: 0x%08x\n",
814  slave->effective_vendor_id);
816  break;
819  EC_SLAVE_DBG(slave, 1, "Product Code: 0x%08x\n",
820  slave->effective_product_code);
822  break;
825  EC_SLAVE_DBG(slave, 1, "Revision: 0x%08x\n",
827  ec_fsm_slave_scan_enter_attach_sii(fsm, datagram);
828  return;
829  default:
830  fsm->slave->error_flag = 1;
832  EC_SLAVE_ERR(slave, "Unexpected offset %u in identity scan.\n",
833  fsm->sii_offset);
834  return;
835  }
836 
837  ec_fsm_sii_read(&fsm->fsm_sii, fsm->slave, fsm->sii_offset,
839  }
840 }
841 #endif
842 
843 #ifdef EC_SII_OVERRIDE
844 /*****************************************************************************/
845 
850 void ec_fsm_slave_scan_state_sii_device(
851  ec_fsm_slave_scan_t *fsm,
852  ec_datagram_t *datagram
853  )
854 {
855  ec_slave_t *slave = fsm->slave;
856 
857  if (ec_fsm_sii_exec(&fsm->fsm_sii, datagram))
858  return;
859 
860  if (!ec_fsm_sii_success(&fsm->fsm_sii)) {
861  EC_SLAVE_ERR(slave, "Failed to determine product and vendor id."
862  " Reading word offset 0x%04x failed.\n",
863  fsm->sii_offset);
864  if (fsm->scan_retries--) {
866  } else {
867  fsm->slave->error_flag = 1;
869  }
870  return;
871  }
872 
873  memcpy(slave->vendor_words + fsm->sii_offset, fsm->fsm_sii.value, 4);
874 
875  if (fsm->sii_offset + 2 < 16) {
876  // fetch the next 2 words
877  fsm->sii_offset += 2;
878  ec_fsm_sii_read(&fsm->fsm_sii, slave, fsm->sii_offset,
880  ec_fsm_sii_exec(&fsm->fsm_sii, datagram); // execute state immediately
881  return;
882  }
883 
884  // Evaluate SII contents
890 
891  // check for invalid vendor id and product code
892  if ( (slave->sii_image->sii.vendor_id == 0) ||
893  (slave->sii_image->sii.product_code == 0) ) {
894  EC_SLAVE_ERR(slave, "Failed to determine product and vendor id."
895  " SII returned a zero value.\n");
896  if (fsm->scan_retries--) {
898  } else {
899  fsm->slave->error_flag = 1;
901  }
902  return;
903  }
904 
905  slave->effective_alias = slave->sii_image->sii.alias;
906 #ifdef EC_SII_CACHE
907  slave->effective_vendor_id = slave->sii_image->sii.vendor_id;
911 #endif
912 
913  ec_fsm_slave_scan_enter_sii_request(fsm, datagram);
914 }
915 
916 /*****************************************************************************/
917 
918 struct firmware_request_context
919 {
920  struct task_struct *fsm_task;
921  ec_fsm_slave_scan_t *fsm;
922  ec_slave_t *slave;
923 };
924 
925 static const struct firmware no_sii_firmware;
926 
927 static void firmware_request_complete(
928  const struct firmware *firmware,
929  void *context
930  )
931 {
932  struct firmware_request_context *ctx = context;
933  ec_fsm_slave_scan_t *fsm = ctx->fsm;
934 
935  if (fsm->slave != ctx->slave) {
936  printk(KERN_ERR "Aborting firmware request; FSM slave changed unexpectedly.\n");
937  ec_release_sii_firmware(firmware);
938  } else if (fsm->state != ec_fsm_slave_scan_state_sii_request) {
939  EC_SLAVE_WARN(fsm->slave, "Aborting firmware request; FSM state changed unexpectedly.\n");
940  ec_release_sii_firmware(firmware);
941  } else {
942  fsm->sii_firmware = firmware ? firmware : &no_sii_firmware;
943  }
944 
945  kfree(ctx);
946 }
947 
948 /*****************************************************************************/
949 
954 void ec_fsm_slave_scan_enter_sii_request(
955  ec_fsm_slave_scan_t *fsm,
956  ec_datagram_t *datagram
957  )
958 {
959  ec_slave_t *slave = fsm->slave;
960  struct firmware_request_context *ctx;
961 
962  if (!(ctx = kmalloc(sizeof(*ctx), GFP_KERNEL))) {
963  EC_SLAVE_ERR(slave, "Unable to allocate firmware request context.\n");
965  return;
966  }
967 
968  ctx->fsm_task = current;
969  ctx->fsm = fsm;
970  ctx->slave = slave;
971 
972  fsm->sii_firmware = NULL;
973  fsm->state = ec_fsm_slave_scan_state_sii_request;
974  ec_request_sii_firmware(slave, ctx, firmware_request_complete);
975  fsm->state(fsm, datagram); // execute state immediately
976 }
977 
978 /*****************************************************************************/
979 
984 void ec_fsm_slave_scan_state_sii_request(
985  ec_fsm_slave_scan_t *fsm,
986  ec_datagram_t *datagram
987  )
988 {
989  ec_slave_t *slave = fsm->slave;
990  const struct firmware *firmware = fsm->sii_firmware;
991 
992  if (firmware == &no_sii_firmware) {
993  EC_SLAVE_DBG(slave, 1, "SII firmware file not found; reading SII data from slave.\n");
994  fsm->sii_firmware = NULL;
995 
996  fsm->sii_offset = EC_FIRST_SII_CATEGORY_OFFSET; // first category header
997  ec_fsm_sii_read(&fsm->fsm_sii, slave, fsm->sii_offset,
1000  fsm->state(fsm, datagram); // execute state immediately
1001  } else if (firmware) {
1002  EC_SLAVE_DBG(slave, 1, "Firmware file found, reading %zu bytes.\n", firmware->size);
1003 
1004  slave->sii_image->nwords = firmware->size / 2;
1005 
1006  if (slave->sii_image->words) {
1007  EC_SLAVE_WARN(slave, "Freeing old SII data...\n");
1008  kfree(slave->sii_image->words);
1009  }
1010  if (!(slave->sii_image->words =
1011  (uint16_t *) kmalloc(slave->sii_image->nwords * 2, GFP_KERNEL))) {
1012  EC_SLAVE_ERR(slave, "Failed to allocate %zu words of SII data.\n",
1013  slave->sii_image->nwords);
1014  slave->sii_image->nwords = 0;
1015  slave->error_flag = 1;
1016  ec_release_sii_firmware(firmware);
1017  fsm->sii_firmware = NULL;
1018 
1020  return;
1021  }
1022 
1023  memcpy(slave->sii_image->words, firmware->data, slave->sii_image->nwords * 2);
1024  ec_release_sii_firmware(firmware);
1025  fsm->sii_firmware = NULL;
1026 
1028  fsm->state(fsm, datagram); // execute state immediately
1029  } else {
1030  // do nothing while waiting for async request to complete
1031  datagram->state = EC_DATAGRAM_INVALID;
1032  }
1033 }
1034 #endif
1035 
1036 /*****************************************************************************/
1037 
1043  ec_fsm_slave_scan_t *fsm,
1044  ec_datagram_t *datagram
1045  )
1046 {
1047  ec_slave_t *slave = fsm->slave;
1048  uint16_t cat_type, cat_size;
1049 
1050  if (ec_fsm_sii_exec(&fsm->fsm_sii, datagram))
1051  return;
1052 
1053  if (!slave->sii_image) {
1054  EC_SLAVE_ERR(slave, "Slave has no SII image attached!\n");
1055  slave->error_flag = 1;
1057  return;
1058  }
1059 
1060  if (!ec_fsm_sii_success(&fsm->fsm_sii)) {
1061  if (fsm->scan_retries--) {
1062  EC_SLAVE_ERR(slave, "Failed to determine SII content size"
1063  " Retrying.\n");
1065  return;
1066  } else {
1067  fsm->slave->error_flag = 1;
1069  EC_SLAVE_ERR(slave, "Failed to determine SII content size:"
1070  " Reading word offset 0x%04x failed. Assuming %u words.\n",
1073  goto alloc_sii;
1074  }
1075  }
1076 
1077  cat_type = EC_READ_U16(fsm->fsm_sii.value);
1078  cat_size = EC_READ_U16(fsm->fsm_sii.value + 2);
1079 
1080  if (cat_type != 0xFFFF) { // not the last category
1081  off_t next_offset = 2UL + fsm->sii_offset + cat_size;
1082  if (next_offset >= EC_MAX_SII_SIZE) {
1083  EC_SLAVE_WARN(slave, "SII size exceeds %u words"
1084  " (0xffff limiter missing?).\n", EC_MAX_SII_SIZE);
1085  // cut off category data...
1087  goto alloc_sii;
1088  }
1089  fsm->sii_offset = next_offset;
1090  ec_fsm_sii_read(&fsm->fsm_sii, slave, fsm->sii_offset,
1092  ec_fsm_sii_exec(&fsm->fsm_sii, datagram); // execute state immediately
1093  return;
1094  }
1095 
1096  slave->sii_image->nwords = fsm->sii_offset + 1;
1097 
1098 alloc_sii:
1099  if (slave->sii_image->words) {
1100  EC_SLAVE_WARN(slave, "Freeing old SII data...\n");
1101  kfree(slave->sii_image->words);
1102  }
1103 
1104  if (!(slave->sii_image->words =
1105  (uint16_t *) kmalloc(slave->sii_image->nwords * 2, GFP_KERNEL))) {
1106  EC_SLAVE_ERR(slave, "Failed to allocate %zu words of SII data.\n",
1107  slave->sii_image->nwords);
1108  slave->sii_image->nwords = 0;
1109  slave->error_flag = 1;
1111  return;
1112  }
1113 
1114 #ifdef EC_SII_OVERRIDE
1115  // Copy vendor data to sii words
1116  memcpy(slave->sii_image->words, slave->vendor_words, 32);
1117  kfree(slave->vendor_words);
1118  slave->vendor_words = NULL;
1119 
1120  // Start fetching rest of SII contents
1121  fsm->sii_offset = 0x0010;
1122 #else
1123  // Start fetching SII contents
1124  fsm->sii_offset = 0x0000;
1125 #endif
1127  ec_fsm_sii_read(&fsm->fsm_sii, slave, fsm->sii_offset,
1129  ec_fsm_sii_exec(&fsm->fsm_sii, datagram); // execute state immediately
1130 }
1131 
1132 /*****************************************************************************/
1133 
1139  ec_fsm_slave_scan_t *fsm,
1140  ec_datagram_t *datagram
1141  )
1142 {
1143  ec_slave_t *slave = fsm->slave;
1144 
1145  if (ec_fsm_sii_exec(&fsm->fsm_sii, datagram)) return;
1146 
1147  if (!ec_fsm_sii_success(&fsm->fsm_sii)) {
1148  EC_SLAVE_ERR(slave, "Failed to fetch SII contents.\n");
1149  if (fsm->scan_retries--) {
1151  } else {
1152  fsm->slave->error_flag = 1;
1154  }
1155  return;
1156  }
1157 
1158  if (!slave->sii_image) {
1159  EC_SLAVE_ERR(slave, "Slave has no SII image attached!\n");
1160  slave->error_flag = 1;
1162  return;
1163  }
1164 
1165  // 2 words fetched
1166 
1167  if (fsm->sii_offset + 2 <= slave->sii_image->nwords) { // 2 words fit
1168  memcpy(slave->sii_image->words + fsm->sii_offset, fsm->fsm_sii.value, 4);
1169  } else { // copy the last word
1170  memcpy(slave->sii_image->words + fsm->sii_offset, fsm->fsm_sii.value, 2);
1171  }
1172 
1173  if (fsm->sii_offset + 2 < slave->sii_image->nwords) {
1174  // fetch the next 2 words
1175  fsm->sii_offset += 2;
1176  ec_fsm_sii_read(&fsm->fsm_sii, slave, fsm->sii_offset,
1178  ec_fsm_sii_exec(&fsm->fsm_sii, datagram); // execute state immediately
1179  return;
1180  }
1181 
1183  fsm->state(fsm, datagram); // execute state immediately
1184 }
1185 
1186 /*****************************************************************************/
1187 
1193  ec_fsm_slave_scan_t *fsm,
1194  ec_datagram_t *datagram
1195  )
1196 {
1197  ec_slave_t *slave = fsm->slave;
1198  uint16_t *cat_word, cat_type, cat_size;
1199 
1200  // Evaluate SII contents
1201 
1203 
1204 #ifndef EC_SII_OVERRIDE
1205  slave->sii_image->sii.alias =
1206  EC_READ_U16(slave->sii_image->words + 0x0004);
1207  slave->effective_alias = slave->sii_image->sii.alias;
1208  slave->sii_image->sii.vendor_id =
1209  EC_READ_U32(slave->sii_image->words + 0x0008);
1210  slave->sii_image->sii.product_code =
1211  EC_READ_U32(slave->sii_image->words + 0x000A);
1212  slave->sii_image->sii.revision_number =
1213  EC_READ_U32(slave->sii_image->words + 0x000C);
1214  slave->sii_image->sii.serial_number =
1215  EC_READ_U32(slave->sii_image->words + 0x000E);
1216 #endif
1218  EC_READ_U16(slave->sii_image->words + 0x0014);
1220  EC_READ_U16(slave->sii_image->words + 0x0015);
1222  EC_READ_U16(slave->sii_image->words + 0x0016);
1224  EC_READ_U16(slave->sii_image->words + 0x0017);
1226  EC_READ_U16(slave->sii_image->words + 0x0018);
1228  EC_READ_U16(slave->sii_image->words + 0x0019);
1230  EC_READ_U16(slave->sii_image->words + 0x001A);
1232  EC_READ_U16(slave->sii_image->words + 0x001B);
1233  slave->sii_image->sii.mailbox_protocols =
1234  EC_READ_U16(slave->sii_image->words + 0x001C);
1235 
1236 #if !defined(EC_SII_OVERRIDE) && defined(EC_SII_CACHE)
1237  slave->effective_vendor_id = slave->sii_image->sii.vendor_id;
1241 #endif
1242 
1243  // clear mailbox settings if invalid values due to invalid sii file
1244  if ((slave->sii_image->sii.boot_rx_mailbox_offset == 0xFFFF) ||
1245  (slave->sii_image->sii.boot_tx_mailbox_offset == 0xFFFF) ||
1246  (slave->sii_image->sii.std_rx_mailbox_offset == 0xFFFF) ||
1247  (slave->sii_image->sii.std_tx_mailbox_offset == 0xFFFF)) {
1248  slave->sii_image->sii.boot_rx_mailbox_offset = 0;
1249  slave->sii_image->sii.boot_tx_mailbox_offset = 0;
1250  slave->sii_image->sii.boot_rx_mailbox_size = 0;
1251  slave->sii_image->sii.boot_tx_mailbox_size = 0;
1252  slave->sii_image->sii.std_rx_mailbox_offset = 0;
1253  slave->sii_image->sii.std_tx_mailbox_offset = 0;
1254  slave->sii_image->sii.std_rx_mailbox_size = 0;
1255  slave->sii_image->sii.std_tx_mailbox_size = 0;
1256  slave->sii_image->sii.mailbox_protocols = 0;
1257  EC_SLAVE_ERR(slave, "Unexpected mailbox offset in SII data.\n");
1258  }
1259 
1261  // sii does not contain category data
1263  return;
1264  }
1265 
1266  if (slave->sii_image->nwords < EC_FIRST_SII_CATEGORY_OFFSET + 1) {
1267  EC_SLAVE_ERR(slave, "Unexpected end of SII data:"
1268  " First category header missing.\n");
1269  goto end;
1270  }
1271 
1272  // evaluate category data
1273  cat_word = slave->sii_image->words + EC_FIRST_SII_CATEGORY_OFFSET;
1274  while (EC_READ_U16(cat_word) != 0xFFFF) {
1275 
1276  // type and size words must fit
1277  if (cat_word + 2 - slave->sii_image->words > slave->sii_image->nwords) {
1278  EC_SLAVE_ERR(slave, "Unexpected end of SII data:"
1279  " Category header incomplete.\n");
1280  goto end;
1281  }
1282 
1283  cat_type = EC_READ_U16(cat_word) & 0x7FFF;
1284  cat_size = EC_READ_U16(cat_word + 1);
1285  cat_word += 2;
1286 
1287  if (cat_word + cat_size - slave->sii_image->words > slave->sii_image->nwords) {
1288  EC_SLAVE_WARN(slave, "Unexpected end of SII data:"
1289  " Category data incomplete.\n");
1290  goto end;
1291  }
1292 
1293  switch (cat_type) {
1294  case 0x000A:
1295  if (ec_slave_fetch_sii_strings(slave, (uint8_t *) cat_word,
1296  cat_size * 2))
1297  goto end;
1298  break;
1299  case 0x001E:
1300  if (ec_slave_fetch_sii_general(slave, (uint8_t *) cat_word,
1301  cat_size * 2))
1302  goto end;
1303  break;
1304  case 0x0028:
1305  break;
1306  case 0x0029:
1307  if (ec_slave_fetch_sii_syncs(slave, (uint8_t *) cat_word,
1308  cat_size * 2))
1309  goto end;
1310  break;
1311  case 0x0032:
1312  if (ec_slave_fetch_sii_pdos( slave, (uint8_t *) cat_word,
1313  cat_size * 2, EC_DIR_INPUT)) // TxPDO
1314  goto end;
1315  break;
1316  case 0x0033:
1317  if (ec_slave_fetch_sii_pdos( slave, (uint8_t *) cat_word,
1318  cat_size * 2, EC_DIR_OUTPUT)) // RxPDO
1319  goto end;
1320  break;
1321  default:
1322  EC_SLAVE_DBG(slave, 1, "Unknown category type 0x%04X.\n",
1323  cat_type);
1324  }
1325 
1326  cat_word += cat_size;
1327  if (cat_word - slave->sii_image->words >= slave->sii_image->nwords) {
1328  EC_SLAVE_WARN(slave, "Unexpected end of SII data:"
1329  " Next category header missing.\n");
1330  goto end;
1331  }
1332  }
1333 
1334 #ifdef EC_REGALIAS
1335  ec_fsm_slave_scan_enter_regalias(fsm, datagram);
1336 #else
1337  if (slave->sii_image->sii.mailbox_protocols & EC_MBOX_COE) {
1338  ec_fsm_slave_scan_enter_preop(fsm, datagram);
1339  } else {
1341  }
1342 #endif
1343  return;
1344 
1345 end:
1346  EC_SLAVE_ERR(slave, "Failed to analyze category data.\n");
1347  fsm->slave->error_flag = 1;
1349 }
1350 
1351 /*****************************************************************************/
1352 
1353 #ifdef EC_REGALIAS
1354 
1357 void ec_fsm_slave_scan_enter_regalias(
1358  ec_fsm_slave_scan_t *fsm,
1359  ec_datagram_t *datagram
1360  )
1361 {
1362  ec_slave_t *slave = fsm->slave;
1363 
1364  // read alias from register
1365  EC_SLAVE_DBG(slave, 1, "Reading alias from register.\n");
1366  ec_datagram_fprd(datagram, slave->station_address, 0x0012, 2);
1367  ec_datagram_zero(datagram);
1368  fsm->retries = EC_FSM_RETRIES;
1369  fsm->state = ec_fsm_slave_scan_state_regalias;
1370 }
1371 
1372 /*****************************************************************************/
1373 
1376 void ec_fsm_slave_scan_state_regalias(
1377  ec_fsm_slave_scan_t *fsm,
1378  ec_datagram_t *datagram
1379  )
1380 {
1381  ec_slave_t *slave = fsm->slave;
1382 
1383  if (fsm->datagram->state == EC_DATAGRAM_TIMED_OUT && fsm->retries--) {
1384  ec_datagram_repeat(datagram, fsm->datagram);
1385  return;
1386  }
1387 
1388  if (fsm->datagram->state != EC_DATAGRAM_RECEIVED) {
1390  EC_SLAVE_ERR(slave, "Failed to receive register alias datagram: ");
1392  return;
1393  }
1394 
1395  if (fsm->datagram->working_counter != 1) {
1396  EC_SLAVE_DBG(slave, 1, "Failed to read register alias.\n");
1397  } else {
1398  slave->effective_alias = EC_READ_U16(fsm->datagram->data);
1399  EC_SLAVE_DBG(slave, 1, "Read alias %u from register.\n",
1400  slave->effective_alias);
1401  }
1402 
1403  if (!slave->sii_image) {
1404  EC_SLAVE_ERR(slave, "Slave has no SII image attached!\n");
1405  slave->error_flag = 1;
1407  return;
1408  }
1409 
1410  if (slave->sii_image->sii.mailbox_protocols & EC_MBOX_COE) {
1411  ec_fsm_slave_scan_enter_preop(fsm, datagram);
1412  } else {
1414  }
1415 }
1416 
1417 #endif // defined EC_REGALIAS
1418 
1419 /*****************************************************************************/
1420 
1424  ec_fsm_slave_scan_t *fsm,
1425  ec_datagram_t *datagram
1426  )
1427 {
1428  ec_slave_t *slave = fsm->slave;
1429  uint8_t current_state = slave->current_state & EC_SLAVE_STATE_MASK;
1430 
1431  if (current_state != EC_SLAVE_STATE_PREOP
1432  && current_state != EC_SLAVE_STATE_SAFEOP
1433  && current_state != EC_SLAVE_STATE_OP) {
1434  if (slave->master->debug_level) {
1435  char str[EC_STATE_STRING_SIZE];
1436  ec_state_string(current_state, str, 0);
1437  EC_SLAVE_DBG(slave, 0, "Slave is not in the state"
1438  " to do mailbox com (%s), setting to PREOP.\n", str);
1439  }
1440 
1445  } else {
1446  EC_SLAVE_DBG(slave, 1, "Reading mailbox"
1447  " sync manager configuration.\n");
1448 
1449  /* Scan current sync manager configuration to get configured mailbox
1450  * sizes. */
1451  ec_datagram_fprd(datagram, slave->station_address, 0x0800,
1452  EC_SYNC_PAGE_SIZE * 2);
1453  ec_datagram_zero(datagram);
1454  fsm->retries = EC_FSM_RETRIES;
1456  }
1457 }
1458 
1459 /*****************************************************************************/
1460 
1464  ec_fsm_slave_scan_t *fsm,
1465  ec_datagram_t *datagram
1466  )
1467 {
1468  if (ec_fsm_slave_config_exec(fsm->fsm_slave_config, datagram))
1469  return;
1470 
1473  return;
1474  }
1475 
1477 }
1478 
1479 /*****************************************************************************/
1480 
1484  ec_fsm_slave_scan_t *fsm,
1485  ec_datagram_t *datagram
1486  )
1487 {
1488  ec_slave_t *slave = fsm->slave;
1489 
1490  if (fsm->datagram->state == EC_DATAGRAM_TIMED_OUT && fsm->retries--) {
1491  ec_datagram_repeat(datagram, fsm->datagram);
1492  return;
1493  }
1494 
1495  if (fsm->datagram->state != EC_DATAGRAM_RECEIVED) {
1497  EC_SLAVE_ERR(slave, "Failed to receive sync manager"
1498  " configuration datagram: ");
1500  return;
1501  }
1502 
1503  if (fsm->datagram->working_counter != 1) {
1504  fsm->slave->error_flag = 1;
1506  EC_SLAVE_ERR(slave, "Failed to read DL status: ");
1508  return;
1509  }
1510 
1514  slave->configured_tx_mailbox_size = EC_READ_U16(fsm->datagram->data + 10);
1515 
1516  EC_SLAVE_DBG(slave, 1, "Mailbox configuration:\n");
1517  EC_SLAVE_DBG(slave, 1, " RX offset=0x%04x size=%u\n",
1520  EC_SLAVE_DBG(slave, 1, " TX offset=0x%04x size=%u\n",
1523 
1524  if (!slave->sii_image) {
1525  EC_SLAVE_ERR(slave, "Slave has no SII image attached!\n");
1526  slave->error_flag = 1;
1528  return;
1529  }
1530 
1531  // allocate memory for mailbox response data for supported mailbox protocols
1533 
1535 }
1536 
1537 /*****************************************************************************/
1538 
1542  ec_fsm_slave_scan_t *fsm,
1543  ec_datagram_t *datagram
1544  )
1545 {
1546  ec_slave_t *slave = fsm->slave;
1547 
1548  // If there is some old data in the slave's mailbox, read it out and
1549  // discard it. We don't need to check the mailbox first, we just ignore
1550  // an error or empty mailbox response.
1551  ec_slave_mbox_prepare_fetch(fsm->slave, datagram);
1552  fsm->retries = EC_FSM_RETRIES;
1554 
1555  slave->valid_mbox_data = 0;
1556 }
1557 
1558 /*****************************************************************************/
1559 
1563  ec_fsm_slave_scan_t *fsm,
1564  ec_datagram_t *datagram
1565  )
1566 {
1567  ec_slave_t *slave = fsm->slave;
1568 
1569 #ifdef EC_SII_CACHE
1570  unsigned int i = 0;
1571  unsigned int fetch_pdos = 1;
1572 #endif
1573 
1574  if (fsm->datagram->state == EC_DATAGRAM_TIMED_OUT && fsm->retries--) {
1575  ec_slave_mbox_prepare_fetch(fsm->slave, datagram);
1576  return;
1577  }
1578 
1579  if (unlikely(slave->master->debug_level > 0)
1580  && fsm->datagram->state == EC_DATAGRAM_RECEIVED
1581  && fsm->datagram->working_counter == 1)
1582  EC_SLAVE_INFO(slave, "Cleared old data from the mailbox\n");
1583 
1584  slave->valid_mbox_data = 1;
1585 
1586  if (!slave->sii_image) {
1587  EC_SLAVE_ERR(slave, "Slave has no SII image attached!\n");
1588  slave->error_flag = 1;
1590  return;
1591  }
1592 
1593 #ifdef EC_SII_CACHE
1594  if ((slave->effective_alias != 0) || (slave->effective_serial_number != 0)) {
1595  // SII data has been stored
1596  for (i = 0; i < slave->sii_image->sii.sync_count; i++) {
1597  if (!list_empty(&slave->sii_image->sii.syncs[i].pdos.list)) {
1598  fetch_pdos = 0; // PDOs already fetched
1599  break;
1600  }
1601  }
1602  }
1603  if (!fetch_pdos) {
1605  }
1606  else
1607 #endif
1608  {
1609  ec_fsm_slave_scan_enter_pdos(fsm, datagram);
1610  }
1611 }
1612 
1613 /*****************************************************************************/
1614 
1618  ec_fsm_slave_scan_t *fsm,
1619  ec_datagram_t *datagram
1620  )
1621 {
1622  ec_slave_t *slave = fsm->slave;
1623 
1624  EC_SLAVE_DBG(slave, 1, "Scanning PDO assignment and mapping.\n");
1626  ec_fsm_pdo_start_reading(fsm->fsm_pdo, slave);
1627  ec_fsm_pdo_exec(fsm->fsm_pdo, datagram); // execute immediately
1628 }
1629 
1630 /*****************************************************************************/
1631 
1635  ec_fsm_slave_scan_t *fsm,
1636  ec_datagram_t *datagram
1637  )
1638 {
1639  if (ec_fsm_pdo_exec(fsm->fsm_pdo, datagram)) {
1640  return;
1641  }
1642 
1643  if (!ec_fsm_pdo_success(fsm->fsm_pdo)) {
1645  return;
1646  }
1647 
1648  // reading PDO configuration finished
1650 }
1651 
1652 /*****************************************************************************/
1653 
1657  ec_fsm_slave_scan_t *fsm,
1658  ec_datagram_t *datagram
1659  )
1660 {
1661  ec_slave_t *slave = fsm->slave;
1662 
1663  fsm->scan_jiffies_start = jiffies;
1665  EC_SLAVE_WARN(slave, "Retrying slave scan.\n");
1666  return;
1667 }
1668 
1669 /*****************************************************************************/
1670 
1674  ec_fsm_slave_scan_t *fsm,
1675  ec_datagram_t *datagram
1676  )
1677 {
1678  // wait for timeout
1679  unsigned long diff_ms =
1680  (jiffies - fsm->scan_jiffies_start) * 1000 / HZ;
1681 
1682  if (diff_ms >= SCAN_RETRY_TIME) {
1684  }
1685 }
1686 
1687 /******************************************************************************
1688  * Common state functions
1689  *****************************************************************************/
1690 
1694  ec_fsm_slave_scan_t *fsm,
1695  ec_datagram_t *datagram
1696  )
1697 {
1698 }
1699 
1700 /*****************************************************************************/
1701 
1705  ec_fsm_slave_scan_t *fsm,
1706  ec_datagram_t *datagram
1707  )
1708 {
1709 }
1710 
1711 /*****************************************************************************/
#define EC_FSM_RETRIES
Number of state machine retries on datagram timeout.
Definition: globals.h:59
#define EC_ALIAS_SII_OFFSET
Word offset of SII alias.
Definition: globals.h:112
ec_slave_t * slave
Slave the FSM runs on.
void ec_mbox_prot_data_prealloc(ec_slave_t *slave, uint16_t protocols, size_t size)
Allocates internal memory for mailbox response data for all slave supported mailbox protocols ...
Definition: datagram.c:738
uint16_t ring_position
Ring position.
Definition: slave.h:221
uint32_t revision_number
Revision number.
Definition: slave.h:162
void ec_fsm_slave_config_start(ec_fsm_slave_config_t *fsm)
Start slave configuration state machine.
uint16_t boot_rx_mailbox_offset
Bootstrap receive mailbox address.
Definition: slave.h:164
#define EC_SYNC_PAGE_SIZE
Size of a sync manager configuration page.
Definition: globals.h:127
void ec_fsm_slave_scan_state_sii_data(ec_fsm_slave_scan_t *, ec_datagram_t *)
Slave scan state: SII DATA.
void ec_fsm_slave_scan_state_sync(ec_fsm_slave_scan_t *, ec_datagram_t *)
Slave scan state: SYNC.
#define EC_SLAVE_STATE_MASK
Slave state mask.
Definition: globals.h:155
int ec_fsm_pdo_exec(ec_fsm_pdo_t *fsm, ec_datagram_t *datagram)
Executes the current state of the state machine.
Definition: fsm_pdo.c:164
void ec_fsm_slave_scan_state_datalink(ec_fsm_slave_scan_t *, ec_datagram_t *)
Slave scan state: DATALINK.
ec_datagram_t * datagram
Datagram used in the state machine.
struct list_head list
List item.
Definition: slave.h:202
uint16_t configured_tx_mailbox_size
Configured send mailbox size.
Definition: slave.h:248
uint16_t base_build
Build number.
Definition: slave.h:253
#define EC_SLAVE_DBG(slave, level, fmt, args...)
Convenience macro for printing slave-specific debug messages to syslog.
Definition: slave.h:108
void ec_fsm_slave_scan_enter_pdos(ec_fsm_slave_scan_t *, ec_datagram_t *)
Enter slave scan state PDOS.
OP (mailbox communication and input/output update)
Definition: globals.h:170
uint16_t configured_tx_mailbox_offset
Configured send mailbox offset.
Definition: slave.h:246
size_t ec_state_string(uint8_t, char *, uint8_t)
Prints slave states in clear text.
Definition: module.c:408
ec_slave_port_t ports[EC_MAX_PORTS]
Ports.
Definition: slave.h:231
ec_slave_state_t current_state
Current application state.
Definition: slave.h:237
Complete slave information interface data image.
Definition: slave.h:201
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:134
ec_slave_port_link_t link
Port link status.
Definition: slave.h:141
#define EC_SLAVE_WARN(slave, fmt, args...)
Convenience macro for printing slave-specific warnings to syslog.
Definition: slave.h:91
EtherCAT datagram.
Definition: datagram.h:88
struct list_head list
List of PDOs.
Definition: pdo_list.h:50
uint32_t serial_number
Serial number.
Definition: slave.h:163
#define EC_WRITE_U8(DATA, VAL)
Write an 8-bit unsigned value to EtherCAT data.
Definition: ecrt.h:2642
void ec_fsm_slave_scan_enter_clear_mailbox(ec_fsm_slave_scan_t *, ec_datagram_t *)
Enter slave scan state: Clear Mailbox.
uint16_t working_counter
Working counter.
Definition: datagram.h:100
int ec_fsm_slave_scan_exec(ec_fsm_slave_scan_t *fsm, ec_datagram_t *datagram)
Executes the current state of the state machine.
void ec_fsm_slave_scan_state_start(ec_fsm_slave_scan_t *, ec_datagram_t *)
Slave scan state: START.
Acknowledge/Error bit (no actual state)
Definition: globals.h:172
int ec_fsm_sii_exec(ec_fsm_sii_t *fsm, ec_datagram_t *datagram)
Executes the SII state machine.
Definition: fsm_sii.c:145
uint16_t boot_tx_mailbox_size
Bootstrap transmit mailbox size.
Definition: slave.h:167
int ec_slave_fetch_sii_strings(ec_slave_t *slave, const uint8_t *data, size_t data_size)
Fetches data from a STRING category.
Definition: slave.c:464
void ec_slave_set_dl_status(ec_slave_t *slave, uint16_t new_state)
Sets the data-link state of a slave.
Definition: slave.c:374
void ec_fsm_slave_scan_enter_attach_sii(ec_fsm_slave_scan_t *, ec_datagram_t *)
Enter slave scan state ATTACH_SII.
EtherCAT slave scanning state machine.
uint16_t station_address
Configured station address.
Definition: slave.h:222
#define EC_MAX_SII_SIZE
Maximum SII size in words, to avoid infinite reading.
Definition: globals.h:68
#define EC_VENDOR_SII_OFFSET
Word offset of SII vendor ID.
Definition: globals.h:115
unsigned int sync_count
Number of sync managers.
Definition: slave.h:191
uint16_t std_rx_mailbox_size
Standard receive mailbox size.
Definition: slave.h:169
#define EC_MAX_FMMUS
Maximum number of FMMUs per slave.
Definition: globals.h:130
uint8_t base_type
Slave type.
Definition: slave.h:251
Global definitions and macros.
uint16_t std_tx_mailbox_offset
Standard transmit mailbox address.
Definition: slave.h:170
void(* state)(ec_fsm_slave_scan_t *, ec_datagram_t *)
State function.
EtherCAT master structure.
SAFEOP (mailbox communication and input update)
Definition: globals.h:168
#define EC_MASTER_DBG(master, level, fmt, args...)
Convenience macro for printing master-specific debug messages to syslog.
Definition: master.h:106
uint16_t boot_tx_mailbox_offset
Bootstrap transmit mailbox address.
Definition: slave.h:166
ec_fsm_slave_config_t * fsm_slave_config
Slave configuration state machine to use.
#define EC_SERIAL_SII_OFFSET
Word offset of SII serial number.
Definition: globals.h:124
EtherCAT slave.
Definition: slave.h:214
int ec_datagram_apwr(ec_datagram_t *datagram, uint16_t ring_position, uint16_t mem_address, size_t data_size)
Initializes an EtherCAT APWR datagram.
Definition: datagram.c:232
void ec_datagram_zero(ec_datagram_t *datagram)
Fills the datagram payload memory with zeros.
Definition: datagram.c:179
void ec_fsm_slave_scan_enter_datalink(ec_fsm_slave_scan_t *, ec_datagram_t *)
Slave scan entry function: DATALINK.
ec_sii_image_t * sii_image
Current complete SII image.
Definition: slave.h:267
ec_datagram_state_t state
State.
Definition: datagram.h:101
CANopen over EtherCAT.
Definition: globals.h:184
void ec_fsm_slave_scan_state_sii_parse(ec_fsm_slave_scan_t *, ec_datagram_t *)
Slave scan state: SII PARSE.
ec_fsm_pdo_t * fsm_pdo
PDO configuration state machine to use.
void ec_slave_sii_image_init(ec_sii_image_t *sii_image)
Definition: slave.c:166
void ec_slave_clear_sync_managers(ec_slave_t *slave)
Clear the sync manager array.
Definition: slave.c:355
Use configured addresses.
Definition: fsm_sii.h:50
uint16_t mailbox_protocols
Supported mailbox protocols.
Definition: slave.h:172
void ec_fsm_slave_scan_state_end(ec_fsm_slave_scan_t *, ec_datagram_t *)
State: END.
void ec_fsm_slave_scan_state_sii_identity(ec_fsm_slave_scan_t *, ec_datagram_t *)
Slave scan state: SII IDENTITY.
void ec_fsm_pdo_start_reading(ec_fsm_pdo_t *fsm, ec_slave_t *slave)
Start reading the PDO configuration.
Definition: fsm_pdo.c:119
ec_fsm_sii_t fsm_sii
SII state machine.
unsigned int debug_level
Master debug level.
Definition: master.h:310
#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:627
ec_slave_dc_range_t base_dc_range
DC range.
Definition: slave.h:258
uint16_t std_rx_mailbox_offset
Standard receive mailbox address.
Definition: slave.h:168
uint8_t base_fmmu_bit_operation
FMMU bit operation is supported.
Definition: slave.h:256
void ec_fsm_slave_scan_state_address(ec_fsm_slave_scan_t *, ec_datagram_t *)
Slave scan state: ADDRESS.
int ec_fsm_slave_scan_running(const ec_fsm_slave_scan_t *fsm)
uint16_t alias
Configured station alias.
Definition: slave.h:159
#define EC_WRITE_U16(DATA, VAL)
Write a 16-bit unsigned value to EtherCAT data.
Definition: ecrt.h:2659
void ec_fsm_slave_scan_state_dc_cap(ec_fsm_slave_scan_t *, ec_datagram_t *)
Slave scan state: DC CAPABILITIES.
void ec_fsm_slave_scan_state_error(ec_fsm_slave_scan_t *, ec_datagram_t *)
State: ERROR.
uint8_t base_fmmu_count
Number of supported FMMUs.
Definition: slave.h:254
uint16_t configured_rx_mailbox_offset
Configured receive mailbox offset.
Definition: slave.h:242
void ec_fsm_slave_scan_state_mailbox_cleared(ec_fsm_slave_scan_t *, ec_datagram_t *)
Slave scan state: Mailbox cleared.
#define EC_READ_U32(DATA)
Read a 32-bit unsigned value from EtherCAT data.
Definition: ecrt.h:2570
uint32_t effective_product_code
Effective product code.
Definition: slave.h:227
ec_slave_t * slave
Slave, the sync manager belongs to.
Definition: sync.h:48
ec_slave_port_desc_t desc
Port descriptors.
Definition: slave.h:140
Finite state machine for scanning an EtherCAT slave.
#define SCAN_RETRY_TIME
Time to wait before slave scan retry [ms].
ec_master_t * master
Master owning the slave.
Definition: slave.h:216
void ec_fsm_slave_scan_state_pdos(ec_fsm_slave_scan_t *, ec_datagram_t *)
Slave scan state: PDOS.
void ec_fsm_slave_scan_state_assign_sii(ec_fsm_slave_scan_t *, ec_datagram_t *)
Slave scan state: ASSIGN_SII.
int ec_datagram_fpwr(ec_datagram_t *datagram, uint16_t configured_address, uint16_t mem_address, size_t data_size)
Initializes an EtherCAT FPWR datagram.
Definition: datagram.c:320
uint8_t has_dc_system_time
The slave supports the DC system time register.
Definition: slave.h:259
void ec_fsm_slave_scan_enter_assign_sii(ec_fsm_slave_scan_t *fsm, ec_datagram_t *datagram)
Enter slave scan state ASSIGN_SII.
void ec_fsm_slave_scan_state_dc_times(ec_fsm_slave_scan_t *, ec_datagram_t *)
Slave scan state: DC TIMES.
#define EC_MASTER_ERR(master, fmt, args...)
Convenience macro for printing master-specific errors to syslog.
Definition: master.h:80
unsigned int retries
Retries on datagram timeout.
int ec_datagram_fprd(ec_datagram_t *datagram, uint16_t configured_address, uint16_t mem_address, size_t data_size)
Initializes an EtherCAT FPRD datagram.
Definition: datagram.c:295
Values read by the master.
Definition: ecrt.h:439
void ec_fsm_slave_scan_state_preop(ec_fsm_slave_scan_t *, ec_datagram_t *)
Slave scan state: PREOP.
PDO configuration state machine.
Definition: fsm_pdo.h:54
#define EC_FIRST_SII_CATEGORY_OFFSET
Word offset of first SII category.
Definition: globals.h:109
uint8_t base_revision
Revision.
Definition: slave.h:252
32 bit.
Definition: globals.h:211
void ec_fsm_sii_read(ec_fsm_sii_t *fsm, ec_slave_t *slave, uint16_t word_offset, ec_fsm_sii_addressing_t mode)
Initializes the SII read state machine.
Definition: fsm_sii.c:106
#define EC_SLAVE_INFO(slave, fmt, args...)
Convenience macro for printing slave-specific information to syslog.
Definition: slave.h:63
void ec_fsm_slave_scan_enter_sii_identity(ec_fsm_slave_scan_t *, ec_datagram_t *)
Enter slave scan state SII_IDENTITY.
uint32_t effective_vendor_id
Effective vendor ID.
Definition: slave.h:226
unsigned long scan_jiffies_start
scan retry start timestamp.
uint16_t * vendor_words
First 16 words of SII image.
Definition: slave.h:266
void ec_fsm_slave_scan_enter_preop(ec_fsm_slave_scan_t *, ec_datagram_t *)
Enter slave scan state PREOP.
uint8_t valid_mbox_data
Received mailbox data is valid.
Definition: slave.h:297
void ec_fsm_sii_clear(ec_fsm_sii_t *fsm)
Destructor.
Definition: fsm_sii.c:96
int ec_fsm_pdo_success(const ec_fsm_pdo_t *fsm)
Get execution result.
Definition: fsm_pdo.c:180
void ec_fsm_slave_scan_state_base(ec_fsm_slave_scan_t *, ec_datagram_t *)
Slave scan state: BASE.
uint16_t effective_alias
Effective alias address.
Definition: slave.h:223
#define EC_PRODUCT_SII_OFFSET
Word offset of SII product number.
Definition: globals.h:118
int ec_fsm_sii_success(ec_fsm_sii_t *fsm)
Returns, if the master startup state machine terminated with success.
Definition: fsm_sii.c:179
#define EC_READ_U16(DATA)
Read a 16-bit unsigned value from EtherCAT data.
Definition: ecrt.h:2554
Finite state machine to configure an EtherCAT slave.
void ec_datagram_print_state(const ec_datagram_t *datagram)
Prints the state of a datagram.
Definition: datagram.c:587
void ec_fsm_slave_scan_start(ec_fsm_slave_scan_t *fsm)
Start slave scan state machine.
Mailbox functionality.
int ec_slave_fetch_sii_syncs(ec_slave_t *slave, const uint8_t *data, size_t data_size)
Fetches data from a SYNC MANAGER category.
Definition: slave.c:581
#define EC_STATE_STRING_SIZE
Minimum size of a buffer used with ec_state_string().
Definition: globals.h:65
uint16_t boot_rx_mailbox_size
Bootstrap receive mailbox size.
Definition: slave.h:165
#define EC_MAX_PORTS
Maximum number of slave ports.
Definition: ecrt.h:217
uint32_t effective_serial_number
Effective serial number.
Definition: slave.h:229
SII "firmware" loader.
void ec_fsm_slave_scan_state_retry_wait(ec_fsm_slave_scan_t *, ec_datagram_t *)
Slave scan state: scan retry wait.
int ec_fsm_slave_config_exec(ec_fsm_slave_config_t *fsm, ec_datagram_t *datagram)
Executes the current state of the state machine.
void ec_fsm_slave_scan_state_state(ec_fsm_slave_scan_t *, ec_datagram_t *)
Slave scan state: STATE.
void ec_fsm_sii_init(ec_fsm_sii_t *fsm)
Constructor.
Definition: fsm_sii.c:83
uint32_t receive_time
Port receive times for delay measurement.
Definition: slave.h:143
Timed out (dequeued).
Definition: datagram.h:79
void ec_fsm_slave_scan_enter_sii_size(ec_fsm_slave_scan_t *, ec_datagram_t *)
Enter slave scan state SII_SIZE.
uint16_t sii_offset
SII offset in words.
ec_pdo_list_t pdos
Current PDO assignment.
Definition: sync.h:53
void ec_slave_request_state(ec_slave_t *slave, ec_slave_state_t state)
Request a slave state and resets the error flag.
Definition: slave.c:436
void ec_fsm_slave_scan_state_retry(ec_fsm_slave_scan_t *, ec_datagram_t *)
Slave scan state: scan retry.
uint16_t configured_rx_mailbox_size
Configured receive mailbox size.
Definition: slave.h:244
uint8_t base_dc_supported
Distributed clocks are supported.
Definition: slave.h:257
uint8_t * data
Datagram payload.
Definition: datagram.h:95
void ec_fsm_slave_scan_state_sii_size(ec_fsm_slave_scan_t *, ec_datagram_t *)
Slave scan state: SII SIZE.
#define EC_REVISION_SII_OFFSET
Word offset of SII revision number.
Definition: globals.h:121
uint8_t base_sync_count
Number of supported sync managers.
Definition: slave.h:255
#define EC_READ_U8(DATA)
Read an 8-bit unsigned value from EtherCAT data.
Definition: ecrt.h:2538
int ec_fsm_slave_config_success(const ec_fsm_slave_config_t *fsm)
void ec_fsm_slave_scan_clear(ec_fsm_slave_scan_t *fsm)
Destructor.
EtherCAT slave configuration structure.
ec_sii_t sii
Extracted SII data.
Definition: slave.h:207
Unused and should not be queued (dequeued).
Definition: datagram.h:81
unsigned int scan_retries
Retries on scan read error.
uint32_t product_code
Vendor-specific product code.
Definition: slave.h:161
PREOP state (mailbox communication, no IO)
Definition: globals.h:164
Values written by the master.
Definition: ecrt.h:438
Received (dequeued).
Definition: datagram.h:78
size_t nwords
Size of the SII contents in words.
Definition: slave.h:205
unsigned int error_flag
Stop processing after an error.
Definition: slave.h:239
ec_sync_t * syncs
SYNC MANAGER categories.
Definition: slave.h:190
uint16_t std_tx_mailbox_size
Standard transmit mailbox size.
Definition: slave.h:171
void ec_fsm_slave_scan_init(ec_fsm_slave_scan_t *fsm, ec_slave_t *slave, ec_fsm_slave_config_t *fsm_slave_config, ec_fsm_pdo_t *fsm_pdo)
Constructor.
uint32_t effective_revision_number
Effective revision number.
Definition: slave.h:228
int ec_slave_fetch_sii_pdos(ec_slave_t *slave, const uint8_t *data, size_t data_size, ec_direction_t dir)
Fetches data from a [RT]xPDO category.
Definition: slave.c:652
#define EC_MAX_SYNC_MANAGERS
Maximum number of sync managers per slave.
Definition: ecrt.h:208
int ec_datagram_repeat(ec_datagram_t *datagram, const ec_datagram_t *source)
Copies a previously constructed datagram for repeated send.
Definition: datagram.c:190
int ec_slave_fetch_sii_general(ec_slave_t *slave, const uint8_t *data, size_t data_size)
Fetches data from a GENERAL category.
Definition: slave.c:525
uint32_t vendor_id
Vendor ID.
Definition: slave.h:160
struct list_head sii_images
List of slave SII images.
Definition: master.h:247
int ec_fsm_slave_scan_success(const ec_fsm_slave_scan_t *fsm)
uint8_t value[4]
raw SII value (32bit)
Definition: fsm_sii.h:70