IgH EtherCAT Master  1.6.10
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 
26 /****************************************************************************/
27 
28 #include <linux/module.h>
29 #include <linux/jiffies.h>
30 #include <linux/slab.h>
31 
32 #include "soe_request.h"
33 
34 /****************************************************************************/
35 
38 #define EC_SOE_REQUEST_RESPONSE_TIMEOUT 1000
39 
40 /****************************************************************************/
41 
43 
44 /****************************************************************************/
45 
49  ec_soe_request_t *req
50  )
51 {
52  INIT_LIST_HEAD(&req->list);
53  req->drive_no = 0x00;
54  req->idn = 0x0000;
56  req->data = NULL;
57  req->mem_size = 0;
58  req->data_size = 0;
59  req->issue_timeout = 0; // no timeout
60  req->dir = EC_DIR_INVALID;
61  req->state = EC_INT_REQUEST_INIT;
62  req->jiffies_start = 0U;
63  req->jiffies_sent = 0U;
64  req->error_code = 0x0000;
65 }
66 
67 /****************************************************************************/
68 
72  ec_soe_request_t *req
73  )
74 {
76 }
77 
78 /****************************************************************************/
79 
85  ec_soe_request_t *req,
86  const ec_soe_request_t *other
87  )
88 {
89  req->drive_no = other->drive_no;
90  req->idn = other->idn;
91  req->al_state = other->al_state;
92  return ec_soe_request_copy_data(req, other->data, other->data_size);
93 }
94 
95 /****************************************************************************/
96 
100  ec_soe_request_t *req,
101  uint8_t drive_no
102  )
103 {
104  req->drive_no = drive_no;
105 }
106 
107 /****************************************************************************/
108 
112  ec_soe_request_t *req,
113  uint16_t idn
114  )
115 {
116  req->idn = idn;
117 }
118 
119 /****************************************************************************/
120 
124  ec_soe_request_t *req
125  )
126 {
127  if (req->data) {
128  kfree(req->data);
129  req->data = NULL;
130  }
131 
132  req->mem_size = 0;
133  req->data_size = 0;
134 }
135 
136 /****************************************************************************/
137 
145  ec_soe_request_t *req,
146  size_t size
147  )
148 {
149  if (size <= req->mem_size)
150  return 0;
151 
153 
154  if (!(req->data = (uint8_t *) kmalloc(size, GFP_KERNEL))) {
155  EC_ERR("Failed to allocate %zu bytes of SoE memory.\n", size);
156  return -ENOMEM;
157  }
158 
159  req->mem_size = size;
160  req->data_size = 0;
161  return 0;
162 }
163 
164 /****************************************************************************/
165 
174  ec_soe_request_t *req,
175  const uint8_t *source,
176  size_t size
177  )
178 {
179  int ret = ec_soe_request_alloc(req, size);
180  if (ret < 0)
181  return ret;
182 
183  memcpy(req->data, source, size);
184  req->data_size = size;
185  return 0;
186 }
187 
188 /****************************************************************************/
189 
198  ec_soe_request_t *req,
199  const uint8_t *source,
200  size_t size
201  )
202 {
203  size_t new_total_size = req->data_size + size;
204 
205  if (new_total_size > req->mem_size) {
206  size_t new_size;
207  if (req->mem_size * 2 >= new_total_size) {
208  // just double it to reduce the number of re-allocations
209  new_size = req->mem_size * 2;
210  }
211  else {
212  new_size = new_total_size;
213  }
214 
215  uint8_t *new_data = (uint8_t *) kmalloc(new_size, GFP_KERNEL);
216  if (!new_data) {
217  EC_ERR("Failed to allocate %zu bytes of SoE memory.\n",
218  new_size);
219  return -ENOMEM;
220  }
221  memcpy(new_data, req->data, req->data_size);
222  kfree(req->data);
223  req->data = new_data;
224  req->mem_size = new_size;
225  }
226 
227  memcpy(req->data + req->data_size, source, size);
228  req->data_size = new_total_size;
229  return 0;
230 }
231 
232 /****************************************************************************/
233 
237  ec_soe_request_t *req
238  )
239 {
240  req->dir = EC_DIR_INPUT;
241  req->state = EC_INT_REQUEST_QUEUED;
242  req->error_code = 0x0000;
243  req->jiffies_start = jiffies;
244  return 0;
245 }
246 
247 /****************************************************************************/
248 
252  ec_soe_request_t *req
253  )
254 {
255  req->dir = EC_DIR_OUTPUT;
256  req->state = EC_INT_REQUEST_QUEUED;
257  req->error_code = 0x0000;
258  req->jiffies_start = jiffies;
259  return 0;
260 }
261 
262 /****************************************************************************/
263 
269 {
270  return req->issue_timeout
271  && jiffies - req->jiffies_start > HZ * req->issue_timeout / 1000;
272 }
273 
274 /*****************************************************************************
275  * Application interface.
276  ****************************************************************************/
277 
278 int ecrt_soe_request_idn(ec_soe_request_t *req, uint8_t drive_no,
279  uint16_t idn)
280 {
281  req->drive_no = drive_no;
282  req->idn = idn;
283  return 0;
284 }
285 
286 /****************************************************************************/
287 
288 int ecrt_soe_request_timeout(ec_soe_request_t *req, uint32_t timeout)
289 {
290  req->issue_timeout = timeout;
291  return 0;
292 }
293 
294 /****************************************************************************/
295 
297 {
298  return req->data;
299 }
300 
301 /****************************************************************************/
302 
304 {
305  return req->data_size;
306 }
307 
308 /****************************************************************************/
309 
311 {
313 }
314 
315 /****************************************************************************/
316 
318 {
319  return ec_soe_request_read(req);
320 }
321 
322 /****************************************************************************/
323 
325 {
326  return ec_soe_request_write(req);
327 }
328 
329 /****************************************************************************/
330 
333 EXPORT_SYMBOL(ecrt_soe_request_idn);
334 EXPORT_SYMBOL(ecrt_soe_request_timeout);
335 EXPORT_SYMBOL(ecrt_soe_request_data);
336 EXPORT_SYMBOL(ecrt_soe_request_data_size);
337 EXPORT_SYMBOL(ecrt_soe_request_state);
338 EXPORT_SYMBOL(ecrt_soe_request_read);
339 EXPORT_SYMBOL(ecrt_soe_request_write);
340 
343 /****************************************************************************/
uint16_t error_code
SoE error code.
Definition: soe_request.h:56
void ec_soe_request_set_idn(ec_soe_request_t *req, uint16_t idn)
Set IDN.
Definition: soe_request.c:111
int ecrt_soe_request_timeout(ec_soe_request_t *req, uint32_t timeout)
Set the timeout for an SoE request.
Definition: soe_request.c:288
ec_direction_t dir
Direction.
Definition: soe_request.h:50
int 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:278
size_t data_size
Size of SDO data.
Definition: soe_request.h:47
int ec_soe_request_write(ec_soe_request_t *req)
Request a write operation.
Definition: soe_request.c:251
ec_al_state_t al_state
AL state (only valid for IDN config).
Definition: soe_request.h:44
unsigned long jiffies_start
Jiffies, when the request was issued.
Definition: soe_request.h:53
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:173
uint32_t issue_timeout
Maximum time in ms, the processing of the request may take.
Definition: soe_request.h:48
uint8_t * ecrt_soe_request_data(const ec_soe_request_t *req)
Access to the SoE request&#39;s data.
Definition: soe_request.c:296
void ec_soe_request_set_drive_no(ec_soe_request_t *req, uint8_t drive_no)
Set drive number.
Definition: soe_request.c:99
struct list_head list
List item.
Definition: soe_request.h:41
void ec_soe_request_clear(ec_soe_request_t *req)
SoE request destructor.
Definition: soe_request.c:71
void ec_soe_request_clear_data(ec_soe_request_t *)
Free allocated memory.
Definition: soe_request.c:123
size_t ecrt_soe_request_data_size(const ec_soe_request_t *req)
Returns the current IDN data size.
Definition: soe_request.c:303
ec_request_state_t ecrt_soe_request_state(const ec_soe_request_t *req)
Get the current state of the SoE request.
Definition: soe_request.c:310
Values read by the master.
Definition: ecrt.h:507
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:197
int ec_soe_request_alloc(ec_soe_request_t *req, size_t size)
Pre-allocates the data memory.
Definition: soe_request.c:144
int ec_soe_request_read(ec_soe_request_t *req)
Request a read operation.
Definition: soe_request.c:236
Invalid direction.
Definition: ecrt.h:505
#define EC_ERR(fmt, args...)
Convenience macro for printing EtherCAT-specific errors to syslog.
Definition: globals.h:223
uint8_t drive_no
Drive number.
Definition: soe_request.h:42
EtherCAT SoE request structure.
int ecrt_soe_request_read(ec_soe_request_t *req)
Schedule an SoE IDN read operation.
Definition: soe_request.c:317
int ec_soe_request_timed_out(const ec_soe_request_t *req)
Checks, if the timeout was exceeded.
Definition: soe_request.c:268
void ec_soe_request_init(ec_soe_request_t *req)
SoE request constructor.
Definition: soe_request.c:48
ec_request_state_t
Request state.
Definition: ecrt.h:604
unsigned long jiffies_sent
Jiffies, when the upload/download request was sent.
Definition: soe_request.h:54
Values written by the master.
Definition: ecrt.h:506
Init.
Definition: ecrt.h:616
int ecrt_soe_request_write(ec_soe_request_t *req)
Schedule an SoE IDN write operation.
Definition: soe_request.c:324
const ec_request_state_t ec_request_state_translation_table[]
Global request state type translation table.
Definition: module.c:658
size_t mem_size
Size of SDO data memory.
Definition: soe_request.h:46
uint16_t idn
Sercos ID-Number.
Definition: soe_request.h:43
ec_internal_request_state_t state
Request state.
Definition: soe_request.h:52
Sercos-over-EtherCAT request.
Definition: soe_request.h:40
uint8_t * data
Pointer to SDO data.
Definition: soe_request.h:45
int ec_soe_request_copy(ec_soe_request_t *req, const ec_soe_request_t *other)
Copy another SoE request.
Definition: soe_request.c:84