52 int __init ec_init_module(void); |
52 int __init ec_init_module(void); |
53 void __exit ec_cleanup_module(void); |
53 void __exit ec_cleanup_module(void); |
54 |
54 |
55 /*****************************************************************************/ |
55 /*****************************************************************************/ |
56 |
56 |
57 static int ec_master_count = 1; /**< parameter value, number of masters */ |
57 static char *main; /**< main devices parameter */ |
58 static struct list_head ec_masters; /**< list of masters */ |
58 static char *backup; /**< backup devices parameter */ |
|
59 |
|
60 static LIST_HEAD(main_device_ids); /**< list of main device IDs */ |
|
61 static LIST_HEAD(backup_device_ids); /**< list of main device IDs */ |
|
62 static LIST_HEAD(masters); /**< list of masters */ |
59 static dev_t device_number; /**< XML character device number */ |
63 static dev_t device_number; /**< XML character device number */ |
60 ec_xmldev_t xmldev; /**< XML character device */ |
64 ec_xmldev_t xmldev; /**< XML character device */ |
61 |
65 |
62 char *ec_master_version_str = EC_MASTER_VERSION; |
66 char *ec_master_version_str = EC_MASTER_VERSION; |
63 |
67 |
64 /*****************************************************************************/ |
68 /*****************************************************************************/ |
65 |
69 |
66 /** \cond */ |
70 /** \cond */ |
67 |
|
68 module_param(ec_master_count, int, S_IRUGO); |
|
69 |
71 |
70 MODULE_AUTHOR("Florian Pose <fp@igh-essen.com>"); |
72 MODULE_AUTHOR("Florian Pose <fp@igh-essen.com>"); |
71 MODULE_DESCRIPTION("EtherCAT master driver module"); |
73 MODULE_DESCRIPTION("EtherCAT master driver module"); |
72 MODULE_LICENSE("GPL"); |
74 MODULE_LICENSE("GPL"); |
73 MODULE_VERSION(EC_MASTER_VERSION); |
75 MODULE_VERSION(EC_MASTER_VERSION); |
74 MODULE_PARM_DESC(ec_master_count, "number of EtherCAT masters to initialize"); |
76 |
|
77 module_param(main, charp, S_IRUGO); |
|
78 MODULE_PARM_DESC(main, "main device IDs"); |
|
79 module_param(backup, charp, S_IRUGO); |
|
80 MODULE_PARM_DESC(backup, "backup device IDs"); |
75 |
81 |
76 /** \endcond */ |
82 /** \endcond */ |
|
83 |
|
84 /*****************************************************************************/ |
|
85 |
|
86 void clear_device_ids(struct list_head *device_ids) |
|
87 { |
|
88 ec_device_id_t *dev_id, *next_dev_id; |
|
89 |
|
90 list_for_each_entry_safe(dev_id, next_dev_id, device_ids, list) { |
|
91 list_del(&dev_id->list); |
|
92 kfree(dev_id); |
|
93 } |
|
94 } |
|
95 |
|
96 /*****************************************************************************/ |
|
97 |
|
98 static int parse_device_id_mac(ec_device_id_t *dev_id, |
|
99 const char *src, const char **remainder) |
|
100 { |
|
101 unsigned int i, value; |
|
102 char *rem; |
|
103 |
|
104 for (i = 0; i < ETH_ALEN; i++) { |
|
105 value = simple_strtoul(src, &rem, 16); |
|
106 if (rem != src + 2 |
|
107 || value > 0xFF |
|
108 || (i < ETH_ALEN - 1 && *rem != ':')) { |
|
109 return -1; |
|
110 } |
|
111 dev_id->octets[i] = value; |
|
112 if (i < ETH_ALEN - 1) |
|
113 src = rem + 1; |
|
114 } |
|
115 |
|
116 dev_id->type = ec_device_id_mac; |
|
117 *remainder = rem; |
|
118 return 0; |
|
119 } |
|
120 |
|
121 /*****************************************************************************/ |
|
122 |
|
123 static int parse_device_ids(struct list_head *device_ids, const char *src) |
|
124 { |
|
125 const char *rem; |
|
126 ec_device_id_t *dev_id; |
|
127 unsigned int index = 0; |
|
128 |
|
129 while (*src) { |
|
130 // allocate new device ID |
|
131 if (!(dev_id = kmalloc(sizeof(ec_device_id_t), GFP_KERNEL))) { |
|
132 EC_ERR("Out of memory!\n"); |
|
133 goto out_free; |
|
134 } |
|
135 |
|
136 if (*src == ';') { // empty device ID |
|
137 dev_id->type = ec_device_id_empty; |
|
138 } |
|
139 else if (*src == 'M') { |
|
140 src++; |
|
141 if (parse_device_id_mac(dev_id, src, &rem)) { |
|
142 EC_ERR("Device ID %u: Invalid MAC syntax!\n", index); |
|
143 kfree(dev_id); |
|
144 goto out_free; |
|
145 } |
|
146 src = rem; |
|
147 } |
|
148 else { |
|
149 EC_ERR("Device ID %u: Unknown format \'%c\'!\n", index, *src); |
|
150 kfree(dev_id); |
|
151 goto out_free; |
|
152 } |
|
153 |
|
154 list_add_tail(&dev_id->list, device_ids); |
|
155 if (*src) { |
|
156 if (*src != ';') { |
|
157 EC_ERR("Invalid delimiter '%c' after device ID %i!\n", |
|
158 *src, index); |
|
159 goto out_free; |
|
160 } |
|
161 src++; // skip delimiter |
|
162 } |
|
163 index++; |
|
164 } |
|
165 |
|
166 return 0; |
|
167 |
|
168 out_free: |
|
169 clear_device_ids(device_ids); |
|
170 return -1; |
|
171 } |
|
172 |
|
173 /*****************************************************************************/ |
|
174 |
|
175 static int create_device_ids(void) |
|
176 { |
|
177 ec_device_id_t *id; |
|
178 unsigned int main_count = 0, backup_count = 0; |
|
179 |
|
180 if (parse_device_ids(&main_device_ids, main)) |
|
181 return -1; |
|
182 |
|
183 if (parse_device_ids(&backup_device_ids, main)) |
|
184 return -1; |
|
185 |
|
186 // count main device IDs and check for empty ones |
|
187 list_for_each_entry(id, &main_device_ids, list) { |
|
188 if (id->type == ec_device_id_empty) { |
|
189 EC_ERR("Main device IDs may not be empty!\n"); |
|
190 return -1; |
|
191 } |
|
192 main_count++; |
|
193 } |
|
194 |
|
195 // count backup device IDs |
|
196 list_for_each_entry(id, &backup_device_ids, list) { |
|
197 backup_count++; |
|
198 } |
|
199 |
|
200 // fill up backup device IDs |
|
201 while (backup_count < main_count) { |
|
202 if (!(id = kmalloc(sizeof(ec_device_id_t), GFP_KERNEL))) { |
|
203 EC_ERR("Out of memory!\n"); |
|
204 return -1; |
|
205 } |
|
206 |
|
207 id->type = ec_device_id_empty; |
|
208 list_add_tail(&id->list, &backup_device_ids); |
|
209 backup_count++; |
|
210 } |
|
211 |
|
212 return 0; |
|
213 } |
|
214 |
|
215 /*****************************************************************************/ |
|
216 |
|
217 static int device_id_check(const ec_device_id_t *dev_id, |
|
218 const struct net_device *dev, const char *driver_name, |
|
219 unsigned int device_index) |
|
220 { |
|
221 unsigned int i; |
|
222 |
|
223 switch (dev_id->type) { |
|
224 case ec_device_id_mac: |
|
225 for (i = 0; i < ETH_ALEN; i++) |
|
226 if (dev->dev_addr[i] != dev_id->octets[i]) |
|
227 return 0; |
|
228 return 1; |
|
229 default: |
|
230 return 0; |
|
231 } |
|
232 } |
|
233 |
77 |
234 |
78 /*****************************************************************************/ |
235 /*****************************************************************************/ |
79 |
236 |
80 /** |
237 /** |
81 Module initialization. |
238 Module initialization. |
83 \return 0 on success, else < 0 |
240 \return 0 on success, else < 0 |
84 */ |
241 */ |
85 |
242 |
86 int __init ec_init_module(void) |
243 int __init ec_init_module(void) |
87 { |
244 { |
88 unsigned int i; |
|
89 ec_master_t *master, *next; |
245 ec_master_t *master, *next; |
|
246 ec_device_id_t *main_dev_id, *backup_dev_id; |
|
247 unsigned int master_index = 0; |
90 |
248 |
91 EC_INFO("Master driver %s\n", EC_MASTER_VERSION); |
249 EC_INFO("Master driver %s\n", EC_MASTER_VERSION); |
92 |
250 |
93 if (ec_master_count < 1) { |
251 if (alloc_chrdev_region(&device_number, 0, 1, "EtherCAT")) { |
94 EC_ERR("Invalid ec_master_count: %i\n", ec_master_count); |
252 EC_ERR("Failed to obtain device number!\n"); |
95 goto out_return; |
253 goto out_return; |
96 } |
254 } |
97 |
255 |
98 if (alloc_chrdev_region(&device_number, 0, ec_master_count, "EtherCAT")) { |
256 if (create_device_ids()) |
99 EC_ERR("Failed to allocate device number!\n"); |
257 goto out_free_ids; |
100 goto out_return; |
258 |
101 } |
259 if (!list_empty(&main_device_ids)) { |
102 |
260 main_dev_id = |
103 EC_INFO("Initializing %i EtherCAT master(s)...\n", ec_master_count); |
261 list_entry(main_device_ids.next, ec_device_id_t, list); |
104 |
262 backup_dev_id = |
105 INIT_LIST_HEAD(&ec_masters); |
263 list_entry(backup_device_ids.next, ec_device_id_t, list); |
106 |
264 |
107 for (i = 0; i < ec_master_count; i++) { |
265 while (1) { |
108 if (!(master = |
266 if (!(master = (ec_master_t *) |
109 (ec_master_t *) kmalloc(sizeof(ec_master_t), GFP_KERNEL))) { |
267 kmalloc(sizeof(ec_master_t), GFP_KERNEL))) { |
110 EC_ERR("Failed to allocate memory for EtherCAT master %i.\n", i); |
268 EC_ERR("Failed to allocate memory for EtherCAT master %i.\n", |
111 goto out_free; |
269 master_index); |
112 } |
270 goto out_free_masters; |
113 |
271 } |
114 if (ec_master_init(master, i, 0)) |
272 |
115 goto out_free; |
273 if (ec_master_init(master, master_index, |
116 |
274 main_dev_id, backup_dev_id, 0)) |
117 list_add_tail(&master->list, &ec_masters); |
275 goto out_free_masters; |
118 } |
276 |
119 |
277 list_add_tail(&master->list, &masters); |
120 EC_INFO("Master driver initialized.\n"); |
278 master_index++; |
|
279 |
|
280 // last device IDs? |
|
281 if (main_dev_id->list.next == &main_device_ids) |
|
282 break; |
|
283 |
|
284 // next device IDs |
|
285 main_dev_id = |
|
286 list_entry(main_dev_id->list.next, ec_device_id_t, list); |
|
287 backup_dev_id = |
|
288 list_entry(backup_dev_id->list.next, ec_device_id_t, list); |
|
289 } |
|
290 } |
|
291 |
|
292 EC_INFO("%u master%s waiting for devices.\n", |
|
293 master_index, (master_index == 1 ? "" : "s")); |
121 return 0; |
294 return 0; |
122 |
295 |
123 out_free: |
296 out_free_masters: |
124 list_for_each_entry_safe(master, next, &ec_masters, list) { |
297 list_for_each_entry_safe(master, next, &masters, list) { |
125 list_del(&master->list); |
298 list_del(&master->list); |
126 kobject_del(&master->kobj); |
299 kobject_del(&master->kobj); |
127 kobject_put(&master->kobj); |
300 kobject_put(&master->kobj); |
128 } |
301 } |
129 out_return: |
302 out_free_ids: |
|
303 clear_device_ids(&main_device_ids); |
|
304 clear_device_ids(&backup_device_ids); |
|
305 unregister_chrdev_region(device_number, 1); |
|
306 out_return: |
130 return -1; |
307 return -1; |
131 } |
308 } |
132 |
309 |
133 /*****************************************************************************/ |
310 /*****************************************************************************/ |
134 |
311 |
268 /****************************************************************************** |
445 /****************************************************************************** |
269 * Device interface |
446 * Device interface |
270 *****************************************************************************/ |
447 *****************************************************************************/ |
271 |
448 |
272 /** |
449 /** |
273 Connects an EtherCAT device to a certain master. |
450 Offers an EtherCAT device to a certain master. |
274 The master will use the device for sending and receiving frames. It is |
451 The master decides, if it wants to use the device for EtherCAT operation, |
275 required that no other instance (for example the kernel IP stack) uses |
452 or not. It is important, that the offered net_device is not used by |
276 the device. |
453 the kernel IP stack. If the master, accepted the offer, the address of |
|
454 the newly created EtherCAT device is written to the ecdev pointer, else |
|
455 the pointer is written to zero. |
277 \return 0 on success, else < 0 |
456 \return 0 on success, else < 0 |
278 \ingroup DeviceInterface |
457 \ingroup DeviceInterface |
279 */ |
458 */ |
280 |
459 |
281 ec_device_t *ecdev_register(unsigned int master_index, /**< master index */ |
460 int ecdev_offer(struct net_device *net_dev, /**< net_device to offer */ |
282 struct net_device *net_dev, /**< net_device of |
461 ec_device_t **ecdev, /**< pointer to store a device on success */ |
283 the device */ |
462 const char *driver_name, /**< name of the network driver */ |
284 ec_pollfunc_t poll, /**< device poll function */ |
463 unsigned int device_index, /**< index of the supported device */ |
285 struct module *module /**< pointer to the module */ |
464 ec_pollfunc_t poll, /**< device poll function */ |
286 ) |
465 struct module *module /**< pointer to the module */ |
|
466 ) |
287 { |
467 { |
288 ec_master_t *master; |
468 ec_master_t *master; |
289 |
469 unsigned int i; |
290 if (!(master = ec_find_master(master_index))) return NULL; |
470 |
291 |
471 list_for_each_entry(master, &masters, list) { |
292 if (down_interruptible(&master->device_sem)) { |
472 if (down_interruptible(&master->device_sem)) { |
293 EC_ERR("Interrupted while waiting for device!\n"); |
473 EC_ERR("Interrupted while waiting for device semaphore!\n"); |
294 goto out_return; |
474 goto out_return; |
295 } |
475 } |
296 |
476 |
297 if (master->device) { |
477 if (device_id_check(master->main_device_id, net_dev, |
298 EC_ERR("Master %i already has a device!\n", master_index); |
478 driver_name, device_index)) { |
299 goto out_up; |
479 |
300 } |
480 EC_INFO("Accepting device %s:%u (", driver_name, device_index); |
301 |
481 for (i = 0; i < ETH_ALEN; i++) { |
302 if (!(master->device = |
482 printk("%02X", net_dev->dev_addr[i]); |
303 (ec_device_t *) kmalloc(sizeof(ec_device_t), GFP_KERNEL))) { |
483 if (i < ETH_ALEN - 1) printk(":"); |
304 EC_ERR("Failed to allocate device!\n"); |
484 } |
305 goto out_up; |
485 printk(") for master %u.\n", master->index); |
306 } |
486 |
307 |
487 if (master->device) { |
308 if (ec_device_init(master->device, master, net_dev, poll, module)) { |
488 EC_ERR("Master already has a device.\n"); |
309 EC_ERR("Failed to init device!\n"); |
489 goto out_up; |
310 goto out_free; |
490 } |
311 } |
491 |
312 |
492 if (!(master->device = (ec_device_t *) |
313 up(&master->device_sem); |
493 kmalloc(sizeof(ec_device_t), GFP_KERNEL))) { |
314 return master->device; |
494 EC_ERR("Failed to allocate device!\n"); |
|
495 goto out_up; |
|
496 } |
|
497 |
|
498 if (ec_device_init(master->device, master, |
|
499 net_dev, poll, module)) { |
|
500 EC_ERR("Failed to init device!\n"); |
|
501 goto out_free; |
|
502 } |
|
503 |
|
504 up(&master->device_sem); |
|
505 sprintf(net_dev->name, "ec%u", master->index); |
|
506 *ecdev = master->device; // offer accepted |
|
507 return 0; // no error |
|
508 } |
|
509 |
|
510 up(&master->device_sem); |
|
511 } |
|
512 |
|
513 *ecdev = NULL; // offer declined |
|
514 return 0; // no error |
315 |
515 |
316 out_free: |
516 out_free: |
317 kfree(master->device); |
517 kfree(master->device); |
318 master->device = NULL; |
518 master->device = NULL; |
319 out_up: |
519 out_up: |
320 up(&master->device_sem); |
520 up(&master->device_sem); |
321 out_return: |
521 out_return: |
322 return NULL; |
522 return 1; |
323 } |
523 } |
324 |
524 |
325 /*****************************************************************************/ |
525 /*****************************************************************************/ |
326 |
526 |
327 /** |
527 /** |
328 Disconnect an EtherCAT device from the master. |
528 Withdraws an EtherCAT device from the master. |
329 The device is disconnected from the master and all device ressources |
529 The device is disconnected from the master and all device ressources |
330 are freed. |
530 are freed. |
331 \attention Before calling this function, the ecdev_stop() function has |
531 \attention Before calling this function, the ecdev_stop() function has |
332 to be called, to be sure that the master does not use the device any more. |
532 to be called, to be sure that the master does not use the device any more. |
333 \ingroup DeviceInterface |
533 \ingroup DeviceInterface |
334 */ |
534 */ |
335 |
535 |
336 void ecdev_unregister(unsigned int master_index, /**< master index */ |
536 void ecdev_withdraw(ec_device_t *device /**< EtherCAT device */) |
337 ec_device_t *device /**< EtherCAT device */ |
537 { |
338 ) |
538 ec_master_t *master = device->master; |
339 { |
539 unsigned int i; |
340 ec_master_t *master; |
|
341 |
|
342 if (!(master = ec_find_master(master_index))) return; |
|
343 |
540 |
344 down(&master->device_sem); |
541 down(&master->device_sem); |
345 |
542 |
346 if (!master->device || master->device != device) { |
543 EC_INFO("Master %u releasing device ", master->index); |
347 up(&master->device_sem); |
544 for (i = 0; i < ETH_ALEN; i++) { |
348 EC_WARN("Unable to unregister device!\n"); |
545 printk("%02X", device->dev->dev_addr[i]); |
349 return; |
546 if (i < ETH_ALEN - 1) printk(":"); |
350 } |
547 } |
351 |
548 printk(".\n"); |
|
549 |
352 ec_device_clear(master->device); |
550 ec_device_clear(master->device); |
353 kfree(master->device); |
551 kfree(master->device); |
354 master->device = NULL; |
552 master->device = NULL; |
355 |
553 |
356 up(&master->device_sem); |
554 up(&master->device_sem); |
357 } |
555 } |
358 |
556 |
359 /*****************************************************************************/ |
557 /*****************************************************************************/ |
360 |
558 |