IgH EtherCAT Master  1.6.0-rc1
module.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 
34 /*****************************************************************************/
35 
36 #include <linux/module.h>
37 #include <linux/device.h>
38 #include <linux/err.h>
39 
40 #include "globals.h"
41 #include "master.h"
42 #include "device.h"
43 
44 /*****************************************************************************/
45 
46 #define MAX_MASTERS 32
48 /*****************************************************************************/
49 
50 int __init ec_init_module(void);
51 void __exit ec_cleanup_module(void);
52 
53 static int ec_mac_parse(uint8_t *, const char *, int);
54 
55 /*****************************************************************************/
56 
57 static char *main_devices[MAX_MASTERS];
58 static unsigned int master_count;
59 static char *backup_devices[MAX_MASTERS];
60 static unsigned int backup_count;
61 static unsigned int debug_level;
64 static ec_lock_t master_sem;
67 struct class *class;
69 static uint8_t macs[MAX_MASTERS][2][ETH_ALEN];
71 char *ec_master_version_str = EC_MASTER_VERSION;
73 /*****************************************************************************/
74 
77 MODULE_AUTHOR("Florian Pose <fp@igh-essen.com>");
78 MODULE_DESCRIPTION("EtherCAT master driver module");
79 MODULE_LICENSE("GPL");
80 MODULE_VERSION(EC_MASTER_VERSION);
81 
82 module_param_array(main_devices, charp, &master_count, S_IRUGO);
83 MODULE_PARM_DESC(main_devices, "MAC addresses of main devices");
84 module_param_array(backup_devices, charp, &backup_count, S_IRUGO);
85 MODULE_PARM_DESC(backup_devices, "MAC addresses of backup devices");
86 module_param_named(debug_level, debug_level, uint, S_IRUGO);
87 MODULE_PARM_DESC(debug_level, "Debug level");
88 
91 /*****************************************************************************/
92 
98 int __init ec_init_module(void)
99 {
100  int i, ret = 0;
101 
102  EC_INFO("Master driver %s\n", EC_MASTER_VERSION);
103 
104  ec_lock_init(&master_sem);
105 
106  if (master_count) {
107  if (alloc_chrdev_region(&device_number,
108  0, master_count, "EtherCAT")) {
109  EC_ERR("Failed to obtain device number(s)!\n");
110  ret = -EBUSY;
111  goto out_return;
112  }
113  }
114 
115 #if LINUX_VERSION_CODE < KERNEL_VERSION(6, 4, 0)
116  class = class_create(THIS_MODULE, "EtherCAT");
117 #else
118  class = class_create("EtherCAT");
119 #endif
120  if (IS_ERR(class)) {
121  EC_ERR("Failed to create device class.\n");
122  ret = PTR_ERR(class);
123  goto out_cdev;
124  }
125 
126  // zero MAC addresses
127  memset(macs, 0x00, sizeof(uint8_t) * MAX_MASTERS * 2 * ETH_ALEN);
128 
129  // process MAC parameters
130  for (i = 0; i < master_count; i++) {
131  ret = ec_mac_parse(macs[i][0], main_devices[i], 0);
132  if (ret)
133  goto out_class;
134 
135  if (i < backup_count) {
136  ret = ec_mac_parse(macs[i][1], backup_devices[i], 1);
137  if (ret)
138  goto out_class;
139  }
140  }
141 
142  // initialize static master variables
144 
145  if (master_count) {
146  if (!(masters = kmalloc(sizeof(ec_master_t) * master_count,
147  GFP_KERNEL))) {
148  EC_ERR("Failed to allocate memory"
149  " for EtherCAT masters.\n");
150  ret = -ENOMEM;
151  goto out_class;
152  }
153  }
154 
155  for (i = 0; i < master_count; i++) {
156  ret = ec_master_init(&masters[i], i, macs[i][0], macs[i][1],
157  device_number, class, debug_level);
158  if (ret)
159  goto out_free_masters;
160  }
161 
162  EC_INFO("%u master%s waiting for devices.\n",
163  master_count, (master_count == 1 ? "" : "s"));
164  return ret;
165 
166 out_free_masters:
167  for (i--; i >= 0; i--)
168  ec_master_clear(&masters[i]);
169  kfree(masters);
170 out_class:
171  class_destroy(class);
172 out_cdev:
173  if (master_count)
174  unregister_chrdev_region(device_number, master_count);
175 out_return:
176  return ret;
177 }
178 
179 /*****************************************************************************/
180 
185 void __exit ec_cleanup_module(void)
186 {
187  unsigned int i;
188 
189  for (i = 0; i < master_count; i++) {
190  ec_master_clear(&masters[i]);
191  }
192 
193  if (master_count)
194  kfree(masters);
195 
196  class_destroy(class);
197 
198  if (master_count)
199  unregister_chrdev_region(device_number, master_count);
200 
201  EC_INFO("Master module cleaned up.\n");
202 }
203 
204 /*****************************************************************************/
205 
208 unsigned int ec_master_count(void)
209 {
210  return master_count;
211 }
212 
213 /*****************************************************************************
214  * MAC address functions
215  ****************************************************************************/
216 
221  const uint8_t *mac1,
222  const uint8_t *mac2
223  )
224 {
225  unsigned int i;
226 
227  for (i = 0; i < ETH_ALEN; i++)
228  if (mac1[i] != mac2[i])
229  return 0;
230 
231  return 1;
232 }
233 
234 /*****************************************************************************/
235 
238 #define EC_MAX_MAC_STRING_SIZE (3 * ETH_ALEN)
239 
247  const uint8_t *mac,
248  char *buffer
249  )
250 {
251  size_t off = 0;
252  unsigned int i;
253 
254  for (i = 0; i < ETH_ALEN; i++) {
255  off += sprintf(buffer + off, "%02X", mac[i]);
256  if (i < ETH_ALEN - 1) off += sprintf(buffer + off, ":");
257  }
258 
259  return off;
260 }
261 
262 /*****************************************************************************/
263 
268  const uint8_t *mac
269  )
270 {
271  unsigned int i;
272 
273  for (i = 0; i < ETH_ALEN; i++)
274  if (mac[i])
275  return 0;
276 
277  return 1;
278 }
279 
280 /*****************************************************************************/
281 
286  const uint8_t *mac
287  )
288 {
289  unsigned int i;
290 
291  for (i = 0; i < ETH_ALEN; i++)
292  if (mac[i] != 0xff)
293  return 0;
294 
295  return 1;
296 }
297 
298 /*****************************************************************************/
299 
307 static int ec_mac_parse(uint8_t *mac, const char *src, int allow_empty)
308 {
309  unsigned int i, value;
310  const char *orig = src;
311  char *rem;
312 
313  if (!strlen(src)) {
314  if (allow_empty){
315  return 0;
316  } else {
317  EC_ERR("MAC address may not be empty.\n");
318  return -EINVAL;
319  }
320  }
321 
322  for (i = 0; i < ETH_ALEN; i++) {
323  value = simple_strtoul(src, &rem, 16);
324  if (rem != src + 2
325  || value > 0xFF
326  || (i < ETH_ALEN - 1 && *rem != ':')) {
327  EC_ERR("Invalid MAC address \"%s\".\n", orig);
328  return -EINVAL;
329  }
330  mac[i] = value;
331  if (i < ETH_ALEN - 1) {
332  src = rem + 1; // skip colon
333  }
334  }
335 
336  return 0;
337 }
338 
339 /*****************************************************************************/
340 
345 void ec_print_data(const uint8_t *data,
346  size_t size
347  )
348 {
349  unsigned int i;
350 
351  EC_DBG("");
352  for (i = 0; i < size; i++) {
353  printk(KERN_CONT "%02X ", data[i]);
354 
355  if ((i + 1) % 16 == 0 && i < size - 1) {
356  printk(KERN_CONT "\n");
357  EC_DBG("");
358  }
359 
360  if (i + 1 == 128 && size > 256) {
361  printk(KERN_CONT "dropped %zu bytes\n", size - 128 - i);
362  i = size - 128;
363  EC_DBG("");
364  }
365  }
366  printk(KERN_CONT "\n");
367 }
368 
369 /*****************************************************************************/
370 
373 void ec_print_data_diff(const uint8_t *d1,
374  const uint8_t *d2,
375  size_t size
376  )
377 {
378  unsigned int i;
379 
380  EC_DBG("");
381  for (i = 0; i < size; i++) {
382  if (d1[i] == d2[i]) {
383  printk(KERN_CONT ".. ");
384  }
385  else {
386  printk(KERN_CONT "%02X ", d2[i]);
387  }
388  if ((i + 1) % 16 == 0) {
389  printk(KERN_CONT "\n");
390  EC_DBG("");
391  }
392  }
393  printk(KERN_CONT "\n");
394 }
395 
396 /*****************************************************************************/
397 
402 size_t ec_state_string(uint8_t states,
403  char *buffer,
405  uint8_t multi
406  )
407 {
408  off_t off = 0;
409  unsigned int first = 1;
410 
411  if (!states) {
412  off += sprintf(buffer + off, "(unknown)");
413  return off;
414  }
415 
416  if (multi) { // multiple slaves
417  if (states & EC_SLAVE_STATE_INIT) {
418  off += sprintf(buffer + off, "INIT");
419  first = 0;
420  }
421  if (states & EC_SLAVE_STATE_PREOP) {
422  if (!first) off += sprintf(buffer + off, ", ");
423  off += sprintf(buffer + off, "PREOP");
424  first = 0;
425  }
426  if (states & EC_SLAVE_STATE_SAFEOP) {
427  if (!first) off += sprintf(buffer + off, ", ");
428  off += sprintf(buffer + off, "SAFEOP");
429  first = 0;
430  }
431  if (states & EC_SLAVE_STATE_OP) {
432  if (!first) off += sprintf(buffer + off, ", ");
433  off += sprintf(buffer + off, "OP");
434  }
435  } else { // single slave
436  if ((states & EC_SLAVE_STATE_MASK) == EC_SLAVE_STATE_INIT) {
437  off += sprintf(buffer + off, "INIT");
438  } else if ((states & EC_SLAVE_STATE_MASK) == EC_SLAVE_STATE_PREOP) {
439  off += sprintf(buffer + off, "PREOP");
440  } else if ((states & EC_SLAVE_STATE_MASK) == EC_SLAVE_STATE_BOOT) {
441  off += sprintf(buffer + off, "BOOT");
442  } else if ((states & EC_SLAVE_STATE_MASK) == EC_SLAVE_STATE_SAFEOP) {
443  off += sprintf(buffer + off, "SAFEOP");
444  } else if ((states & EC_SLAVE_STATE_MASK) == EC_SLAVE_STATE_OP) {
445  off += sprintf(buffer + off, "OP");
446  } else {
447  off += sprintf(buffer + off, "(invalid)");
448  }
449  first = 0;
450  }
451 
452  if (states & EC_SLAVE_STATE_ACK_ERR) {
453  if (!first) off += sprintf(buffer + off, " + ");
454  off += sprintf(buffer + off, "ERROR");
455  }
456 
457  return off;
458 }
459 
460 /******************************************************************************
461  * Device interface
462  *****************************************************************************/
463 
466 const char *ec_device_names[2] = {
467  "main",
468  "backup"
469 };
470 
482  struct net_device *net_dev,
483  ec_pollfunc_t poll,
484  struct module *module
485  )
486 {
487  ec_master_t *master;
488  char str[EC_MAX_MAC_STRING_SIZE];
489  unsigned int i, dev_idx;
490 
491  for (i = 0; i < master_count; i++) {
492  master = &masters[i];
493  ec_mac_print(net_dev->dev_addr, str);
494 
495  if (ec_lock_down_interruptible(&master->device_sem)) {
496  EC_MASTER_WARN(master, "%s() interrupted!\n", __func__);
497  return NULL;
498  }
499 
500  for (dev_idx = EC_DEVICE_MAIN;
501  dev_idx < ec_master_num_devices(master); dev_idx++) {
502  if (!master->devices[dev_idx].dev
503  && (ec_mac_equal(master->macs[dev_idx], net_dev->dev_addr)
504  || ec_mac_is_broadcast(master->macs[dev_idx]))) {
505 
506  EC_INFO("Accepting %s as %s device for master %u.\n",
507  str, ec_device_names[dev_idx != 0], master->index);
508 
509  ec_device_attach(&master->devices[dev_idx],
510  net_dev, poll, module);
511  ec_lock_up(&master->device_sem);
512 
513  snprintf(net_dev->name, IFNAMSIZ, "ec%c%u",
514  ec_device_names[dev_idx != 0][0], master->index);
515 
516  return &master->devices[dev_idx]; // offer accepted
517  }
518  }
519 
520  ec_lock_up(&master->device_sem);
521 
522  EC_MASTER_DBG(master, 1, "Master declined device %s.\n", str);
523  }
524 
525  return NULL; // offer declined
526 }
527 
528 /******************************************************************************
529  * Application interface
530  *****************************************************************************/
531 
539  unsigned int master_index
540  )
541 {
542  ec_master_t *master, *errptr = NULL;
543  unsigned int dev_idx = EC_DEVICE_MAIN;
544 
545  EC_INFO("Requesting master %u...\n", master_index);
546 
547  if (master_index >= master_count) {
548  EC_ERR("Invalid master index %u.\n", master_index);
549  errptr = ERR_PTR(-EINVAL);
550  goto out_return;
551  }
552  master = &masters[master_index];
553 
554  if (ec_lock_down_interruptible(&master_sem)) {
555  errptr = ERR_PTR(-EINTR);
556  goto out_return;
557  }
558 
559  if (master->reserved) {
560  ec_lock_up(&master_sem);
561  EC_MASTER_ERR(master, "Master already in use!\n");
562  errptr = ERR_PTR(-EBUSY);
563  goto out_return;
564  }
565  master->reserved = 1;
566  ec_lock_up(&master_sem);
567 
568  if (ec_lock_down_interruptible(&master->device_sem)) {
569  errptr = ERR_PTR(-EINTR);
570  goto out_release;
571  }
572 
573  if (master->phase != EC_IDLE) {
574  ec_lock_up(&master->device_sem);
575  EC_MASTER_ERR(master, "Master still waiting for devices!\n");
576  errptr = ERR_PTR(-ENODEV);
577  goto out_release;
578  }
579 
580  for (; dev_idx < ec_master_num_devices(master); dev_idx++) {
581  ec_device_t *device = &master->devices[dev_idx];
582  if (!try_module_get(device->module)) {
583  ec_lock_up(&master->device_sem);
584  EC_MASTER_ERR(master, "Device module is unloading!\n");
585  errptr = ERR_PTR(-ENODEV);
586  goto out_module_put;
587  }
588  }
589 
590  ec_lock_up(&master->device_sem);
591 
592  if (ec_master_enter_operation_phase(master)) {
593  EC_MASTER_ERR(master, "Failed to enter OPERATION phase!\n");
594  errptr = ERR_PTR(-EIO);
595  goto out_module_put;
596  }
597 
598  EC_INFO("Successfully requested master %u.\n", master_index);
599  return master;
600 
601  out_module_put:
602  for (; dev_idx > 0; dev_idx--) {
603  ec_device_t *device = &master->devices[dev_idx - 1];
604  module_put(device->module);
605  }
606  out_release:
607  master->reserved = 0;
608  out_return:
609  return errptr;
610 }
611 
612 /*****************************************************************************/
613 
614 ec_master_t *ecrt_request_master(unsigned int master_index)
615 {
616  ec_master_t *master = ecrt_request_master_err(master_index);
617  return IS_ERR(master) ? NULL : master;
618 }
619 
620 /*****************************************************************************/
621 
623 {
624  unsigned int dev_idx;
625 
626  EC_MASTER_INFO(master, "Releasing master...\n");
627 
628  if (!master->reserved) {
629  EC_MASTER_WARN(master, "%s(): Master was was not requested!\n",
630  __func__);
631  return;
632  }
633 
635 
636  for (dev_idx = EC_DEVICE_MAIN; dev_idx < ec_master_num_devices(master);
637  dev_idx++) {
638  module_put(master->devices[dev_idx].module);
639  }
640 
641  master->reserved = 0;
642 
643  EC_MASTER_INFO(master, "Released.\n");
644 }
645 
646 /*****************************************************************************/
647 
648 unsigned int ecrt_version_magic(void)
649 {
650  return ECRT_VERSION_MAGIC;
651 }
652 
653 /*****************************************************************************/
654 
660  EC_REQUEST_UNUSED, // EC_INT_REQUEST_INIT,
661  EC_REQUEST_BUSY, // EC_INT_REQUEST_QUEUED,
662  EC_REQUEST_BUSY, // EC_INT_REQUEST_BUSY,
663  EC_REQUEST_SUCCESS, // EC_INT_REQUEST_SUCCESS,
664  EC_REQUEST_ERROR // EC_INT_REQUEST_FAILURE
665 };
666 
667 /*****************************************************************************/
668 
671 module_init(ec_init_module);
672 module_exit(ec_cleanup_module);
673 
674 EXPORT_SYMBOL(ecdev_offer);
675 
676 EXPORT_SYMBOL(ecrt_request_master);
677 EXPORT_SYMBOL(ecrt_release_master);
678 EXPORT_SYMBOL(ecrt_version_magic);
679 
682 /*****************************************************************************/
unsigned int reserved
True, if the master is in use.
Definition: master.h:191
void ec_print_data(const uint8_t *data, size_t size)
Outputs frame contents for debugging purposes.
Definition: module.c:345
#define EC_SLAVE_STATE_MASK
Slave state mask.
Definition: globals.h:123
static char * backup_devices[MAX_MASTERS]
Backup devices parameter.
Definition: module.c:59
size_t ec_state_string(uint8_t states, char *buffer, uint8_t multi)
Prints slave states in clear text.
Definition: module.c:402
int ec_mac_is_broadcast(const uint8_t *mac)
Definition: module.c:285
void ecrt_release_master(ec_master_t *master)
Releases a requested EtherCAT master.
Definition: module.c:622
void ec_master_clear(ec_master_t *master)
Destructor.
Definition: master.c:408
OP (mailbox communication and input/output update)
Definition: globals.h:138
void ec_master_leave_operation_phase(ec_master_t *master)
Transition function from OPERATION to IDLE phase.
Definition: master.c:775
static ec_lock_t master_sem
Master semaphore.
Definition: module.c:64
#define ec_master_num_devices(MASTER)
Number of Ethernet devices.
Definition: master.h:327
#define EC_MAX_MAC_STRING_SIZE
Maximum MAC string size.
Definition: module.c:238
struct module * module
pointer to the device&#39;s owning module
Definition: device.h:86
dev_t device_number
Device number for master cdevs.
Definition: module.c:66
Bootstrap state (mailbox communication, firmware update)
Definition: globals.h:134
int ec_mac_is_zero(const uint8_t *mac)
Definition: module.c:267
#define MAX_MASTERS
Maximum number of masters.
Definition: module.c:46
static ec_master_t * masters
Array of masters.
Definition: module.c:63
char * ec_master_version_str
Version string.
Definition: module.c:71
Acknowledge/Error bit (no actual state)
Definition: globals.h:140
static unsigned int debug_level
Debug level parameter.
Definition: module.c:61
const uint8_t * macs[EC_MAX_NUM_DEVICES]
Device MAC addresses.
Definition: master.h:207
void ec_print_data_diff(const uint8_t *d1, const uint8_t *d2, size_t size)
Outputs frame contents and differences for debugging purposes.
Definition: module.c:373
ec_master_t * ecrt_request_master_err(unsigned int master_index)
Request a master.
Definition: module.c:538
Global definitions and macros.
EtherCAT master structure.
void __exit ec_cleanup_module(void)
Module cleanup.
Definition: module.c:185
SAFEOP (mailbox communication and input update)
Definition: globals.h:136
Not requested.
Definition: ecrt.h:536
#define EC_MASTER_DBG(master, level, fmt, args...)
Convenience macro for printing master-specific debug messages to syslog.
Definition: master.h:106
ec_lock_t device_sem
Device semaphore.
Definition: master.h:213
ec_master_t * ecrt_request_master(unsigned int master_index)
Requests an EtherCAT master for realtime operation.
Definition: module.c:614
Request is being processed.
Definition: ecrt.h:537
static uint8_t macs[MAX_MASTERS][2][ETH_ALEN]
MAC addresses.
Definition: module.c:69
ec_master_phase_t phase
Master phase.
Definition: master.h:218
static unsigned int master_count
Number of masters.
Definition: module.c:58
void(* ec_pollfunc_t)(struct net_device *)
Device poll function type.
Definition: ecdev.h:57
EtherCAT device.
Definition: device.h:81
int __init ec_init_module(void)
Module initialization.
Definition: module.c:98
Main device.
Definition: globals.h:205
unsigned int ecrt_version_magic(void)
Returns the version magic of the realtime interface.
Definition: module.c:648
int ec_master_init(ec_master_t *master, unsigned int index, const uint8_t *main_mac, const uint8_t *backup_mac, dev_t device_number, struct class *class, unsigned int debug_level)
Master constructor.
Definition: master.c:142
#define EC_MASTER_WARN(master, fmt, args...)
Convenience macro for printing master-specific warnings to syslog.
Definition: master.h:92
int ec_master_enter_operation_phase(ec_master_t *master)
Transition function from IDLE to OPERATION phase.
Definition: master.c:704
struct class * class
Device class.
Definition: module.c:67
#define EC_MASTER_ERR(master, fmt, args...)
Convenience macro for printing master-specific errors to syslog.
Definition: master.h:80
int ec_mac_equal(const uint8_t *mac1, const uint8_t *mac2)
Definition: module.c:220
INIT state (no mailbox communication, no IO)
Definition: globals.h:130
Idle phase.
Definition: master.h:128
#define EC_DBG(fmt, args...)
Convenience macro for printing EtherCAT debug messages to syslog.
Definition: globals.h:250
#define EC_INFO(fmt, args...)
Convenience macro for printing EtherCAT-specific information to syslog.
Definition: globals.h:220
#define EC_ERR(fmt, args...)
Convenience macro for printing EtherCAT-specific errors to syslog.
Definition: globals.h:230
ec_device_t * ecdev_offer(struct net_device *net_dev, ec_pollfunc_t poll, struct module *module)
Offers an EtherCAT device to a certain master.
Definition: module.c:481
unsigned int ec_master_count(void)
Get the number of masters.
Definition: module.c:208
const ec_request_state_t ec_request_state_translation_table[]
Global request state type translation table.
Definition: module.c:659
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:182
EtherCAT device structure.
static int ec_mac_parse(uint8_t *, const char *, int)
Parse a MAC address from a string.
Definition: module.c:307
struct net_device * dev
pointer to the assigned net_device
Definition: device.h:84
Request was processed successfully.
Definition: ecrt.h:538
static unsigned int backup_count
Number of backup devices.
Definition: module.c:60
ec_request_state_t
Request state.
Definition: ecrt.h:535
unsigned int index
Index.
Definition: master.h:190
PREOP state (mailbox communication, no IO)
Definition: globals.h:132
#define EC_MASTER_INFO(master, fmt, args...)
Convenience macro for printing master-specific information to syslog.
Definition: master.h:68
static char * main_devices[MAX_MASTERS]
Main devices parameter.
Definition: module.c:57
EtherCAT master.
Definition: master.h:189
Request processing failed.
Definition: ecrt.h:539
ec_device_t devices[EC_MAX_NUM_DEVICES]
EtherCAT devices.
Definition: master.h:206
size_t ec_mac_print(const uint8_t *mac, char *buffer)
Print a MAC address to a buffer.
Definition: module.c:246
void ec_master_init_static(void)
Static variables initializer.
Definition: master.c:121
#define ECRT_VERSION_MAGIC
EtherCAT realtime interface version word.
Definition: ecrt.h:160
const char * ec_device_names[2]
Device names.
Definition: module.c:466