IgH EtherCAT Master  1.7.0
slave.c
Go to the documentation of this file.
1 /*****************************************************************************
2  *
3  * Copyright (C) 2006-2026 Florian Pose, Ingenieurgemeinschaft IgH
4  *
5  * This file is part of the IgH EtherCAT Master.
6  *
7  * The IgH EtherCAT Master is free software; you can redistribute it and/or
8  * modify it under the terms of the GNU General Public License version 2, as
9  * published by the Free Software Foundation.
10  *
11  * The IgH EtherCAT Master is distributed in the hope that it will be useful,
12  * but WITHOUT ANY WARRANTY; without even the implied warranty of
13  * MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the GNU General
14  * Public License for more details.
15  *
16  * You should have received a copy of the GNU General Public License along
17  * with the IgH EtherCAT Master; if not, write to the Free Software
18  * Foundation, Inc., 51 Franklin St, Fifth Floor, Boston, MA 02110-1301 USA
19  *
20  ****************************************************************************/
21 
27 /****************************************************************************/
28 
29 #include <linux/module.h>
30 #include <linux/delay.h>
31 
32 #include "globals.h"
33 #include "datagram.h"
34 #include "master.h"
35 #include "slave_config.h"
36 
37 #include "slave.h"
38 
39 /****************************************************************************/
40 
41 extern const ec_code_msg_t al_status_messages[];
42 
43 /****************************************************************************/
44 
45 // prototypes for private methods
46 char *ec_slave_sii_string(const ec_slave_t *, unsigned int);
48 unsigned int ec_slave_get_previous_port(const ec_slave_t *, unsigned int);
49 unsigned int ec_slave_get_next_port(const ec_slave_t *, unsigned int);
50 uint32_t ec_slave_calc_rtt_sum(const ec_slave_t *);
52 int ec_slave_fetch_sii_strings(ec_slave_t *, const uint8_t *, size_t);
53 int ec_slave_fetch_sii_general(ec_slave_t *, const uint8_t *, size_t);
54 int ec_slave_fetch_sii_syncs(ec_slave_t *, const uint8_t *, size_t);
55 int ec_slave_fetch_sii_pdos(ec_slave_t *, const uint8_t *, size_t,
57 
58 /****************************************************************************/
59 
66  ec_slave_t *slave,
67  ec_master_t *master,
68  ec_device_index_t dev_idx,
69  uint16_t ring_position,
70  uint16_t station_address
71  )
72 {
73  unsigned int i;
74 
75  slave->master = master;
76  slave->device_index = dev_idx;
77  slave->ring_position = ring_position;
78  slave->station_address = station_address;
79  slave->effective_alias = 0x0000;
80 
81  slave->config = NULL;
84  slave->error_flag = 0;
85  slave->force_config = 0;
86  slave->configured_rx_mailbox_offset = 0x0000;
87  slave->configured_rx_mailbox_size = 0x0000;
88  slave->configured_tx_mailbox_offset = 0x0000;
89  slave->configured_tx_mailbox_size = 0x0000;
90 
91  slave->base_type = 0;
92  slave->base_revision = 0;
93  slave->base_build = 0;
94  slave->base_fmmu_count = 0;
95  slave->base_sync_count = 0;
96 
97  for (i = 0; i < EC_MAX_PORTS; i++) {
99 
100  slave->ports[i].link.link_up = 0;
101  slave->ports[i].link.loop_closed = 0;
102  slave->ports[i].link.signal_detected = 0;
103  slave->sii.physical_layer[i] = 0xFF;
104 
105  slave->ports[i].receive_time = 0U;
106 
107  slave->ports[i].next_slave = NULL;
108  slave->ports[i].delay_to_next_dc = 0U;
109  }
110 
111  slave->base_fmmu_bit_operation = 0;
112  slave->base_dc_supported = 0;
113  slave->base_dc_range = EC_DC_32;
114  slave->has_dc_system_time = 0;
115  slave->transmission_delay = 0U;
116 
117  ec_sii_page_init(&slave->sii_page);
118  slave->sii_parallel_words = 0;
119 
120  slave->sii.alias = 0x0000;
121  slave->sii.vendor_id = 0x00000000;
122  slave->sii.product_code = 0x00000000;
123  slave->sii.revision_number = 0x00000000;
124  slave->sii.serial_number = 0x00000000;
125  slave->sii.boot_rx_mailbox_offset = 0x0000;
126  slave->sii.boot_rx_mailbox_size = 0x0000;
127  slave->sii.boot_tx_mailbox_offset = 0x0000;
128  slave->sii.boot_tx_mailbox_size = 0x0000;
129  slave->sii.std_rx_mailbox_offset = 0x0000;
130  slave->sii.std_rx_mailbox_size = 0x0000;
131  slave->sii.std_tx_mailbox_offset = 0x0000;
132  slave->sii.std_tx_mailbox_size = 0x0000;
133  slave->sii.mailbox_protocols = 0;
134 
135  slave->sii.strings = NULL;
136  slave->sii.string_count = 0;
137 
138  slave->sii.has_general = 0;
139  slave->sii.group = NULL;
140  slave->sii.image = NULL;
141  slave->sii.order = NULL;
142  slave->sii.name = NULL;
143  memset(&slave->sii.coe_details, 0x00, sizeof(ec_sii_coe_details_t));
144  memset(&slave->sii.general_flags, 0x00, sizeof(ec_sii_general_flags_t));
145  slave->sii.current_on_ebus = 0;
146 
147  slave->sii.syncs = NULL;
148  slave->sii.sync_count = 0;
149 
150  INIT_LIST_HEAD(&slave->sii.pdos);
151 
152  INIT_LIST_HEAD(&slave->sdo_dictionary);
153 
154  slave->sdo_dictionary_fetched = 0;
155  slave->jiffies_preop = 0;
156 
157  INIT_LIST_HEAD(&slave->sdo_requests);
158  INIT_LIST_HEAD(&slave->reg_requests);
159  INIT_LIST_HEAD(&slave->foe_requests);
160  INIT_LIST_HEAD(&slave->soe_requests);
161  INIT_LIST_HEAD(&slave->eoe_requests);
162 
163  // create state machine object
164  ec_fsm_slave_init(&slave->fsm, slave);
165 
166  slave->read_mbox_busy = 0;
167 
168 #ifdef EC_EOE
170 #endif
175 
176  slave->valid_mbox_data = 0;
177 }
178 
179 /****************************************************************************/
180 
188 {
189  clear_bit_unlock(0, &slave->read_mbox_busy);
190 }
191 
192 /****************************************************************************/
193 
202 {
203  return test_and_set_bit_lock(0, &slave->read_mbox_busy);
204 }
205 
206 /****************************************************************************/
207 
214 {
215  ec_sdo_t *sdo, *next_sdo;
216  unsigned int i;
217  ec_pdo_t *pdo, *next_pdo;
218 
219  // abort all pending requests
220 
221  while (!list_empty(&slave->sdo_requests)) {
222  ec_sdo_request_t *request =
223  list_entry(slave->sdo_requests.next, ec_sdo_request_t, list);
224  list_del_init(&request->list); // dequeue
225  EC_SLAVE_WARN(slave, "Discarding SDO request,"
226  " slave about to be deleted.\n");
227  request->state = EC_INT_REQUEST_FAILURE;
228  }
229 
230  while (!list_empty(&slave->reg_requests)) {
231  ec_reg_request_t *reg =
232  list_entry(slave->reg_requests.next, ec_reg_request_t, list);
233  list_del_init(&reg->list); // dequeue
234  EC_SLAVE_WARN(slave, "Discarding register request,"
235  " slave about to be deleted.\n");
236  reg->state = EC_INT_REQUEST_FAILURE;
237  }
238 
239  while (!list_empty(&slave->foe_requests)) {
240  ec_foe_request_t *request =
241  list_entry(slave->foe_requests.next, ec_foe_request_t, list);
242  list_del_init(&request->list); // dequeue
243  EC_SLAVE_WARN(slave, "Discarding FoE request,"
244  " slave about to be deleted.\n");
245  request->state = EC_INT_REQUEST_FAILURE;
246  }
247 
248  while (!list_empty(&slave->soe_requests)) {
249  ec_soe_request_t *request =
250  list_entry(slave->soe_requests.next, ec_soe_request_t, list);
251  list_del_init(&request->list); // dequeue
252  EC_SLAVE_WARN(slave, "Discarding SoE request,"
253  " slave about to be deleted.\n");
254  request->state = EC_INT_REQUEST_FAILURE;
255  }
256 
257 #ifdef EC_EOE
258  while (!list_empty(&slave->eoe_requests)) {
259  ec_eoe_request_t *request =
260  list_entry(slave->eoe_requests.next, ec_eoe_request_t, list);
261  list_del_init(&request->list); // dequeue
262  EC_SLAVE_WARN(slave, "Discarding EoE request,"
263  " slave about to be deleted.\n");
264  request->state = EC_INT_REQUEST_FAILURE;
265  }
266 #endif
267 
268  wake_up_all(&slave->master->request_queue);
269 
270  if (slave->config) {
272  }
273 
274  // free all SDOs
275  list_for_each_entry_safe(sdo, next_sdo, &slave->sdo_dictionary, list) {
276  list_del(&sdo->list);
277  ec_sdo_clear(sdo);
278  kfree(sdo);
279  }
280 
281  // free all strings
282  if (slave->sii.strings) {
283  for (i = 0; i < slave->sii.string_count; i++)
284  kfree(slave->sii.strings[i]);
285  kfree(slave->sii.strings);
286  }
287 
288  // free all sync managers
290 
291  // free all SII PDOs
292  list_for_each_entry_safe(pdo, next_pdo, &slave->sii.pdos, list) {
293  list_del(&pdo->list);
294  ec_pdo_clear(pdo);
295  kfree(pdo);
296  }
297 
298  ec_sii_page_clear(&slave->sii_page);
299 
300  // free mailbox response data
301 #ifdef EC_EOE
303 #endif
308 
309  ec_fsm_slave_clear(&slave->fsm);
310 }
311 
312 /****************************************************************************/
313 
317 {
318  unsigned int i;
319 
320  if (slave->sii.syncs) {
321  for (i = 0; i < slave->sii.sync_count; i++) {
322  ec_sync_clear(&slave->sii.syncs[i]);
323  }
324  kfree(slave->sii.syncs);
325  slave->sii.syncs = NULL;
326  }
327 }
328 
329 /****************************************************************************/
330 
336  ec_slave_state_t new_state
337  )
338 {
339  if (new_state != slave->current_state) {
340  if (slave->master->debug_level) {
341  char old_state[EC_STATE_STRING_SIZE],
342  cur_state[EC_STATE_STRING_SIZE];
343  ec_state_string(slave->current_state, old_state, 0);
344  ec_state_string(new_state, cur_state, 0);
345  EC_SLAVE_DBG(slave, 0, "%s -> %s.\n", old_state, cur_state);
346  }
347  slave->current_state = new_state;
348  }
349 }
350 
351 /****************************************************************************/
352 
358  ec_slave_state_t state
359  )
360 {
361  slave->requested_state = state;
362  slave->error_flag = 0;
363 }
364 
365 /****************************************************************************/
366 
373  ec_slave_t *slave
374  )
375 {
376  uint16_t *cat_word, cat_type, cat_size;
377  int ret;
378 
380 
381  slave->sii.alias =
383  slave->effective_alias = slave->sii.alias;
384  slave->sii_page.alias = slave->sii.alias;
385 
386  slave->sii.vendor_id =
388  slave->sii_page.vendor_id = slave->sii.vendor_id;
389 
390  slave->sii.product_code =
391  EC_READ_U32(slave->sii_page.words + 0x000A);
392  slave->sii_page.product_code = slave->sii.product_code;
393 
394  slave->sii.revision_number =
395  EC_READ_U32(slave->sii_page.words + 0x000C);
397 
398  slave->sii.serial_number =
399  EC_READ_U32(slave->sii_page.words + 0x000E);
400  slave->sii_page.serial_number = slave->sii.serial_number;
401 
402  slave->sii.boot_rx_mailbox_offset =
403  EC_READ_U16(slave->sii_page.words + 0x0014);
404  slave->sii.boot_rx_mailbox_size =
405  EC_READ_U16(slave->sii_page.words + 0x0015);
406  slave->sii.boot_tx_mailbox_offset =
407  EC_READ_U16(slave->sii_page.words + 0x0016);
408  slave->sii.boot_tx_mailbox_size =
409  EC_READ_U16(slave->sii_page.words + 0x0017);
410  slave->sii.std_rx_mailbox_offset =
411  EC_READ_U16(slave->sii_page.words + 0x0018);
412  slave->sii.std_rx_mailbox_size =
413  EC_READ_U16(slave->sii_page.words + 0x0019);
414  slave->sii.std_tx_mailbox_offset =
415  EC_READ_U16(slave->sii_page.words + 0x001A);
416  slave->sii.std_tx_mailbox_size =
417  EC_READ_U16(slave->sii_page.words + 0x001B);
418  slave->sii.mailbox_protocols =
419  EC_READ_U16(slave->sii_page.words + 0x001C);
420  if (slave->sii.mailbox_protocols) {
421  int need_delim = 0;
422  uint16_t all = EC_MBOX_AOE | EC_MBOX_COE | EC_MBOX_FOE |
424  if ((slave->sii.mailbox_protocols & all) &&
425  slave->master->debug_level >= 1) {
426  EC_SLAVE_DBG(slave, 1, "Slave announces to support ");
427  if (slave->sii.mailbox_protocols & EC_MBOX_AOE) {
428  printk(KERN_CONT "AoE");
429  need_delim = 1;
430  }
431  if (slave->sii.mailbox_protocols & EC_MBOX_COE) {
432  if (need_delim) {
433  printk(KERN_CONT ", ");
434  }
435  printk(KERN_CONT "CoE");
436  need_delim = 1;
437  }
438  if (slave->sii.mailbox_protocols & EC_MBOX_FOE) {
439  if (need_delim) {
440  printk(KERN_CONT ", ");
441  }
442  printk(KERN_CONT "FoE");
443  need_delim = 1;
444  }
445  if (slave->sii.mailbox_protocols & EC_MBOX_SOE) {
446  if (need_delim) {
447  printk(KERN_CONT ", ");
448  }
449  printk(KERN_CONT "SoE");
450  need_delim = 1;
451  }
452  if (slave->sii.mailbox_protocols & EC_MBOX_VOE) {
453  if (need_delim) {
454  printk(KERN_CONT ", ");
455  }
456  printk(KERN_CONT "VoE");
457  need_delim = 1;
458  }
459  printk(KERN_CONT ".\n");
460  }
461  if (slave->sii.mailbox_protocols & ~all) {
462  EC_SLAVE_DBG(slave, 1, "Slave announces to support unknown"
463  " mailbox protocols 0x%04X.",
464  slave->sii.mailbox_protocols & ~all);
465  }
466  }
467  else {
468  EC_SLAVE_DBG(slave, 1, "Slave announces to support no mailbox"
469  " protocols.");
470  }
471 
472  if (slave->sii.boot_rx_mailbox_offset == 0xffff ||
473  slave->sii.boot_rx_mailbox_size == 0xffff ||
474  slave->sii.boot_tx_mailbox_offset == 0xffff ||
475  slave->sii.boot_tx_mailbox_size == 0xffff ||
476  slave->sii.std_rx_mailbox_offset == 0xffff ||
477  slave->sii.std_rx_mailbox_size == 0xffff ||
478  slave->sii.std_tx_mailbox_offset == 0xffff ||
479  slave->sii.std_tx_mailbox_size == 0xffff) {
480  slave->sii.mailbox_protocols = 0x0000;
481  EC_SLAVE_ERR(slave, "Invalid mailbox settings in SII."
482  " Disabling mailbox communication.");
483  }
484 
486  // SII does not contain category data
487  return 0;
488  }
489 
491  EC_SLAVE_ERR(slave, "Unexpected end of SII data:"
492  " First category header missing.\n");
493  return -ENOENT;
494  }
495 
496  // evaluate category data
497  cat_word = slave->sii_page.words + EC_FIRST_SII_CATEGORY_OFFSET;
498  while (EC_READ_U16(cat_word) != 0xFFFF) {
499  // type and size words must fit
500  if (cat_word + 2 - slave->sii_page.words
501  > slave->sii_page.word_count) {
502  EC_SLAVE_ERR(slave, "Unexpected end of SII data:"
503  " Category header incomplete.\n");
504  return -ENOENT;
505  }
506 
507  cat_type = EC_READ_U16(cat_word) & 0x7FFF;
508  cat_size = EC_READ_U16(cat_word + 1);
509  cat_word += 2;
510 
511  if (cat_word + cat_size - slave->sii_page.words
512  > slave->sii_page.word_count) {
513  EC_SLAVE_WARN(slave, "Unexpected end of SII data:"
514  " Category data incomplete.\n");
515  return -ENOENT;
516  }
517 
518  switch (cat_type) {
519  case 0x000A:
520  ret = ec_slave_fetch_sii_strings(slave, (uint8_t *) cat_word,
521  cat_size * 2);
522  if (ret) {
523  return ret;
524  }
525  break;
526 
527  case 0x001E:
528  ret = ec_slave_fetch_sii_general(slave, (uint8_t *) cat_word,
529  cat_size * 2);
530  if (ret) {
531  return ret;
532  }
533  break;
534 
535  case 0x0028:
536  break;
537 
538  case 0x0029:
539  ret = ec_slave_fetch_sii_syncs(slave, (uint8_t *) cat_word,
540  cat_size * 2);
541  if (ret) {
542  return ret;
543  }
544  break;
545 
546  case 0x0032:
547  ret = ec_slave_fetch_sii_pdos(slave, (uint8_t *) cat_word,
548  cat_size * 2, EC_DIR_INPUT); // TxPDO
549  if (ret) {
550  return ret;
551  }
552  break;
553 
554  case 0x0033:
555  ret = ec_slave_fetch_sii_pdos(slave, (uint8_t *) cat_word,
556  cat_size * 2, EC_DIR_OUTPUT); // RxPDO
557  if (ret) {
558  return ret;
559  }
560  break;
561 
562  default:
563  EC_SLAVE_DBG(slave, 1, "Unknown category type 0x%04X.\n",
564  cat_type);
565  }
566 
567  cat_word += cat_size;
568  if (cat_word - slave->sii_page.words >= slave->sii_page.word_count) {
569  EC_SLAVE_WARN(slave, "Unexpected end of SII data:"
570  " Next category header missing.\n");
571  return -ENOENT;
572  }
573  }
574 
575  return 0;
576 }
577 
578 /****************************************************************************/
579 
587  ec_slave_t *slave,
588  const uint8_t *data,
589  size_t data_size
590  )
591 {
592  int i, err;
593  size_t size;
594  off_t offset;
595 
596  slave->sii.string_count = data[0];
597 
598  if (slave->sii.string_count) {
599  if (!(slave->sii.strings =
600  kmalloc(sizeof(char *) * slave->sii.string_count,
601  GFP_KERNEL))) {
602  EC_SLAVE_ERR(slave, "Failed to allocate string array memory.\n");
603  err = -ENOMEM;
604  goto out_zero;
605  }
606 
607  offset = 1;
608  for (i = 0; i < slave->sii.string_count; i++) {
609  size = data[offset];
610  // allocate memory for string structure and data at a single blow
611  if (!(slave->sii.strings[i] =
612  kmalloc(sizeof(char) * size + 1, GFP_KERNEL))) {
613  EC_SLAVE_ERR(slave, "Failed to allocate string memory.\n");
614  err = -ENOMEM;
615  goto out_free;
616  }
617  memcpy(slave->sii.strings[i], data + offset + 1, size);
618  slave->sii.strings[i][size] = 0x00; // append binary zero
619  offset += 1 + size;
620  }
621  }
622 
623  return 0;
624 
625 out_free:
626  for (i--; i >= 0; i--)
627  kfree(slave->sii.strings[i]);
628  kfree(slave->sii.strings);
629  slave->sii.strings = NULL;
630 out_zero:
631  slave->sii.string_count = 0;
632  return err;
633 }
634 
635 /****************************************************************************/
636 
643  ec_slave_t *slave,
644  const uint8_t *data,
645  size_t data_size
646  )
647 {
648  unsigned int i;
649  uint8_t flags;
650 
651  if (data_size != 32) {
652  EC_SLAVE_ERR(slave, "Wrong size of general category (%zu/32).\n",
653  data_size);
654  return -EINVAL;
655  }
656 
657  slave->sii.group = ec_slave_sii_string(slave, data[0]);
658  slave->sii.image = ec_slave_sii_string(slave, data[1]);
659  slave->sii.order = ec_slave_sii_string(slave, data[2]);
660  slave->sii.name = ec_slave_sii_string(slave, data[3]);
661 
662  for (i = 0; i < 4; i++)
663  slave->sii.physical_layer[i] =
664  (data[4] & (0x03 << (i * 2))) >> (i * 2);
665 
666  // read CoE details
667  flags = EC_READ_U8(data + 5);
668  slave->sii.coe_details.enable_sdo = (flags >> 0) & 0x01;
669  slave->sii.coe_details.enable_sdo_info = (flags >> 1) & 0x01;
670  slave->sii.coe_details.enable_pdo_assign = (flags >> 2) & 0x01;
671  slave->sii.coe_details.enable_pdo_configuration = (flags >> 3) & 0x01;
672  slave->sii.coe_details.enable_upload_at_startup = (flags >> 4) & 0x01;
673  slave->sii.coe_details.enable_sdo_complete_access = (flags >> 5) & 0x01;
674 
675  // read general flags
676  flags = EC_READ_U8(data + 0x000B);
677  slave->sii.general_flags.enable_safeop = (flags >> 0) & 0x01;
678  slave->sii.general_flags.enable_not_lrw = (flags >> 1) & 0x01;
679 
680  slave->sii.current_on_ebus = EC_READ_S16(data + 0x0C);
681  slave->sii.has_general = 1;
682  return 0;
683 }
684 
685 /****************************************************************************/
686 
694  ec_slave_t *slave,
695  const uint8_t *data,
696  size_t data_size
697  )
698 {
699  unsigned int i, count, total_count;
700  ec_sync_t *sync;
701  size_t memsize;
702  ec_sync_t *syncs;
703  uint8_t index;
704 
705  // one sync manager struct is 4 words long
706  if (data_size % 8) {
707  EC_SLAVE_ERR(slave, "Invalid SII sync manager category size %zu.\n",
708  data_size);
709  return -EINVAL;
710  }
711 
712  count = data_size / 8;
713 
714  if (count) {
715  total_count = count + slave->sii.sync_count;
716  if (total_count > EC_MAX_SYNC_MANAGERS) {
717  EC_SLAVE_ERR(slave, "Exceeded maximum number of"
718  " sync managers!\n");
719  return -EOVERFLOW;
720  }
721  memsize = sizeof(ec_sync_t) * total_count;
722  if (!(syncs = kmalloc(memsize, GFP_KERNEL))) {
723  EC_SLAVE_ERR(slave, "Failed to allocate %zu bytes"
724  " for sync managers.\n", memsize);
725  return -ENOMEM;
726  }
727 
728  for (i = 0; i < slave->sii.sync_count; i++)
729  ec_sync_init_copy(syncs + i, slave->sii.syncs + i);
730 
731  // initialize new sync managers
732  for (i = 0; i < count; i++, data += 8) {
733  index = i + slave->sii.sync_count;
734  sync = &syncs[index];
735 
736  ec_sync_init(sync, slave);
737  sync->physical_start_address = EC_READ_U16(data);
738  sync->default_length = EC_READ_U16(data + 2);
739  sync->control_register = EC_READ_U8(data + 4);
740  sync->enable = EC_READ_U8(data + 6);
741  }
742 
743  if (slave->sii.syncs)
744  kfree(slave->sii.syncs);
745  slave->sii.syncs = syncs;
746  slave->sii.sync_count = total_count;
747  }
748 
749  return 0;
750 }
751 
752 /****************************************************************************/
753 
760  ec_slave_t *slave,
761  const uint8_t *data,
762  size_t data_size,
763  ec_direction_t dir
764  )
765 {
766  int ret;
767  ec_pdo_t *pdo;
768  ec_pdo_entry_t *entry;
769  unsigned int entry_count, i;
770 
771  while (data_size >= 8) {
772  if (!(pdo = kmalloc(sizeof(ec_pdo_t), GFP_KERNEL))) {
773  EC_SLAVE_ERR(slave, "Failed to allocate PDO memory.\n");
774  return -ENOMEM;
775  }
776 
777  ec_pdo_init(pdo);
778  pdo->index = EC_READ_U16(data);
779  entry_count = EC_READ_U8(data + 2);
780  pdo->sync_index = EC_READ_U8(data + 3);
781  ret = ec_pdo_set_name(pdo,
782  ec_slave_sii_string(slave, EC_READ_U8(data + 5)));
783  if (ret) {
784  ec_pdo_clear(pdo);
785  kfree(pdo);
786  return ret;
787  }
788  list_add_tail(&pdo->list, &slave->sii.pdos);
789 
790  data_size -= 8;
791  data += 8;
792 
793  for (i = 0; i < entry_count; i++) {
794  if (!(entry = kmalloc(sizeof(ec_pdo_entry_t), GFP_KERNEL))) {
795  EC_SLAVE_ERR(slave, "Failed to allocate PDO entry memory.\n");
796  return -ENOMEM;
797  }
798 
799  ec_pdo_entry_init(entry);
800  entry->index = EC_READ_U16(data);
801  entry->subindex = EC_READ_U8(data + 2);
802  ret = ec_pdo_entry_set_name(entry,
803  ec_slave_sii_string(slave, EC_READ_U8(data + 3)));
804  if (ret) {
805  ec_pdo_entry_clear(entry);
806  kfree(entry);
807  return ret;
808  }
809  entry->bit_length = EC_READ_U8(data + 5);
810  list_add_tail(&entry->list, &pdo->entries);
811 
812  data_size -= 8;
813  data += 8;
814  }
815 
816  // if sync manager index is positive, the PDO is mapped by default
817  if (pdo->sync_index >= 0) {
818  ec_sync_t *sync;
819 
820  if (!(sync = ec_slave_get_sync(slave, pdo->sync_index))) {
821  EC_SLAVE_ERR(slave, "Invalid SM index %i for PDO 0x%04X.",
822  pdo->sync_index, pdo->index);
823  return -ENOENT;
824  }
825 
826  ret = ec_pdo_list_add_pdo_copy(&sync->pdos, pdo);
827  if (ret)
828  return ret;
829  }
830  }
831 
832  return 0;
833 }
834 
835 /****************************************************************************/
836 
843  const ec_slave_t *slave,
844  unsigned int index
845  )
846 {
847  if (!index--)
848  return NULL;
849 
850  if (index >= slave->sii.string_count) {
851  EC_SLAVE_DBG(slave, 1, "String %u not found.\n", index);
852  return NULL;
853  }
854 
855  return slave->sii.strings[index];
856 }
857 
858 /****************************************************************************/
859 
865  ec_slave_t *slave,
866  uint8_t sync_index
867  )
868 {
869  if (sync_index < slave->sii.sync_count) {
870  return &slave->sii.syncs[sync_index];
871  } else {
872  return NULL;
873  }
874 }
875 
876 /****************************************************************************/
877 
883  unsigned int *sdo_count,
884  unsigned int *entry_count
886  )
887 {
888  unsigned int sdos = 0, entries = 0;
889  ec_sdo_t *sdo;
890  ec_sdo_entry_t *entry;
891 
892  list_for_each_entry(sdo, &slave->sdo_dictionary, list) {
893  sdos++;
894  list_for_each_entry(entry, &sdo->entries, list) {
895  entries++;
896  }
897  }
898 
899  *sdo_count = sdos;
900  *entry_count = entries;
901 }
902 
903 /****************************************************************************/
904 
911  ec_slave_t *slave,
912  uint16_t index
913  )
914 {
915  ec_sdo_t *sdo;
916 
917  list_for_each_entry(sdo, &slave->sdo_dictionary, list) {
918  if (sdo->index != index)
919  continue;
920  return sdo;
921  }
922 
923  return NULL;
924 }
925 
926 /****************************************************************************/
927 
937  const ec_slave_t *slave,
938  uint16_t index
939  )
940 {
941  const ec_sdo_t *sdo;
942 
943  list_for_each_entry(sdo, &slave->sdo_dictionary, list) {
944  if (sdo->index != index)
945  continue;
946  return sdo;
947  }
948 
949  return NULL;
950 }
951 
952 /****************************************************************************/
953 
959  const ec_slave_t *slave,
960  uint16_t sdo_position
961  )
962 {
963  const ec_sdo_t *sdo;
964 
965  list_for_each_entry(sdo, &slave->sdo_dictionary, list) {
966  if (sdo_position--)
967  continue;
968  return sdo;
969  }
970 
971  return NULL;
972 }
973 
974 /****************************************************************************/
975 
981  const ec_slave_t *slave
982  )
983 {
984  const ec_sdo_t *sdo;
985  uint16_t count = 0;
986 
987  list_for_each_entry(sdo, &slave->sdo_dictionary, list) {
988  count++;
989  }
990 
991  return count;
992 }
993 
994 /****************************************************************************/
995 
1000  const ec_slave_t *slave,
1001  uint16_t index
1002  )
1003 {
1004  unsigned int i;
1005  const ec_sync_t *sync;
1006  const ec_pdo_t *pdo;
1007 
1008  for (i = 0; i < slave->sii.sync_count; i++) {
1009  sync = &slave->sii.syncs[i];
1010 
1011  if (!(pdo = ec_pdo_list_find_pdo_const(&sync->pdos, index)))
1012  continue;
1013 
1014  return pdo;
1015  }
1016 
1017  return NULL;
1018 }
1019 
1020 /****************************************************************************/
1021 
1025  ec_slave_t *slave,
1026  ec_pdo_t *pdo
1027  )
1028 {
1029  const ec_sdo_t *sdo;
1030  ec_pdo_entry_t *pdo_entry;
1031  const ec_sdo_entry_t *sdo_entry;
1032 
1033  list_for_each_entry(sdo, &slave->sdo_dictionary, list) {
1034  if (sdo->index == pdo->index) {
1035  ec_pdo_set_name(pdo, sdo->name);
1036  } else {
1037  list_for_each_entry(pdo_entry, &pdo->entries, list) {
1038  if (sdo->index == pdo_entry->index) {
1039  sdo_entry = ec_sdo_get_entry_const(
1040  sdo, pdo_entry->subindex);
1041  if (sdo_entry) {
1042  ec_pdo_entry_set_name(pdo_entry,
1043  sdo_entry->description);
1044  }
1045  }
1046  }
1047  }
1048  }
1049 }
1050 
1051 /****************************************************************************/
1052 
1056  ec_slave_t *slave
1057  )
1058 {
1059  unsigned int i;
1060  ec_sync_t *sync;
1061  ec_pdo_t *pdo;
1062 
1063  for (i = 0; i < slave->sii.sync_count; i++) {
1064  sync = slave->sii.syncs + i;
1065  list_for_each_entry(pdo, &sync->pdos.list, list) {
1066  ec_slave_find_names_for_pdo(slave, pdo);
1067  }
1068  }
1069 }
1070 
1071 /****************************************************************************/
1072 
1078  const ec_slave_t *slave,
1079  unsigned int port_index
1080  )
1081 {
1082  static const unsigned int prev_table[EC_MAX_PORTS] = {
1083  2, 3, 1, 0
1084  };
1085 
1086  if (port_index >= EC_MAX_PORTS) {
1087  EC_SLAVE_WARN(slave, "%s(port_index=%u): Invalid port index!\n",
1088  __func__, port_index);
1089  }
1090 
1091  do {
1092  port_index = prev_table[port_index];
1093  if (slave->ports[port_index].next_slave) {
1094  return port_index;
1095  }
1096  } while (port_index);
1097 
1098  return 0;
1099 }
1100 
1101 /****************************************************************************/
1102 
1108  const ec_slave_t *slave,
1109  unsigned int port_index
1110  )
1111 {
1112  static const unsigned int next_table[EC_MAX_PORTS] = {
1113  3, 2, 0, 1
1114  };
1115 
1116  if (port_index >= EC_MAX_PORTS) {
1117  EC_SLAVE_WARN(slave, "%s(port_index=%u): Invalid port index!\n",
1118  __func__, port_index);
1119  }
1120 
1121  do {
1122  port_index = next_table[port_index];
1123  if (slave->ports[port_index].next_slave) {
1124  return port_index;
1125  }
1126  } while (port_index);
1127 
1128  return 0;
1129 }
1130 
1131 /****************************************************************************/
1132 
1138  const ec_slave_t *slave
1139  )
1140 {
1141  uint32_t rtt_sum = 0, rtt;
1142  unsigned int port_index = ec_slave_get_next_port(slave, 0);
1143 
1144  while (port_index != 0) {
1145  unsigned int prev_index =
1146  ec_slave_get_previous_port(slave, port_index);
1147 
1148  rtt = slave->ports[port_index].receive_time -
1149  slave->ports[prev_index].receive_time;
1150  rtt_sum += rtt;
1151  port_index = ec_slave_get_next_port(slave, port_index);
1152  }
1153 
1154  return rtt_sum;
1155 }
1156 
1157 /****************************************************************************/
1158 
1164  ec_slave_t *slave
1165  )
1166 {
1167  unsigned int port_index;
1168  ec_slave_t *dc_slave = NULL;
1169 
1170  if (slave->base_dc_supported) {
1171  dc_slave = slave;
1172  } else {
1173  port_index = ec_slave_get_next_port(slave, 0);
1174 
1175  while (port_index != 0) {
1176  ec_slave_t *next = slave->ports[port_index].next_slave;
1177 
1178  if (next) {
1179  dc_slave = ec_slave_find_next_dc_slave(next);
1180 
1181  if (dc_slave) {
1182  break;
1183  }
1184  }
1185  port_index = ec_slave_get_next_port(slave, port_index);
1186  }
1187  }
1188 
1189  return dc_slave;
1190 }
1191 
1192 /****************************************************************************/
1193 
1197  ec_slave_t *slave
1198  )
1199 {
1200  unsigned int port_index;
1201  ec_slave_t *next_slave, *next_dc;
1202  uint32_t rtt, next_rtt_sum;
1203 
1204  if (!slave->base_dc_supported)
1205  return;
1206 
1207  port_index = ec_slave_get_next_port(slave, 0);
1208 
1209  while (port_index != 0) {
1210  next_slave = slave->ports[port_index].next_slave;
1211  next_dc = ec_slave_find_next_dc_slave(next_slave);
1212 
1213  if (next_dc) {
1214  unsigned int prev_port =
1215  ec_slave_get_previous_port(slave, port_index);
1216 
1217  rtt = slave->ports[port_index].receive_time -
1218  slave->ports[prev_port].receive_time;
1219  next_rtt_sum = ec_slave_calc_rtt_sum(next_dc);
1220 
1221  slave->ports[port_index].delay_to_next_dc =
1222  (rtt - next_rtt_sum) / 2; // FIXME
1223  next_dc->ports[0].delay_to_next_dc =
1224  (rtt - next_rtt_sum) / 2;
1225 
1226 #if 0
1227  EC_SLAVE_DBG(slave, 1, "delay %u:%u rtt=%u"
1228  " next_rtt_sum=%u delay=%u\n",
1229  slave->ring_position, port_index, rtt, next_rtt_sum,
1230  slave->ports[port_index].delay_to_next_dc);
1231 #endif
1232  }
1233 
1234  port_index = ec_slave_get_next_port(slave, port_index);
1235  }
1236 }
1237 
1238 /****************************************************************************/
1239 
1243  ec_slave_t *slave,
1244  ec_slave_t *came_from,
1246  uint32_t *delay
1247  )
1248 {
1249  unsigned int i, first;
1250  ec_slave_t *next_dc;
1251 
1252  EC_SLAVE_DBG(slave, 1, "%s(delay = %u ns)\n", __func__, *delay);
1253 
1254  slave->transmission_delay = *delay;
1255 
1256  // Visit every open port in frame-traversal order (downstream ports
1257  // first, the master-facing upstream port last), skipping the port we
1258  // arrived through. Link delays are symmetric, so each edge adds the
1259  // same amount whether descended or ascended, and the round-trip is
1260  // accounted by adding the edge delay both before and after recursing.
1261  // Starting the walk at the reference clock and allowing the upstream
1262  // direction re-roots the delay tree at the reference, so slaves
1263  // upstream of a non-default reference get recomputed too (previously
1264  // they kept stale delays from the old default).
1265  first = ec_slave_get_next_port(slave, 0);
1266  i = first;
1267 
1268  do {
1269  ec_slave_port_t *port = &slave->ports[i];
1270  // ec_slave_get_next_port() falls back to port 0 when no
1271  // further connected port exists; on the first slave that port faces
1272  // the master and has no next_slave. Also skip a next_dc that resolves
1273  // back to ourselves (possible when ascending through a non-DC slave,
1274  // whose downstream search would find us again).
1275  next_dc = port->next_slave ?
1277  if (next_dc && next_dc != came_from && next_dc != slave) {
1278  *delay = *delay + port->delay_to_next_dc;
1279 #if 0
1280  EC_SLAVE_DBG(slave, 1, "%u:%u %u\n",
1281  slave->ring_position, i, *delay);
1282 #endif
1283  ec_slave_calc_transmission_delays_rec(next_dc, slave, delay);
1284  *delay = *delay + port->delay_to_next_dc;
1285  }
1286 
1287  i = ec_slave_get_next_port(slave, i);
1288  } while (i != first);
1289 }
1290 
1291 /****************************************************************************/
ec_sii_general_flags_t general_flags
General flags.
Definition: slave.h:155
Slave information interface general flags.
Definition: globals.h:171
ec_internal_request_state_t state
Request state.
Definition: reg_request.h:48
CANopen over EtherCAT.
Definition: globals.h:152
uint16_t ring_position
Ring position.
Definition: slave.h:177
uint32_t revision_number
Revision number.
Definition: slave.h:131
const ec_sdo_entry_t * ec_sdo_get_entry_const(const ec_sdo_t *sdo, uint8_t subindex)
Get an SDO entry from an SDO via its subindex.
Definition: sdo.c:108
uint16_t ec_slave_sdo_count(const ec_slave_t *slave)
Get the number of SDOs in the dictionary.
Definition: slave.c:980
uint16_t boot_rx_mailbox_offset
Bootstrap rx mailbox address.
Definition: slave.h:133
int ec_slave_analyze_sii_data(ec_slave_t *slave)
Analyzes SII data.
Definition: slave.c:372
void ec_fsm_slave_clear(ec_fsm_slave_t *fsm)
Destructor.
Definition: fsm_slave.c:87
ec_sii_t sii
Extracted SII data.
Definition: slave.h:218
size_t word_count
Size of the SII contents in words.
Definition: sii_page.h:61
uint16_t configured_tx_mailbox_size
Configured send mailbox size.
Definition: slave.h:195
uint8_t enable_upload_at_startup
?.
Definition: globals.h:165
void ec_mbox_data_clear(ec_mbox_data_t *mbox_data)
Free internal memory for mailbox response data.
Definition: mailbox.c:53
void ec_slave_attach_pdo_names(ec_slave_t *slave)
Attach PDO names.
Definition: slave.c:1055
uint16_t base_build
Build number.
Definition: slave.h:200
#define EC_SLAVE_DBG(slave, level, fmt, args...)
Convenience macro for printing slave-specific debug messages to syslog.
Definition: slave.h:100
CANopen SDO entry.
Definition: sdo_entry.h:46
const ec_pdo_t * ec_pdo_list_find_pdo_const(const ec_pdo_list_t *pl, uint16_t index)
Finds a PDO with the given index and returns a const pointer.
Definition: pdo_list.c:257
uint8_t enable_not_lrw
Slave does not support LRW.
Definition: globals.h:173
uint16_t configured_tx_mailbox_offset
Configured send mailbox offset.
Definition: slave.h:193
size_t ec_state_string(uint8_t, char *, uint8_t)
Prints slave states in clear text.
Definition: module.c:405
ec_slave_port_t ports[EC_MAX_PORTS]
Ports.
Definition: slave.h:181
#define EC_SII_WORD_OFFSET_ALIAS
Word offset of alias address.
Definition: globals.h:89
CANopen SDO request.
Definition: sdo_request.h:40
ec_slave_state_t current_state
Current application state.
Definition: slave.h:186
const ec_code_msg_t al_status_messages[]
Application layer status messages.
Definition: fsm_change.c:382
EtherCAT slave structure.
ec_internal_request_state_t state
SDO request state.
Definition: sdo_request.h:55
Register request.
Definition: reg_request.h:40
ec_mbox_data_t mbox_foe_data
Received mailbox data for FoE.
Definition: slave.h:239
ec_sdo_t * ec_slave_get_sdo(ec_slave_t *slave, uint16_t index)
Get an SDO from the dictionary.
Definition: slave.c:910
ec_slave_port_link_t link
Port link status.
Definition: slave.h:114
Servo-Profile over EtherCAT.
Definition: globals.h:154
#define EC_SLAVE_WARN(slave, fmt, args...)
Convenience macro for printing slave-specific warnings to syslog.
Definition: slave.h:84
uint8_t enable_sdo
Enable SDO access.
Definition: globals.h:161
struct list_head list
List of PDOs.
Definition: pdo_list.h:42
uint32_t serial_number
Serial number.
Definition: slave.h:132
ec_sii_coe_details_t coe_details
CoE detail flags.
Definition: slave.h:154
char * order
Order number.
Definition: slave.h:151
int ec_pdo_set_name(ec_pdo_t *pdo, const char *name)
Set PDO name.
Definition: pdo.c:117
void ec_slave_calc_transmission_delays_rec(ec_slave_t *slave, ec_slave_t *came_from, uint32_t *delay)
Recursively calculates transmission delays.
Definition: slave.c:1242
ec_mbox_data_t mbox_eoe_data
Received mailbox data for EoE.
Definition: slave.h:236
void ec_slave_find_names_for_pdo(ec_slave_t *, ec_pdo_t *)
Find name for a PDO and its entries.
Definition: slave.c:1024
ec_fsm_slave_t fsm
Slave state machine.
Definition: slave.h:230
void ec_slave_set_state(ec_slave_t *slave, ec_slave_state_t new_state)
Sets the application state of a slave.
Definition: slave.c:335
struct list_head reg_requests
Register access requests.
Definition: slave.h:225
struct list_head list
List item.
Definition: sdo.h:42
void ec_pdo_init(ec_pdo_t *pdo)
PDO constructor.
Definition: pdo.c:38
const ec_pdo_t * ec_slave_find_pdo(const ec_slave_t *slave, uint16_t index)
Finds a mapped PDO.
Definition: slave.c:999
CANopen SDO.
Definition: sdo.h:41
uint16_t index
SDO index.
Definition: sdo.h:44
int16_t current_on_ebus
Power consumption in mA.
Definition: slave.h:156
ec_slave_t * ec_slave_find_next_dc_slave(ec_slave_t *)
Finds the next slave supporting DC delay measurement.
Definition: slave.c:1163
uint16_t boot_tx_mailbox_size
Bootstrap transmit mailbox size.
Definition: slave.h:136
int ec_slave_fetch_sii_strings(ec_slave_t *, const uint8_t *, size_t)
Fetches data from a STRING category.
Definition: slave.c:586
uint16_t alias
Configured station alias.
Definition: sii_page.h:56
wait_queue_head_t request_queue
Wait queue for external requests from user space.
Definition: master.h:311
uint16_t station_address
Configured station address.
Definition: slave.h:178
unsigned int sync_count
Number of sync managers.
Definition: slave.h:160
void ec_slave_clear(ec_slave_t *slave)
Slave destructor.
Definition: slave.c:213
struct list_head sdo_dictionary
SDO dictionary list.
Definition: slave.h:220
uint16_t std_rx_mailbox_size
Standard receive mailbox size.
Definition: slave.h:138
uint8_t base_type
Slave type.
Definition: slave.h:198
Global definitions and macros.
uint16_t std_tx_mailbox_offset
Standard transmit mailbox address.
Definition: slave.h:139
PDO entry description.
Definition: pdo_entry.h:40
EtherCAT master structure.
void ec_pdo_clear(ec_pdo_t *pdo)
PDO destructor.
Definition: pdo.c:86
uint16_t index
PDO index.
Definition: pdo.h:43
int8_t sync_index
Assigned sync manager.
Definition: pdo.h:44
uint16_t boot_tx_mailbox_offset
Bootstrap tx mailbox address.
Definition: slave.h:135
uint16_t index
PDO entry index.
Definition: pdo_entry.h:42
void ec_slave_sdo_dict_info(const ec_slave_t *slave, unsigned int *sdo_count, unsigned int *entry_count)
Counts the total number of SDOs and entries in the dictionary.
Definition: slave.c:882
EtherCAT slave.
Definition: slave.h:170
struct list_head sdo_requests
SDO access requests.
Definition: slave.h:224
char * description
Description.
Definition: sdo_entry.h:54
Code/Message pair.
Definition: globals.h:280
struct list_head soe_requests
SoE requests.
Definition: slave.h:227
Slave information interface CANopen over EtherCAT details flags.
Definition: globals.h:160
uint8_t enable_safeop
?.
Definition: globals.h:172
ec_slave_config_t * config
Current configuration.
Definition: slave.h:184
unsigned int ec_slave_get_next_port(const ec_slave_t *, unsigned int)
Returns the next connected port of a given port.
Definition: slave.c:1107
char * ec_slave_sii_string(const ec_slave_t *, unsigned int)
Searches the string list for an index.
Definition: slave.c:842
void ec_pdo_entry_clear(ec_pdo_entry_t *entry)
PDO entry destructor.
Definition: pdo_entry.c:68
void ec_slave_clear_sync_managers(ec_slave_t *slave)
Clear the sync manager array.
Definition: slave.c:316
uint32_t revision_number
Revision number.
Definition: sii_page.h:54
uint8_t enable_sdo_info
SDO information service available.
Definition: globals.h:162
uint8_t enable_sdo_complete_access
Complete access possible.
Definition: globals.h:166
void ec_slave_calc_port_delays(ec_slave_t *slave)
Calculates the port transmission delays.
Definition: slave.c:1196
PDO description.
Definition: pdo.h:41
uint8_t sdo_dictionary_fetched
Dictionary has been fetched.
Definition: slave.h:221
uint16_t mailbox_protocols
Supported mailbox protocols.
Definition: slave.h:141
unsigned int debug_level
Master debug level.
Definition: master.h:284
#define EC_SLAVE_ERR(slave, fmt, args...)
Convenience macro for printing slave-specific errors to syslog.
Definition: slave.h:70
int ec_pdo_list_add_pdo_copy(ec_pdo_list_t *pl, const ec_pdo_t *pdo)
Add the copy of an existing PDO to the list.
Definition: pdo_list.c:133
ec_slave_dc_range_t base_dc_range
DC range.
Definition: slave.h:205
uint8_t bit_length
entry length in bit
Definition: pdo_entry.h:45
Sync manager.
Definition: sync.h:39
uint16_t std_rx_mailbox_offset
Standard receive mailbox address.
Definition: slave.h:137
uint8_t base_fmmu_bit_operation
FMMU bit operation is supported.
Definition: slave.h:203
struct list_head list
List item.
Definition: soe_request.h:41
uint32_t transmission_delay
DC system time transmission delay (offset from reference clock).
Definition: slave.h:209
ec_device_index_t
Master devices.
Definition: globals.h:203
char * name
SDO name.
Definition: sdo.h:46
uint16_t alias
Configured station alias.
Definition: slave.h:128
ec_direction_t
Direction type for PDO assignment functions.
Definition: ecrt.h:522
uint8_t base_fmmu_count
Number of supported FMMUs.
Definition: slave.h:201
uint16_t configured_rx_mailbox_offset
Configured receive mailbox offset.
Definition: slave.h:189
File-Access over EtherCAT.
Definition: globals.h:153
#define EC_READ_U32(DATA)
Read a 32-bit unsigned value from EtherCAT data.
Definition: ecrt.h:3277
struct list_head entries
List of PDO entries.
Definition: pdo.h:46
ec_slave_port_desc_t desc
Port descriptors.
Definition: slave.h:113
unsigned int string_count
Number of SII strings.
Definition: slave.h:145
ec_master_t * master
Master owning the slave.
Definition: slave.h:172
void ec_pdo_entry_init(ec_pdo_entry_t *entry)
PDO entry constructor.
Definition: pdo_entry.c:37
#define EC_SII_WORD_OFFSET_VENDOR
Word offset of vendor ID.
Definition: globals.h:92
const ec_sdo_t * ec_slave_get_sdo_by_pos_const(const ec_slave_t *slave, uint16_t sdo_position)
Get an SDO from the dictionary, given its position in the list.
Definition: slave.c:958
uint8_t has_dc_system_time
The slave supports the DC system time register.
Definition: slave.h:206
char ** strings
Strings in SII categories.
Definition: slave.h:144
ec_slave_state_t
State of an EtherCAT slave.
Definition: globals.h:127
uint32_t vendor_id
Vendor ID.
Definition: sii_page.h:52
uint8_t subindex
PDO entry subindex.
Definition: pdo_entry.h:43
EtherCAT datagram structure.
uint8_t control_register
Control register value.
Definition: sync.h:43
int ec_read_mbox_locked(ec_slave_t *slave)
Return the current mailbox lock status and lock it if not locked.
Definition: slave.c:201
Values read by the master.
Definition: ecrt.h:525
void ec_sync_clear(ec_sync_t *sync)
Destructor.
Definition: sync.c:73
#define EC_FIRST_SII_CATEGORY_OFFSET
Word offset of first SII category.
Definition: globals.h:86
Port is not implemented.
Definition: ecrt.h:445
uint8_t base_revision
Revision.
Definition: slave.h:199
32 bit.
Definition: globals.h:179
Ethernet-over-EtherCAT set IP parameter request.
Definition: eoe_request.h:41
void ec_read_mbox_lock_clear(ec_slave_t *slave)
Clears the mailbox lock.
Definition: slave.c:187
const ec_sdo_t * ec_slave_get_sdo_const(const ec_slave_t *slave, uint16_t index)
Get an SDO from the dictionary.
Definition: slave.c:936
uint8_t valid_mbox_data
Received mailbox data is valid.
Definition: slave.h:243
FoE request.
Definition: foe_request.h:42
uint16_t effective_alias
Effective alias address.
Definition: slave.h:179
void ec_sii_page_clear(ec_sii_page_t *page)
Slave destructor.
Definition: sii_page.c:62
struct list_head entries
List of entries.
Definition: sdo.h:48
ec_internal_request_state_t state
Request state.
Definition: eoe_request.h:43
#define EC_READ_U16(DATA)
Read a 16-bit unsigned value from EtherCAT data.
Definition: ecrt.h:3261
struct list_head foe_requests
FoE requests.
Definition: slave.h:226
uint8_t enable
Enable bit.
Definition: sync.h:44
int ec_slave_fetch_sii_syncs(ec_slave_t *, const uint8_t *, size_t)
Fetches data from a SYNC MANAGER category.
Definition: slave.c:693
#define EC_STATE_STRING_SIZE
Minimum size of a buffer used with ec_state_string().
Definition: globals.h:54
uint16_t boot_rx_mailbox_size
Bootstrap receive mailbox size.
Definition: slave.h:134
#define EC_MAX_PORTS
Maximum number of slave ports.
Definition: ecrt.h:294
uint16_t * words
Complete SII image.
Definition: sii_page.h:60
struct list_head list
List item.
Definition: sdo_request.h:41
void ec_fsm_slave_init(ec_fsm_slave_t *fsm, ec_slave_t *slave)
Constructor.
Definition: fsm_slave.c:56
uint32_t product_code
Vendor-specific product code.
Definition: sii_page.h:53
void ec_slave_init(ec_slave_t *slave, ec_master_t *master, ec_device_index_t dev_idx, uint16_t ring_position, uint16_t station_address)
Slave constructor.
Definition: slave.c:65
ec_slave_t * next_slave
Connected slaves.
Definition: slave.h:115
ec_sii_page_t sii_page
The SII contents, either fetched or taken from the cache.
Definition: slave.h:213
uint32_t receive_time
Port receive times for delay measurement.
Definition: slave.h:116
uint32_t ec_slave_calc_rtt_sum(const ec_slave_t *)
Calculates the sum of round-trip-times of connected ports 1-3.
Definition: slave.c:1137
Slave port.
Definition: slave.h:112
char * image
Image name.
Definition: slave.h:150
ec_pdo_list_t pdos
Current PDO assignment.
Definition: sync.h:45
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:357
uint16_t physical_start_address
Physical start address.
Definition: sync.h:41
ec_mbox_data_t mbox_voe_data
Received mailbox data for VoE.
Definition: slave.h:241
unsigned long jiffies_preop
Time, the slave went to PREOP.
Definition: slave.h:222
void ec_sii_page_init(ec_sii_page_t *page)
SII page constructor.
Definition: sii_page.c:39
uint16_t configured_rx_mailbox_size
Configured receive mailbox size.
Definition: slave.h:191
uint8_t base_dc_supported
Distributed clocks are supported.
Definition: slave.h:204
void ec_sync_init_copy(ec_sync_t *sync, const ec_sync_t *other)
Copy constructor.
Definition: sync.c:55
char * group
Group name.
Definition: slave.h:149
uint8_t physical_layer[EC_MAX_PORTS]
Port media.
Definition: slave.h:153
struct list_head list
list item
Definition: pdo_entry.h:41
void ec_sdo_clear(ec_sdo_t *sdo)
SDO destructor.
Definition: sdo.c:59
uint8_t base_sync_count
Number of supported sync managers.
Definition: slave.h:202
#define EC_READ_U8(DATA)
Read an 8-bit unsigned value from EtherCAT data.
Definition: ecrt.h:3245
void ec_mbox_data_init(ec_mbox_data_t *mbox_data)
Initialize mailbox response data.
Definition: mailbox.c:40
EtherCAT slave configuration structure.
ec_internal_request_state_t state
FoE request state.
Definition: foe_request.h:55
#define EC_READ_S16(DATA)
Read a 16-bit signed value from EtherCAT data.
Definition: ecrt.h:3269
unsigned long read_mbox_busy
Bit 0 is set during a mailbox read request.
Definition: slave.h:232
ec_device_index_t device_index
Index of device the slave responds on.
Definition: slave.h:173
void ec_slave_config_detach(ec_slave_config_t *sc)
Detaches the configuration from a slave object.
Definition: slave_config.c:315
unsigned int ec_slave_get_previous_port(const ec_slave_t *, unsigned int)
Returns the previous connected port of a given port.
Definition: slave.c:1077
uint16_t default_length
Data length in bytes.
Definition: sync.h:42
uint32_t product_code
Vendor-specific product code.
Definition: slave.h:130
PREOP state (mailbox communication, no IO)
Definition: globals.h:132
Values written by the master.
Definition: ecrt.h:524
uint32_t serial_number
Serial number.
Definition: sii_page.h:55
struct list_head list
List item.
Definition: pdo.h:42
unsigned int error_flag
Stop processing after an error.
Definition: slave.h:187
ec_sync_t * syncs
SYNC MANAGER categories.
Definition: slave.h:159
uint16_t std_tx_mailbox_size
Standard transmit mailbox size.
Definition: slave.h:140
EtherCAT master.
Definition: master.h:194
uint8_t enable_pdo_configuration
PDO configuration possible.
Definition: globals.h:164
struct list_head list
List item.
Definition: reg_request.h:41
ec_slave_state_t requested_state
Requested application state.
Definition: slave.h:185
struct list_head eoe_requests
EoE set IP parameter requests.
Definition: slave.h:228
Vendor specific.
Definition: globals.h:155
int ec_slave_fetch_sii_pdos(ec_slave_t *, const uint8_t *, size_t, ec_direction_t)
Fetches data from a [RT]xPDO category.
Definition: slave.c:759
#define EC_MAX_SYNC_MANAGERS
Maximum number of sync managers per slave.
Definition: ecrt.h:285
ec_internal_request_state_t state
Request state.
Definition: soe_request.h:52
void ec_sync_init(ec_sync_t *sync, ec_slave_t *slave)
Constructor.
Definition: sync.c:38
struct list_head list
List item.
Definition: eoe_request.h:42
int ec_slave_fetch_sii_general(ec_slave_t *, const uint8_t *, size_t)
Fetches data from a GENERAL category.
Definition: slave.c:642
ADS over EtherCAT.
Definition: globals.h:150
Sercos-over-EtherCAT request.
Definition: soe_request.h:40
char * name
Slave name.
Definition: slave.h:152
ec_mbox_data_t mbox_coe_data
Received mailbox data for CoE.
Definition: slave.h:238
int ec_pdo_entry_set_name(ec_pdo_entry_t *entry, const char *name)
Set PDO entry name.
Definition: pdo_entry.c:81
unknown state
Definition: globals.h:128
ec_mbox_data_t mbox_soe_data
Received mailbox data for SoE.
Definition: slave.h:240
uint32_t vendor_id
Vendor ID.
Definition: slave.h:129
uint32_t delay_to_next_dc
Delay to next slave with DC support behind this port [ns].
Definition: slave.h:118
struct list_head pdos
SII [RT]XPDO categories.
Definition: slave.h:163
unsigned int force_config
Force (re-)configuration.
Definition: slave.h:188
struct list_head list
List item.
Definition: foe_request.h:43
unsigned int has_general
General category present.
Definition: slave.h:148
ec_sync_t * ec_slave_get_sync(ec_slave_t *slave, uint8_t sync_index)
Get the sync manager given an index.
Definition: slave.c:864
uint8_t enable_pdo_assign
PDO mapping configurable.
Definition: globals.h:163
unsigned int sii_parallel_words
How many SII words the slave can read at once.
Definition: slave.h:215