IgH EtherCAT Master  1.7.0
device.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/skbuff.h>
31 #include <linux/if_ether.h>
32 #include <linux/netdevice.h>
33 
34 #include "device.h"
35 #include "master.h"
36 
37 #ifdef EC_DEBUG_RING
38 #if LINUX_VERSION_CODE < KERNEL_VERSION(5, 6, 0)
39 #define timersub(a, b, result) \
40  do { \
41  (result)->tv_sec = (a)->tv_sec - (b)->tv_sec; \
42  (result)->tv_usec = (a)->tv_usec - (b)->tv_usec; \
43  if ((result)->tv_usec < 0) { \
44  --(result)->tv_sec; \
45  (result)->tv_usec += 1000000; \
46  } \
47  } while (0)
48 #endif
49 #endif
50 
51 /****************************************************************************/
52 
53 enum {
54  /* genet driver needs extra headroom in skb for status block */
55  EXTRA_HEADROOM = 64,
56 };
57 
63  ec_device_t *device,
64  ec_master_t *master
65  )
66 {
67  int ret;
68  unsigned int i;
69  struct ethhdr *eth;
70 #ifdef EC_DEBUG_IF
71  char ifname[10];
72  char mb = 'x';
73 #endif
74 
75  device->master = master;
76  device->dev = NULL;
77  device->poll = NULL;
78  device->module = NULL;
79  device->open = 0;
80  device->link_state = 0;
81  for (i = 0; i < EC_TX_RING_SIZE; i++) {
82  device->tx_skb[i] = NULL;
83  }
84  device->tx_ring_index = 0;
85 #ifdef EC_HAVE_CYCLES
86  device->cycles_poll = 0;
87 #endif
88 #ifdef EC_DEBUG_RING
89  device->timeval_poll.tv_sec = 0;
90 #if LINUX_VERSION_CODE >= KERNEL_VERSION(5, 6, 0)
91  device->timeval_poll.tv_nsec = 0;
92 #else
93  device->timeval_poll.tv_usec = 0;
94 #endif
95 #endif
96  device->jiffies_poll = 0;
97 
98  ec_device_clear_stats(device);
99 
100 #ifdef EC_DEBUG_RING
101  for (i = 0; i < EC_DEBUG_RING_SIZE; i++) {
102  ec_debug_frame_t *df = &device->debug_frames[i];
103  df->dir = TX;
104  df->t.tv_sec = 0;
105 #if LINUX_VERSION_CODE >= KERNEL_VERSION(5, 6, 0)
106  df->t.tv_nsec = 0;
107 #else
108  df->t.tv_usec = 0;
109 #endif
110  memset(df->data, 0, EC_MAX_DATA_SIZE);
111  df->data_size = 0;
112  }
113 #endif
114 #ifdef EC_DEBUG_RING
115  device->debug_frame_index = 0;
116  device->debug_frame_count = 0;
117 #endif
118 
119 #ifdef EC_DEBUG_IF
120  if (device == &master->devices[EC_DEVICE_MAIN]) {
121  mb = 'm';
122  }
123  else {
124  mb = 'b';
125  }
126 
127  sprintf(ifname, "ecdbg%c%u", mb, master->index);
128 
129  ret = ec_debug_init(&device->dbg, device, ifname);
130  if (ret < 0) {
131  EC_MASTER_ERR(master, "Failed to init debug device!\n");
132  goto out_return;
133  }
134 #endif
135 
136  for (i = 0; i < EC_TX_RING_SIZE; i++) {
137  if (!(device->tx_skb[i] =
138  dev_alloc_skb(ETH_FRAME_LEN + EXTRA_HEADROOM))) {
139  EC_MASTER_ERR(master,
140  "Error allocating device socket buffer!\n");
141  ret = -ENOMEM;
142  goto out_tx_ring;
143  }
144 
145  // add Ethernet-II-header
146  skb_reserve(device->tx_skb[i], ETH_HLEN + EXTRA_HEADROOM);
147  eth = (struct ethhdr *) skb_push(device->tx_skb[i], ETH_HLEN);
148  eth->h_proto = htons(0x88A4);
149  memset(eth->h_dest, 0xFF, ETH_ALEN);
150  }
151 
152  return 0;
153 
154 out_tx_ring:
155  for (i = 0; i < EC_TX_RING_SIZE; i++) {
156  if (device->tx_skb[i]) {
157  dev_kfree_skb(device->tx_skb[i]);
158  }
159  }
160 #ifdef EC_DEBUG_IF
161  ec_debug_clear(&device->dbg);
162 out_return:
163 #endif
164  return ret;
165 }
166 
167 /****************************************************************************/
168 
172  ec_device_t *device
173  )
174 {
175  unsigned int i;
176 
177  if (device->open) {
178  ec_device_close(device);
179  }
180 
181  for (i = 0; i < EC_TX_RING_SIZE; i++) {
182  dev_kfree_skb(device->tx_skb[i]);
183  }
184 
185 #ifdef EC_DEBUG_IF
186  ec_debug_clear(&device->dbg);
187 #endif
188 }
189 
190 /****************************************************************************/
191 
195  ec_device_t *device,
196  struct net_device *net_dev,
197  ec_pollfunc_t poll,
198  struct module *module
199  )
200 {
201  unsigned int i;
202  struct ethhdr *eth;
203 
204  ec_device_detach(device); // resets fields
205 
206  device->dev = net_dev;
207  device->poll = poll;
208  device->module = module;
209 
210  for (i = 0; i < EC_TX_RING_SIZE; i++) {
211  device->tx_skb[i]->dev = net_dev;
212  eth = (struct ethhdr *) (device->tx_skb[i]->data);
213  memcpy(eth->h_source, net_dev->dev_addr, ETH_ALEN);
214  }
215 
216 #ifdef EC_DEBUG_IF
217  ec_debug_register(&device->dbg, net_dev);
218 #endif
219 } // NOLINT(whitespace/indent) false positive
220 
221 /****************************************************************************/
222 
226  ec_device_t *device
227  )
228 {
229  unsigned int i;
230 
231 #ifdef EC_DEBUG_IF
232  ec_debug_unregister(&device->dbg);
233 #endif
234 
235  device->dev = NULL;
236  device->poll = NULL;
237  device->module = NULL;
238  device->open = 0;
239  device->link_state = 0; // down
240 
241  ec_device_clear_stats(device);
242 
243  for (i = 0; i < EC_TX_RING_SIZE; i++) {
244  device->tx_skb[i]->dev = NULL;
245  }
246 }
247 
248 /****************************************************************************/
249 
255  ec_device_t *device
256  )
257 {
258  int ret;
259 
260  if (!device->dev) {
261  EC_MASTER_ERR(device->master, "No net_device to open!\n");
262  return -ENODEV;
263  }
264 
265  if (device->open) {
266  EC_MASTER_WARN(device->master, "Device already opened!\n");
267  return 0;
268  }
269 
270  device->link_state = 0;
271 
272  ec_device_clear_stats(device);
273 
274  ret = device->dev->netdev_ops->ndo_open(device->dev);
275  if (!ret)
276  device->open = 1;
277 
278  return ret;
279 }
280 
281 /****************************************************************************/
282 
288  ec_device_t *device
289  )
290 {
291  int ret;
292 
293  if (!device->dev) {
294  EC_MASTER_ERR(device->master, "No device to close!\n");
295  return -ENODEV;
296  }
297 
298  if (!device->open) {
299  EC_MASTER_WARN(device->master, "Device already closed!\n");
300  return 0;
301  }
302 
303  ret = device->dev->netdev_ops->ndo_stop(device->dev);
304  if (!ret)
305  device->open = 0;
306 
307  return ret;
308 }
309 
310 /****************************************************************************/
311 
317  ec_device_t *device
318  )
319 {
320  /* cycle through socket buffers, because otherwise there is a race
321  * condition, if multiple frames are sent and the DMA is not scheduled in
322  * between. */
323  device->tx_ring_index++;
324  device->tx_ring_index %= EC_TX_RING_SIZE;
325  return device->tx_skb[device->tx_ring_index]->data + ETH_HLEN;
326 }
327 
328 /****************************************************************************/
329 
336  ec_device_t *device,
337  size_t size
338  )
339 {
340  struct sk_buff *skb = device->tx_skb[device->tx_ring_index];
341 
342  // set the right length for the data
343  skb->len = ETH_HLEN + size;
344 
345  if (unlikely(device->master->debug_level > 1)) {
346  EC_MASTER_DBG(device->master, 2, "Sending frame:\n");
347  ec_print_data(skb->data, ETH_HLEN + size);
348  }
349 
350  // start sending
351  if (device->dev->netdev_ops->ndo_start_xmit(skb, device->dev) ==
352  NETDEV_TX_OK)
353  {
354  device->tx_count++;
355  device->master->device_stats.tx_count++;
356  device->tx_bytes += ETH_HLEN + size;
357  device->master->device_stats.tx_bytes += ETH_HLEN + size;
358 #ifdef EC_DEBUG_IF
359  ec_debug_send(&device->dbg, skb->data, ETH_HLEN + size);
360 #endif
361 #ifdef EC_DEBUG_RING
362  ec_device_debug_ring_append(
363  device, TX, skb->data + ETH_HLEN, size);
364 #endif
365  } else {
366  device->tx_errors++;
367  }
368 }
369 
370 /****************************************************************************/
371 
375  ec_device_t *device
376  )
377 {
378  unsigned int i;
379 
380  // zero frame statistics
381  device->tx_count = 0;
382  device->last_tx_count = 0;
383  device->rx_count = 0;
384  device->last_rx_count = 0;
385  device->tx_bytes = 0;
386  device->last_tx_bytes = 0;
387  device->rx_bytes = 0;
388  device->last_rx_bytes = 0;
389  device->tx_errors = 0;
390 
391  for (i = 0; i < EC_RATE_COUNT; i++) {
392  device->tx_frame_rates[i] = 0;
393  device->rx_frame_rates[i] = 0;
394  device->tx_byte_rates[i] = 0;
395  device->rx_byte_rates[i] = 0;
396  }
397 }
398 
399 /****************************************************************************/
400 
401 #ifdef EC_DEBUG_RING
402 
404 void ec_device_debug_ring_append(
405  ec_device_t *device,
406  ec_debug_frame_dir_t dir,
407  const void *data,
408  size_t size
409  )
410 {
411  ec_debug_frame_t *df = &device->debug_frames[device->debug_frame_index];
412 
413  df->dir = dir;
414  if (dir == TX) {
415 #if LINUX_VERSION_CODE >= KERNEL_VERSION(5, 6, 0)
416  ktime_get_real_ts64(&df->t);
417 #else
418  do_gettimeofday(&df->t);
419 #endif
420  }
421  else {
422  df->t = device->timeval_poll;
423  }
424  memcpy(df->data, data, size);
425  df->data_size = size;
426 
427  device->debug_frame_index++;
428  device->debug_frame_index %= EC_DEBUG_RING_SIZE;
429  if (unlikely(device->debug_frame_count < EC_DEBUG_RING_SIZE))
430  device->debug_frame_count++;
431 }
432 
433 /****************************************************************************/
434 
437 void ec_device_debug_ring_print(
438  const ec_device_t *device
439  )
440 {
441  int i;
442  unsigned int ring_index;
443  const ec_debug_frame_t *df;
444 #if LINUX_VERSION_CODE >= KERNEL_VERSION(5, 6, 0)
445  struct timespec64 t0, diff;
446 #else
447  struct timeval t0, diff;
448 #endif
449 
450  // calculate index of the newest frame in the ring to get its time
451  ring_index = (device->debug_frame_index + EC_DEBUG_RING_SIZE - 1)
452  % EC_DEBUG_RING_SIZE;
453  t0 = device->debug_frames[ring_index].t;
454 
455  EC_MASTER_DBG(device->master, 1, "Debug ring %u:\n", ring_index);
456 
457  // calculate index of the oldest frame in the ring
458  ring_index = (device->debug_frame_index + EC_DEBUG_RING_SIZE
459  - device->debug_frame_count) % EC_DEBUG_RING_SIZE;
460 
461  for (i = 0; i < device->debug_frame_count; i++) {
462  df = &device->debug_frames[ring_index];
463 #if LINUX_VERSION_CODE >= KERNEL_VERSION(5, 6, 0)
464  diff = timespec64_sub(t0, df->t);
465 #else
466  timersub(&t0, &df->t, &diff);
467 #endif
468 
469 #if LINUX_VERSION_CODE >= KERNEL_VERSION(5, 6, 0)
470  EC_MASTER_DBG(device->master, 1, "Frame %u, dt=%u.%06u s, %s:\n",
471  i + 1 - device->debug_frame_count,
472  (unsigned int) diff.tv_sec,
473  (unsigned int) (diff.tv_nsec / 1000),
474  (df->dir == TX) ? "TX" : "RX");
475 #else
476  EC_MASTER_DBG(device->master, 1, "Frame %u, dt=%u.%06u s, %s:\n",
477  i + 1 - device->debug_frame_count,
478  (unsigned int) diff.tv_sec,
479  (unsigned int) diff.tv_usec,
480  (df->dir == TX) ? "TX" : "RX");
481 #endif
482  ec_print_data(df->data, df->data_size);
483 
484  ring_index++;
485  ring_index %= EC_DEBUG_RING_SIZE;
486  }
487 }
488 #endif
489 
490 /****************************************************************************/
491 
499  ec_device_t *device
500  )
501 {
502 #ifdef EC_HAVE_CYCLES
503  device->cycles_poll = get_cycles();
504 #endif
505  device->jiffies_poll = jiffies;
506 #ifdef EC_DEBUG_RING
507 #if LINUX_VERSION_CODE >= KERNEL_VERSION(5, 6, 0)
508  ktime_get_real_ts64(&device->timeval_poll);
509 #else
510  do_gettimeofday(&device->timeval_poll);
511 #endif
512 #endif
513  device->poll(device->dev);
514 }
515 
516 /****************************************************************************/
517 
521  ec_device_t *device
522  )
523 {
524  unsigned int i;
525 
526  s32 tx_frame_rate = (device->tx_count - device->last_tx_count) * 1000;
527  s32 rx_frame_rate = (device->rx_count - device->last_rx_count) * 1000;
528  s32 tx_byte_rate = (device->tx_bytes - device->last_tx_bytes);
529  s32 rx_byte_rate = (device->rx_bytes - device->last_rx_bytes);
530 
531  /* Low-pass filter:
532  * Y_n = y_(n - 1) + T / tau * (x - y_(n - 1)) | T = 1
533  * -> Y_n += (x - y_(n - 1)) / tau
534  */
535  for (i = 0; i < EC_RATE_COUNT; i++) {
536  s32 n = rate_intervals[i];
537  device->tx_frame_rates[i] +=
538  (tx_frame_rate - device->tx_frame_rates[i]) / n;
539  device->rx_frame_rates[i] +=
540  (rx_frame_rate - device->rx_frame_rates[i]) / n;
541  device->tx_byte_rates[i] +=
542  (tx_byte_rate - device->tx_byte_rates[i]) / n;
543  device->rx_byte_rates[i] +=
544  (rx_byte_rate - device->rx_byte_rates[i]) / n;
545  }
546 
547  device->last_tx_count = device->tx_count;
548  device->last_rx_count = device->rx_count;
549  device->last_tx_bytes = device->tx_bytes;
550  device->last_rx_bytes = device->rx_bytes;
551 }
552 
553 /*****************************************************************************
554  * Device interface
555  ****************************************************************************/
556 
568 {
569  ec_master_t *master = device->master;
570  char dev_str[20], mac_str[20];
571 
572  ec_mac_print(device->dev->dev_addr, mac_str);
573 
574  if (device == &master->devices[EC_DEVICE_MAIN]) {
575  sprintf(dev_str, "main");
576  } else if (device == &master->devices[EC_DEVICE_BACKUP]) {
577  sprintf(dev_str, "backup");
578  } else {
579  EC_MASTER_WARN(master, "%s() called with unknown device %s!\n",
580  __func__, mac_str);
581  sprintf(dev_str, "UNKNOWN");
582  }
583 
584  EC_MASTER_INFO(master, "Releasing %s device %s.\n", dev_str, mac_str);
585 
586  down(&master->device_sem);
587  ec_device_detach(device);
588  up(&master->device_sem);
589 }
590 
591 /****************************************************************************/
592 
598 int ecdev_open(ec_device_t *device )
599 {
600  int ret;
601  ec_master_t *master = device->master;
602  unsigned int all_open = 1, dev_idx;
603 
604  ret = ec_device_open(device);
605  if (ret) {
606  EC_MASTER_ERR(master, "Failed to open device: error %d!\n", ret);
607  return ret;
608  }
609 
610  for (dev_idx = EC_DEVICE_MAIN;
611  dev_idx < ec_master_num_devices(device->master); dev_idx++) {
612  if (!master->devices[dev_idx].open) {
613  all_open = 0;
614  break;
615  }
616  }
617 
618  if (all_open) {
619  ret = ec_master_enter_idle_phase(device->master);
620  if (ret) {
621  EC_MASTER_ERR(device->master, "Failed to enter IDLE phase!\n");
622  return ret;
623  }
624  }
625 
626  return 0;
627 }
628 
629 /****************************************************************************/
630 
636 void ecdev_close(ec_device_t *device )
637 {
638  ec_master_t *master = device->master;
639 
640  if (master->phase == EC_IDLE) {
642  }
643 
644  if (ec_device_close(device)) {
645  EC_MASTER_WARN(master, "Failed to close device!\n");
646  }
647 }
648 
649 /****************************************************************************/
650 
661  ec_device_t *device,
662  const void *data,
663  size_t size
664  )
665 {
666  const void *ec_data = data + ETH_HLEN;
667  size_t ec_size = size - ETH_HLEN;
668 
669  if (unlikely(!data)) {
670  EC_MASTER_WARN(device->master, "%s() called with NULL data.\n",
671  __func__);
672  return;
673  }
674 
675  device->rx_count++;
676  device->master->device_stats.rx_count++;
677  device->rx_bytes += size;
678  device->master->device_stats.rx_bytes += size;
679 
680  if (unlikely(device->master->debug_level > 1)) {
681  EC_MASTER_DBG(device->master, 2, "Received frame:\n");
682  ec_print_data(data, size);
683  }
684 
685 #ifdef EC_DEBUG_IF
686  ec_debug_send(&device->dbg, data, size);
687 #endif
688 #ifdef EC_DEBUG_RING
689  ec_device_debug_ring_append(device, RX, ec_data, ec_size);
690 #endif
691 
692  ec_master_receive_datagrams(device->master, device, ec_data, ec_size);
693 }
694 
695 /****************************************************************************/
696 
705  ec_device_t *device,
706  uint8_t state
707  )
708 {
709  if (unlikely(!device)) {
710  EC_WARN("ecdev_set_link() called with null device!\n");
711  return;
712  }
713 
714  if (likely(state != device->link_state)) {
715  device->link_state = state;
716  EC_MASTER_INFO(device->master,
717  "Link state of %s changed to %s.\n",
718  device->dev->name, (state ? "UP" : "DOWN"));
719  }
720 }
721 
722 /****************************************************************************/
723 
731  const ec_device_t *device
732  )
733 {
734  if (unlikely(!device)) {
735  EC_WARN("ecdev_get_link() called with null device!\n");
736  return 0;
737  }
738 
739  return device->link_state;
740 }
741 
742 /****************************************************************************/
743 
746 EXPORT_SYMBOL(ecdev_withdraw);
747 EXPORT_SYMBOL(ecdev_open);
748 EXPORT_SYMBOL(ecdev_close);
749 EXPORT_SYMBOL(ecdev_receive);
750 EXPORT_SYMBOL(ecdev_get_link);
751 EXPORT_SYMBOL(ecdev_set_link);
752 
755 /****************************************************************************/
#define EC_WARN(fmt, args...)
Convenience macro for printing EtherCAT-specific warnings to syslog.
Definition: globals.h:239
struct sk_buff * tx_skb[EC_TX_RING_SIZE]
transmit skb ring
Definition: device.h:86
u64 tx_count
Number of frames sent.
Definition: master.h:149
const unsigned int rate_intervals[]
List of intervals for statistics [s].
Definition: master.c:110
void ecdev_close(ec_device_t *device)
Makes the master leave IDLE phase and closes the network device.
Definition: device.c:636
ec_pollfunc_t poll
pointer to the device&#39;s poll function
Definition: device.h:82
void ec_debug_clear(ec_debug_t *dbg)
Debug interface destructor.
Definition: debug.c:103
unsigned long jiffies_poll
jiffies of last poll
Definition: device.h:98
u64 last_tx_count
Number of frames sent of last statistics cycle.
Definition: device.h:102
#define ec_master_num_devices(MASTER)
Number of Ethernet devices.
Definition: master.h:326
#define EC_RATE_COUNT
Number of statistic rate intervals to maintain.
Definition: globals.h:60
int ecdev_open(ec_device_t *device)
Opens the network device and makes the master enter IDLE phase.
Definition: device.c:598
struct module * module
pointer to the device&#39;s owning module
Definition: device.h:83
void ec_device_clear(ec_device_t *device)
Destructor.
Definition: device.c:171
int ec_device_open(ec_device_t *device)
Opens the EtherCAT device.
Definition: device.c:254
s32 tx_frame_rates[EC_RATE_COUNT]
Transmit rates in frames/s for different statistics cycle periods.
Definition: device.h:112
void ec_device_update_stats(ec_device_t *device)
Update device statistics.
Definition: device.c:520
uint8_t link_state
device link state
Definition: device.h:85
u64 rx_count
Number of frames received.
Definition: device.h:103
u64 last_tx_bytes
Number of bytes sent of last statistics cycle.
Definition: device.h:107
int ec_master_enter_idle_phase(ec_master_t *master)
Transition function from ORPHANED to IDLE phase.
Definition: master.c:679
s32 rx_frame_rates[EC_RATE_COUNT]
Receive rates in frames/s for different statistics cycle periods.
Definition: device.h:115
EtherCAT master structure.
void ec_debug_unregister(ec_debug_t *dbg)
Unregister debug interface.
Definition: debug.c:144
void ec_device_send(ec_device_t *device, size_t size)
Sends the content of the transmit socket buffer.
Definition: device.c:335
#define EC_MASTER_DBG(master, level, fmt, args...)
Convenience macro for printing master-specific debug messages to syslog.
Definition: master.h:100
#define EC_TX_RING_SIZE
Size of the transmit ring.
Definition: device.h:43
ec_device_stats_t device_stats
Device statistics.
Definition: master.h:208
u64 last_rx_count
Number of frames received of last statistics cycle.
Definition: device.h:104
ec_master_phase_t phase
Master phase.
Definition: master.h:212
void(* ec_pollfunc_t)(struct net_device *)
Device poll function type.
Definition: ecdev.h:49
struct semaphore device_sem
Device semaphore.
Definition: master.h:207
s32 rx_byte_rates[EC_RATE_COUNT]
Receive rates in byte/s for different statistics cycle periods.
Definition: device.h:120
EtherCAT device.
Definition: device.h:78
unsigned int tx_ring_index
last ring entry used to transmit
Definition: device.h:87
unsigned int debug_level
Master debug level.
Definition: master.h:277
void ec_master_leave_idle_phase(ec_master_t *master)
Transition function from IDLE to ORPHANED phase.
Definition: master.c:712
s32 tx_byte_rates[EC_RATE_COUNT]
Transmit rates in byte/s for different statistics cycle periods.
Definition: device.h:118
Main device.
Definition: globals.h:204
int ec_device_init(ec_device_t *device, ec_master_t *master)
Constructor.
Definition: device.c:62
#define EC_MASTER_WARN(master, fmt, args...)
Convenience macro for printing master-specific warnings to syslog.
Definition: master.h:86
ec_master_t * master
EtherCAT master.
Definition: device.h:80
u64 rx_bytes
Number of bytes received.
Definition: device.h:108
u64 tx_count
Number of frames sent.
Definition: device.h:101
uint8_t ecdev_get_link(const ec_device_t *device)
Reads the link state.
Definition: device.c:730
#define EC_MASTER_ERR(master, fmt, args...)
Convenience macro for printing master-specific errors to syslog.
Definition: master.h:74
void ec_debug_send(ec_debug_t *dbg, const uint8_t *data, size_t size)
Sends frame data to the interface.
Definition: debug.c:159
void ec_debug_register(ec_debug_t *dbg, const struct net_device *net_dev)
Register debug interface.
Definition: debug.c:115
int ec_debug_init(ec_debug_t *dbg, ec_device_t *device, const char *name)
Debug interface constructor.
Definition: debug.c:64
uint8_t * ec_device_tx_data(ec_device_t *device)
Returns a pointer to the device&#39;s transmit memory.
Definition: device.c:316
void ec_print_data(const uint8_t *, size_t)
Outputs frame contents for debugging purposes.
Definition: module.c:348
Idle phase.
Definition: master.h:126
uint8_t open
true, if the net_device has been opened
Definition: device.h:84
u64 tx_errors
Number of transmit errors.
Definition: device.h:111
ssize_t ec_mac_print(const uint8_t *, char *)
Print a MAC address to a buffer.
Definition: module.c:249
u64 last_rx_bytes
Number of bytes received of last statistics cycle.
Definition: device.h:109
u64 tx_bytes
Number of bytes sent.
Definition: master.h:154
void ecdev_receive(ec_device_t *device, const void *data, size_t size)
Accepts a received frame.
Definition: device.c:660
int ec_device_close(ec_device_t *device)
Stops the EtherCAT device.
Definition: device.c:287
u64 rx_count
Number of frames received.
Definition: master.h:151
void ecdev_set_link(ec_device_t *device, uint8_t state)
Sets a new link state.
Definition: device.c:704
void ec_device_attach(ec_device_t *device, struct net_device *net_dev, ec_pollfunc_t poll, struct module *module)
Associate with net_device.
Definition: device.c:194
void ec_device_detach(ec_device_t *device)
Disconnect from net_device.
Definition: device.c:225
EtherCAT device structure.
struct net_device * dev
pointer to the assigned net_device
Definition: device.h:81
void ec_device_poll(ec_device_t *device)
Calls the poll function of the assigned net_device.
Definition: device.c:498
unsigned int index
Index.
Definition: master.h:188
Backup device.
Definition: globals.h:205
void ecdev_withdraw(ec_device_t *device)
Withdraws an EtherCAT device from the master.
Definition: device.c:567
u64 rx_bytes
Number of bytes received.
Definition: master.h:156
#define EC_MASTER_INFO(master, fmt, args...)
Convenience macro for printing master-specific information to syslog.
Definition: master.h:62
EtherCAT master.
Definition: master.h:187
void ec_master_receive_datagrams(ec_master_t *master, ec_device_t *device, const uint8_t *frame_data, size_t size)
Processes a received frame.
Definition: master.c:1164
ec_device_t devices[EC_MAX_NUM_DEVICES]
EtherCAT devices.
Definition: master.h:200
u64 tx_bytes
Number of bytes sent.
Definition: device.h:106
void ec_device_clear_stats(ec_device_t *device)
Clears the frame statistics.
Definition: device.c:374
#define EC_MAX_DATA_SIZE
Resulting maximum data size of a single datagram in a frame.
Definition: globals.h:79