IgH EtherCAT Master  1.5.3
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 
311 unsigned 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 /*****************************************************************************/
EtherCAT PDO list.
Definition: pdo_list.h:49
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
void ec_pdo_list_print(const ec_pdo_list_t *pl)
Outputs the PDOs in the list.
Definition: pdo_list.c:329
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
void ec_pdo_list_clear(ec_pdo_list_t *pl)
PDO list destructor.
Definition: pdo_list.c:61
struct list_head list
List of PDOs.
Definition: pdo_list.h:50
void ec_pdo_list_clear_pdos(ec_pdo_list_t *pl)
Clears the list of mapped PDOs.
Definition: pdo_list.c:70
void ec_pdo_init(ec_pdo_t *pdo)
PDO constructor.
Definition: pdo.c:46
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
Global definitions and macros.
PDO entry description.
Definition: pdo_entry.h:48
EtherCAT master structure.
void ec_pdo_clear(ec_pdo_t *pdo)
PDO destructor.
Definition: pdo.c:94
uint16_t index
PDO index.
Definition: pdo.h:51
EtherCAT PDO list structure.
int ec_pdo_init_copy(ec_pdo_t *pdo, const ec_pdo_t *other_pdo)
PDO copy constructor.
Definition: pdo.c:62
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
PDO description.
Definition: pdo.h:49
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
uint8_t bit_length
entry length in bit
Definition: pdo_entry.h:53
struct list_head entries
List of PDO entries.
Definition: pdo.h:54
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
#define EC_ERR(fmt, args...)
Convenience macro for printing EtherCAT-specific errors to syslog.
Definition: globals.h:215
void ec_pdo_list_init(ec_pdo_list_t *pl)
PDO list constructor.
Definition: pdo_list.c:50
EtherCAT slave configuration structure.
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
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
struct list_head list
List item.
Definition: pdo.h:50
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
EtherCAT Process data object structure.