IgH EtherCAT Master  1.6.1
datagram_pair.c
Go to the documentation of this file.
1 /*****************************************************************************
2  *
3  * Copyright (C) 2006-2012 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/slab.h>
30 
31 #include "master.h"
32 #include "datagram_pair.h"
33 
34 /****************************************************************************/
35 
41  ec_datagram_pair_t *pair,
42  ec_domain_t *domain,
43  uint32_t logical_offset,
44  uint8_t *data,
45  size_t data_size,
46  const unsigned int used[]
47  )
48 {
49  ec_device_index_t dev_idx;
50  int ret;
51 
52  INIT_LIST_HEAD(&pair->list);
53  pair->domain = domain;
54 
55  for (dev_idx = EC_DEVICE_MAIN;
56  dev_idx < ec_master_num_devices(domain->master); dev_idx++) {
57  ec_datagram_init(&pair->datagrams[dev_idx]);
58  snprintf(pair->datagrams[dev_idx].name,
59  EC_DATAGRAM_NAME_SIZE, "domain%u-%u-%s", domain->index,
60  logical_offset, ec_device_names[dev_idx != 0]);
61  pair->datagrams[dev_idx].device_index = dev_idx;
62  }
63 
64  pair->expected_working_counter = 0U;
65 
66  for (dev_idx = EC_DEVICE_BACKUP;
67  dev_idx < ec_master_num_devices(domain->master); dev_idx++) {
68  /* backup datagrams have their own memory */
69  ret = ec_datagram_prealloc(&pair->datagrams[dev_idx], data_size);
70  if (ret) {
71  goto out_datagrams;
72  }
73  }
74 
75 #if EC_MAX_NUM_DEVICES > 1
76  if (!(pair->send_buffer = kmalloc(data_size, GFP_KERNEL))) {
77  EC_MASTER_ERR(domain->master,
78  "Failed to allocate domain send buffer!\n");
79  ret = -ENOMEM;
80  goto out_datagrams;
81  }
82 #endif
83 
84  /* The ec_datagram_lxx() calls below can not fail, because either the
85  * datagram has external memory or it is preallocated. */
86 
87  if (used[EC_DIR_OUTPUT] && used[EC_DIR_INPUT]) { // inputs and outputs
89  logical_offset, data_size, data);
90 
91  for (dev_idx = EC_DEVICE_BACKUP;
92  dev_idx < ec_master_num_devices(domain->master); dev_idx++) {
93  ec_datagram_lrw(&pair->datagrams[dev_idx],
94  logical_offset, data_size);
95  }
96 
97  // If LRW is used, output FMMUs increment the working counter by 2,
98  // while input FMMUs increment it by 1.
100  used[EC_DIR_OUTPUT] * 2 + used[EC_DIR_INPUT];
101  } else if (used[EC_DIR_OUTPUT]) { // outputs only
103  logical_offset, data_size, data);
104  for (dev_idx = EC_DEVICE_BACKUP;
105  dev_idx < ec_master_num_devices(domain->master); dev_idx++) {
106  ec_datagram_lwr(&pair->datagrams[dev_idx],
107  logical_offset, data_size);
108  }
109 
111  } else { // inputs only (or nothing)
113  logical_offset, data_size, data);
114  for (dev_idx = EC_DEVICE_BACKUP;
115  dev_idx < ec_master_num_devices(domain->master); dev_idx++) {
116  ec_datagram_lrd(&pair->datagrams[dev_idx], logical_offset,
117  data_size);
118  }
119 
121  }
122 
123  for (dev_idx = EC_DEVICE_MAIN;
124  dev_idx < ec_master_num_devices(domain->master); dev_idx++) {
125  ec_datagram_zero(&pair->datagrams[dev_idx]);
126  }
127 
128  return 0;
129 
130 out_datagrams:
131  for (dev_idx = EC_DEVICE_MAIN;
132  dev_idx < ec_master_num_devices(domain->master); dev_idx++) {
133  ec_datagram_clear(&pair->datagrams[dev_idx]);
134  }
135 
136  return ret;
137 }
138 
139 /****************************************************************************/
140 
144  ec_datagram_pair_t *pair
145  )
146 {
147  unsigned int dev_idx;
148 
149  for (dev_idx = EC_DEVICE_MAIN;
150  dev_idx < ec_master_num_devices(pair->domain->master);
151  dev_idx++) {
152  ec_datagram_clear(&pair->datagrams[dev_idx]);
153  }
154 
155 #if EC_MAX_NUM_DEVICES > 1
156  if (pair->send_buffer) {
157  kfree(pair->send_buffer);
158  }
159 #endif
160 }
161 
162 /****************************************************************************/
163 
169  ec_datagram_pair_t *pair,
170  uint16_t wc_sum[]
171  )
172 {
173  unsigned int dev_idx;
174  uint16_t pair_wc = 0;
175 
176  for (dev_idx = 0; dev_idx < ec_master_num_devices(pair->domain->master);
177  dev_idx++) {
178  ec_datagram_t *datagram = &pair->datagrams[dev_idx];
179 
180 #ifdef EC_RT_SYSLOG
181  ec_datagram_output_stats(datagram);
182 #endif
183 
184  if (datagram->state == EC_DATAGRAM_RECEIVED) {
185  pair_wc += datagram->working_counter;
186  wc_sum[dev_idx] += datagram->working_counter;
187  }
188  }
189 
190  return pair_wc;
191 }
192 
193 /****************************************************************************/
#define EC_DATAGRAM_NAME_SIZE
Size of the datagram description string.
Definition: globals.h:104
Domain datagram pair.
Definition: datagram_pair.h:41
unsigned int expected_working_counter
Expectord working conter.
Definition: datagram_pair.h:48
#define ec_master_num_devices(MASTER)
Number of Ethernet devices.
Definition: master.h:321
int ec_datagram_lwr_ext(ec_datagram_t *datagram, uint32_t offset, size_t data_size, uint8_t *external_memory)
Initializes an EtherCAT LWR datagram with external memory.
Definition: datagram.c:510
EtherCAT datagram.
Definition: datagram.h:79
char name[EC_DATAGRAM_NAME_SIZE]
Description of the datagram.
Definition: datagram.h:106
uint16_t working_counter
Working counter.
Definition: datagram.h:93
const char * ec_device_names[2]
Device names.
Definition: module.c:465
void ec_datagram_output_stats(ec_datagram_t *datagram)
Outputs datagram statistics at most every second.
Definition: datagram.c:614
int ec_datagram_lwr(ec_datagram_t *datagram, uint32_t offset, size_t data_size)
Initializes an EtherCAT LWR datagram.
Definition: datagram.c:444
EtherCAT master structure.
void ec_datagram_zero(ec_datagram_t *datagram)
Fills the datagram payload memory with zeros.
Definition: datagram.c:170
ec_datagram_state_t state
State.
Definition: datagram.h:94
uint16_t ec_datagram_pair_process(ec_datagram_pair_t *pair, uint16_t wc_sum[])
Process received data.
ec_device_index_t
Master devices.
Definition: globals.h:198
void ec_datagram_pair_clear(ec_datagram_pair_t *pair)
Datagram pair destructor.
unsigned int index
Index (just a number).
Definition: domain.h:50
Main device.
Definition: globals.h:199
int ec_datagram_lrd_ext(ec_datagram_t *datagram, uint32_t offset, size_t data_size, uint8_t *external_memory)
Initializes an EtherCAT LRD datagram with external memory.
Definition: datagram.c:485
#define EC_MASTER_ERR(master, fmt, args...)
Convenience macro for printing master-specific errors to syslog.
Definition: master.h:74
Values read by the master.
Definition: ecrt.h:507
ec_device_index_t device_index
Device via which the datagram shall be / was sent.
Definition: datagram.h:84
int ec_datagram_lrd(ec_datagram_t *datagram, uint32_t offset, size_t data_size)
Initializes an EtherCAT LRD datagram.
Definition: datagram.c:425
int ec_datagram_prealloc(ec_datagram_t *datagram, size_t size)
Allocates internal payload memory.
Definition: datagram.c:142
int ec_datagram_pair_init(ec_datagram_pair_t *pair, ec_domain_t *domain, uint32_t logical_offset, uint8_t *data, size_t data_size, const unsigned int used[])
Datagram pair constructor.
Definition: datagram_pair.c:40
ec_domain_t * domain
Parent domain.
Definition: datagram_pair.h:43
void ec_datagram_init(ec_datagram_t *datagram)
Constructor.
Definition: datagram.c:80
struct list_head list
List header.
Definition: datagram_pair.h:42
EtherCAT datagram pair structure.
int ec_datagram_lrw_ext(ec_datagram_t *datagram, uint32_t offset, size_t data_size, uint8_t *external_memory)
Initializes an EtherCAT LRW datagram with external memory.
Definition: datagram.c:535
ec_datagram_t datagrams[EC_MAX_NUM_DEVICES]
Datagrams.
Definition: datagram_pair.h:44
Backup device.
Definition: globals.h:200
Values written by the master.
Definition: ecrt.h:506
Received (dequeued).
Definition: datagram.h:70
int ec_datagram_lrw(ec_datagram_t *datagram, uint32_t offset, size_t data_size)
Initializes an EtherCAT LRW datagram.
Definition: datagram.c:463
EtherCAT domain.
Definition: domain.h:46
ec_master_t * master
EtherCAT master owning the domain.
Definition: domain.h:49
void ec_datagram_clear(ec_datagram_t *datagram)
Destructor.
Definition: datagram.c:110