Staging: epl: run Lindent on *.h files
[GitHub/mt8127/android_kernel_alcatel_ttab.git] / drivers / staging / epl / EplApiLinuxKernel.c
CommitLineData
9d7164cf
DK
1/****************************************************************************
2
3 (c) SYSTEC electronic GmbH, D-07973 Greiz, August-Bebel-Str. 29
4 www.systec-electronic.com
5
6 Project: openPOWERLINK
7
8 Description: Linux kernel module as wrapper of EPL API layer,
9 i.e. counterpart to a Linux application
10
11 License:
12
13 Redistribution and use in source and binary forms, with or without
14 modification, are permitted provided that the following conditions
15 are met:
16
17 1. Redistributions of source code must retain the above copyright
18 notice, this list of conditions and the following disclaimer.
19
20 2. Redistributions in binary form must reproduce the above copyright
21 notice, this list of conditions and the following disclaimer in the
22 documentation and/or other materials provided with the distribution.
23
24 3. Neither the name of SYSTEC electronic GmbH nor the names of its
25 contributors may be used to endorse or promote products derived
26 from this software without prior written permission. For written
27 permission, please contact info@systec-electronic.com.
28
29 THIS SOFTWARE IS PROVIDED BY THE COPYRIGHT HOLDERS AND CONTRIBUTORS
30 "AS IS" AND ANY EXPRESS OR IMPLIED WARRANTIES, INCLUDING, BUT NOT
31 LIMITED TO, THE IMPLIED WARRANTIES OF MERCHANTABILITY AND FITNESS
32 FOR A PARTICULAR PURPOSE ARE DISCLAIMED. IN NO EVENT SHALL THE
33 COPYRIGHT HOLDERS OR CONTRIBUTORS BE LIABLE FOR ANY DIRECT, INDIRECT,
34 INCIDENTAL, SPECIAL, EXEMPLARY, OR CONSEQUENTIAL DAMAGES (INCLUDING,
35 BUT NOT LIMITED TO, PROCUREMENT OF SUBSTITUTE GOODS OR SERVICES;
36 LOSS OF USE, DATA, OR PROFITS; OR BUSINESS INTERRUPTION) HOWEVER
37 CAUSED AND ON ANY THEORY OF LIABILITY, WHETHER IN CONTRACT, STRICT
38 LIABILITY, OR TORT (INCLUDING NEGLIGENCE OR OTHERWISE) ARISING IN
39 ANY WAY OUT OF THE USE OF THIS SOFTWARE, EVEN IF ADVISED OF THE
40 POSSIBILITY OF SUCH DAMAGE.
41
42 Severability Clause:
43
44 If a provision of this License is or becomes illegal, invalid or
45 unenforceable in any jurisdiction, that shall not affect:
46 1. the validity or enforceability in that jurisdiction of any other
47 provision of this License; or
48 2. the validity or enforceability in other jurisdictions of that or
49 any other provision of this License.
50
51 -------------------------------------------------------------------------
52
53 $RCSfile: EplApiLinuxKernel.c,v $
54
55 $Author: D.Krueger $
56
57 $Revision: 1.9 $ $Date: 2008/11/21 09:00:38 $
58
59 $State: Exp $
60
61 Build Environment:
62 GNU-Compiler for m68k
63
64 -------------------------------------------------------------------------
65
66 Revision History:
67
68 2006/10/11 d.k.: Initial Version
69 2008/04/10 m.u.: Changed to new char driver init
70
71****************************************************************************/
72
73
74// kernel modul and driver
75
76//#include <linux/version.h>
77//#include <linux/config.h>
78
79#include <linux/module.h>
80#include <linux/fs.h>
81#include <linux/cdev.h>
82#include <linux/types.h>
83
84//#include <linux/module.h>
85//#include <linux/kernel.h>
86//#include <linux/init.h>
87//#include <linux/errno.h>
88
89// scheduling
90#include <linux/sched.h>
91
92// memory access
93#include <asm/uaccess.h>
94#include <linux/vmalloc.h>
95
96#ifdef CONFIG_DEVFS_FS
97#include <linux/major.h>
98#include <linux/devfs_fs_kernel.h>
99#endif
100
101#include "Epl.h"
102#include "EplApiLinux.h"
103//#include "kernel/EplPdokCal.h"
104#include "proc_fs.h"
105
106
107
108#if LINUX_VERSION_CODE >= KERNEL_VERSION(2,6,0)
109 // remove ("make invisible") obsolete symbols for kernel versions 2.6
110 // and higher
111 #define MOD_INC_USE_COUNT
112 #define MOD_DEC_USE_COUNT
113 #define EXPORT_NO_SYMBOLS
114#else
115 #error "This driver needs a 2.6.x kernel or higher"
116#endif
117
118
119/***************************************************************************/
120/* */
121/* */
122/* G L O B A L D E F I N I T I O N S */
123/* */
124/* */
125/***************************************************************************/
126
127// Metainformation
128MODULE_LICENSE("Dual BSD/GPL");
129#ifdef MODULE_AUTHOR
130 MODULE_AUTHOR("Daniel.Krueger@SYSTEC-electronic.com");
131 MODULE_DESCRIPTION("EPL API driver");
132#endif
133
134
135//---------------------------------------------------------------------------
136// Configuration
137//---------------------------------------------------------------------------
138
139
140#define EPLLIN_DRV_NAME "systec_epl" // used for <register_chrdev>
141
142
143
144//---------------------------------------------------------------------------
145// Constant definitions
146//---------------------------------------------------------------------------
147
148// TracePoint support for realtime-debugging
149#ifdef _DBG_TRACE_POINTS_
150 void PUBLIC TgtDbgSignalTracePoint (BYTE bTracePointNumber_p);
151 #define TGT_DBG_SIGNAL_TRACE_POINT(p) TgtDbgSignalTracePoint(p)
152#else
153 #define TGT_DBG_SIGNAL_TRACE_POINT(p)
154#endif
155
156#define EVENT_STATE_INIT 0
157#define EVENT_STATE_IOCTL 1 // ioctl entered and ready to receive EPL event
158#define EVENT_STATE_READY 2 // EPL event can be forwarded to user application
159#define EVENT_STATE_TERM 3 // terminate processing
160
161#define EPL_STATE_NOTOPEN 0
162#define EPL_STATE_NOTINIT 1
163#define EPL_STATE_RUNNING 2
164#define EPL_STATE_SHUTDOWN 3
165
166
167//---------------------------------------------------------------------------
168// Global variables
169//---------------------------------------------------------------------------
170
171#ifdef CONFIG_DEVFS_FS
172
173 // driver major number
174 static int nDrvMajorNumber_g;
175
176#else
177
178 // device number (major and minor)
179 static dev_t nDevNum_g;
180 static struct cdev *pEpl_cdev_g;
181
182#endif
183
184
185static volatile unsigned int uiEplState_g = EPL_STATE_NOTOPEN;
186
187static struct semaphore SemaphoreCbEvent_g; // semaphore for EplLinCbEvent
188static wait_queue_head_t WaitQueueCbEvent_g; // wait queue EplLinCbEvent
189static wait_queue_head_t WaitQueueProcess_g; // wait queue for EplApiProcess (user process)
190static wait_queue_head_t WaitQueueRelease_g; // wait queue for EplLinRelease
191static atomic_t AtomicEventState_g = ATOMIC_INIT(EVENT_STATE_INIT);
192static tEplApiEventType EventType_g; // event type (enum)
193static tEplApiEventArg* pEventArg_g; // event argument (union)
194static tEplKernel RetCbEvent_g; // return code from event callback function
195static wait_queue_head_t WaitQueueCbSync_g; // wait queue EplLinCbSync
196static wait_queue_head_t WaitQueuePI_In_g; // wait queue for EplApiProcessImageExchangeIn (user process)
197static atomic_t AtomicSyncState_g = ATOMIC_INIT(EVENT_STATE_INIT);
198
199
200//---------------------------------------------------------------------------
201// Local types
202//---------------------------------------------------------------------------
203
204typedef struct
205{
206 void* m_pUserArg;
207 void* m_pData;
208
209} tEplLinSdoBufHeader;
210
211
212//---------------------------------------------------------------------------
213// Local variables
214//---------------------------------------------------------------------------
215
216
217
218//---------------------------------------------------------------------------
219// Prototypes of internal functions
220//---------------------------------------------------------------------------
221
222tEplKernel PUBLIC EplLinCbEvent(
223 tEplApiEventType EventType_p, // IN: event type (enum)
224 tEplApiEventArg* pEventArg_p, // IN: event argument (union)
225 void GENERIC* pUserArg_p);
226
227tEplKernel PUBLIC EplLinCbSync(void);
228
229static int __init EplLinInit (void);
230static void __exit EplLinExit (void);
231
232
233static int EplLinOpen (struct inode* pDeviceFile_p, struct file* pInstance_p);
234static int EplLinRelease (struct inode* pDeviceFile_p, struct file* pInstance_p);
235static ssize_t EplLinRead (struct file* pInstance_p, char* pDstBuff_p, size_t BuffSize_p, loff_t* pFileOffs_p);
236static ssize_t EplLinWrite (struct file* pInstance_p, const char* pSrcBuff_p, size_t BuffSize_p, loff_t* pFileOffs_p);
237static int EplLinIoctl (struct inode* pDeviceFile_p, struct file* pInstance_p, unsigned int uiIoctlCmd_p, unsigned long ulArg_p);
238
239
240
241
242//---------------------------------------------------------------------------
243// Kernel Module specific Data Structures
244//---------------------------------------------------------------------------
245
246EXPORT_NO_SYMBOLS;
247
248
249
250module_init(EplLinInit);
251module_exit(EplLinExit);
252
253
254
255
256static struct file_operations EplLinFileOps_g =
257{
258 .owner = THIS_MODULE,
259 .open = EplLinOpen,
260 .release = EplLinRelease,
261 .read = EplLinRead,
262 .write = EplLinWrite,
263 .ioctl = EplLinIoctl,
264
265};
266
267
268
269//=========================================================================//
270// //
271// P U B L I C F U N C T I O N S //
272// //
273//=========================================================================//
274
275//---------------------------------------------------------------------------
276// Initailize Driver
277//---------------------------------------------------------------------------
278// -> insmod driver
279//---------------------------------------------------------------------------
280
281static int __init EplLinInit (void)
282{
283
284tEplKernel EplRet;
285int iErr;
286int iRet;
287#ifdef CONFIG_DEVFS_FS
288int nMinorNumber;
289#endif
290
291 TRACE0("EPL: + EplLinInit...\n");
292 TRACE2("EPL: Driver build: %s / %s\n", __DATE__, __TIME__);
293
294 iRet = 0;
295
296 // initialize global variables
297 atomic_set(&AtomicEventState_g, EVENT_STATE_INIT);
298 sema_init(&SemaphoreCbEvent_g, 1);
299 init_waitqueue_head(&WaitQueueCbEvent_g);
300 init_waitqueue_head(&WaitQueueProcess_g);
301 init_waitqueue_head(&WaitQueueRelease_g);
302
303
304
305#ifdef CONFIG_DEVFS_FS
306
307 // register character device handler
308 TRACE2("EPL: Installing Driver '%s', Version %s...\n", EPLLIN_DRV_NAME, EPL_PRODUCT_VERSION);
309 TRACE0("EPL: (using dynamic major number assignment)\n");
310 nDrvMajorNumber_g = register_chrdev (0, EPLLIN_DRV_NAME, &EplLinFileOps_g);
311 if (nDrvMajorNumber_g != 0)
312 {
313 TRACE2("EPL: Driver '%s' installed successful, assigned MajorNumber=%d\n", EPLLIN_DRV_NAME, nDrvMajorNumber_g);
314 }
315 else
316 {
317 TRACE1("EPL: ERROR: Driver '%s' is unable to get a free MajorNumber!\n", EPLLIN_DRV_NAME);
318 iRet = -EIO;
319 goto Exit;
320 }
321
322
323 // create device node in DEVFS
324 nMinorNumber = 0;
325 TRACE1("EPL: Creating device node '/dev/%s'...\n", EPLLIN_DEV_NAME);
326 iErr = devfs_mk_cdev (MKDEV(nDrvMajorNumber_g, nMinorNumber), S_IFCHR | S_IRUGO | S_IWUGO, EPLLIN_DEV_NAME);
327 if (iErr == 0)
328 {
329 TRACE1("EPL: Device node '/dev/%s' created successful.\n", EPLLIN_DEV_NAME);
330 }
331 else
332 {
333 TRACE1("EPL: ERROR: unable to create device node '/dev/%s'\n", EPLLIN_DEV_NAME);
334 iRet = -EIO;
335 goto Exit;
336 }
337
338#else
339
340 // register character device handler
341 // only one Minor required
342 TRACE2("EPL: Installing Driver '%s', Version %s...\n", EPLLIN_DRV_NAME, EPL_PRODUCT_VERSION);
343 iRet = alloc_chrdev_region (&nDevNum_g, 0, 1, EPLLIN_DRV_NAME);
344 if (iRet == 0)
345 {
346 TRACE2("EPL: Driver '%s' installed successful, assigned MajorNumber=%d\n", EPLLIN_DRV_NAME, MAJOR(nDevNum_g));
347 }
348 else
349 {
350 TRACE1("EPL: ERROR: Driver '%s' is unable to get a free MajorNumber!\n", EPLLIN_DRV_NAME);
351 iRet = -EIO;
352 goto Exit;
353 }
354
355 // register cdev structure
356 pEpl_cdev_g = cdev_alloc();
357 pEpl_cdev_g->ops = &EplLinFileOps_g;
358 pEpl_cdev_g->owner = THIS_MODULE;
359 iErr = cdev_add (pEpl_cdev_g, nDevNum_g, 1);
360 if (iErr)
361 {
362 TRACE2("EPL: ERROR %d: Driver '%s' could not be added!\n", iErr, EPLLIN_DRV_NAME);
363 iRet = -EIO;
364 goto Exit;
365 }
366
367#endif
368
369 // create device node in PROCFS
370 EplRet = EplLinProcInit();
371 if (EplRet != kEplSuccessful)
372 {
373 goto Exit;
374 }
375
376
377Exit:
378
379 TRACE1("EPL: - EplLinInit (iRet=%d)\n", iRet);
380 return (iRet);
381
382}
383
384
385
386//---------------------------------------------------------------------------
387// Remove Driver
388//---------------------------------------------------------------------------
389// -> rmmod driver
390//---------------------------------------------------------------------------
391
392static void __exit EplLinExit (void)
393{
394
395tEplKernel EplRet;
396
397 // delete instance for all modules
398// EplRet = EplApiShutdown();
399// printk("EplApiShutdown(): 0x%X\n", EplRet);
400
401 // deinitialize proc fs
402 EplRet = EplLinProcFree();
403 printk("EplLinProcFree(): 0x%X\n", EplRet);
404
405
406 TRACE0("EPL: + EplLinExit...\n");
407
408
409#ifdef CONFIG_DEVFS_FS
410
411 // remove device node from DEVFS
412 devfs_remove (EPLLIN_DEV_NAME);
413 TRACE1("EPL: Device node '/dev/%s' removed.\n", EPLLIN_DEV_NAME);
414
415 // unregister character device handler
416 unregister_chrdev (nDrvMajorNumber_g, EPLLIN_DRV_NAME);
417
418#else
419
420 // remove cdev structure
421 cdev_del(pEpl_cdev_g);
422
423 // unregister character device handler
424 unregister_chrdev_region (nDevNum_g, 1);
425
426#endif
427
428 TRACE1("EPL: Driver '%s' removed.\n", EPLLIN_DRV_NAME);
429
430
431 TRACE0("EPL: - EplLinExit\n");
432
433}
434
435
436
437//---------------------------------------------------------------------------
438// Open Driver
439//---------------------------------------------------------------------------
440// -> open("/dev/driver", O_RDWR)...
441//---------------------------------------------------------------------------
442
443static int EplLinOpen (
444 struct inode* pDeviceFile_p, // information about the device to open
445 struct file* pInstance_p) // information about driver instance
446{
447
448int iRet;
449
450
451 TRACE0("EPL: + EplLinOpen...\n");
452
453 MOD_INC_USE_COUNT;
454
455 if (uiEplState_g != EPL_STATE_NOTOPEN)
456 { // stack already initialized
457 iRet = -EALREADY;
458 }
459 else
460 {
461 atomic_set(&AtomicEventState_g, EVENT_STATE_INIT);
462 sema_init(&SemaphoreCbEvent_g, 1);
463 init_waitqueue_head(&WaitQueueCbEvent_g);
464 init_waitqueue_head(&WaitQueueProcess_g);
465 init_waitqueue_head(&WaitQueueRelease_g);
466 atomic_set(&AtomicSyncState_g, EVENT_STATE_INIT);
467 init_waitqueue_head(&WaitQueueCbSync_g);
468 init_waitqueue_head(&WaitQueuePI_In_g);
469
470 uiEplState_g = EPL_STATE_NOTINIT;
471 iRet = 0;
472 }
473
474 TRACE1("EPL: - EplLinOpen (iRet=%d)\n", iRet);
475 return (iRet);
476
477}
478
479
480
481//---------------------------------------------------------------------------
482// Close Driver
483//---------------------------------------------------------------------------
484// -> close(device)...
485//---------------------------------------------------------------------------
486
487static int EplLinRelease (
488 struct inode* pDeviceFile_p, // information about the device to open
489 struct file* pInstance_p) // information about driver instance
490{
491
492tEplKernel EplRet = kEplSuccessful;
493int iRet;
494
495
496 TRACE0("EPL: + EplLinRelease...\n");
497
498 if (uiEplState_g != EPL_STATE_NOTINIT)
499 {
500 // pass control to sync kernel thread, but signal termination
501 atomic_set(&AtomicSyncState_g, EVENT_STATE_TERM);
502 wake_up_interruptible(&WaitQueueCbSync_g);
503 wake_up_interruptible(&WaitQueuePI_In_g);
504
505 // pass control to event queue kernel thread
506 atomic_set(&AtomicEventState_g, EVENT_STATE_TERM);
507 wake_up_interruptible(&WaitQueueCbEvent_g);
508
509 if (uiEplState_g == EPL_STATE_RUNNING)
510 { // post NmtEventSwitchOff
511 EplRet = EplApiExecNmtCommand(kEplNmtEventSwitchOff);
512
513 }
514
515 if (EplRet == kEplSuccessful)
516 {
517 TRACE0("EPL: waiting for NMT_GS_OFF\n");
518 wait_event_interruptible(WaitQueueRelease_g,
519 (uiEplState_g == EPL_STATE_SHUTDOWN));
520 }
521 else
522 { // post NmtEventSwitchOff failed
523 TRACE0("EPL: event post failed\n");
524 }
525
526 // $$$ d.k.: What if waiting was interrupted by signal?
527
528 TRACE0("EPL: call EplApiShutdown()\n");
529 // EPL stack can be safely shut down
530 // delete instance for all EPL modules
531 EplRet = EplApiShutdown();
532 printk("EplApiShutdown(): 0x%X\n", EplRet);
533 }
534
535 uiEplState_g = EPL_STATE_NOTOPEN;
536 iRet = 0;
537
538
539 MOD_DEC_USE_COUNT;
540
541
542 TRACE1("EPL: - EplLinRelease (iRet=%d)\n", iRet);
543 return (iRet);
544
545}
546
547
548
549//---------------------------------------------------------------------------
550// Read Data from Driver
551//---------------------------------------------------------------------------
552// -> read(...)
553//---------------------------------------------------------------------------
554
555static ssize_t EplLinRead (
556 struct file* pInstance_p, // information about driver instance
557 char* pDstBuff_p, // address of buffer to fill with data
558 size_t BuffSize_p, // length of the buffer
559 loff_t* pFileOffs_p) // offset in the file
560{
561
562int iRet;
563
564
565 TRACE0("EPL: + EplLinRead...\n");
566
567
568 TRACE0("EPL: Sorry, this operation isn't supported.\n");
569 iRet = -EINVAL;
570
571
572 TRACE1("EPL: - EplLinRead (iRet=%d)\n", iRet);
573 return (iRet);
574
575}
576
577
578
579//---------------------------------------------------------------------------
580// Write Data to Driver
581//---------------------------------------------------------------------------
582// -> write(...)
583//---------------------------------------------------------------------------
584
585static ssize_t EplLinWrite (
586 struct file* pInstance_p, // information about driver instance
587 const char* pSrcBuff_p, // address of buffer to get data from
588 size_t BuffSize_p, // length of the buffer
589 loff_t* pFileOffs_p) // offset in the file
590{
591
592int iRet;
593
594
595 TRACE0("EPL: + EplLinWrite...\n");
596
597
598 TRACE0("EPL: Sorry, this operation isn't supported.\n");
599 iRet = -EINVAL;
600
601
602 TRACE1("EPL: - EplLinWrite (iRet=%d)\n", iRet);
603 return (iRet);
604
605}
606
607
608
609//---------------------------------------------------------------------------
610// Generic Access to Driver
611//---------------------------------------------------------------------------
612// -> ioctl(...)
613//---------------------------------------------------------------------------
614
615static int EplLinIoctl (
616 struct inode* pDeviceFile_p, // information about the device to open
617 struct file* pInstance_p, // information about driver instance
618 unsigned int uiIoctlCmd_p, // Ioctl command to execute
619 unsigned long ulArg_p) // Ioctl command specific argument/parameter
620{
621
622tEplKernel EplRet;
623int iErr;
624int iRet;
625
626
627// TRACE1("EPL: + EplLinIoctl (uiIoctlCmd_p=%d)...\n", uiIoctlCmd_p);
628
629
630 iRet = -EINVAL;
631
632 switch (uiIoctlCmd_p)
633 {
634 // ----------------------------------------------------------
635 case EPLLIN_CMD_INITIALIZE:
636 {
637 tEplApiInitParam EplApiInitParam;
638
639 iErr = copy_from_user(&EplApiInitParam, (const void*)ulArg_p, sizeof (EplApiInitParam));
640 if (iErr != 0)
641 {
642 iRet = -EIO;
643 goto Exit;
644 }
645
646 EplApiInitParam.m_pfnCbEvent = EplLinCbEvent;
647 EplApiInitParam.m_pfnCbSync = EplLinCbSync;
648
649 EplRet = EplApiInitialize(&EplApiInitParam);
650
651 uiEplState_g = EPL_STATE_RUNNING;
652
653 iRet = (int) EplRet;
654 break;
655 }
656
657
658 // ----------------------------------------------------------
659 case EPLLIN_CMD_SHUTDOWN:
660 { // shutdown the threads
661
662 // pass control to sync kernel thread, but signal termination
663 atomic_set(&AtomicSyncState_g, EVENT_STATE_TERM);
664 wake_up_interruptible(&WaitQueueCbSync_g);
665 wake_up_interruptible(&WaitQueuePI_In_g);
666
667 // pass control to event queue kernel thread
668 atomic_set(&AtomicEventState_g, EVENT_STATE_TERM);
669 wake_up_interruptible(&WaitQueueCbEvent_g);
670
671 if (uiEplState_g == EPL_STATE_RUNNING)
672 { // post NmtEventSwitchOff
673 EplRet = EplApiExecNmtCommand(kEplNmtEventSwitchOff);
674
675 }
676
677 iRet = 0;
678 break;
679 }
680
681
682 // ----------------------------------------------------------
683 case EPLLIN_CMD_READ_LOCAL_OBJECT:
684 {
685 tEplLinLocalObject LocalObject;
686 void* pData;
687
688 iErr = copy_from_user(&LocalObject, (const void*)ulArg_p, sizeof (LocalObject));
689 if (iErr != 0)
690 {
691 iRet = -EIO;
692 goto Exit;
693 }
694
695 if ((LocalObject.m_pData == NULL) || (LocalObject.m_uiSize == 0))
696 {
697 iRet = (int) kEplApiInvalidParam;
698 goto Exit;
699 }
700
701 pData = vmalloc(LocalObject.m_uiSize);
702 if (pData == NULL)
703 { // no memory available
704 iRet = -ENOMEM;
705 goto Exit;
706 }
707
708 EplRet = EplApiReadLocalObject(LocalObject.m_uiIndex, LocalObject.m_uiSubindex, pData, &LocalObject.m_uiSize);
709
710 if (EplRet == kEplSuccessful)
711 {
712 iErr = copy_to_user(LocalObject.m_pData, pData, LocalObject.m_uiSize);
713
714 vfree(pData);
715
716 if (iErr != 0)
717 {
718 iRet = -EIO;
719 goto Exit;
720 }
721
722 // return actual size (LocalObject.m_uiSize)
723 iErr = put_user(LocalObject.m_uiSize,
724 (unsigned int*)(ulArg_p + (unsigned long)&LocalObject.m_uiSize - (unsigned long)&LocalObject));
725 if (iErr != 0)
726 {
727 iRet = -EIO;
728 goto Exit;
729 }
730
731 }
732 else
733 {
734 vfree(pData);
735 }
736
737 iRet = (int) EplRet;
738 break;
739 }
740
741
742 // ----------------------------------------------------------
743 case EPLLIN_CMD_WRITE_LOCAL_OBJECT:
744 {
745 tEplLinLocalObject LocalObject;
746 void* pData;
747
748 iErr = copy_from_user(&LocalObject, (const void*)ulArg_p, sizeof (LocalObject));
749 if (iErr != 0)
750 {
751 iRet = -EIO;
752 goto Exit;
753 }
754
755 if ((LocalObject.m_pData == NULL) || (LocalObject.m_uiSize == 0))
756 {
757 iRet = (int) kEplApiInvalidParam;
758 goto Exit;
759 }
760
761 pData = vmalloc(LocalObject.m_uiSize);
762 if (pData == NULL)
763 { // no memory available
764 iRet = -ENOMEM;
765 goto Exit;
766 }
767 iErr = copy_from_user(pData, LocalObject.m_pData, LocalObject.m_uiSize);
768 if (iErr != 0)
769 {
770 iRet = -EIO;
771 goto Exit;
772 }
773
774 EplRet = EplApiWriteLocalObject(LocalObject.m_uiIndex, LocalObject.m_uiSubindex, pData, LocalObject.m_uiSize);
775
776 vfree(pData);
777
778 iRet = (int) EplRet;
779 break;
780 }
781
782
783 case EPLLIN_CMD_READ_OBJECT:
784 {
785 tEplLinSdoObject SdoObject;
786 void* pData;
787 tEplLinSdoBufHeader* pBufHeader;
788 tEplSdoComConHdl* pSdoComConHdl;
789
790 iErr = copy_from_user(&SdoObject, (const void*)ulArg_p, sizeof (SdoObject));
791 if (iErr != 0)
792 {
793 iRet = -EIO;
794 goto Exit;
795 }
796
797 if ((SdoObject.m_le_pData == NULL) || (SdoObject.m_uiSize == 0))
798 {
799 iRet = (int) kEplApiInvalidParam;
800 goto Exit;
801 }
802
803 pBufHeader = (tEplLinSdoBufHeader*) vmalloc(sizeof (tEplLinSdoBufHeader) + SdoObject.m_uiSize);
804 if (pBufHeader == NULL)
805 { // no memory available
806 iRet = -ENOMEM;
807 goto Exit;
808 }
809
810 // initiate temporary buffer
811 pBufHeader->m_pUserArg = SdoObject.m_pUserArg; // original user argument pointer
812 pBufHeader->m_pData = SdoObject.m_le_pData; // original data pointer from app
813 pData = pBufHeader + sizeof (tEplLinSdoBufHeader);
814
815 if (SdoObject.m_fValidSdoComConHdl != FALSE)
816 {
817 pSdoComConHdl = &SdoObject.m_SdoComConHdl;
818 }
819 else
820 {
821 pSdoComConHdl = NULL;
822 }
823
824 EplRet = EplApiReadObject(pSdoComConHdl, SdoObject.m_uiNodeId, SdoObject.m_uiIndex,
825 SdoObject.m_uiSubindex, pData, &SdoObject.m_uiSize,
826 SdoObject.m_SdoType, pBufHeader);
827
828 // return actual SDO handle (SdoObject.m_SdoComConHdl)
829 iErr = put_user(SdoObject.m_SdoComConHdl,
830 (unsigned int*)(ulArg_p + (unsigned long)&SdoObject.m_SdoComConHdl - (unsigned long)&SdoObject));
831 if (iErr != 0)
832 {
833 iRet = -EIO;
834 goto Exit;
835 }
836
837 if (EplRet == kEplSuccessful)
838 {
839 iErr = copy_to_user(SdoObject.m_le_pData, pData, SdoObject.m_uiSize);
840
841 vfree(pBufHeader);
842
843 if (iErr != 0)
844 {
845 iRet = -EIO;
846 goto Exit;
847 }
848
849 // return actual size (SdoObject.m_uiSize)
850 iErr = put_user(SdoObject.m_uiSize,
851 (unsigned int*)(ulArg_p + (unsigned long)&SdoObject.m_uiSize - (unsigned long)&SdoObject));
852 if (iErr != 0)
853 {
854 iRet = -EIO;
855 goto Exit;
856 }
857 }
858 else if (EplRet != kEplApiTaskDeferred)
859 { // error ocurred
860 vfree(pBufHeader);
861 if (iErr != 0)
862 {
863 iRet = -EIO;
864 goto Exit;
865 }
866 }
867
868 iRet = (int) EplRet;
869 break;
870 }
871
872
873 case EPLLIN_CMD_WRITE_OBJECT:
874 {
875 tEplLinSdoObject SdoObject;
876 void* pData;
877 tEplLinSdoBufHeader* pBufHeader;
878 tEplSdoComConHdl* pSdoComConHdl;
879
880 iErr = copy_from_user(&SdoObject, (const void*)ulArg_p, sizeof (SdoObject));
881 if (iErr != 0)
882 {
883 iRet = -EIO;
884 goto Exit;
885 }
886
887 if ((SdoObject.m_le_pData == NULL) || (SdoObject.m_uiSize == 0))
888 {
889 iRet = (int) kEplApiInvalidParam;
890 goto Exit;
891 }
892
893 pBufHeader = (tEplLinSdoBufHeader*) vmalloc(sizeof (tEplLinSdoBufHeader) + SdoObject.m_uiSize);
894 if (pBufHeader == NULL)
895 { // no memory available
896 iRet = -ENOMEM;
897 goto Exit;
898 }
899
900 // initiate temporary buffer
901 pBufHeader->m_pUserArg = SdoObject.m_pUserArg; // original user argument pointer
902 pBufHeader->m_pData = SdoObject.m_le_pData; // original data pointer from app
903 pData = pBufHeader + sizeof (tEplLinSdoBufHeader);
904
905 iErr = copy_from_user(pData, SdoObject.m_le_pData, SdoObject.m_uiSize);
906
907 if (iErr != 0)
908 {
909 iRet = -EIO;
910 goto Exit;
911 }
912
913 if (SdoObject.m_fValidSdoComConHdl != FALSE)
914 {
915 pSdoComConHdl = &SdoObject.m_SdoComConHdl;
916 }
917 else
918 {
919 pSdoComConHdl = NULL;
920 }
921
922 EplRet = EplApiWriteObject(pSdoComConHdl, SdoObject.m_uiNodeId, SdoObject.m_uiIndex,
923 SdoObject.m_uiSubindex, pData, SdoObject.m_uiSize,
924 SdoObject.m_SdoType, pBufHeader);
925
926 // return actual SDO handle (SdoObject.m_SdoComConHdl)
927 iErr = put_user(SdoObject.m_SdoComConHdl,
928 (unsigned int*)(ulArg_p + (unsigned long)&SdoObject.m_SdoComConHdl - (unsigned long)&SdoObject));
929 if (iErr != 0)
930 {
931 iRet = -EIO;
932 goto Exit;
933 }
934
935 if (EplRet != kEplApiTaskDeferred)
936 { // succeeded or error ocurred, but task not deferred
937 vfree(pBufHeader);
938 }
939
940 iRet = (int) EplRet;
941 break;
942 }
943
944
945 // ----------------------------------------------------------
946 case EPLLIN_CMD_FREE_SDO_CHANNEL:
947 {
948 // forward SDO handle to EPL stack
949 EplRet = EplApiFreeSdoChannel((tEplSdoComConHdl)ulArg_p);
950
951 iRet = (int) EplRet;
952 break;
953 }
954
955
956#if (((EPL_MODULE_INTEGRATION) & (EPL_MODULE_NMT_MN)) != 0)
957 // ----------------------------------------------------------
958 case EPLLIN_CMD_MN_TRIGGER_STATE_CHANGE:
959 {
960 tEplLinNodeCmdObject NodeCmdObject;
961
962 iErr = copy_from_user(&NodeCmdObject, (const void*)ulArg_p, sizeof (NodeCmdObject));
963 if (iErr != 0)
964 {
965 iRet = -EIO;
966 goto Exit;
967 }
968
969 EplRet = EplApiMnTriggerStateChange(NodeCmdObject.m_uiNodeId,
970 NodeCmdObject.m_NodeCommand);
971 iRet = (int) EplRet;
972 break;
973 }
974#endif
975
976
977 // ----------------------------------------------------------
978 case EPLLIN_CMD_GET_EVENT:
979 {
980 tEplLinEvent Event;
981
982 // save event structure
983 iErr = copy_from_user(&Event, (const void*)ulArg_p, sizeof (Event));
984 if (iErr != 0)
985 {
986 iRet = -EIO;
987 goto Exit;
988 }
989
990 // save return code from application's event callback function
991 RetCbEvent_g = Event.m_RetCbEvent;
992
993 if (RetCbEvent_g == kEplShutdown)
994 {
995 // pass control to event queue kernel thread, but signal termination
996 atomic_set(&AtomicEventState_g, EVENT_STATE_TERM);
997 wake_up_interruptible(&WaitQueueCbEvent_g);
998 // exit with error -> EplApiProcess() will leave the infinite loop
999 iRet = 1;
1000 goto Exit;
1001 }
1002
1003 // pass control to event queue kernel thread
1004 atomic_set(&AtomicEventState_g, EVENT_STATE_IOCTL);
1005 wake_up_interruptible(&WaitQueueCbEvent_g);
1006
1007 // fall asleep itself in own wait queue
1008 iErr = wait_event_interruptible(WaitQueueProcess_g,
1009 (atomic_read(&AtomicEventState_g) == EVENT_STATE_READY)
1010 || (atomic_read(&AtomicEventState_g) == EVENT_STATE_TERM));
1011 if (iErr != 0)
1012 { // waiting was interrupted by signal
1013 // pass control to event queue kernel thread, but signal termination
1014 atomic_set(&AtomicEventState_g, EVENT_STATE_TERM);
1015 wake_up_interruptible(&WaitQueueCbEvent_g);
1016 // exit with this error -> EplApiProcess() will leave the infinite loop
1017 iRet = iErr;
1018 goto Exit;
1019 }
1020 else if (atomic_read(&AtomicEventState_g) == EVENT_STATE_TERM)
1021 { // termination in progress
1022 // pass control to event queue kernel thread, but signal termination
1023 wake_up_interruptible(&WaitQueueCbEvent_g);
1024 // exit with this error -> EplApiProcess() will leave the infinite loop
1025 iRet = 1;
1026 goto Exit;
1027 }
1028
1029 // copy event to user space
1030 iErr = copy_to_user(Event.m_pEventType, &EventType_g, sizeof (EventType_g));
1031 if (iErr != 0)
1032 { // not all data could be copied
1033 iRet = -EIO;
1034 goto Exit;
1035 }
1036
1037 // $$$ d.k. perform SDO event processing
1038 if (EventType_g == kEplApiEventSdo)
1039 {
1040 void* pData;
1041 tEplLinSdoBufHeader* pBufHeader;
1042
1043 pBufHeader = (tEplLinSdoBufHeader*) pEventArg_g->m_Sdo.m_pUserArg;
1044 pData = pBufHeader + sizeof (tEplLinSdoBufHeader);
1045
1046 if (pEventArg_g->m_Sdo.m_SdoAccessType == kEplSdoAccessTypeRead)
1047 {
1048 // copy read data to user space
1049 iErr = copy_to_user(pBufHeader->m_pData, pData, pEventArg_g->m_Sdo.m_uiTransferredByte);
1050 if (iErr != 0)
1051 { // not all data could be copied
1052 iRet = -EIO;
1053 goto Exit;
1054 }
1055 }
1056 pEventArg_g->m_Sdo.m_pUserArg = pBufHeader->m_pUserArg;
1057 vfree(pBufHeader);
1058 }
1059
1060 iErr = copy_to_user(Event.m_pEventArg, pEventArg_g, min(sizeof (tEplApiEventArg), Event.m_uiEventArgSize));
1061 if (iErr != 0)
1062 { // not all data could be copied
1063 iRet = -EIO;
1064 goto Exit;
1065 }
1066
1067 // return to EplApiProcess(), which will call the application's event callback function
1068 iRet = 0;
1069
1070 break;
1071 }
1072
1073
1074 // ----------------------------------------------------------
1075 case EPLLIN_CMD_PI_SETUP:
1076 {
1077 EplRet = EplApiProcessImageSetup();
1078 iRet = (int) EplRet;
1079
1080 break;
1081 }
1082
1083
1084 // ----------------------------------------------------------
1085 case EPLLIN_CMD_PI_IN:
1086 {
1087 tEplApiProcessImage ProcessImageIn;
1088
1089 // save process image structure
1090 iErr = copy_from_user(&ProcessImageIn, (const void*)ulArg_p, sizeof (ProcessImageIn));
1091 if (iErr != 0)
1092 {
1093 iRet = -EIO;
1094 goto Exit;
1095 }
1096
1097 // pass control to event queue kernel thread
1098 atomic_set(&AtomicSyncState_g, EVENT_STATE_IOCTL);
1099
1100 // fall asleep itself in own wait queue
1101 iErr = wait_event_interruptible(WaitQueuePI_In_g,
1102 (atomic_read(&AtomicSyncState_g) == EVENT_STATE_READY)
1103 || (atomic_read(&AtomicSyncState_g) == EVENT_STATE_TERM));
1104 if (iErr != 0)
1105 { // waiting was interrupted by signal
1106 // pass control to sync kernel thread, but signal termination
1107 atomic_set(&AtomicSyncState_g, EVENT_STATE_TERM);
1108 wake_up_interruptible(&WaitQueueCbSync_g);
1109 // exit with this error -> application will leave the infinite loop
1110 iRet = iErr;
1111 goto Exit;
1112 }
1113 else if (atomic_read(&AtomicSyncState_g) == EVENT_STATE_TERM)
1114 { // termination in progress
1115 // pass control to sync kernel thread, but signal termination
1116 wake_up_interruptible(&WaitQueueCbSync_g);
1117 // exit with this error -> application will leave the infinite loop
1118 iRet = 1;
1119 goto Exit;
1120 }
1121
1122 // exchange process image
1123 EplRet = EplApiProcessImageExchangeIn(&ProcessImageIn);
1124
1125 // return to EplApiProcessImageExchangeIn()
1126 iRet = (int) EplRet;
1127
1128 break;
1129 }
1130
1131
1132 // ----------------------------------------------------------
1133 case EPLLIN_CMD_PI_OUT:
1134 {
1135 tEplApiProcessImage ProcessImageOut;
1136
1137 // save process image structure
1138 iErr = copy_from_user(&ProcessImageOut, (const void*)ulArg_p, sizeof (ProcessImageOut));
1139 if (iErr != 0)
1140 {
1141 iRet = -EIO;
1142 goto Exit;
1143 }
1144
1145 if (atomic_read(&AtomicSyncState_g) != EVENT_STATE_READY)
1146 {
1147 iRet = (int) kEplInvalidOperation;
1148 goto Exit;
1149 }
1150
1151 // exchange process image
1152 EplRet = EplApiProcessImageExchangeOut(&ProcessImageOut);
1153
1154 // pass control to sync kernel thread
1155 atomic_set(&AtomicSyncState_g, EVENT_STATE_TERM);
1156 wake_up_interruptible(&WaitQueueCbSync_g);
1157
1158 // return to EplApiProcessImageExchangeout()
1159 iRet = (int) EplRet;
1160
1161 break;
1162 }
1163
1164
1165 // ----------------------------------------------------------
1166 case EPLLIN_CMD_NMT_COMMAND:
1167 {
1168 // forward NMT command to EPL stack
1169 EplRet = EplApiExecNmtCommand((tEplNmtEvent)ulArg_p);
1170
1171 iRet = (int) EplRet;
1172
1173 break;
1174 }
1175
1176
1177
1178 // ----------------------------------------------------------
1179 default:
1180 {
1181 break;
1182 }
1183 }
1184
1185
1186Exit:
1187
1188// TRACE1("EPL: - EplLinIoctl (iRet=%d)\n", iRet);
1189 return (iRet);
1190
1191}
1192
1193
1194
1195
1196
1197//=========================================================================//
1198// //
1199// P R I V A T E F U N C T I O N S //
1200// //
1201//=========================================================================//
1202
1203
1204tEplKernel PUBLIC EplLinCbEvent(
1205 tEplApiEventType EventType_p, // IN: event type (enum)
1206 tEplApiEventArg* pEventArg_p, // IN: event argument (union)
1207 void GENERIC* pUserArg_p)
1208{
1209tEplKernel EplRet = kEplSuccessful;
1210int iErr;
1211
1212 // block any further call to this function, i.e. enter critical section
1213 iErr = down_interruptible(&SemaphoreCbEvent_g);
1214 if (iErr != 0)
1215 { // waiting was interrupted by signal
1216 EplRet = kEplShutdown;
1217 goto Exit;
1218 }
1219
1220 // wait for EplApiProcess() to call ioctl
1221 // normally it should be waiting already for us to pass a new event
1222 iErr = wait_event_interruptible(WaitQueueCbEvent_g,
1223 (atomic_read(&AtomicEventState_g) == EVENT_STATE_IOCTL)
1224 || (atomic_read(&AtomicEventState_g) == EVENT_STATE_TERM));
1225 if ((iErr != 0) || (atomic_read(&AtomicEventState_g) == EVENT_STATE_TERM))
1226 { // waiting was interrupted by signal
1227 EplRet = kEplShutdown;
1228 goto LeaveCriticalSection;
1229 }
1230
1231 // save event information for ioctl
1232 EventType_g = EventType_p;
1233 pEventArg_g = pEventArg_p;
1234
1235 // pass control to application's event callback function, i.e. EplApiProcess()
1236 atomic_set(&AtomicEventState_g, EVENT_STATE_READY);
1237 wake_up_interruptible(&WaitQueueProcess_g);
1238
1239 // now, the application's event callback function processes the event
1240
1241 // wait for completion of application's event callback function, i.e. EplApiProcess() calls ioctl again
1242 iErr = wait_event_interruptible(WaitQueueCbEvent_g,
1243 (atomic_read(&AtomicEventState_g) == EVENT_STATE_IOCTL)
1244 || (atomic_read(&AtomicEventState_g) == EVENT_STATE_TERM));
1245 if ((iErr != 0) || (atomic_read(&AtomicEventState_g) == EVENT_STATE_TERM))
1246 { // waiting was interrupted by signal
1247 EplRet = kEplShutdown;
1248 goto LeaveCriticalSection;
1249 }
1250
1251 // read return code from application's event callback function
1252 EplRet = RetCbEvent_g;
1253
1254
1255LeaveCriticalSection:
1256 up(&SemaphoreCbEvent_g);
1257
1258Exit:
1259 // check if NMT_GS_OFF is reached
1260 if (EventType_p == kEplApiEventNmtStateChange)
1261 {
1262 if (pEventArg_p->m_NmtStateChange.m_NewNmtState == kEplNmtGsOff)
1263 { // NMT state machine was shut down
1264 TRACE0("EPL: EplLinCbEvent(NMT_GS_OFF)\n");
1265 uiEplState_g = EPL_STATE_SHUTDOWN;
1266 atomic_set(&AtomicEventState_g, EVENT_STATE_TERM);
1267 wake_up(&WaitQueueRelease_g);
1268 }
1269 else
1270 { // NMT state machine is running
1271 uiEplState_g = EPL_STATE_RUNNING;
1272 }
1273 }
1274
1275
1276 return EplRet;
1277}
1278
1279
1280tEplKernel PUBLIC EplLinCbSync(void)
1281{
1282tEplKernel EplRet = kEplSuccessful;
1283int iErr;
1284
1285 // check if user process waits for sync
1286 if (atomic_read(&AtomicSyncState_g) == EVENT_STATE_IOCTL)
1287 {
1288 // pass control to application, i.e. EplApiProcessImageExchangeIn()
1289 atomic_set(&AtomicSyncState_g, EVENT_STATE_READY);
1290 wake_up_interruptible(&WaitQueuePI_In_g);
1291
1292 // now, the application processes the sync event
1293
1294 // wait for call of EplApiProcessImageExchangeOut()
1295 iErr = wait_event_interruptible(WaitQueueCbSync_g,
1296 (atomic_read(&AtomicSyncState_g) == EVENT_STATE_IOCTL)
1297 || (atomic_read(&AtomicSyncState_g) == EVENT_STATE_TERM));
1298 if ((iErr != 0) || (atomic_read(&AtomicEventState_g) == EVENT_STATE_IOCTL))
1299 { // waiting was interrupted by signal or application called wrong function
1300 EplRet = kEplShutdown;
1301 }
1302 }
1303 else
1304 { // application is currently not waiting for sync
1305 // continue without interruption
1306 // TPDO are set valid by caller (i.e. EplEventkProcess())
1307 }
1308
1309 TGT_DBG_SIGNAL_TRACE_POINT(1);
1310
1311 return EplRet;
1312}
1313
1314
1315
1316// EOF
1317