IgH EtherCAT Master  1.6.9
pdo_list.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
26
27/****************************************************************************/
28
29#include <linux/module.h>
30
31#include "globals.h"
32#include "pdo.h"
33#include "slave_config.h"
34#include "master.h"
35
36#include "pdo_list.h"
37
38/****************************************************************************/
39
43 ec_pdo_list_t *pl
44 )
45{
46 INIT_LIST_HEAD(&pl->list);
47}
48
49/****************************************************************************/
50
57
58/****************************************************************************/
59
63{
64 ec_pdo_t *pdo, *next;
65
66 list_for_each_entry_safe(pdo, next, &pl->list, list) {
67 list_del_init(&pdo->list);
68 ec_pdo_clear(pdo);
69 kfree(pdo);
70 }
71}
72
73/****************************************************************************/
74
80 const ec_pdo_list_t *pl
81 )
82{
83 unsigned int bit_size;
84 const ec_pdo_t *pdo;
85 const ec_pdo_entry_t *pdo_entry;
86 uint16_t byte_size;
87
88 bit_size = 0;
89 list_for_each_entry(pdo, &pl->list, list) {
90 list_for_each_entry(pdo_entry, &pdo->entries, list) {
91 bit_size += pdo_entry->bit_length;
92 }
93 }
94
95 if (bit_size % 8) // round up to full bytes
96 byte_size = bit_size / 8 + 1;
97 else
98 byte_size = bit_size / 8;
99
100 return byte_size;
101}
102
103/****************************************************************************/
104
110 ec_pdo_list_t *pl,
111 uint16_t index
112 )
113{
114 ec_pdo_t *pdo;
115
116 if (!(pdo = (ec_pdo_t *) kmalloc(sizeof(ec_pdo_t), GFP_KERNEL))) {
117 EC_ERR("Failed to allocate memory for PDO.\n");
118 return ERR_PTR(-ENOMEM);
119 }
120
121 ec_pdo_init(pdo);
122 pdo->index = index;
123 list_add_tail(&pdo->list, &pl->list);
124 return pdo;
125}
126
127/****************************************************************************/
128
134 ec_pdo_list_t *pl,
135 const ec_pdo_t *pdo
136 )
137{
138 ec_pdo_t *mapped_pdo;
139 int ret;
140
141 // PDO already mapped?
142 list_for_each_entry(mapped_pdo, &pl->list, list) {
143 if (mapped_pdo->index != pdo->index) continue;
144 EC_ERR("PDO 0x%04X is already mapped!\n", pdo->index);
145 return -EEXIST;
146 }
147
148 if (!(mapped_pdo = kmalloc(sizeof(ec_pdo_t), GFP_KERNEL))) {
149 EC_ERR("Failed to allocate PDO memory.\n");
150 return -ENOMEM;
151 }
152
153 ret = ec_pdo_init_copy(mapped_pdo, pdo);
154 if (ret < 0) {
155 kfree(mapped_pdo);
156 return ret;
157 }
158
159 list_add_tail(&mapped_pdo->list, &pl->list);
160 return 0;
161}
162
163/****************************************************************************/
164
170 ec_pdo_list_t *pl,
171 const ec_pdo_list_t *other
172 )
173{
174 ec_pdo_t *other_pdo;
175 int ret;
176
178
179 // PDO already mapped?
180 list_for_each_entry(other_pdo, &other->list, list) {
181 ret = ec_pdo_list_add_pdo_copy(pl, other_pdo);
182 if (ret)
183 return ret;
184 }
185
186 return 0;
187}
188
189/****************************************************************************/
190
200 const ec_pdo_list_t *pl1,
201 const ec_pdo_list_t *pl2
202 )
203{
204 const struct list_head *h1, *h2, *l1, *l2;
205 const ec_pdo_t *p1, *p2;
206
207 h1 = l1 = &pl1->list;
208 h2 = l2 = &pl2->list;
209
210 while (1) {
211 l1 = l1->next;
212 l2 = l2->next;
213
214 if ((l1 == h1) ^ (l2 == h2)) // unequal lengths
215 return 0;
216 if (l1 == h1) // both finished
217 break;
218
219 p1 = list_entry(l1, ec_pdo_t, list);
220 p2 = list_entry(l2, ec_pdo_t, list);
221
222 if (p1->index != p2->index)
223 return 0;
224 }
225
226 return 1;
227}
228
229/****************************************************************************/
230
236 const ec_pdo_list_t *pl,
237 uint16_t index
238 )
239{
240 ec_pdo_t *pdo;
241
242 list_for_each_entry(pdo, &pl->list, list) {
243 if (pdo->index != index)
244 continue;
245 return pdo;
246 }
247
248 return NULL;
249}
250
251/****************************************************************************/
252
258 const ec_pdo_list_t *pl,
259 uint16_t index
260 )
261{
262 const ec_pdo_t *pdo;
263
264 list_for_each_entry(pdo, &pl->list, list) {
265 if (pdo->index != index)
266 continue;
267 return pdo;
268 }
269
270 return NULL;
271}
272
273/****************************************************************************/
274
282 const ec_pdo_list_t *pl,
283 unsigned int pos
284 )
285{
286 const ec_pdo_t *pdo;
287
288 list_for_each_entry(pdo, &pl->list, list) {
289 if (pos--)
290 continue;
291 return pdo;
292 }
293
294 return NULL;
295}
296
297/****************************************************************************/
298
303unsigned int ec_pdo_list_count(
304 const ec_pdo_list_t *pl
305 )
306{
307 const ec_pdo_t *pdo;
308 unsigned int num = 0;
309
310 list_for_each_entry(pdo, &pl->list, list) {
311 num++;
312 }
313
314 return num;
315}
316
317/****************************************************************************/
318
322 const ec_pdo_list_t *pl
323 )
324{
325 const ec_pdo_t *pdo;
326
327 if (list_empty(&pl->list)) {
328 printk(KERN_CONT "(none)");
329 } else {
330 list_for_each_entry(pdo, &pl->list, list) {
331 printk(KERN_CONT "0x%04X", pdo->index);
332 if (pdo->list.next != &pl->list)
333 printk(KERN_CONT " ");
334 }
335 }
336}
337
338/****************************************************************************/
Global definitions and macros.
#define EC_ERR(fmt, args...)
Convenience macro for printing EtherCAT-specific errors to syslog.
Definition globals.h:224
EtherCAT master structure.
void ec_pdo_init(ec_pdo_t *pdo)
PDO constructor.
Definition pdo.c:38
void ec_pdo_clear(ec_pdo_t *pdo)
PDO destructor.
Definition pdo.c:86
int ec_pdo_init_copy(ec_pdo_t *pdo, const ec_pdo_t *other_pdo)
PDO copy constructor.
Definition pdo.c:54
EtherCAT Process data object structure.
ec_pdo_t * ec_pdo_list_add_pdo(ec_pdo_list_t *pl, uint16_t index)
Add a new PDO to the list.
Definition pdo_list.c:109
const ec_pdo_t * ec_pdo_list_find_pdo_const(const ec_pdo_list_t *pl, uint16_t index)
Finds a PDO with the given index and returns a const pointer.
Definition pdo_list.c:257
int ec_pdo_list_add_pdo_copy(ec_pdo_list_t *pl, const ec_pdo_t *pdo)
Add the copy of an existing PDO to the list.
Definition pdo_list.c:133
void ec_pdo_list_clear(ec_pdo_list_t *pl)
PDO list destructor.
Definition pdo_list.c:53
uint16_t ec_pdo_list_total_size(const ec_pdo_list_t *pl)
Calculates the total size of the mapped PDO entries.
Definition pdo_list.c:79
unsigned int ec_pdo_list_count(const ec_pdo_list_t *pl)
Get the number of PDOs in the list.
Definition pdo_list.c:303
void ec_pdo_list_print(const ec_pdo_list_t *pl)
Outputs the PDOs in the list.
Definition pdo_list.c:321
ec_pdo_t * ec_pdo_list_find_pdo(const ec_pdo_list_t *pl, uint16_t index)
Finds a PDO with the given index.
Definition pdo_list.c:235
int ec_pdo_list_equal(const ec_pdo_list_t *pl1, const ec_pdo_list_t *pl2)
Compares two PDO lists.
Definition pdo_list.c:199
void ec_pdo_list_init(ec_pdo_list_t *pl)
PDO list constructor.
Definition pdo_list.c:42
int ec_pdo_list_copy(ec_pdo_list_t *pl, const ec_pdo_list_t *other)
Makes a deep copy of another PDO list.
Definition pdo_list.c:169
const ec_pdo_t * ec_pdo_list_find_pdo_by_pos_const(const ec_pdo_list_t *pl, unsigned int pos)
Finds a PDO via its position in the list.
Definition pdo_list.c:281
void ec_pdo_list_clear_pdos(ec_pdo_list_t *pl)
Clears the list of mapped PDOs.
Definition pdo_list.c:62
EtherCAT PDO list structure.
EtherCAT slave configuration structure.
PDO entry description.
Definition pdo_entry.h:40
uint8_t bit_length
entry length in bit
Definition pdo_entry.h:45
EtherCAT PDO list.
Definition pdo_list.h:41
struct list_head list
List of PDOs.
Definition pdo_list.h:42
PDO description.
Definition pdo.h:41
struct list_head list
List item.
Definition pdo.h:42
struct list_head entries
List of PDO entries.
Definition pdo.h:46
uint16_t index
PDO index.
Definition pdo.h:43