IgH EtherCAT Master  1.6.1
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  if (req->data_size + size > req->mem_size) {
204  size_t new_size = req->mem_size ? req->mem_size * 2 : size;
205  uint8_t *new_data = (uint8_t *) kmalloc(new_size, GFP_KERNEL);
206  if (!new_data) {
207  EC_ERR("Failed to allocate %zu bytes of SoE memory.\n",
208  new_size);
209  return -ENOMEM;
210  }
211  memcpy(new_data, req->data, req->data_size);
212  kfree(req->data);
213  req->data = new_data;
214  req->mem_size = new_size;
215  }
216 
217  memcpy(req->data + req->data_size, source, size);
218  req->data_size += size;
219  return 0;
220 }
221 
222 /****************************************************************************/
223 
227  ec_soe_request_t *req
228  )
229 {
230  req->dir = EC_DIR_INPUT;
231  req->state = EC_INT_REQUEST_QUEUED;
232  req->error_code = 0x0000;
233  req->jiffies_start = jiffies;
234  return 0;
235 }
236 
237 /****************************************************************************/
238 
242  ec_soe_request_t *req
243  )
244 {
245  req->dir = EC_DIR_OUTPUT;
246  req->state = EC_INT_REQUEST_QUEUED;
247  req->error_code = 0x0000;
248  req->jiffies_start = jiffies;
249  return 0;
250 }
251 
252 /****************************************************************************/
253 
259 {
260  return req->issue_timeout
261  && jiffies - req->jiffies_start > HZ * req->issue_timeout / 1000;
262 }
263 
264 /*****************************************************************************
265  * Application interface.
266  ****************************************************************************/
267 
268 int ecrt_soe_request_idn(ec_soe_request_t *req, uint8_t drive_no,
269  uint16_t idn)
270 {
271  req->drive_no = drive_no;
272  req->idn = idn;
273  return 0;
274 }
275 
276 /****************************************************************************/
277 
278 int ecrt_soe_request_timeout(ec_soe_request_t *req, uint32_t timeout)
279 {
280  req->issue_timeout = timeout;
281  return 0;
282 }
283 
284 /****************************************************************************/
285 
287 {
288  return req->data;
289 }
290 
291 /****************************************************************************/
292 
294 {
295  return req->data_size;
296 }
297 
298 /****************************************************************************/
299 
301 {
303 }
304 
305 /****************************************************************************/
306 
308 {
309  return ec_soe_request_read(req);
310 }
311 
312 /****************************************************************************/
313 
315 {
316  return ec_soe_request_write(req);
317 }
318 
319 /****************************************************************************/
320 
323 EXPORT_SYMBOL(ecrt_soe_request_idn);
324 EXPORT_SYMBOL(ecrt_soe_request_timeout);
325 EXPORT_SYMBOL(ecrt_soe_request_data);
326 EXPORT_SYMBOL(ecrt_soe_request_data_size);
327 EXPORT_SYMBOL(ecrt_soe_request_state);
328 EXPORT_SYMBOL(ecrt_soe_request_read);
329 EXPORT_SYMBOL(ecrt_soe_request_write);
330 
333 /****************************************************************************/
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:278
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:268
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:241
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:286
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:293
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:300
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:226
Invalid direction.
Definition: ecrt.h:505
#define EC_ERR(fmt, args...)
Convenience macro for printing EtherCAT-specific errors to syslog.
Definition: globals.h:224
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:307
int ec_soe_request_timed_out(const ec_soe_request_t *req)
Checks, if the timeout was exceeded.
Definition: soe_request.c:258
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:314
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