IgH EtherCAT Master  1.5.4
soe_request.c
Go to the documentation of this file.
1 /******************************************************************************
2  *
3  * Copyright (C) 2006-2023 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  *
22  * The license mentioned above concerns the source code only. Using the
23  * EtherCAT technology and brand is only permitted in compliance with the
24  * industrial property and similar rights of Beckhoff Automation GmbH.
25  *
26  *****************************************************************************/
27 
32 /*****************************************************************************/
33 
34 #include <linux/module.h>
35 #include <linux/jiffies.h>
36 #include <linux/slab.h>
37 
38 #include "soe_request.h"
39 
40 /*****************************************************************************/
41 
44 #define EC_SOE_REQUEST_RESPONSE_TIMEOUT 1000
45 
46 /*****************************************************************************/
47 
49 
50 /*****************************************************************************/
51 
55  ec_soe_request_t *req
56  )
57 {
58  INIT_LIST_HEAD(&req->list);
59  req->drive_no = 0x00;
60  req->idn = 0x0000;
62  req->data = NULL;
63  req->mem_size = 0;
64  req->data_size = 0;
65  req->issue_timeout = 0; // no timeout
66  req->dir = EC_DIR_INVALID;
67  req->state = EC_INT_REQUEST_INIT;
68  req->jiffies_start = 0U;
69  req->jiffies_sent = 0U;
70  req->error_code = 0x0000;
71 }
72 
73 /*****************************************************************************/
74 
78  ec_soe_request_t *req
79  )
80 {
82 }
83 
84 /*****************************************************************************/
85 
91  ec_soe_request_t *req,
92  const ec_soe_request_t *other
93  )
94 {
95  req->drive_no = other->drive_no;
96  req->idn = other->idn;
97  req->al_state = other->al_state;
98  return ec_soe_request_copy_data(req, other->data, other->data_size);
99 }
100 
101 /*****************************************************************************/
102 
106  ec_soe_request_t *req,
107  uint8_t drive_no
108  )
109 {
110  req->drive_no = drive_no;
111 }
112 
113 /*****************************************************************************/
114 
118  ec_soe_request_t *req,
119  uint16_t idn
120  )
121 {
122  req->idn = idn;
123 }
124 
125 /*****************************************************************************/
126 
130  ec_soe_request_t *req
131  )
132 {
133  if (req->data) {
134  kfree(req->data);
135  req->data = NULL;
136  }
137 
138  req->mem_size = 0;
139  req->data_size = 0;
140 }
141 
142 /*****************************************************************************/
143 
151  ec_soe_request_t *req,
152  size_t size
153  )
154 {
155  if (size <= req->mem_size)
156  return 0;
157 
159 
160  if (!(req->data = (uint8_t *) kmalloc(size, GFP_KERNEL))) {
161  EC_ERR("Failed to allocate %zu bytes of SoE memory.\n", size);
162  return -ENOMEM;
163  }
164 
165  req->mem_size = size;
166  req->data_size = 0;
167  return 0;
168 }
169 
170 /*****************************************************************************/
171 
180  ec_soe_request_t *req,
181  const uint8_t *source,
182  size_t size
183  )
184 {
185  int ret = ec_soe_request_alloc(req, size);
186  if (ret < 0)
187  return ret;
188 
189  memcpy(req->data, source, size);
190  req->data_size = size;
191  return 0;
192 }
193 
194 /*****************************************************************************/
195 
204  ec_soe_request_t *req,
205  const uint8_t *source,
206  size_t size
207  )
208 {
209  size_t new_total_size = req->data_size + size;
210 
211  if (new_total_size > req->mem_size) {
212  size_t new_size;
213  if (req->mem_size * 2 >= new_total_size) {
214  // just double it to reduce the number of re-allocations
215  new_size = req->mem_size * 2;
216  }
217  else {
218  new_size = new_total_size;
219  }
220 
221  uint8_t *new_data = (uint8_t *) kmalloc(new_size, GFP_KERNEL);
222  if (!new_data) {
223  EC_ERR("Failed to allocate %zu bytes of SoE memory.\n",
224  new_size);
225  return -ENOMEM;
226  }
227  memcpy(new_data, req->data, req->data_size);
228  kfree(req->data);
229  req->data = new_data;
230  req->mem_size = new_size;
231  }
232 
233  memcpy(req->data + req->data_size, source, size);
234  req->data_size = new_total_size;
235  return 0;
236 }
237 
238 /*****************************************************************************/
239 
243  ec_soe_request_t *req
244  )
245 {
246  req->dir = EC_DIR_INPUT;
247  req->state = EC_INT_REQUEST_QUEUED;
248  req->error_code = 0x0000;
249  req->jiffies_start = jiffies;
250 }
251 
252 /*****************************************************************************/
253 
257  ec_soe_request_t *req
258  )
259 {
260  req->dir = EC_DIR_OUTPUT;
261  req->state = EC_INT_REQUEST_QUEUED;
262  req->error_code = 0x0000;
263  req->jiffies_start = jiffies;
264 }
265 
266 /*****************************************************************************/
267 
273 {
274  return req->issue_timeout
275  && jiffies - req->jiffies_start > HZ * req->issue_timeout / 1000;
276 }
277 
278 /*****************************************************************************
279  * Application interface.
280  ****************************************************************************/
281 
282 void ecrt_soe_request_idn(ec_soe_request_t *req, uint8_t drive_no,
283  uint16_t idn)
284 {
285  req->drive_no = drive_no;
286  req->idn = idn;
287 }
288 
289 /*****************************************************************************/
290 
291 void ecrt_soe_request_timeout(ec_soe_request_t *req, uint32_t timeout)
292 {
293  req->issue_timeout = timeout;
294 }
295 
296 /*****************************************************************************/
297 
299 {
300  return req->data;
301 }
302 
303 /*****************************************************************************/
304 
306 {
307  return req->data_size;
308 }
309 
310 /*****************************************************************************/
311 
313 {
315 }
316 
317 /*****************************************************************************/
318 
320 {
321  ec_soe_request_read(req);
322 }
323 
324 /*****************************************************************************/
325 
327 {
329 }
330 
331 /*****************************************************************************/
332 
335 EXPORT_SYMBOL(ecrt_soe_request_idn);
336 EXPORT_SYMBOL(ecrt_soe_request_timeout);
337 EXPORT_SYMBOL(ecrt_soe_request_data);
338 EXPORT_SYMBOL(ecrt_soe_request_data_size);
339 EXPORT_SYMBOL(ecrt_soe_request_state);
340 EXPORT_SYMBOL(ecrt_soe_request_read);
341 EXPORT_SYMBOL(ecrt_soe_request_write);
342 
345 /*****************************************************************************/
uint16_t error_code
SoE error code.
Definition: soe_request.h:64
void ec_soe_request_set_idn(ec_soe_request_t *req, uint16_t idn)
Set IDN.
Definition: soe_request.c:117
ec_direction_t dir
Direction.
Definition: soe_request.h:58
void ec_soe_request_read(ec_soe_request_t *req)
Request a read operation.
Definition: soe_request.c:242
uint8_t * ecrt_soe_request_data(ec_soe_request_t *req)
Access to the SoE request&#39;s data.
Definition: soe_request.c:298
size_t data_size
Size of SDO data.
Definition: soe_request.h:55
void ecrt_soe_request_idn(ec_soe_request_t *req, uint8_t drive_no, uint16_t idn)
Set the request&#39;s drive and Sercos ID numbers.
Definition: soe_request.c:282
ec_al_state_t al_state
AL state (only valid for IDN config).
Definition: soe_request.h:52
unsigned long jiffies_start
Jiffies, when the request was issued.
Definition: soe_request.h:61
int ec_soe_request_copy_data(ec_soe_request_t *req, const uint8_t *source, size_t size)
Copies SoE data from an external source.
Definition: soe_request.c:179
uint32_t issue_timeout
Maximum time in ms, the processing of the request may take.
Definition: soe_request.h:56
void ec_soe_request_set_drive_no(ec_soe_request_t *req, uint8_t drive_no)
Set drive number.
Definition: soe_request.c:105
struct list_head list
List item.
Definition: soe_request.h:49
void ec_soe_request_clear(ec_soe_request_t *req)
SoE request destructor.
Definition: soe_request.c:77
void ec_soe_request_clear_data(ec_soe_request_t *)
Free allocated memory.
Definition: soe_request.c:129
ec_request_state_t ecrt_soe_request_state(ec_soe_request_t *req)
Get the current state of the SoE request.
Definition: soe_request.c:312
Values read by the master.
Definition: ecrt.h:449
int ec_soe_request_append_data(ec_soe_request_t *req, const uint8_t *source, size_t size)
Copies SoE data from an external source.
Definition: soe_request.c:203
int ec_soe_request_alloc(ec_soe_request_t *req, size_t size)
Pre-allocates the data memory.
Definition: soe_request.c:150
Invalid direction.
Definition: ecrt.h:447
#define EC_ERR(fmt, args...)
Convenience macro for printing EtherCAT-specific errors to syslog.
Definition: globals.h:215
uint8_t drive_no
Drive number.
Definition: soe_request.h:50
void ecrt_soe_request_write(ec_soe_request_t *req)
Schedule an SoE IDN write operation.
Definition: soe_request.c:326
void ecrt_soe_request_read(ec_soe_request_t *req)
Schedule an SoE IDN read operation.
Definition: soe_request.c:319
EtherCAT SoE request structure.
int ec_soe_request_timed_out(const ec_soe_request_t *req)
Checks, if the timeout was exceeded.
Definition: soe_request.c:272
void ec_soe_request_write(ec_soe_request_t *req)
Request a write operation.
Definition: soe_request.c:256
void ec_soe_request_init(ec_soe_request_t *req)
SoE request constructor.
Definition: soe_request.c:54
void ecrt_soe_request_timeout(ec_soe_request_t *req, uint32_t timeout)
Set the timeout for an SoE request.
Definition: soe_request.c:291
ec_request_state_t
Request state.
Definition: ecrt.h:546
unsigned long jiffies_sent
Jiffies, when the upload/download request was sent.
Definition: soe_request.h:62
Values written by the master.
Definition: ecrt.h:448
Init.
Definition: ecrt.h:558
const ec_request_state_t ec_request_state_translation_table[]
Global request state type translation table.
Definition: module.c:662
size_t mem_size
Size of SDO data memory.
Definition: soe_request.h:54
size_t ecrt_soe_request_data_size(const ec_soe_request_t *req)
Returns the current IDN data size.
Definition: soe_request.c:305
uint16_t idn
Sercos ID-Number.
Definition: soe_request.h:51
ec_internal_request_state_t state
Request state.
Definition: soe_request.h:60
Sercos-over-EtherCAT request.
Definition: soe_request.h:48
uint8_t * data
Pointer to SDO data.
Definition: soe_request.h:53
int ec_soe_request_copy(ec_soe_request_t *req, const ec_soe_request_t *other)
Copy another SoE request.
Definition: soe_request.c:90