IgH EtherCAT Master  1.6.1
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 
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 
54 {
56 }
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 
303 unsigned 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 /****************************************************************************/
EtherCAT PDO list.
Definition: pdo_list.h:41
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
void ec_pdo_list_print(const ec_pdo_list_t *pl)
Outputs the PDOs in the list.
Definition: pdo_list.c:321
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
void ec_pdo_list_clear(ec_pdo_list_t *pl)
PDO list destructor.
Definition: pdo_list.c:53
struct list_head list
List of PDOs.
Definition: pdo_list.h:42
void ec_pdo_list_clear_pdos(ec_pdo_list_t *pl)
Clears the list of mapped PDOs.
Definition: pdo_list.c:62
void ec_pdo_init(ec_pdo_t *pdo)
PDO constructor.
Definition: pdo.c:38
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
Global definitions and macros.
PDO entry description.
Definition: pdo_entry.h:40
EtherCAT master structure.
void ec_pdo_clear(ec_pdo_t *pdo)
PDO destructor.
Definition: pdo.c:86
uint16_t index
PDO index.
Definition: pdo.h:43
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:54
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
PDO description.
Definition: pdo.h:41
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
uint8_t bit_length
entry length in bit
Definition: pdo_entry.h:45
struct list_head entries
List of PDO entries.
Definition: pdo.h:46
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
#define EC_ERR(fmt, args...)
Convenience macro for printing EtherCAT-specific errors to syslog.
Definition: globals.h:224
void ec_pdo_list_init(ec_pdo_list_t *pl)
PDO list constructor.
Definition: pdo_list.c:42
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:199
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
struct list_head list
List item.
Definition: pdo.h:42
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
EtherCAT Process data object structure.