Merge branch 'next' into for-linus
[linux-2.6] / drivers / staging / epl / demo_main.c
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:  demoapplication for EPL MN (with SDO over UDP)
9                 under Linux on X86 with RTL8139 Ethernet controller
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: demo_main.c,v $
54
55                 $Author: D.Krueger $
56
57                 $Revision: 1.10 $  $Date: 2008/11/19 18:11:43 $
58
59                 $State: Exp $
60
61                 Build Environment:
62                 GCC
63
64   -------------------------------------------------------------------------
65
66   Revision History:
67
68   2006/09/01 d.k.:   start of implementation
69
70 ****************************************************************************/
71
72 #include <linux/module.h>
73 #include <linux/kernel.h>
74 #include <linux/init.h>
75 #include <linux/errno.h>
76 #include <linux/major.h>
77 #include <asm/io.h>
78 #include <asm/uaccess.h>
79 #include <asm/atomic.h>
80 #include <linux/sched.h>
81 #include <linux/kmod.h>
82 #include <linux/slab.h>
83 #include <linux/pci.h>
84 #include <linux/proc_fs.h>
85
86 #include "Epl.h"
87 #include "proc_fs.h"
88
89 /***************************************************************************/
90 /*                                                                         */
91 /*                                                                         */
92 /*          G L O B A L   D E F I N I T I O N S                            */
93 /*                                                                         */
94 /*                                                                         */
95 /***************************************************************************/
96
97 // Metainformation
98 MODULE_LICENSE("Dual BSD/GPL");
99 #ifdef MODULE_AUTHOR
100 MODULE_AUTHOR("Daniel.Krueger@SYSTEC-electronic.com");
101 MODULE_DESCRIPTION("EPL MN demo");
102 #endif
103
104 //---------------------------------------------------------------------------
105 // const defines
106 //---------------------------------------------------------------------------
107
108 // TracePoint support for realtime-debugging
109 #ifdef _DBG_TRACE_POINTS_
110 void TgtDbgSignalTracePoint(u8 bTracePointNumber_p);
111 #define TGT_DBG_SIGNAL_TRACE_POINT(p)   TgtDbgSignalTracePoint(p)
112 #else
113 #define TGT_DBG_SIGNAL_TRACE_POINT(p)
114 #endif
115
116 #define NODEID      0xF0        //=> MN
117 #define CYCLE_LEN   5000        // [us]
118 #define IP_ADDR     0xc0a86401  // 192.168.100.1
119 #define SUBNET_MASK 0xFFFFFF00  // 255.255.255.0
120 #define HOSTNAME    "SYS TEC electronic EPL Stack    "
121 #define IF_ETH      EPL_VETH_NAME
122
123 // LIGHT EFFECT
124 #define DEFAULT_MAX_CYCLE_COUNT 20      // 6 is very fast
125 #define APP_DEFAULT_MODE        0x01
126 #define APP_LED_COUNT           5       // number of LEDs in one row
127 #define APP_LED_MASK            ((1 << APP_LED_COUNT) - 1)
128 #define APP_DOUBLE_LED_MASK     ((1 << (APP_LED_COUNT * 2)) - 1)
129 #define APP_MODE_COUNT          5
130 #define APP_MODE_MASK           ((1 << APP_MODE_COUNT) - 1)
131
132 //---------------------------------------------------------------------------
133 // local types
134 //---------------------------------------------------------------------------
135
136 //---------------------------------------------------------------------------
137 // modul globale vars
138 //---------------------------------------------------------------------------
139
140 static const u8 abMacAddr[] = { 0x00, 0x00, 0x00, 0x00, 0x00, 0x00 };
141
142 static u8 bVarIn1_l;
143 static u8 bVarOut1_l;
144 static u8 bVarOut1Old_l;
145 static u8 bModeSelect_l;                // state of the pushbuttons to select the mode
146 static u8 bSpeedSelect_l;               // state of the pushbuttons to increase/decrease the speed
147 static u8 bSpeedSelectOld_l;            // old state of the pushbuttons
148 static u32 dwLeds_l;                    // current state of all LEDs
149 static u8 bLedsRow1_l;          // current state of the LEDs in row 1
150 static u8 bLedsRow2_l;          // current state of the LEDs in row 2
151 static u8 abSelect_l[3];                // pushbuttons from CNs
152
153 static u32 dwMode_l;                    // current mode
154 static int iCurCycleCount_l;            // current cycle count
155 static int iMaxCycleCount_l;            // maximum cycle count (i.e. number of cycles until next light movement step)
156 static int iToggle;                     // indicates the light movement direction
157
158 //static u8 abDomain_l[3000];
159
160 static wait_queue_head_t WaitQueueShutdown_g;   // wait queue for tEplNmtEventSwitchOff
161 static atomic_t AtomicShutdown_g = ATOMIC_INIT(FALSE);
162
163 static u32 dw_le_CycleLen_g;
164
165 static uint uiNodeId_g = EPL_C_ADR_INVALID;
166 module_param_named(nodeid, uiNodeId_g, uint, 0);
167
168 static uint uiCycleLen_g = CYCLE_LEN;
169 module_param_named(cyclelen, uiCycleLen_g, uint, 0);
170
171 //---------------------------------------------------------------------------
172 // local function prototypes
173 //---------------------------------------------------------------------------
174
175 // This function is the entry point for your object dictionary. It is defined
176 // in OBJDICT.C by define EPL_OBD_INIT_RAM_NAME. Use this function name to define
177 // this function prototype here. If you want to use more than one Epl
178 // instances then the function name of each object dictionary has to differ.
179
180 tEplKernel EplObdInitRam(tEplObdInitParam *pInitParam_p);
181
182 tEplKernel AppCbEvent(tEplApiEventType EventType_p,     // IN: event type (enum)
183                       tEplApiEventArg *pEventArg_p,     // IN: event argument (union)
184                       void *pUserArg_p);
185
186 tEplKernel AppCbSync(void);
187
188
189 //---------------------------------------------------------------------------
190 //  Kernel Module specific Data Structures
191 //---------------------------------------------------------------------------
192
193 //module_init(EplLinInit);
194 //module_exit(EplLinExit);
195
196 //=========================================================================//
197 //                                                                         //
198 //          P U B L I C   F U N C T I O N S                                //
199 //                                                                         //
200 //=========================================================================//
201
202 //---------------------------------------------------------------------------
203 //
204 // Function:
205 //
206 // Description:
207 //
208 //
209 //
210 // Parameters:
211 //
212 //
213 // Returns:
214 //
215 //
216 // State:
217 //
218 //---------------------------------------------------------------------------
219 #if 0
220 static int __init EplLinInit(void)
221 {
222         tEplKernel EplRet;
223         int iRet;
224         static tEplApiInitParam EplApiInitParam = { 0 };
225         char *sHostname = HOSTNAME;
226         char *argv[4], *envp[3];
227         char sBuffer[16];
228         unsigned int uiVarEntries;
229         tEplObdSize ObdSize;
230
231         atomic_set(&AtomicShutdown_g, TRUE);
232
233         // get node ID from insmod command line
234         EplApiInitParam.m_uiNodeId = uiNodeId_g;
235
236         if (EplApiInitParam.m_uiNodeId == EPL_C_ADR_INVALID) {  // invalid node ID set
237                 // set default node ID
238                 EplApiInitParam.m_uiNodeId = NODEID;
239         }
240
241         uiNodeId_g = EplApiInitParam.m_uiNodeId;
242
243         // calculate IP address
244         EplApiInitParam.m_dwIpAddress =
245             (0xFFFFFF00 & IP_ADDR) | EplApiInitParam.m_uiNodeId;
246
247         EplApiInitParam.m_fAsyncOnly = FALSE;
248
249         EplApiInitParam.m_uiSizeOfStruct = sizeof(EplApiInitParam);
250         EPL_MEMCPY(EplApiInitParam.m_abMacAddress, abMacAddr,
251                    sizeof(EplApiInitParam.m_abMacAddress));
252 //      EplApiInitParam.m_abMacAddress[5] = (u8) EplApiInitParam.m_uiNodeId;
253         EplApiInitParam.m_dwFeatureFlags = -1;
254         EplApiInitParam.m_dwCycleLen = uiCycleLen_g;    // required for error detection
255         EplApiInitParam.m_uiIsochrTxMaxPayload = 100;   // const
256         EplApiInitParam.m_uiIsochrRxMaxPayload = 100;   // const
257         EplApiInitParam.m_dwPresMaxLatency = 50000;     // const; only required for IdentRes
258         EplApiInitParam.m_uiPreqActPayloadLimit = 36;   // required for initialisation (+28 bytes)
259         EplApiInitParam.m_uiPresActPayloadLimit = 36;   // required for initialisation of Pres frame (+28 bytes)
260         EplApiInitParam.m_dwAsndMaxLatency = 150000;    // const; only required for IdentRes
261         EplApiInitParam.m_uiMultiplCycleCnt = 0;        // required for error detection
262         EplApiInitParam.m_uiAsyncMtu = 1500;    // required to set up max frame size
263         EplApiInitParam.m_uiPrescaler = 2;      // required for sync
264         EplApiInitParam.m_dwLossOfFrameTolerance = 500000;
265         EplApiInitParam.m_dwAsyncSlotTimeout = 3000000;
266         EplApiInitParam.m_dwWaitSocPreq = 150000;
267         EplApiInitParam.m_dwDeviceType = -1;    // NMT_DeviceType_U32
268         EplApiInitParam.m_dwVendorId = -1;      // NMT_IdentityObject_REC.VendorId_U32
269         EplApiInitParam.m_dwProductCode = -1;   // NMT_IdentityObject_REC.ProductCode_U32
270         EplApiInitParam.m_dwRevisionNumber = -1;        // NMT_IdentityObject_REC.RevisionNo_U32
271         EplApiInitParam.m_dwSerialNumber = -1;  // NMT_IdentityObject_REC.SerialNo_U32
272         EplApiInitParam.m_dwSubnetMask = SUBNET_MASK;
273         EplApiInitParam.m_dwDefaultGateway = 0;
274         EPL_MEMCPY(EplApiInitParam.m_sHostname, sHostname,
275                    sizeof(EplApiInitParam.m_sHostname));
276
277         // currently unset parameters left at default value 0
278         //EplApiInitParam.m_qwVendorSpecificExt1;
279         //EplApiInitParam.m_dwVerifyConfigurationDate; // CFM_VerifyConfiguration_REC.ConfDate_U32
280         //EplApiInitParam.m_dwVerifyConfigurationTime; // CFM_VerifyConfiguration_REC.ConfTime_U32
281         //EplApiInitParam.m_dwApplicationSwDate;       // PDL_LocVerApplSw_REC.ApplSwDate_U32 on programmable device or date portion of NMT_ManufactSwVers_VS on non-programmable device
282         //EplApiInitParam.m_dwApplicationSwTime;       // PDL_LocVerApplSw_REC.ApplSwTime_U32 on programmable device or time portion of NMT_ManufactSwVers_VS on non-programmable device
283         //EplApiInitParam.m_abVendorSpecificExt2[48];
284
285         // set callback functions
286         EplApiInitParam.m_pfnCbEvent = AppCbEvent;
287         EplApiInitParam.m_pfnCbSync = AppCbSync;
288
289         printk
290             ("\n\n Hello, I'm a simple POWERLINK node running as %s!\n  (build: %s / %s)\n\n",
291              (uiNodeId_g ==
292               EPL_C_ADR_MN_DEF_NODE_ID ? "Managing Node" : "Controlled Node"),
293              __DATE__, __TIME__);
294
295         // initialize the Linux a wait queue for shutdown of this module
296         init_waitqueue_head(&WaitQueueShutdown_g);
297
298         // initialize the procfs device
299         EplRet = EplLinProcInit();
300         if (EplRet != kEplSuccessful) {
301                 goto Exit;
302         }
303         // initialize POWERLINK stack
304         EplRet = EplApiInitialize(&EplApiInitParam);
305         if (EplRet != kEplSuccessful) {
306                 goto Exit;
307         }
308         // link process variables used by CN to object dictionary
309         ObdSize = sizeof(bVarIn1_l);
310         uiVarEntries = 1;
311         EplRet =
312             EplApiLinkObject(0x6000, &bVarIn1_l, &uiVarEntries, &ObdSize, 0x01);
313         if (EplRet != kEplSuccessful) {
314                 goto Exit;
315         }
316
317         ObdSize = sizeof(bVarOut1_l);
318         uiVarEntries = 1;
319         EplRet =
320             EplApiLinkObject(0x6200, &bVarOut1_l, &uiVarEntries, &ObdSize,
321                              0x01);
322         if (EplRet != kEplSuccessful) {
323                 goto Exit;
324         }
325         // link process variables used by MN to object dictionary
326 #if(((EPL_MODULE_INTEGRATION) & (EPL_MODULE_NMT_MN)) != 0)
327         ObdSize = sizeof(bLedsRow1_l);
328         uiVarEntries = 1;
329         EplRet =
330             EplApiLinkObject(0x2000, &bLedsRow1_l, &uiVarEntries, &ObdSize,
331                              0x01);
332         if (EplRet != kEplSuccessful) {
333                 goto Exit;
334         }
335
336         ObdSize = sizeof(bLedsRow2_l);
337         uiVarEntries = 1;
338         EplRet =
339             EplApiLinkObject(0x2000, &bLedsRow2_l, &uiVarEntries, &ObdSize,
340                              0x02);
341         if (EplRet != kEplSuccessful) {
342                 goto Exit;
343         }
344
345         ObdSize = sizeof(bSpeedSelect_l);
346         uiVarEntries = 1;
347         EplRet =
348             EplApiLinkObject(0x2000, &bSpeedSelect_l, &uiVarEntries, &ObdSize,
349                              0x03);
350         if (EplRet != kEplSuccessful) {
351                 goto Exit;
352         }
353
354         ObdSize = sizeof(bSpeedSelectOld_l);
355         uiVarEntries = 1;
356         EplRet =
357             EplApiLinkObject(0x2000, &bSpeedSelectOld_l, &uiVarEntries,
358                              &ObdSize, 0x04);
359         if (EplRet != kEplSuccessful) {
360                 goto Exit;
361         }
362
363         ObdSize = sizeof(abSelect_l[0]);
364         uiVarEntries = sizeof(abSelect_l);
365         EplRet =
366             EplApiLinkObject(0x2200, &abSelect_l[0], &uiVarEntries, &ObdSize,
367                              0x01);
368         if (EplRet != kEplSuccessful) {
369                 goto Exit;
370         }
371 #endif
372
373         // link a DOMAIN to object 0x6100, but do not exit, if it is missing
374         ObdSize = sizeof(abDomain_l);
375         uiVarEntries = 1;
376         EplRet =
377             EplApiLinkObject(0x6100, &abDomain_l, &uiVarEntries, &ObdSize,
378                              0x00);
379         if (EplRet != kEplSuccessful) {
380                 printk("EplApiLinkObject(0x6100): returns 0x%X\n", EplRet);
381         }
382         // reset old process variables
383         bVarOut1Old_l = 0;
384         bSpeedSelectOld_l = 0;
385         dwMode_l = APP_DEFAULT_MODE;
386         iMaxCycleCount_l = DEFAULT_MAX_CYCLE_COUNT;
387
388         // configure IP address of virtual network interface
389         // for TCP/IP communication over the POWERLINK network
390         sprintf(sBuffer, "%u.%u.%u.%u",
391                 (EplApiInitParam.m_dwIpAddress >> 24),
392                 ((EplApiInitParam.m_dwIpAddress >> 16) & 0xFF),
393                 ((EplApiInitParam.m_dwIpAddress >> 8) & 0xFF),
394                 (EplApiInitParam.m_dwIpAddress & 0xFF));
395         /* set up a minimal environment */
396         iRet = 0;
397         envp[iRet++] = "HOME=/";
398         envp[iRet++] = "PATH=/sbin:/bin:/usr/sbin:/usr/bin";
399         envp[iRet] = NULL;
400
401         /* set up the argument list */
402         iRet = 0;
403         argv[iRet++] = "/sbin/ifconfig";
404         argv[iRet++] = IF_ETH;
405         argv[iRet++] = sBuffer;
406         argv[iRet] = NULL;
407
408         /* call ifconfig to configure the virtual network interface */
409         iRet = call_usermodehelper(argv[0], argv, envp, 1);
410         printk("ifconfig %s %s returned %d\n", argv[1], argv[2], iRet);
411
412         // start the NMT state machine
413         EplRet = EplApiExecNmtCommand(kEplNmtEventSwReset);
414         atomic_set(&AtomicShutdown_g, FALSE);
415
416       Exit:
417         printk("EplLinInit(): returns 0x%X\n", EplRet);
418         return EplRet;
419 }
420
421 static void __exit EplLinExit(void)
422 {
423         tEplKernel EplRet;
424
425         // halt the NMT state machine
426         // so the processing of POWERLINK frames stops
427         EplRet = EplApiExecNmtCommand(kEplNmtEventSwitchOff);
428
429         // wait until NMT state machine is shut down
430         wait_event_interruptible(WaitQueueShutdown_g,
431                                  (atomic_read(&AtomicShutdown_g) == TRUE));
432 /*    if ((iErr != 0) || (atomic_read(&AtomicShutdown_g) == EVENT_STATE_IOCTL))
433     {   // waiting was interrupted by signal or application called wrong function
434         EplRet = kEplShutdown;
435     }*/
436         // delete instance for all modules
437         EplRet = EplApiShutdown();
438         printk("EplApiShutdown():  0x%X\n", EplRet);
439
440         // deinitialize proc fs
441         EplRet = EplLinProcFree();
442         printk("EplLinProcFree():        0x%X\n", EplRet);
443
444 }
445 #endif
446 //=========================================================================//
447 //                                                                         //
448 //          P R I V A T E   F U N C T I O N S                              //
449 //                                                                         //
450 //=========================================================================//
451
452 //---------------------------------------------------------------------------
453 //
454 // Function:    AppCbEvent
455 //
456 // Description: event callback function called by EPL API layer within
457 //              user part (low priority).
458 //
459 // Parameters:  EventType_p     = event type
460 //              pEventArg_p     = pointer to union, which describes
461 //                                the event in detail
462 //              pUserArg_p      = user specific argument
463 //
464 // Returns:     tEplKernel      = error code,
465 //                                kEplSuccessful = no error
466 //                                kEplReject = reject further processing
467 //                                otherwise = post error event to API layer
468 //
469 // State:
470 //
471 //---------------------------------------------------------------------------
472
473 tEplKernel AppCbEvent(tEplApiEventType EventType_p,     // IN: event type (enum)
474                       tEplApiEventArg *pEventArg_p,     // IN: event argument (union)
475                       void *pUserArg_p)
476 {
477         tEplKernel EplRet = kEplSuccessful;
478
479         // check if NMT_GS_OFF is reached
480         switch (EventType_p) {
481         case kEplApiEventNmtStateChange:
482                 {
483                         switch (pEventArg_p->m_NmtStateChange.m_NewNmtState) {
484                         case kEplNmtGsOff:
485                                 {       // NMT state machine was shut down,
486                                         // because of user signal (CTRL-C) or critical EPL stack error
487                                         // -> also shut down EplApiProcess() and main()
488                                         EplRet = kEplShutdown;
489
490                                         printk
491                                             ("AppCbEvent(kEplNmtGsOff) originating event = 0x%X\n",
492                                              pEventArg_p->m_NmtStateChange.
493                                              m_NmtEvent);
494
495                                         // wake up EplLinExit()
496                                         atomic_set(&AtomicShutdown_g, TRUE);
497                                         wake_up_interruptible
498                                             (&WaitQueueShutdown_g);
499                                         break;
500                                 }
501
502                         case kEplNmtGsResetCommunication:
503                                 {
504                                         u32 dwBuffer;
505
506                                         // configure OD for MN in state ResetComm after reseting the OD
507                                         // TODO: setup your own network configuration here
508                                         dwBuffer = (EPL_NODEASSIGN_NODE_IS_CN | EPL_NODEASSIGN_NODE_EXISTS);    // 0x00000003L
509                                         EplRet =
510                                             EplApiWriteLocalObject(0x1F81, 0x01,
511                                                                    &dwBuffer,
512                                                                    4);
513                                         EplRet =
514                                             EplApiWriteLocalObject(0x1F81, 0x02,
515                                                                    &dwBuffer,
516                                                                    4);
517                                         EplRet =
518                                             EplApiWriteLocalObject(0x1F81, 0x03,
519                                                                    &dwBuffer,
520                                                                    4);
521                                         EplRet =
522                                             EplApiWriteLocalObject(0x1F81, 0x04,
523                                                                    &dwBuffer,
524                                                                    4);
525                                         EplRet =
526                                             EplApiWriteLocalObject(0x1F81, 0x05,
527                                                                    &dwBuffer,
528                                                                    4);
529                                         EplRet =
530                                             EplApiWriteLocalObject(0x1F81, 0x06,
531                                                                    &dwBuffer,
532                                                                    4);
533                                         EplRet =
534                                             EplApiWriteLocalObject(0x1F81, 0x07,
535                                                                    &dwBuffer,
536                                                                    4);
537                                         EplRet =
538                                             EplApiWriteLocalObject(0x1F81, 0x08,
539                                                                    &dwBuffer,
540                                                                    4);
541                                         EplRet =
542                                             EplApiWriteLocalObject(0x1F81, 0x20,
543                                                                    &dwBuffer,
544                                                                    4);
545                                         EplRet =
546                                             EplApiWriteLocalObject(0x1F81, 0xFE,
547                                                                    &dwBuffer,
548                                                                    4);
549                                         EplRet =
550                                             EplApiWriteLocalObject(0x1F81, 0x6E,
551                                                                    &dwBuffer,
552                                                                    4);
553
554 //                    dwBuffer |= EPL_NODEASSIGN_MANDATORY_CN;    // 0x0000000BL
555 //                    EplRet = EplApiWriteLocalObject(0x1F81, 0x6E, &dwBuffer, 4);
556                                         dwBuffer = (EPL_NODEASSIGN_MN_PRES | EPL_NODEASSIGN_NODE_EXISTS);       // 0x00010001L
557                                         EplRet =
558                                             EplApiWriteLocalObject(0x1F81, 0xF0,
559                                                                    &dwBuffer,
560                                                                    4);
561
562                                         // continue
563                                 }
564
565                         case kEplNmtGsResetConfiguration:
566                                 {
567                                         unsigned int uiSize;
568
569                                         // fetch object 0x1006 NMT_CycleLen_U32 from local OD (in little endian byte order)
570                                         // for configuration of remote CN
571                                         uiSize = 4;
572                                         EplRet =
573                                             EplApiReadObject(NULL, 0, 0x1006,
574                                                              0x00,
575                                                              &dw_le_CycleLen_g,
576                                                              &uiSize,
577                                                              kEplSdoTypeAsnd,
578                                                              NULL);
579                                         if (EplRet != kEplSuccessful) { // local OD access failed
580                                                 break;
581                                         }
582                                         // continue
583                                 }
584
585                         case kEplNmtMsPreOperational1:
586                                 {
587                                         printk
588                                             ("AppCbEvent(0x%X) originating event = 0x%X\n",
589                                              pEventArg_p->m_NmtStateChange.
590                                              m_NewNmtState,
591                                              pEventArg_p->m_NmtStateChange.
592                                              m_NmtEvent);
593
594                                         // continue
595                                 }
596
597                         case kEplNmtGsInitialising:
598                         case kEplNmtGsResetApplication:
599                         case kEplNmtMsNotActive:
600                         case kEplNmtCsNotActive:
601                         case kEplNmtCsPreOperational1:
602                                 {
603                                         break;
604                                 }
605
606                         case kEplNmtCsOperational:
607                         case kEplNmtMsOperational:
608                                 {
609                                         break;
610                                 }
611
612                         default:
613                                 {
614                                         break;
615                                 }
616                         }
617
618 /*
619             switch (pEventArg_p->m_NmtStateChange.m_NmtEvent)
620             {
621                 case kEplNmtEventSwReset:
622                 case kEplNmtEventResetNode:
623                 case kEplNmtEventResetCom:
624                 case kEplNmtEventResetConfig:
625                 case kEplNmtEventInternComError:
626                 case kEplNmtEventNmtCycleError:
627                 {
628                     printk("AppCbEvent(0x%X) originating event = 0x%X\n",
629                            pEventArg_p->m_NmtStateChange.m_NewNmtState,
630                            pEventArg_p->m_NmtStateChange.m_NmtEvent);
631                     break;
632                 }
633
634                 default:
635                 {
636                     break;
637                 }
638             }
639 */
640                         break;
641                 }
642
643         case kEplApiEventCriticalError:
644         case kEplApiEventWarning:
645                 {               // error or warning occured within the stack or the application
646                         // on error the API layer stops the NMT state machine
647
648                         printk
649                             ("AppCbEvent(Err/Warn): Source=%02X EplError=0x%03X",
650                              pEventArg_p->m_InternalError.m_EventSource,
651                              pEventArg_p->m_InternalError.m_EplError);
652                         // check additional argument
653                         switch (pEventArg_p->m_InternalError.m_EventSource) {
654                         case kEplEventSourceEventk:
655                         case kEplEventSourceEventu:
656                                 {       // error occured within event processing
657                                         // either in kernel or in user part
658                                         printk(" OrgSource=%02X\n",
659                                                pEventArg_p->m_InternalError.
660                                                m_Arg.m_EventSource);
661                                         break;
662                                 }
663
664                         case kEplEventSourceDllk:
665                                 {       // error occured within the data link layer (e.g. interrupt processing)
666                                         // the u32 argument contains the DLL state and the NMT event
667                                         printk(" val=%X\n",
668                                                pEventArg_p->m_InternalError.
669                                                m_Arg.m_dwArg);
670                                         break;
671                                 }
672
673                         default:
674                                 {
675                                         printk("\n");
676                                         break;
677                                 }
678                         }
679                         break;
680                 }
681
682         case kEplApiEventNode:
683                 {
684 //            printk("AppCbEvent(Node): Source=%02X EplError=0x%03X", pEventArg_p->m_InternalError.m_EventSource, pEventArg_p->m_InternalError.m_EplError);
685                         // check additional argument
686                         switch (pEventArg_p->m_Node.m_NodeEvent) {
687                         case kEplNmtNodeEventCheckConf:
688                                 {
689                                         tEplSdoComConHdl SdoComConHdl;
690                                         // update object 0x1006 on CN
691                                         EplRet =
692                                             EplApiWriteObject(&SdoComConHdl,
693                                                               pEventArg_p->
694                                                               m_Node.m_uiNodeId,
695                                                               0x1006, 0x00,
696                                                               &dw_le_CycleLen_g,
697                                                               4,
698                                                               kEplSdoTypeAsnd,
699                                                               NULL);
700                                         if (EplRet == kEplApiTaskDeferred) {    // SDO transfer started
701                                                 EplRet = kEplReject;
702                                         } else if (EplRet == kEplSuccessful) {  // local OD access (should not occur)
703                                                 printk
704                                                     ("AppCbEvent(Node) write to local OD\n");
705                                         } else {        // error occured
706                                                 TGT_DBG_SIGNAL_TRACE_POINT(1);
707
708                                                 EplRet =
709                                                     EplApiFreeSdoChannel
710                                                     (SdoComConHdl);
711                                                 SdoComConHdl = 0;
712
713                                                 EplRet =
714                                                     EplApiWriteObject
715                                                     (&SdoComConHdl,
716                                                      pEventArg_p->m_Node.
717                                                      m_uiNodeId, 0x1006, 0x00,
718                                                      &dw_le_CycleLen_g, 4,
719                                                      kEplSdoTypeAsnd, NULL);
720                                                 if (EplRet == kEplApiTaskDeferred) {    // SDO transfer started
721                                                         EplRet = kEplReject;
722                                                 } else {
723                                                         printk
724                                                             ("AppCbEvent(Node): EplApiWriteObject() returned 0x%02X\n",
725                                                              EplRet);
726                                                 }
727                                         }
728
729                                         break;
730                                 }
731
732                         default:
733                                 {
734                                         break;
735                                 }
736                         }
737                         break;
738                 }
739
740         case kEplApiEventSdo:
741                 {               // SDO transfer finished
742                         EplRet =
743                             EplApiFreeSdoChannel(pEventArg_p->m_Sdo.
744                                                  m_SdoComConHdl);
745                         if (EplRet != kEplSuccessful) {
746                                 break;
747                         }
748 #if(((EPL_MODULE_INTEGRATION) & (EPL_MODULE_NMT_MN)) != 0)
749                         if (pEventArg_p->m_Sdo.m_SdoComConState == kEplSdoComTransferFinished) {        // continue boot-up of CN with NMT command Reset Configuration
750                                 EplRet =
751                                     EplApiMnTriggerStateChange(pEventArg_p->
752                                                                m_Sdo.m_uiNodeId,
753                                                                kEplNmtNodeCommandConfReset);
754                         } else {        // indicate configuration error CN
755                                 EplRet =
756                                     EplApiMnTriggerStateChange(pEventArg_p->
757                                                                m_Sdo.m_uiNodeId,
758                                                                kEplNmtNodeCommandConfErr);
759                         }
760 #endif
761
762                         break;
763                 }
764
765         default:
766                 break;
767         }
768
769         return EplRet;
770 }
771
772 //---------------------------------------------------------------------------
773 //
774 // Function:    AppCbSync
775 //
776 // Description: sync event callback function called by event module within
777 //              kernel part (high priority).
778 //              This function sets the outputs, reads the inputs and runs
779 //              the control loop.
780 //
781 // Parameters:  void
782 //
783 // Returns:     tEplKernel      = error code,
784 //                                kEplSuccessful = no error
785 //                                otherwise = post error event to API layer
786 //
787 // State:
788 //
789 //---------------------------------------------------------------------------
790
791 tEplKernel AppCbSync(void)
792 {
793         tEplKernel EplRet = kEplSuccessful;
794
795         if (bVarOut1Old_l != bVarOut1_l) {      // output variable has changed
796                 bVarOut1Old_l = bVarOut1_l;
797                 // set LEDs
798
799 //        printk("bVarIn = 0x%02X bVarOut = 0x%02X\n", (u16) bVarIn_l, (u16) bVarOut_l);
800         }
801         if (uiNodeId_g != EPL_C_ADR_MN_DEF_NODE_ID) {
802                 bVarIn1_l++;
803         }
804
805         if (uiNodeId_g == EPL_C_ADR_MN_DEF_NODE_ID) {   // we are the master and must run the control loop
806
807                 // collect inputs from CNs and own input
808                 bSpeedSelect_l = (bVarIn1_l | abSelect_l[0]) & 0x07;
809
810                 bModeSelect_l = abSelect_l[1] | abSelect_l[2];
811
812                 if ((bModeSelect_l & APP_MODE_MASK) != 0) {
813                         dwMode_l = bModeSelect_l & APP_MODE_MASK;
814                 }
815
816                 iCurCycleCount_l--;
817
818                 if (iCurCycleCount_l <= 0) {
819                         if ((dwMode_l & 0x01) != 0) {   // fill-up
820                                 if (iToggle) {
821                                         if ((dwLeds_l & APP_DOUBLE_LED_MASK) ==
822                                             0x00) {
823                                                 dwLeds_l = 0x01;
824                                         } else {
825                                                 dwLeds_l <<= 1;
826                                                 dwLeds_l++;
827                                                 if (dwLeds_l >=
828                                                     APP_DOUBLE_LED_MASK) {
829                                                         iToggle = 0;
830                                                 }
831                                         }
832                                 } else {
833                                         dwLeds_l <<= 1;
834                                         if ((dwLeds_l & APP_DOUBLE_LED_MASK) ==
835                                             0x00) {
836                                                 iToggle = 1;
837                                         }
838                                 }
839                                 bLedsRow1_l =
840                                     (unsigned char)(dwLeds_l & APP_LED_MASK);
841                                 bLedsRow2_l =
842                                     (unsigned char)((dwLeds_l >> APP_LED_COUNT)
843                                                     & APP_LED_MASK);
844                         }
845
846                         else if ((dwMode_l & 0x02) != 0) {      // running light forward
847                                 dwLeds_l <<= 1;
848                                 if ((dwLeds_l > APP_DOUBLE_LED_MASK)
849                                     || (dwLeds_l == 0x00000000L)) {
850                                         dwLeds_l = 0x01;
851                                 }
852                                 bLedsRow1_l =
853                                     (unsigned char)(dwLeds_l & APP_LED_MASK);
854                                 bLedsRow2_l =
855                                     (unsigned char)((dwLeds_l >> APP_LED_COUNT)
856                                                     & APP_LED_MASK);
857                         }
858
859                         else if ((dwMode_l & 0x04) != 0) {      // running light backward
860                                 dwLeds_l >>= 1;
861                                 if ((dwLeds_l > APP_DOUBLE_LED_MASK)
862                                     || (dwLeds_l == 0x00000000L)) {
863                                         dwLeds_l = 1 << (APP_LED_COUNT * 2);
864                                 }
865                                 bLedsRow1_l =
866                                     (unsigned char)(dwLeds_l & APP_LED_MASK);
867                                 bLedsRow2_l =
868                                     (unsigned char)((dwLeds_l >> APP_LED_COUNT)
869                                                     & APP_LED_MASK);
870                         }
871
872                         else if ((dwMode_l & 0x08) != 0) {      // Knightrider
873                                 if (bLedsRow1_l == 0x00) {
874                                         bLedsRow1_l = 0x01;
875                                         iToggle = 1;
876                                 } else if (iToggle) {
877                                         bLedsRow1_l <<= 1;
878                                         if (bLedsRow1_l >=
879                                             (1 << (APP_LED_COUNT - 1))) {
880                                                 iToggle = 0;
881                                         }
882                                 } else {
883                                         bLedsRow1_l >>= 1;
884                                         if (bLedsRow1_l <= 0x01) {
885                                                 iToggle = 1;
886                                         }
887                                 }
888                                 bLedsRow2_l = bLedsRow1_l;
889                         }
890
891                         else if ((dwMode_l & 0x10) != 0) {      // Knightrider
892                                 if ((bLedsRow1_l == 0x00)
893                                     || (bLedsRow2_l == 0x00)
894                                     || ((bLedsRow2_l & ~APP_LED_MASK) != 0)) {
895                                         bLedsRow1_l = 0x01;
896                                         bLedsRow2_l =
897                                             (1 << (APP_LED_COUNT - 1));
898                                         iToggle = 1;
899                                 } else if (iToggle) {
900                                         bLedsRow1_l <<= 1;
901                                         bLedsRow2_l >>= 1;
902                                         if (bLedsRow1_l >=
903                                             (1 << (APP_LED_COUNT - 1))) {
904                                                 iToggle = 0;
905                                         }
906                                 } else {
907                                         bLedsRow1_l >>= 1;
908                                         bLedsRow2_l <<= 1;
909                                         if (bLedsRow1_l <= 0x01) {
910                                                 iToggle = 1;
911                                         }
912                                 }
913                         }
914                         // set own output
915                         bVarOut1_l = bLedsRow1_l;
916 //            bVarOut1_l = (bLedsRow1_l & 0x03) | (bLedsRow2_l << 2);
917
918                         // restart cycle counter
919                         iCurCycleCount_l = iMaxCycleCount_l;
920                 }
921
922                 if (bSpeedSelectOld_l == 0) {
923                         if ((bSpeedSelect_l & 0x01) != 0) {
924                                 if (iMaxCycleCount_l < 200) {
925                                         iMaxCycleCount_l++;
926                                 }
927                                 bSpeedSelectOld_l = bSpeedSelect_l;
928                         } else if ((bSpeedSelect_l & 0x02) != 0) {
929                                 if (iMaxCycleCount_l > 1) {
930                                         iMaxCycleCount_l--;
931                                 }
932                                 bSpeedSelectOld_l = bSpeedSelect_l;
933                         } else if ((bSpeedSelect_l & 0x04) != 0) {
934                                 iMaxCycleCount_l = DEFAULT_MAX_CYCLE_COUNT;
935                                 bSpeedSelectOld_l = bSpeedSelect_l;
936                         }
937                 } else if (bSpeedSelect_l == 0) {
938                         bSpeedSelectOld_l = 0;
939                 }
940         }
941
942         TGT_DBG_SIGNAL_TRACE_POINT(1);
943
944         return EplRet;
945 }
946
947 // EOF