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