3 * $Id$ |
3 * $Id$ |
4 * |
4 * |
5 * ec_rtdm.c Copyright (C) 2009-2010 Moehwald GmbH B.Benner |
5 * ec_rtdm.c Copyright (C) 2009-2010 Moehwald GmbH B.Benner |
6 * 2011 IgH Andreas Stewering-Bone |
6 * 2011 IgH Andreas Stewering-Bone |
7 * |
7 * |
8 * This file is used for Prisma RT to interface to EtherCAT devices |
|
9 * |
8 * |
10 * This file is part of ethercatrtdm interface to IgH EtherCAT master |
9 * This file is part of the IgH EtherCAT master |
11 * |
10 * |
12 * The Moehwald ec_rtdm interface is free software; you can |
11 * The IgH EtherCAT master is free software; you can |
13 * redistribute it and/or modify it under the terms of the GNU Lesser General |
12 * redistribute it and/or modify it under the terms of the GNU Lesser General |
14 * Public License as published by the Free Software Foundation; version 2.1 |
13 * Public License as published by the Free Software Foundation; version 2.1 |
15 * of the License. |
14 * of the License. |
16 * |
15 * |
17 * The IgH EtherCAT master userspace library is distributed in the hope that |
16 * The IgH EtherCAT master userspace library is distributed in the hope that |
41 #include "../include/ec_rtdm.h" |
40 #include "../include/ec_rtdm.h" |
42 |
41 |
43 #define EC_RTDM_MAX_MASTERS 5 /**< Maximum number of masters. */ |
42 #define EC_RTDM_MAX_MASTERS 5 /**< Maximum number of masters. */ |
44 |
43 |
45 #define EC_RTDM_GINFO(fmt, args...) \ |
44 #define EC_RTDM_GINFO(fmt, args...) \ |
46 printk(KERN_INFO "EtherCATrtdm: " fmt, ##args) |
45 rtdm_printk(KERN_INFO "EtherCATrtdm: " fmt, ##args) |
47 |
46 |
48 #define EC_RTDM_GERR(fmt, args...) \ |
47 #define EC_RTDM_GERR(fmt, args...) \ |
49 printk(KERN_ERR "EtherCATrtdm ERROR: " fmt, ##args) |
48 rtdm_printk(KERN_ERR "EtherCATrtdm ERROR: " fmt, ##args) |
50 |
49 |
51 #define EC_RTDM_GWARN(fmt, args...) \ |
50 #define EC_RTDM_GWARN(fmt, args...) \ |
52 printk(KERN_WARNING "EtherCATrtdm WARNING: " fmt, ##args) |
51 rtdm_printk(KERN_WARNING "EtherCATrtdm WARNING: " fmt, ##args) |
53 |
52 |
54 |
53 |
55 #define EC_RTDM_INFO(devno, fmt, args...) \ |
54 #define EC_RTDM_INFO(devno, fmt, args...) \ |
56 printk(KERN_INFO "EtherCATrtdm %u: " fmt, devno, ##args) |
55 rtdm_printk(KERN_INFO "EtherCATrtdm %u: " fmt, devno, ##args) |
57 |
56 |
58 #define EC_RTDM_ERR(devno, fmt, args...) \ |
57 #define EC_RTDM_ERR(devno, fmt, args...) \ |
59 printk(KERN_ERR "EtherCATrtdm %u ERROR: " fmt, devno, ##args) |
58 rtdm_printk(KERN_ERR "EtherCATrtdm %u ERROR: " fmt, devno, ##args) |
60 |
59 |
61 #define EC_RTDM_WARN(devno, fmt, args...) \ |
60 #define EC_RTDM_WARN(devno, fmt, args...) \ |
62 printk(KERN_WARNING "EtherCATrtdm %u WARNING: " fmt, devno, ##args) |
61 rtdm_printk(KERN_WARNING "EtherCATrtdm %u WARNING: " fmt, devno, ##args) |
63 |
62 |
64 |
63 |
65 |
64 |
66 |
65 |
67 typedef struct _EC_RTDM_DRV_STRUCT { |
66 typedef struct _EC_RTDM_DRV_STRUCT { |
159 ecrt_master_receive(pdrvstruc->master); |
158 ecrt_master_receive(pdrvstruc->master); |
160 rt_mutex_release(&pdrvstruc->masterlock); |
159 rt_mutex_release(&pdrvstruc->masterlock); |
161 } |
160 } |
162 } |
161 } |
163 |
162 |
164 void receive_process(EC_RTDM_DRV_STRUCT * pdrvstruc) |
163 |
165 { |
164 |
166 if (pdrvstruc->master) |
|
167 { |
|
168 rt_mutex_acquire(&pdrvstruc->masterlock,TM_INFINITE); |
|
169 ecrt_master_receive(pdrvstruc->master); |
|
170 ecrt_domain_process(pdrvstruc->domain); |
|
171 pdrvstruc->reccnt++; |
|
172 rt_mutex_release(&pdrvstruc->masterlock); |
|
173 } |
|
174 } |
|
175 |
|
176 void send_process(EC_RTDM_DRV_STRUCT * pdrvstruc) |
|
177 { |
|
178 if (pdrvstruc->master) |
|
179 { |
|
180 rt_mutex_acquire(&pdrvstruc->masterlock,TM_INFINITE); |
|
181 ecrt_domain_queue(pdrvstruc->domain); |
|
182 ecrt_master_send(pdrvstruc->master); |
|
183 pdrvstruc->sendcnt++; |
|
184 rt_mutex_release(&pdrvstruc->masterlock); |
|
185 } |
|
186 } |
|
187 |
165 |
188 void detach_master(EC_RTDM_DRV_STRUCT * pdrvstruc) |
166 void detach_master(EC_RTDM_DRV_STRUCT * pdrvstruc) |
189 { |
167 { |
190 |
168 |
191 if (pdrvstruc->isattached) |
169 if (pdrvstruc->isattached) |
340 return -EFAULT; |
318 return -EFAULT; |
341 } |
319 } |
342 } |
320 } |
343 } |
321 } |
344 break; |
322 break; |
345 |
323 case EC_RTDM_MASTER_RECEIVE: |
346 case EC_RTDM_MSTRRECEIVE: |
|
347 { |
324 { |
348 if (pdrvstruc->isattached) |
325 if (pdrvstruc->isattached) |
349 { |
326 { |
350 receive_process(pdrvstruc); |
|
351 } |
|
352 } |
|
353 break; |
|
354 case EC_RTDM_MSTRSEND: |
|
355 { |
|
356 |
|
357 if (pdrvstruc->isattached) |
|
358 { |
|
359 send_process(pdrvstruc); |
|
360 } |
|
361 } |
|
362 break; |
|
363 case EC_RTDM_MASTER_APP_TIME: |
|
364 { |
|
365 if (!pdrvstruc->isattached) |
|
366 { |
|
367 return -EFAULT; |
|
368 } |
|
369 if (rtdm_rw_user_ok(user_info, arg, sizeof(app_time))) |
|
370 { |
|
371 // copy data from user |
|
372 if (rtdm_copy_from_user(user_info, &app_time, arg, sizeof(app_time))) |
|
373 { |
|
374 return -EFAULT; |
|
375 } |
|
376 if (pdrvstruc->master) |
327 if (pdrvstruc->master) |
377 { |
328 { |
378 rt_mutex_acquire(&pdrvstruc->masterlock,TM_INFINITE); |
329 rt_mutex_acquire(&pdrvstruc->masterlock,TM_INFINITE); |
379 |
330 ecrt_master_receive(pdrvstruc->master); |
380 ecrt_master_application_time(pdrvstruc->master, app_time); |
331 pdrvstruc->reccnt++; |
381 |
|
382 rt_mutex_release(&pdrvstruc->masterlock); |
332 rt_mutex_release(&pdrvstruc->masterlock); |
383 |
|
384 } |
333 } |
385 } |
334 } |
386 } |
335 } |
387 break; |
336 break; |
|
337 case EC_RTDM_DOMAIN_PROCESS: |
|
338 { |
|
339 if (pdrvstruc->isattached) |
|
340 { |
|
341 rt_mutex_acquire(&pdrvstruc->masterlock,TM_INFINITE); |
|
342 ecrt_domain_process(pdrvstruc->domain); |
|
343 rt_mutex_release(&pdrvstruc->masterlock); |
|
344 } |
|
345 } |
|
346 break; |
|
347 case EC_RTDM_MASTER_SEND: |
|
348 { |
|
349 |
|
350 if (pdrvstruc->isattached) |
|
351 { |
|
352 if (pdrvstruc->master) |
|
353 { |
|
354 rt_mutex_acquire(&pdrvstruc->masterlock,TM_INFINITE); |
|
355 ecrt_master_send(pdrvstruc->master); |
|
356 pdrvstruc->sendcnt++; |
|
357 rt_mutex_release(&pdrvstruc->masterlock); |
|
358 } |
|
359 } |
|
360 } |
|
361 break; |
|
362 case EC_RTDM_DOMAIN_QUEQUE: |
|
363 { |
|
364 if (pdrvstruc->isattached) |
|
365 { |
|
366 rt_mutex_acquire(&pdrvstruc->masterlock,TM_INFINITE); |
|
367 ecrt_domain_queue(pdrvstruc->domain); |
|
368 rt_mutex_release(&pdrvstruc->masterlock); |
|
369 } |
|
370 } |
|
371 break; |
|
372 |
|
373 case EC_RTDM_MASTER_APP_TIME: |
|
374 { |
|
375 if (!pdrvstruc->isattached) |
|
376 { |
|
377 rtdm_printk("ERROR : No Master attached\n"); |
|
378 return -EFAULT; |
|
379 } |
|
380 if (rtdm_safe_copy_from_user(user_info, &app_time, arg, sizeof(app_time))) |
|
381 { |
|
382 rtdm_printk("ERROR : can't copy data to driver\n"); |
|
383 return -EFAULT; |
|
384 } |
|
385 |
|
386 if (pdrvstruc->master) |
|
387 { |
|
388 rt_mutex_acquire(&pdrvstruc->masterlock,TM_INFINITE); |
|
389 |
|
390 ecrt_master_application_time(pdrvstruc->master, app_time); |
|
391 rt_mutex_release(&pdrvstruc->masterlock); |
|
392 |
|
393 } |
|
394 } |
|
395 break; |
388 case EC_RTDM_SYNC_REF_CLOCK: |
396 case EC_RTDM_SYNC_REF_CLOCK: |
389 { |
397 { |
390 if (!pdrvstruc->isattached) |
398 if (!pdrvstruc->isattached) |
391 { |
399 { |
392 return -EFAULT; |
400 return -EFAULT; |
414 |
422 |
415 ecrt_master_sync_slave_clocks(pdrvstruc->master); |
423 ecrt_master_sync_slave_clocks(pdrvstruc->master); |
416 |
424 |
417 rt_mutex_release(&pdrvstruc->masterlock); |
425 rt_mutex_release(&pdrvstruc->masterlock); |
418 |
426 |
|
427 } |
|
428 } |
|
429 break; |
|
430 case EC_RTDM_MASTER_SYNC_MONITOR_QUEQUE: |
|
431 { |
|
432 if (!pdrvstruc->isattached) |
|
433 { |
|
434 return -EFAULT; |
|
435 } |
|
436 if (pdrvstruc->master) |
|
437 { |
|
438 rt_mutex_acquire(&pdrvstruc->masterlock,TM_INFINITE); |
|
439 ecrt_master_sync_monitor_queue(pdrvstruc->master); |
|
440 rt_mutex_release(&pdrvstruc->masterlock); |
|
441 } |
|
442 } |
|
443 break; |
|
444 case EC_RTDM_MASTER_SYNC_MONITOR_PROCESS: |
|
445 { |
|
446 uint32_t ret; |
|
447 if (!pdrvstruc->isattached) |
|
448 { |
|
449 return -EFAULT; |
|
450 } |
|
451 if (pdrvstruc->master) |
|
452 { |
|
453 rt_mutex_acquire(&pdrvstruc->masterlock,TM_INFINITE); |
|
454 ret = ecrt_master_sync_monitor_process(pdrvstruc->master); |
|
455 rt_mutex_release(&pdrvstruc->masterlock); |
|
456 if (rtdm_safe_copy_to_user(user_info, arg, &ret, sizeof(ret))) |
|
457 { |
|
458 EC_RTDM_ERR(pdrvstruc->masterno,"copy to user param failed!\n"); |
|
459 ret=-EFAULT; |
|
460 } |
419 } |
461 } |
420 } |
462 } |
421 break; |
463 break; |
422 case EC_RTDM_MSTRATTACH: |
464 case EC_RTDM_MSTRATTACH: |
423 { |
465 { |
648 device_class: RTDM_CLASS_EXPERIMENTAL, |
690 device_class: RTDM_CLASS_EXPERIMENTAL, |
649 device_sub_class: 222, |
691 device_sub_class: 222, |
650 driver_name: EC_RTDM_DEV_FILE_NAME, |
692 driver_name: EC_RTDM_DEV_FILE_NAME, |
651 driver_version: RTDM_DRIVER_VER(1,0,1), |
693 driver_version: RTDM_DRIVER_VER(1,0,1), |
652 peripheral_name: EC_RTDM_DEV_FILE_NAME, |
694 peripheral_name: EC_RTDM_DEV_FILE_NAME, |
653 provider_name: "Moehwald GmbH - Bosch Group", |
695 provider_name: "EtherLab Community", |
654 // proc_name: ethcatrtdm_device.device_name, |
696 // proc_name: ethcatrtdm_device.device_name, |
655 }; |
697 }; |
656 |
698 |
657 |
699 |
658 static struct rtdm_device ec_rtdm_devices[EC_RTDM_MAX_MASTERS]; |
700 static struct rtdm_device ec_rtdm_devices[EC_RTDM_MAX_MASTERS]; |
701 /**********************************************************/ |
743 /**********************************************************/ |
702 void cleanup_module(void) |
744 void cleanup_module(void) |
703 { |
745 { |
704 unsigned int i; |
746 unsigned int i; |
705 |
747 |
706 EC_RTDM_GINFO("Cleanup EtherCAT RTDM Interface to Igh EtherCAT Master - Moehwald GmbH\n"); |
748 EC_RTDM_GINFO("Cleanup EtherCAT RTDM Interface \n"); |
707 for (i=0;i<EC_RTDM_MAX_MASTERS;i++) |
749 for (i=0;i<EC_RTDM_MAX_MASTERS;i++) |
708 { |
750 { |
709 if (ec_rtdm_masterintf[i].isattached) |
751 if (ec_rtdm_masterintf[i].isattached) |
710 { |
752 { |
711 detach_master(&ec_rtdm_masterintf[i]); |
753 detach_master(&ec_rtdm_masterintf[i]); |