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