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