IgH EtherCAT Master  1.5.2
pdo_list.c
Go to the documentation of this file.
1/******************************************************************************
2 *
3 * $Id$
4 *
5 * Copyright (C) 2006-2008 Florian Pose, Ingenieurgemeinschaft IgH
6 *
7 * This file is part of the IgH EtherCAT Master.
8 *
9 * The IgH EtherCAT Master is free software; you can redistribute it and/or
10 * modify it under the terms of the GNU General Public License version 2, as
11 * published by the Free Software Foundation.
12 *
13 * The IgH EtherCAT Master is distributed in the hope that it will be useful,
14 * but WITHOUT ANY WARRANTY; without even the implied warranty of
15 * MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the GNU General
16 * Public License for more details.
17 *
18 * You should have received a copy of the GNU General Public License along
19 * with the IgH EtherCAT Master; if not, write to the Free Software
20 * Foundation, Inc., 51 Franklin St, Fifth Floor, Boston, MA 02110-1301 USA
21 *
22 * ---
23 *
24 * The license mentioned above concerns the source code only. Using the
25 * EtherCAT technology and brand is only permitted in compliance with the
26 * industrial property and similar rights of Beckhoff Automation GmbH.
27 *
28 *****************************************************************************/
29
35/*****************************************************************************/
36
37#include <linux/module.h>
38
39#include "globals.h"
40#include "pdo.h"
41#include "slave_config.h"
42#include "master.h"
43
44#include "pdo_list.h"
45
46/*****************************************************************************/
47
51 ec_pdo_list_t *pl
52 )
53{
54 INIT_LIST_HEAD(&pl->list);
55}
56
57/*****************************************************************************/
58
62{
64}
65
66/*****************************************************************************/
67
71{
72 ec_pdo_t *pdo, *next;
73
74 list_for_each_entry_safe(pdo, next, &pl->list, list) {
75 list_del_init(&pdo->list);
76 ec_pdo_clear(pdo);
77 kfree(pdo);
78 }
79}
80
81/*****************************************************************************/
82
88 const ec_pdo_list_t *pl
89 )
90{
91 unsigned int bit_size;
92 const ec_pdo_t *pdo;
93 const ec_pdo_entry_t *pdo_entry;
94 uint16_t byte_size;
95
96 bit_size = 0;
97 list_for_each_entry(pdo, &pl->list, list) {
98 list_for_each_entry(pdo_entry, &pdo->entries, list) {
99 bit_size += pdo_entry->bit_length;
100 }
101 }
102
103 if (bit_size % 8) // round up to full bytes
104 byte_size = bit_size / 8 + 1;
105 else
106 byte_size = bit_size / 8;
107
108 return byte_size;
109}
110
111/*****************************************************************************/
112
118 ec_pdo_list_t *pl,
119 uint16_t index
120 )
121{
122 ec_pdo_t *pdo;
123
124 if (!(pdo = (ec_pdo_t *) kmalloc(sizeof(ec_pdo_t), GFP_KERNEL))) {
125 EC_ERR("Failed to allocate memory for PDO.\n");
126 return ERR_PTR(-ENOMEM);
127 }
128
129 ec_pdo_init(pdo);
130 pdo->index = index;
131 list_add_tail(&pdo->list, &pl->list);
132 return pdo;
133}
134
135/*****************************************************************************/
136
142 ec_pdo_list_t *pl,
143 const ec_pdo_t *pdo
144 )
145{
146 ec_pdo_t *mapped_pdo;
147 int ret;
148
149 // PDO already mapped?
150 list_for_each_entry(mapped_pdo, &pl->list, list) {
151 if (mapped_pdo->index != pdo->index) continue;
152 EC_ERR("PDO 0x%04X is already mapped!\n", pdo->index);
153 return -EEXIST;
154 }
155
156 if (!(mapped_pdo = kmalloc(sizeof(ec_pdo_t), GFP_KERNEL))) {
157 EC_ERR("Failed to allocate PDO memory.\n");
158 return -ENOMEM;
159 }
160
161 ret = ec_pdo_init_copy(mapped_pdo, pdo);
162 if (ret < 0) {
163 kfree(mapped_pdo);
164 return ret;
165 }
166
167 list_add_tail(&mapped_pdo->list, &pl->list);
168 return 0;
169}
170
171/*****************************************************************************/
172
178 ec_pdo_list_t *pl,
179 const ec_pdo_list_t *other
180 )
181{
182 ec_pdo_t *other_pdo;
183 int ret;
184
186
187 // PDO already mapped?
188 list_for_each_entry(other_pdo, &other->list, list) {
189 ret = ec_pdo_list_add_pdo_copy(pl, other_pdo);
190 if (ret)
191 return ret;
192 }
193
194 return 0;
195}
196
197/*****************************************************************************/
198
208 const ec_pdo_list_t *pl1,
209 const ec_pdo_list_t *pl2
210 )
211{
212 const struct list_head *h1, *h2, *l1, *l2;
213 const ec_pdo_t *p1, *p2;
214
215 h1 = l1 = &pl1->list;
216 h2 = l2 = &pl2->list;
217
218 while (1) {
219 l1 = l1->next;
220 l2 = l2->next;
221
222 if ((l1 == h1) ^ (l2 == h2)) // unequal lengths
223 return 0;
224 if (l1 == h1) // both finished
225 break;
226
227 p1 = list_entry(l1, ec_pdo_t, list);
228 p2 = list_entry(l2, ec_pdo_t, list);
229
230 if (p1->index != p2->index)
231 return 0;
232 }
233
234 return 1;
235}
236
237/*****************************************************************************/
238
244 const ec_pdo_list_t *pl,
245 uint16_t index
246 )
247{
248 ec_pdo_t *pdo;
249
250 list_for_each_entry(pdo, &pl->list, list) {
251 if (pdo->index != index)
252 continue;
253 return pdo;
254 }
255
256 return NULL;
257}
258
259/*****************************************************************************/
260
266 const ec_pdo_list_t *pl,
267 uint16_t index
268 )
269{
270 const ec_pdo_t *pdo;
271
272 list_for_each_entry(pdo, &pl->list, list) {
273 if (pdo->index != index)
274 continue;
275 return pdo;
276 }
277
278 return NULL;
279}
280
281/*****************************************************************************/
282
290 const ec_pdo_list_t *pl,
291 unsigned int pos
292 )
293{
294 const ec_pdo_t *pdo;
295
296 list_for_each_entry(pdo, &pl->list, list) {
297 if (pos--)
298 continue;
299 return pdo;
300 }
301
302 return NULL;
303}
304
305/*****************************************************************************/
306
311unsigned int ec_pdo_list_count(
312 const ec_pdo_list_t *pl
313 )
314{
315 const ec_pdo_t *pdo;
316 unsigned int num = 0;
317
318 list_for_each_entry(pdo, &pl->list, list) {
319 num++;
320 }
321
322 return num;
323}
324
325/*****************************************************************************/
326
330 const ec_pdo_list_t *pl
331 )
332{
333 const ec_pdo_t *pdo;
334
335 if (list_empty(&pl->list)) {
336 printk(KERN_CONT "(none)");
337 } else {
338 list_for_each_entry(pdo, &pl->list, list) {
339 printk(KERN_CONT "0x%04X", pdo->index);
340 if (pdo->list.next != &pl->list)
341 printk(KERN_CONT " ");
342 }
343 }
344}
345
346/*****************************************************************************/
Global definitions and macros.
#define EC_ERR(fmt, args...)
Convenience macro for printing EtherCAT-specific errors to syslog.
Definition: globals.h:215
EtherCAT master structure.
void ec_pdo_init(ec_pdo_t *pdo)
PDO constructor.
Definition: pdo.c:46
void ec_pdo_clear(ec_pdo_t *pdo)
PDO destructor.
Definition: pdo.c:94
int ec_pdo_init_copy(ec_pdo_t *pdo, const ec_pdo_t *other_pdo)
PDO copy constructor.
Definition: pdo.c:62
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:117
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:265
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:141
void ec_pdo_list_clear(ec_pdo_list_t *pl)
PDO list destructor.
Definition: pdo_list.c:61
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:87
unsigned int ec_pdo_list_count(const ec_pdo_list_t *pl)
Get the number of PDOs in the list.
Definition: pdo_list.c:311
void ec_pdo_list_print(const ec_pdo_list_t *pl)
Outputs the PDOs in the list.
Definition: pdo_list.c:329
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:243
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:207
void ec_pdo_list_init(ec_pdo_list_t *pl)
PDO list constructor.
Definition: pdo_list.c:50
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:177
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:289
void ec_pdo_list_clear_pdos(ec_pdo_list_t *pl)
Clears the list of mapped PDOs.
Definition: pdo_list.c:70
EtherCAT PDO list structure.
EtherCAT slave configuration structure.
PDO entry description.
Definition: pdo_entry.h:48
uint8_t bit_length
entry length in bit
Definition: pdo_entry.h:53
EtherCAT PDO list.
Definition: pdo_list.h:49
struct list_head list
List of PDOs.
Definition: pdo_list.h:50
PDO description.
Definition: pdo.h:49
struct list_head list
List item.
Definition: pdo.h:50
struct list_head entries
List of PDO entries.
Definition: pdo.h:54
uint16_t index
PDO index.
Definition: pdo.h:51