Merge branch 'kmemtrace-for-linus' of git://git.kernel.org/pub/scm/linux/kernel/git...
[sfrench/cifs-2.6.git] / drivers / staging / epl / EplNmtMnu.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:  source file for NMT-MN-Module
9
10   License:
11
12     Redistribution and use in source and binary forms, with or without
13     modification, are permitted provided that the following conditions
14     are met:
15
16     1. Redistributions of source code must retain the above copyright
17        notice, this list of conditions and the following disclaimer.
18
19     2. Redistributions in binary form must reproduce the above copyright
20        notice, this list of conditions and the following disclaimer in the
21        documentation and/or other materials provided with the distribution.
22
23     3. Neither the name of SYSTEC electronic GmbH nor the names of its
24        contributors may be used to endorse or promote products derived
25        from this software without prior written permission. For written
26        permission, please contact info@systec-electronic.com.
27
28     THIS SOFTWARE IS PROVIDED BY THE COPYRIGHT HOLDERS AND CONTRIBUTORS
29     "AS IS" AND ANY EXPRESS OR IMPLIED WARRANTIES, INCLUDING, BUT NOT
30     LIMITED TO, THE IMPLIED WARRANTIES OF MERCHANTABILITY AND FITNESS
31     FOR A PARTICULAR PURPOSE ARE DISCLAIMED. IN NO EVENT SHALL THE
32     COPYRIGHT HOLDERS OR CONTRIBUTORS BE LIABLE FOR ANY DIRECT, INDIRECT,
33     INCIDENTAL, SPECIAL, EXEMPLARY, OR CONSEQUENTIAL DAMAGES (INCLUDING,
34     BUT NOT LIMITED TO, PROCUREMENT OF SUBSTITUTE GOODS OR SERVICES;
35     LOSS OF USE, DATA, OR PROFITS; OR BUSINESS INTERRUPTION) HOWEVER
36     CAUSED AND ON ANY THEORY OF LIABILITY, WHETHER IN CONTRACT, STRICT
37     LIABILITY, OR TORT (INCLUDING NEGLIGENCE OR OTHERWISE) ARISING IN
38     ANY WAY OUT OF THE USE OF THIS SOFTWARE, EVEN IF ADVISED OF THE
39     POSSIBILITY OF SUCH DAMAGE.
40
41     Severability Clause:
42
43         If a provision of this License is or becomes illegal, invalid or
44         unenforceable in any jurisdiction, that shall not affect:
45         1. the validity or enforceability in that jurisdiction of any other
46            provision of this License; or
47         2. the validity or enforceability in other jurisdictions of that or
48            any other provision of this License.
49
50   -------------------------------------------------------------------------
51
52                 $RCSfile: EplNmtMnu.c,v $
53
54                 $Author: D.Krueger $
55
56                 $Revision: 1.18 $  $Date: 2008/11/19 09:52:24 $
57
58                 $State: Exp $
59
60                 Build Environment:
61                     GCC V3.4
62
63   -------------------------------------------------------------------------
64
65   Revision History:
66
67   2006/06/09 k.t.:   start of the implementation
68
69 ****************************************************************************/
70
71 #include "user/EplNmtMnu.h"
72 #include "user/EplTimeru.h"
73 #include "user/EplIdentu.h"
74 #include "user/EplStatusu.h"
75 #include "user/EplObdu.h"
76 #include "user/EplDlluCal.h"
77 #include "Benchmark.h"
78
79 #if (((EPL_MODULE_INTEGRATION) & (EPL_MODULE_NMT_MN)) != 0)
80
81 #if (((EPL_MODULE_INTEGRATION) & (EPL_MODULE_OBDU)) == 0) && (EPL_OBD_USE_KERNEL == FALSE)
82 #error "EPL NmtMnu module needs EPL module OBDU or OBDK!"
83 #endif
84
85 //=========================================================================//
86 //                                                                         //
87 //          P R I V A T E   D E F I N I T I O N S                          //
88 //                                                                         //
89 //=========================================================================//
90
91 //---------------------------------------------------------------------------
92 // const defines
93 //---------------------------------------------------------------------------
94
95 // TracePoint support for realtime-debugging
96 #ifdef _DBG_TRACE_POINTS_
97 void TgtDbgSignalTracePoint(u8 bTracePointNumber_p);
98 void TgtDbgPostTraceValue(u32 dwTraceValue_p);
99 #define TGT_DBG_SIGNAL_TRACE_POINT(p)   TgtDbgSignalTracePoint(p)
100 #define TGT_DBG_POST_TRACE_VALUE(v)     TgtDbgPostTraceValue(v)
101 #else
102 #define TGT_DBG_SIGNAL_TRACE_POINT(p)
103 #define TGT_DBG_POST_TRACE_VALUE(v)
104 #endif
105 #define EPL_NMTMNU_DBG_POST_TRACE_VALUE(Event_p, uiNodeId_p, wErrorCode_p) \
106     TGT_DBG_POST_TRACE_VALUE((kEplEventSinkNmtMnu << 28) | (Event_p << 24) \
107                              | (uiNodeId_p << 16) | wErrorCode_p)
108
109 // defines for flags in node info structure
110 #define EPL_NMTMNU_NODE_FLAG_ISOCHRON       0x0001      // CN is being accessed isochronously
111 #define EPL_NMTMNU_NODE_FLAG_NOT_SCANNED    0x0002      // CN was not scanned once -> decrement SignalCounter and reset flag
112 #define EPL_NMTMNU_NODE_FLAG_HALTED         0x0004      // boot process for this CN is halted
113 #define EPL_NMTMNU_NODE_FLAG_NMT_CMD_ISSUED 0x0008      // NMT command was just issued, wrong NMT states will be tolerated
114 #define EPL_NMTMNU_NODE_FLAG_COUNT_STATREQ  0x0300      // counter for StatusRequest timer handle
115 #define EPL_NMTMNU_NODE_FLAG_COUNT_LONGER   0x0C00      // counter for longer timeouts timer handle
116 #define EPL_NMTMNU_NODE_FLAG_INC_STATREQ    0x0100      // increment for StatusRequest timer handle
117 #define EPL_NMTMNU_NODE_FLAG_INC_LONGER     0x0400      // increment for longer timeouts timer handle
118                     // These counters will be incremented at every timer start
119                     // and copied to timerarg. When the timer event occures
120                     // both will be compared and if unequal the timer event
121                     // will be discarded, because it is an old one.
122
123 // defines for timer arguments to draw a distinction between serveral events
124 #define EPL_NMTMNU_TIMERARG_NODE_MASK   0x000000FFL     // mask that contains the node-ID
125 #define EPL_NMTMNU_TIMERARG_IDENTREQ    0x00010000L     // timer event is for IdentRequest
126 #define EPL_NMTMNU_TIMERARG_STATREQ     0x00020000L     // timer event is for StatusRequest
127 #define EPL_NMTMNU_TIMERARG_LONGER      0x00040000L     // timer event is for longer timeouts
128 #define EPL_NMTMNU_TIMERARG_STATE_MON   0x00080000L     // timer event for StatusRequest to monitor execution of NMT state changes
129 #define EPL_NMTMNU_TIMERARG_COUNT_SR    0x00000300L     // counter for StatusRequest
130 #define EPL_NMTMNU_TIMERARG_COUNT_LO    0x00000C00L     // counter for longer timeouts
131                     // The counters must have the same position as in the node flags above.
132
133 #define EPL_NMTMNU_SET_FLAGS_TIMERARG_STATREQ(pNodeInfo_p, uiNodeId_p, TimerArg_p) \
134     pNodeInfo_p->m_wFlags = \
135         ((pNodeInfo_p->m_wFlags + EPL_NMTMNU_NODE_FLAG_INC_STATREQ) \
136          & EPL_NMTMNU_NODE_FLAG_COUNT_STATREQ) \
137         | (pNodeInfo_p->m_wFlags & ~EPL_NMTMNU_NODE_FLAG_COUNT_STATREQ); \
138     TimerArg_p.m_ulArg = EPL_NMTMNU_TIMERARG_STATREQ | uiNodeId_p | \
139         (pNodeInfo_p->m_wFlags & EPL_NMTMNU_NODE_FLAG_COUNT_STATREQ); \
140     TimerArg_p.m_EventSink = kEplEventSinkNmtMnu;
141
142 #define EPL_NMTMNU_SET_FLAGS_TIMERARG_IDENTREQ(pNodeInfo_p, uiNodeId_p, TimerArg_p) \
143     pNodeInfo_p->m_wFlags = \
144         ((pNodeInfo_p->m_wFlags + EPL_NMTMNU_NODE_FLAG_INC_STATREQ) \
145          & EPL_NMTMNU_NODE_FLAG_COUNT_STATREQ) \
146         | (pNodeInfo_p->m_wFlags & ~EPL_NMTMNU_NODE_FLAG_COUNT_STATREQ); \
147     TimerArg_p.m_ulArg = EPL_NMTMNU_TIMERARG_IDENTREQ | uiNodeId_p | \
148         (pNodeInfo_p->m_wFlags & EPL_NMTMNU_NODE_FLAG_COUNT_STATREQ); \
149     TimerArg_p.m_EventSink = kEplEventSinkNmtMnu;
150
151 #define EPL_NMTMNU_SET_FLAGS_TIMERARG_LONGER(pNodeInfo_p, uiNodeId_p, TimerArg_p) \
152     pNodeInfo_p->m_wFlags = \
153         ((pNodeInfo_p->m_wFlags + EPL_NMTMNU_NODE_FLAG_INC_LONGER) \
154          & EPL_NMTMNU_NODE_FLAG_COUNT_LONGER) \
155         | (pNodeInfo_p->m_wFlags & ~EPL_NMTMNU_NODE_FLAG_COUNT_LONGER); \
156     TimerArg_p.m_ulArg = EPL_NMTMNU_TIMERARG_LONGER | uiNodeId_p | \
157         (pNodeInfo_p->m_wFlags & EPL_NMTMNU_NODE_FLAG_COUNT_LONGER); \
158     TimerArg_p.m_EventSink = kEplEventSinkNmtMnu;
159
160 #define EPL_NMTMNU_SET_FLAGS_TIMERARG_STATE_MON(pNodeInfo_p, uiNodeId_p, TimerArg_p) \
161     pNodeInfo_p->m_wFlags = \
162         ((pNodeInfo_p->m_wFlags + EPL_NMTMNU_NODE_FLAG_INC_STATREQ) \
163          & EPL_NMTMNU_NODE_FLAG_COUNT_STATREQ) \
164         | (pNodeInfo_p->m_wFlags & ~EPL_NMTMNU_NODE_FLAG_COUNT_STATREQ); \
165     TimerArg_p.m_ulArg = EPL_NMTMNU_TIMERARG_STATE_MON | uiNodeId_p | \
166         (pNodeInfo_p->m_wFlags & EPL_NMTMNU_NODE_FLAG_COUNT_STATREQ); \
167     TimerArg_p.m_EventSink = kEplEventSinkNmtMnu;
168
169 // defines for global flags
170 #define EPL_NMTMNU_FLAG_HALTED          0x0001  // boot process is halted
171 #define EPL_NMTMNU_FLAG_APP_INFORMED    0x0002  // application was informed about possible NMT state change
172
173 // return pointer to node info structure for specified node ID
174 // d.k. may be replaced by special (hash) function if node ID array is smaller than 254
175 #define EPL_NMTMNU_GET_NODEINFO(uiNodeId_p) (&EplNmtMnuInstance_g.m_aNodeInfo[uiNodeId_p - 1])
176
177 //---------------------------------------------------------------------------
178 // local types
179 //---------------------------------------------------------------------------
180
181 typedef enum {
182         kEplNmtMnuIntNodeEventNoIdentResponse = 0x00,
183         kEplNmtMnuIntNodeEventIdentResponse = 0x01,
184         kEplNmtMnuIntNodeEventBoot = 0x02,
185         kEplNmtMnuIntNodeEventExecReset = 0x03,
186         kEplNmtMnuIntNodeEventConfigured = 0x04,
187         kEplNmtMnuIntNodeEventNoStatusResponse = 0x05,
188         kEplNmtMnuIntNodeEventStatusResponse = 0x06,
189         kEplNmtMnuIntNodeEventHeartbeat = 0x07,
190         kEplNmtMnuIntNodeEventNmtCmdSent = 0x08,
191         kEplNmtMnuIntNodeEventTimerIdentReq = 0x09,
192         kEplNmtMnuIntNodeEventTimerStatReq = 0x0A,
193         kEplNmtMnuIntNodeEventTimerStateMon = 0x0B,
194         kEplNmtMnuIntNodeEventTimerLonger = 0x0C,
195         kEplNmtMnuIntNodeEventError = 0x0D,
196
197 } tEplNmtMnuIntNodeEvent;
198
199 typedef enum {
200         kEplNmtMnuNodeStateUnknown = 0x00,
201         kEplNmtMnuNodeStateIdentified = 0x01,
202         kEplNmtMnuNodeStateResetConf = 0x02,    // CN reset after configuration update
203         kEplNmtMnuNodeStateConfigured = 0x03,   // BootStep1 completed
204         kEplNmtMnuNodeStateReadyToOp = 0x04,    // BootStep2 completed
205         kEplNmtMnuNodeStateComChecked = 0x05,   // Communication checked successfully
206         kEplNmtMnuNodeStateOperational = 0x06,  // CN is in NMT state OPERATIONAL
207
208 } tEplNmtMnuNodeState;
209
210 typedef struct {
211         tEplTimerHdl m_TimerHdlStatReq; // timer to delay StatusRequests and IdentRequests
212         tEplTimerHdl m_TimerHdlLonger;  // 2nd timer for NMT command EnableReadyToOp and CheckCommunication
213         tEplNmtMnuNodeState m_NodeState;        // internal node state (kind of sub state of NMT state)
214         u32 m_dwNodeCfg;        // subindex from 0x1F81
215         u16 m_wFlags;           // flags: CN is being accessed isochronously
216
217 } tEplNmtMnuNodeInfo;
218
219 typedef struct {
220         tEplNmtMnuNodeInfo m_aNodeInfo[EPL_NMT_MAX_NODE_ID];
221         tEplTimerHdl m_TimerHdlNmtState;        // timeout for stay in NMT state
222         unsigned int m_uiMandatorySlaveCount;
223         unsigned int m_uiSignalSlaveCount;
224         unsigned long m_ulStatusRequestDelay;   // in [ms] (object 0x1006 * EPL_C_NMT_STATREQ_CYCLE)
225         unsigned long m_ulTimeoutReadyToOp;     // in [ms] (object 0x1F89/5)
226         unsigned long m_ulTimeoutCheckCom;      // in [ms] (object 0x1006 * MultiplexedCycleCount)
227         u16 m_wFlags;           // global flags
228         u32 m_dwNmtStartup;     // object 0x1F80 NMT_StartUp_U32
229         tEplNmtMnuCbNodeEvent m_pfnCbNodeEvent;
230         tEplNmtMnuCbBootEvent m_pfnCbBootEvent;
231
232 } tEplNmtMnuInstance;
233
234 //---------------------------------------------------------------------------
235 // local vars
236 //---------------------------------------------------------------------------
237
238 static tEplNmtMnuInstance EplNmtMnuInstance_g;
239
240 //---------------------------------------------------------------------------
241 // local function prototypes
242 //---------------------------------------------------------------------------
243
244 static tEplKernel EplNmtMnuCbNmtRequest(tEplFrameInfo *pFrameInfo_p);
245
246 static tEplKernel EplNmtMnuCbIdentResponse(unsigned int uiNodeId_p,
247                                            tEplIdentResponse *pIdentResponse_p);
248
249 static tEplKernel EplNmtMnuCbStatusResponse(unsigned int uiNodeId_p,
250                                             tEplStatusResponse *pStatusResponse_p);
251
252 static tEplKernel EplNmtMnuCheckNmtState(unsigned int uiNodeId_p,
253                                          tEplNmtMnuNodeInfo * pNodeInfo_p,
254                                          tEplNmtState NodeNmtState_p,
255                                          u16 wErrorCode_p,
256                                          tEplNmtState LocalNmtState_p);
257
258 static tEplKernel EplNmtMnuStartBootStep1(void);
259
260 static tEplKernel EplNmtMnuStartBootStep2(void);
261
262 static tEplKernel EplNmtMnuStartCheckCom(void);
263
264 static tEplKernel EplNmtMnuNodeBootStep2(unsigned int uiNodeId_p,
265                                          tEplNmtMnuNodeInfo * pNodeInfo_p);
266
267 static tEplKernel EplNmtMnuNodeCheckCom(unsigned int uiNodeId_p,
268                                         tEplNmtMnuNodeInfo * pNodeInfo_p);
269
270 static tEplKernel EplNmtMnuStartNodes(void);
271
272 static tEplKernel EplNmtMnuProcessInternalEvent(unsigned int uiNodeId_p,
273                                                 tEplNmtState NodeNmtState_p,
274                                                 u16 wErrorCode_p,
275                                                 tEplNmtMnuIntNodeEvent
276                                                 NodeEvent_p);
277
278 static tEplKernel EplNmtMnuReset(void);
279
280 //=========================================================================//
281 //                                                                         //
282 //          P U B L I C   F U N C T I O N S                                //
283 //                                                                         //
284 //=========================================================================//
285
286 //---------------------------------------------------------------------------
287 //
288 // Function:    EplNmtMnuInit
289 //
290 // Description: init first instance of the module
291 //
292 //
293 //
294 // Parameters:
295 //
296 //
297 // Returns:     tEplKernel  = errorcode
298 //
299 //
300 // State:
301 //
302 //---------------------------------------------------------------------------
303
304 tEplKernel EplNmtMnuInit(tEplNmtMnuCbNodeEvent pfnCbNodeEvent_p,
305                          tEplNmtMnuCbBootEvent pfnCbBootEvent_p)
306 {
307         tEplKernel Ret;
308
309         Ret = EplNmtMnuAddInstance(pfnCbNodeEvent_p, pfnCbBootEvent_p);
310
311         return Ret;
312 }
313
314 //---------------------------------------------------------------------------
315 //
316 // Function:    EplNmtMnuAddInstance
317 //
318 // Description: init other instances of the module
319 //
320 //
321 //
322 // Parameters:
323 //
324 //
325 // Returns:     tEplKernel  = errorcode
326 //
327 //
328 // State:
329 //
330 //---------------------------------------------------------------------------
331
332 tEplKernel EplNmtMnuAddInstance(tEplNmtMnuCbNodeEvent pfnCbNodeEvent_p,
333                                 tEplNmtMnuCbBootEvent pfnCbBootEvent_p)
334 {
335         tEplKernel Ret;
336
337         Ret = kEplSuccessful;
338
339         // reset instance structure
340         EPL_MEMSET(&EplNmtMnuInstance_g, 0, sizeof(EplNmtMnuInstance_g));
341
342         if ((pfnCbNodeEvent_p == NULL) || (pfnCbBootEvent_p == NULL)) {
343                 Ret = kEplNmtInvalidParam;
344                 goto Exit;
345         }
346         EplNmtMnuInstance_g.m_pfnCbNodeEvent = pfnCbNodeEvent_p;
347         EplNmtMnuInstance_g.m_pfnCbBootEvent = pfnCbBootEvent_p;
348
349         // initialize StatusRequest delay
350         EplNmtMnuInstance_g.m_ulStatusRequestDelay = 5000L;
351
352         // register NmtMnResponse callback function
353         Ret =
354             EplDlluCalRegAsndService(kEplDllAsndNmtRequest,
355                                      EplNmtMnuCbNmtRequest,
356                                      kEplDllAsndFilterLocal);
357
358       Exit:
359         return Ret;
360
361 }
362
363 //---------------------------------------------------------------------------
364 //
365 // Function:    EplNmtMnuDelInstance
366 //
367 // Description: delete instance
368 //
369 //
370 //
371 // Parameters:
372 //
373 //
374 // Returns:     tEplKernel  = errorcode
375 //
376 //
377 // State:
378 //
379 //---------------------------------------------------------------------------
380
381 tEplKernel EplNmtMnuDelInstance(void)
382 {
383         tEplKernel Ret;
384
385         Ret = kEplSuccessful;
386
387         // deregister NmtMnResponse callback function
388         Ret =
389             EplDlluCalRegAsndService(kEplDllAsndNmtRequest, NULL,
390                                      kEplDllAsndFilterNone);
391
392         Ret = EplNmtMnuReset();
393
394         return Ret;
395
396 }
397
398 //---------------------------------------------------------------------------
399 //
400 // Function:    EplNmtMnuSendNmtCommandEx
401 //
402 // Description: sends the specified NMT command to the specified node.
403 //
404 // Parameters:  uiNodeId_p              = node ID to which the NMT command will be sent
405 //              NmtCommand_p            = NMT command
406 //
407 // Returns:     tEplKernel              = error code
408 //
409 // State:
410 //
411 //---------------------------------------------------------------------------
412
413 tEplKernel EplNmtMnuSendNmtCommandEx(unsigned int uiNodeId_p,
414                                      tEplNmtCommand NmtCommand_p,
415                                      void *pNmtCommandData_p,
416                                      unsigned int uiDataSize_p)
417 {
418         tEplKernel Ret = kEplSuccessful;
419         tEplFrameInfo FrameInfo;
420         u8 abBuffer[EPL_C_DLL_MINSIZE_NMTCMDEXT];
421         tEplFrame *pFrame = (tEplFrame *) abBuffer;
422         BOOL fSoftDeleteNode = FALSE;
423
424         if ((uiNodeId_p == 0) || (uiNodeId_p > EPL_C_ADR_BROADCAST)) {  // invalid node ID specified
425                 Ret = kEplInvalidNodeId;
426                 goto Exit;
427         }
428
429         if ((pNmtCommandData_p != NULL)
430             && (uiDataSize_p >
431                 (EPL_C_DLL_MINSIZE_NMTCMDEXT - EPL_C_DLL_MINSIZE_NMTCMD))) {
432                 Ret = kEplNmtInvalidParam;
433                 goto Exit;
434         }
435         // $$$ d.k. may be check in future versions if the caller wants to perform prohibited state transitions
436         //     the CN should not perform these transitions, but the expected NMT state will be changed and never fullfilled.
437
438         // build frame
439         EPL_MEMSET(pFrame, 0x00, sizeof(abBuffer));
440         AmiSetByteToLe(&pFrame->m_le_bDstNodeId, (u8) uiNodeId_p);
441         AmiSetByteToLe(&pFrame->m_Data.m_Asnd.m_le_bServiceId,
442                        (u8) kEplDllAsndNmtCommand);
443         AmiSetByteToLe(&pFrame->m_Data.m_Asnd.m_Payload.m_NmtCommandService.
444                        m_le_bNmtCommandId, (u8) NmtCommand_p);
445         if ((pNmtCommandData_p != NULL) && (uiDataSize_p > 0)) {        // copy command data to frame
446                 EPL_MEMCPY(&pFrame->m_Data.m_Asnd.m_Payload.m_NmtCommandService.
447                            m_le_abNmtCommandData[0], pNmtCommandData_p,
448                            uiDataSize_p);
449         }
450         // build info structure
451         FrameInfo.m_NetTime.m_dwNanoSec = 0;
452         FrameInfo.m_NetTime.m_dwSec = 0;
453         FrameInfo.m_pFrame = pFrame;
454         FrameInfo.m_uiFrameSize = sizeof(abBuffer);
455
456         // send NMT-Request
457 #if(((EPL_MODULE_INTEGRATION) & (EPL_MODULE_DLLU)) != 0)
458         Ret = EplDlluCalAsyncSend(&FrameInfo,   // pointer to frameinfo
459                                   kEplDllAsyncReqPrioNmt);      // priority
460 #endif
461         if (Ret != kEplSuccessful) {
462                 goto Exit;
463         }
464
465         EPL_DBGLVL_NMTMN_TRACE2("NMTCmd(%02X->%02X)\n", NmtCommand_p,
466                                 uiNodeId_p);
467
468         switch (NmtCommand_p) {
469         case kEplNmtCmdStartNode:
470         case kEplNmtCmdEnterPreOperational2:
471         case kEplNmtCmdEnableReadyToOperate:
472                 {
473                         // nothing left to do,
474                         // because any further processing is done
475                         // when the NMT command is actually sent
476                         goto Exit;
477                 }
478
479         case kEplNmtCmdStopNode:
480                 {
481                         fSoftDeleteNode = TRUE;
482                         break;
483                 }
484
485         case kEplNmtCmdResetNode:
486         case kEplNmtCmdResetCommunication:
487         case kEplNmtCmdResetConfiguration:
488         case kEplNmtCmdSwReset:
489                 {
490                         break;
491                 }
492
493         default:
494                 goto Exit;
495         }
496
497         // remove CN from isochronous phase;
498         // This must be done here and not when NMT command is actually sent
499         // because it will be too late and may cause unwanted errors
500         if (uiNodeId_p != EPL_C_ADR_BROADCAST) {
501                 if (fSoftDeleteNode == FALSE) { // remove CN immediately from isochronous phase
502                         Ret = EplDlluCalDeleteNode(uiNodeId_p);
503                 } else {        // remove CN from isochronous phase softly
504                         Ret = EplDlluCalSoftDeleteNode(uiNodeId_p);
505                 }
506         } else {                // do it for all active CNs
507                 for (uiNodeId_p = 1;
508                      uiNodeId_p <= tabentries(EplNmtMnuInstance_g.m_aNodeInfo);
509                      uiNodeId_p++) {
510                         if ((EPL_NMTMNU_GET_NODEINFO(uiNodeId_p)->
511                              m_dwNodeCfg & (EPL_NODEASSIGN_NODE_IS_CN |
512                                             EPL_NODEASSIGN_NODE_EXISTS)) != 0) {
513                                 if (fSoftDeleteNode == FALSE) { // remove CN immediately from isochronous phase
514                                         Ret = EplDlluCalDeleteNode(uiNodeId_p);
515                                 } else {        // remove CN from isochronous phase softly
516                                         Ret =
517                                             EplDlluCalSoftDeleteNode
518                                             (uiNodeId_p);
519                                 }
520                         }
521                 }
522         }
523
524       Exit:
525         return Ret;
526 }
527
528 //---------------------------------------------------------------------------
529 //
530 // Function:    EplNmtMnuSendNmtCommand
531 //
532 // Description: sends the specified NMT command to the specified node.
533 //
534 // Parameters:  uiNodeId_p              = node ID to which the NMT command will be sent
535 //              NmtCommand_p            = NMT command
536 //
537 // Returns:     tEplKernel              = error code
538 //
539 // State:
540 //
541 //---------------------------------------------------------------------------
542
543 tEplKernel EplNmtMnuSendNmtCommand(unsigned int uiNodeId_p,
544                                    tEplNmtCommand NmtCommand_p)
545 {
546         tEplKernel Ret = kEplSuccessful;
547
548         Ret = EplNmtMnuSendNmtCommandEx(uiNodeId_p, NmtCommand_p, NULL, 0);
549
550 //Exit:
551         return Ret;
552 }
553
554 //---------------------------------------------------------------------------
555 //
556 // Function:    EplNmtMnuTriggerStateChange
557 //
558 // Description: triggers the specified node command for the specified node.
559 //
560 // Parameters:  uiNodeId_p              = node ID for which the node command will be executed
561 //              NodeCommand_p           = node command
562 //
563 // Returns:     tEplKernel              = error code
564 //
565 // State:
566 //
567 //---------------------------------------------------------------------------
568
569 tEplKernel EplNmtMnuTriggerStateChange(unsigned int uiNodeId_p,
570                                        tEplNmtNodeCommand NodeCommand_p)
571 {
572         tEplKernel Ret = kEplSuccessful;
573         tEplNmtMnuIntNodeEvent NodeEvent;
574         tEplObdSize ObdSize;
575         u8 bNmtState;
576         u16 wErrorCode = EPL_E_NO_ERROR;
577
578         if ((uiNodeId_p == 0) || (uiNodeId_p >= EPL_C_ADR_BROADCAST)) {
579                 Ret = kEplInvalidNodeId;
580                 goto Exit;
581         }
582
583         switch (NodeCommand_p) {
584         case kEplNmtNodeCommandBoot:
585                 {
586                         NodeEvent = kEplNmtMnuIntNodeEventBoot;
587                         break;
588                 }
589
590         case kEplNmtNodeCommandConfOk:
591                 {
592                         NodeEvent = kEplNmtMnuIntNodeEventConfigured;
593                         break;
594                 }
595
596         case kEplNmtNodeCommandConfErr:
597                 {
598                         NodeEvent = kEplNmtMnuIntNodeEventError;
599                         wErrorCode = EPL_E_NMT_BPO1_CF_VERIFY;
600                         break;
601                 }
602
603         case kEplNmtNodeCommandConfReset:
604                 {
605                         NodeEvent = kEplNmtMnuIntNodeEventExecReset;
606                         break;
607                 }
608
609         default:
610                 {               // invalid node command
611                         goto Exit;
612                 }
613         }
614
615         // fetch current NMT state
616         ObdSize = 1;
617         Ret = EplObduReadEntry(0x1F8E, uiNodeId_p, &bNmtState, &ObdSize);
618         if (Ret != kEplSuccessful) {
619                 goto Exit;
620         }
621
622         Ret = EplNmtMnuProcessInternalEvent(uiNodeId_p,
623                                             (tEplNmtState) (bNmtState |
624                                                             EPL_NMT_TYPE_CS),
625                                             wErrorCode, NodeEvent);
626
627       Exit:
628         return Ret;
629 }
630
631 //---------------------------------------------------------------------------
632 //
633 // Function:    EplNmtMnuCbNmtStateChange
634 //
635 // Description: callback function for NMT state changes
636 //
637 // Parameters:  NmtStateChange_p        = NMT state change event
638 //
639 // Returns:     tEplKernel              = error code
640 //
641 //
642 // State:
643 //
644 //---------------------------------------------------------------------------
645
646 tEplKernel EplNmtMnuCbNmtStateChange(tEplEventNmtStateChange NmtStateChange_p)
647 {
648         tEplKernel Ret = kEplSuccessful;
649
650         // do work which must be done in that state
651         switch (NmtStateChange_p.m_NewNmtState) {
652                 // EPL stack is not running
653 /*        case kEplNmtGsOff:
654             break;
655
656         // first init of the hardware
657         case kEplNmtGsInitialising:
658             break;
659
660         // init of the manufacturer-specific profile area and the
661         // standardised device profile area
662         case kEplNmtGsResetApplication:
663         {
664             break;
665         }
666
667         // init of the communication profile area
668         case kEplNmtGsResetCommunication:
669         {
670             break;
671         }
672 */
673                 // build the configuration with infos from OD
674         case kEplNmtGsResetConfiguration:
675                 {
676                         u32 dwTimeout;
677                         tEplObdSize ObdSize;
678
679                         // read object 0x1F80 NMT_StartUp_U32
680                         ObdSize = 4;
681                         Ret =
682                             EplObduReadEntry(0x1F80, 0,
683                                              &EplNmtMnuInstance_g.
684                                              m_dwNmtStartup, &ObdSize);
685                         if (Ret != kEplSuccessful) {
686                                 break;
687                         }
688                         // compute StatusReqDelay = object 0x1006 * EPL_C_NMT_STATREQ_CYCLE
689                         ObdSize = sizeof(dwTimeout);
690                         Ret = EplObduReadEntry(0x1006, 0, &dwTimeout, &ObdSize);
691                         if (Ret != kEplSuccessful) {
692                                 break;
693                         }
694                         if (dwTimeout != 0L) {
695                                 EplNmtMnuInstance_g.m_ulStatusRequestDelay =
696                                     dwTimeout * EPL_C_NMT_STATREQ_CYCLE / 1000L;
697                                 if (EplNmtMnuInstance_g.
698                                     m_ulStatusRequestDelay == 0L) {
699                                         EplNmtMnuInstance_g.m_ulStatusRequestDelay = 1L;        // at least 1 ms
700                                 }
701                                 // $$$ fetch and use MultiplexedCycleCount from OD
702                                 EplNmtMnuInstance_g.m_ulTimeoutCheckCom =
703                                     dwTimeout * EPL_C_NMT_STATREQ_CYCLE / 1000L;
704                                 if (EplNmtMnuInstance_g.m_ulTimeoutCheckCom ==
705                                     0L) {
706                                         EplNmtMnuInstance_g.m_ulTimeoutCheckCom = 1L;   // at least 1 ms
707                                 }
708                         }
709                         // fetch ReadyToOp Timeout from OD
710                         ObdSize = sizeof(dwTimeout);
711                         Ret = EplObduReadEntry(0x1F89, 5, &dwTimeout, &ObdSize);
712                         if (Ret != kEplSuccessful) {
713                                 break;
714                         }
715                         if (dwTimeout != 0L) {
716                                 // convert [us] to [ms]
717                                 dwTimeout /= 1000L;
718                                 if (dwTimeout == 0L) {
719                                         dwTimeout = 1L; // at least 1 ms
720                                 }
721                                 EplNmtMnuInstance_g.m_ulTimeoutReadyToOp =
722                                     dwTimeout;
723                         } else {
724                                 EplNmtMnuInstance_g.m_ulTimeoutReadyToOp = 0L;
725                         }
726                         break;
727                 }
728 /*
729         //-----------------------------------------------------------
730         // CN part of the state machine
731
732         // node liste for EPL-Frames and check timeout
733         case kEplNmtCsNotActive:
734         {
735             break;
736         }
737
738         // node process only async frames
739         case kEplNmtCsPreOperational1:
740         {
741             break;
742         }
743
744         // node process isochronus and asynchronus frames
745         case kEplNmtCsPreOperational2:
746         {
747             break;
748         }
749
750         // node should be configured und application is ready
751         case kEplNmtCsReadyToOperate:
752         {
753             break;
754         }
755
756         // normal work state
757         case kEplNmtCsOperational:
758         {
759             break;
760         }
761
762         // node stopped by MN
763         // -> only process asynchronus frames
764         case kEplNmtCsStopped:
765         {
766             break;
767         }
768
769         // no EPL cycle
770         // -> normal ethernet communication
771         case kEplNmtCsBasicEthernet:
772         {
773             break;
774         }
775 */
776                 //-----------------------------------------------------------
777                 // MN part of the state machine
778
779                 // node listens for EPL-Frames and check timeout
780         case kEplNmtMsNotActive:
781                 {
782                         break;
783                 }
784
785                 // node processes only async frames
786         case kEplNmtMsPreOperational1:
787                 {
788                         u32 dwTimeout;
789                         tEplTimerArg TimerArg;
790                         tEplObdSize ObdSize;
791                         tEplEvent Event;
792
793                         // clear global flags, e.g. reenable boot process
794                         EplNmtMnuInstance_g.m_wFlags = 0;
795
796                         // reset IdentResponses and running IdentRequests and StatusRequests
797                         Ret = EplIdentuReset();
798                         Ret = EplStatusuReset();
799
800                         // reset timers
801                         Ret = EplNmtMnuReset();
802
803                         // 2008/11/18 d.k. reset internal node info is not necessary,
804                         //                 because timer flags are important and other
805                         //                 things are reset by EplNmtMnuStartBootStep1().
806 /*
807             EPL_MEMSET(EplNmtMnuInstance_g.m_aNodeInfo,
808                        0,
809                        sizeof (EplNmtMnuInstance_g.m_aNodeInfo));
810 */
811
812                         // inform DLL about NMT state change,
813                         // so that it can clear the asynchonous queues and start the reduced cycle
814                         Event.m_EventSink = kEplEventSinkDllk;
815                         Event.m_EventType = kEplEventTypeDllkStartReducedCycle;
816                         EPL_MEMSET(&Event.m_NetTime, 0x00,
817                                    sizeof(Event.m_NetTime));
818                         Event.m_pArg = NULL;
819                         Event.m_uiSize = 0;
820                         Ret = EplEventuPost(&Event);
821                         if (Ret != kEplSuccessful) {
822                                 break;
823                         }
824                         // reset all nodes
825                         // d.k.: skip this step if was just done before, e.g. because of a ResetNode command from a diagnostic node
826                         if (NmtStateChange_p.m_NmtEvent ==
827                             kEplNmtEventTimerMsPreOp1) {
828                                 BENCHMARK_MOD_07_TOGGLE(9);
829
830                                 EPL_NMTMNU_DBG_POST_TRACE_VALUE(0,
831                                                                 EPL_C_ADR_BROADCAST,
832                                                                 kEplNmtCmdResetNode);
833
834                                 Ret =
835                                     EplNmtMnuSendNmtCommand(EPL_C_ADR_BROADCAST,
836                                                             kEplNmtCmdResetNode);
837                                 if (Ret != kEplSuccessful) {
838                                         break;
839                                 }
840                         }
841                         // start network scan
842                         Ret = EplNmtMnuStartBootStep1();
843
844                         // start timer for 0x1F89/2 MNTimeoutPreOp1_U32
845                         ObdSize = sizeof(dwTimeout);
846                         Ret = EplObduReadEntry(0x1F89, 2, &dwTimeout, &ObdSize);
847                         if (Ret != kEplSuccessful) {
848                                 break;
849                         }
850                         if (dwTimeout != 0L) {
851                                 dwTimeout /= 1000L;
852                                 if (dwTimeout == 0L) {
853                                         dwTimeout = 1L; // at least 1 ms
854                                 }
855                                 TimerArg.m_EventSink = kEplEventSinkNmtMnu;
856                                 TimerArg.m_ulArg = 0;
857                                 Ret =
858                                     EplTimeruModifyTimerMs(&EplNmtMnuInstance_g.
859                                                            m_TimerHdlNmtState,
860                                                            dwTimeout, TimerArg);
861                         }
862                         break;
863                 }
864
865                 // node processes isochronous and asynchronous frames
866         case kEplNmtMsPreOperational2:
867                 {
868                         // add identified CNs to isochronous phase
869                         // send EnableReadyToOp to all identified CNs
870                         Ret = EplNmtMnuStartBootStep2();
871
872                         // wait for NMT state change of CNs
873                         break;
874                 }
875
876                 // node should be configured und application is ready
877         case kEplNmtMsReadyToOperate:
878                 {
879                         // check if PRes of CNs are OK
880                         // d.k. that means wait CycleLength * MultiplexCycleCount (i.e. start timer)
881                         //      because Dllk checks PRes of CNs automatically in ReadyToOp
882                         Ret = EplNmtMnuStartCheckCom();
883                         break;
884                 }
885
886                 // normal work state
887         case kEplNmtMsOperational:
888                 {
889                         // send StartNode to CNs
890                         // wait for NMT state change of CNs
891                         Ret = EplNmtMnuStartNodes();
892                         break;
893                 }
894
895                 // no EPL cycle
896                 // -> normal ethernet communication
897         case kEplNmtMsBasicEthernet:
898                 {
899                         break;
900                 }
901
902         default:
903                 {
904 //            TRACE0("EplNmtMnuCbNmtStateChange(): unhandled NMT state\n");
905                 }
906         }
907
908         return Ret;
909 }
910
911 //---------------------------------------------------------------------------
912 //
913 // Function:    EplNmtMnuCbCheckEvent
914 //
915 // Description: callback funktion for NMT events before they are actually executed.
916 //              The EPL API layer must forward NMT events from NmtCnu module.
917 //              This module will reject some NMT commands while MN.
918 //
919 // Parameters:  NmtEvent_p              = outstanding NMT event for approval
920 //
921 // Returns:     tEplKernel              = error code
922 //                      kEplReject      = reject the NMT event
923 //
924 // State:
925 //
926 //---------------------------------------------------------------------------
927
928 tEplKernel EplNmtMnuCbCheckEvent(tEplNmtEvent NmtEvent_p)
929 {
930         tEplKernel Ret = kEplSuccessful;
931
932         return Ret;
933 }
934
935 //---------------------------------------------------------------------------
936 //
937 // Function:    EplNmtuProcessEvent
938 //
939 // Description: processes events from event queue
940 //
941 // Parameters:  pEvent_p        = pointer to event
942 //
943 // Returns:     tEplKernel      = errorcode
944 //
945 // State:
946 //
947 //---------------------------------------------------------------------------
948
949 tEplKernel EplNmtMnuProcessEvent(tEplEvent *pEvent_p)
950 {
951         tEplKernel Ret;
952
953         Ret = kEplSuccessful;
954
955         // process event
956         switch (pEvent_p->m_EventType) {
957                 // timer event
958         case kEplEventTypeTimer:
959                 {
960                         tEplTimerEventArg *pTimerEventArg =
961                             (tEplTimerEventArg *) pEvent_p->m_pArg;
962                         unsigned int uiNodeId;
963
964                         uiNodeId =
965                             (unsigned int)(pTimerEventArg->
966                                            m_ulArg &
967                                            EPL_NMTMNU_TIMERARG_NODE_MASK);
968                         if (uiNodeId != 0) {
969                                 tEplObdSize ObdSize;
970                                 u8 bNmtState;
971                                 tEplNmtMnuNodeInfo *pNodeInfo;
972
973                                 pNodeInfo = EPL_NMTMNU_GET_NODEINFO(uiNodeId);
974
975                                 ObdSize = 1;
976                                 Ret =
977                                     EplObduReadEntry(0x1F8E, uiNodeId,
978                                                      &bNmtState, &ObdSize);
979                                 if (Ret != kEplSuccessful) {
980                                         break;
981                                 }
982
983                                 if ((pTimerEventArg->
984                                      m_ulArg & EPL_NMTMNU_TIMERARG_IDENTREQ) !=
985                                     0L) {
986                                         if ((pNodeInfo->
987                                              m_wFlags &
988                                              EPL_NMTMNU_NODE_FLAG_COUNT_STATREQ)
989                                             != (pTimerEventArg->m_ulArg & EPL_NMTMNU_TIMERARG_COUNT_SR)) {      // this is an old (already deleted or modified) timer
990                                                 // but not the current timer
991                                                 // so discard it
992                                                 EPL_NMTMNU_DBG_POST_TRACE_VALUE
993                                                     (kEplNmtMnuIntNodeEventTimerIdentReq,
994                                                      uiNodeId,
995                                                      ((pNodeInfo->
996                                                        m_NodeState << 8)
997                                                       | 0xFF));
998
999                                                 break;
1000                                         }
1001 /*
1002                     EPL_NMTMNU_DBG_POST_TRACE_VALUE(kEplNmtMnuIntNodeEventTimerIdentReq,
1003                                                     uiNodeId,
1004                                                     ((pNodeInfo->m_NodeState << 8)
1005                                                      | 0x80
1006                                                      | ((pNodeInfo->m_wFlags & EPL_NMTMNU_NODE_FLAG_COUNT_STATREQ) >> 6)
1007                                                      | ((pTimerEventArg->m_ulArg & EPL_NMTMNU_TIMERARG_COUNT_SR) >> 8)));
1008 */
1009                                         Ret =
1010                                             EplNmtMnuProcessInternalEvent
1011                                             (uiNodeId,
1012                                              (tEplNmtState) (bNmtState |
1013                                                              EPL_NMT_TYPE_CS),
1014                                              EPL_E_NO_ERROR,
1015                                              kEplNmtMnuIntNodeEventTimerIdentReq);
1016                                 }
1017
1018                                 else if ((pTimerEventArg->
1019                                           m_ulArg & EPL_NMTMNU_TIMERARG_STATREQ)
1020                                          != 0L) {
1021                                         if ((pNodeInfo->
1022                                              m_wFlags &
1023                                              EPL_NMTMNU_NODE_FLAG_COUNT_STATREQ)
1024                                             != (pTimerEventArg->m_ulArg & EPL_NMTMNU_TIMERARG_COUNT_SR)) {      // this is an old (already deleted or modified) timer
1025                                                 // but not the current timer
1026                                                 // so discard it
1027                                                 EPL_NMTMNU_DBG_POST_TRACE_VALUE
1028                                                     (kEplNmtMnuIntNodeEventTimerStatReq,
1029                                                      uiNodeId,
1030                                                      ((pNodeInfo->
1031                                                        m_NodeState << 8)
1032                                                       | 0xFF));
1033
1034                                                 break;
1035                                         }
1036 /*
1037                     EPL_NMTMNU_DBG_POST_TRACE_VALUE(kEplNmtMnuIntNodeEventTimerStatReq,
1038                                                     uiNodeId,
1039                                                     ((pNodeInfo->m_NodeState << 8)
1040                                                      | 0x80
1041                                                      | ((pNodeInfo->m_wFlags & EPL_NMTMNU_NODE_FLAG_COUNT_STATREQ) >> 6)
1042                                                      | ((pTimerEventArg->m_ulArg & EPL_NMTMNU_TIMERARG_COUNT_SR) >> 8)));
1043 */
1044                                         Ret =
1045                                             EplNmtMnuProcessInternalEvent
1046                                             (uiNodeId,
1047                                              (tEplNmtState) (bNmtState |
1048                                                              EPL_NMT_TYPE_CS),
1049                                              EPL_E_NO_ERROR,
1050                                              kEplNmtMnuIntNodeEventTimerStatReq);
1051                                 }
1052
1053                                 else if ((pTimerEventArg->
1054                                           m_ulArg &
1055                                           EPL_NMTMNU_TIMERARG_STATE_MON) !=
1056                                          0L) {
1057                                         if ((pNodeInfo->
1058                                              m_wFlags &
1059                                              EPL_NMTMNU_NODE_FLAG_COUNT_STATREQ)
1060                                             != (pTimerEventArg->m_ulArg & EPL_NMTMNU_TIMERARG_COUNT_SR)) {      // this is an old (already deleted or modified) timer
1061                                                 // but not the current timer
1062                                                 // so discard it
1063                                                 EPL_NMTMNU_DBG_POST_TRACE_VALUE
1064                                                     (kEplNmtMnuIntNodeEventTimerStateMon,
1065                                                      uiNodeId,
1066                                                      ((pNodeInfo->
1067                                                        m_NodeState << 8)
1068                                                       | 0xFF));
1069
1070                                                 break;
1071                                         }
1072 /*
1073                     EPL_NMTMNU_DBG_POST_TRACE_VALUE(kEplNmtMnuIntNodeEventTimerStatReq,
1074                                                     uiNodeId,
1075                                                     ((pNodeInfo->m_NodeState << 8)
1076                                                      | 0x80
1077                                                      | ((pNodeInfo->m_wFlags & EPL_NMTMNU_NODE_FLAG_COUNT_STATREQ) >> 6)
1078                                                      | ((pTimerEventArg->m_ulArg & EPL_NMTMNU_TIMERARG_COUNT_SR) >> 8)));
1079 */
1080                                         Ret =
1081                                             EplNmtMnuProcessInternalEvent
1082                                             (uiNodeId,
1083                                              (tEplNmtState) (bNmtState |
1084                                                              EPL_NMT_TYPE_CS),
1085                                              EPL_E_NO_ERROR,
1086                                              kEplNmtMnuIntNodeEventTimerStateMon);
1087                                 }
1088
1089                                 else if ((pTimerEventArg->
1090                                           m_ulArg & EPL_NMTMNU_TIMERARG_LONGER)
1091                                          != 0L) {
1092                                         if ((pNodeInfo->
1093                                              m_wFlags &
1094                                              EPL_NMTMNU_NODE_FLAG_COUNT_LONGER)
1095                                             != (pTimerEventArg->m_ulArg & EPL_NMTMNU_TIMERARG_COUNT_LO)) {      // this is an old (already deleted or modified) timer
1096                                                 // but not the current timer
1097                                                 // so discard it
1098                                                 EPL_NMTMNU_DBG_POST_TRACE_VALUE
1099                                                     (kEplNmtMnuIntNodeEventTimerLonger,
1100                                                      uiNodeId,
1101                                                      ((pNodeInfo->
1102                                                        m_NodeState << 8)
1103                                                       | 0xFF));
1104
1105                                                 break;
1106                                         }
1107 /*
1108                     EPL_NMTMNU_DBG_POST_TRACE_VALUE(kEplNmtMnuIntNodeEventTimerLonger,
1109                                                     uiNodeId,
1110                                                     ((pNodeInfo->m_NodeState << 8)
1111                                                      | 0x80
1112                                                      | ((pNodeInfo->m_wFlags & EPL_NMTMNU_NODE_FLAG_COUNT_LONGER) >> 6)
1113                                                      | ((pTimerEventArg->m_ulArg & EPL_NMTMNU_TIMERARG_COUNT_LO) >> 8)));
1114 */
1115                                         Ret =
1116                                             EplNmtMnuProcessInternalEvent
1117                                             (uiNodeId,
1118                                              (tEplNmtState) (bNmtState |
1119                                                              EPL_NMT_TYPE_CS),
1120                                              EPL_E_NO_ERROR,
1121                                              kEplNmtMnuIntNodeEventTimerLonger);
1122                                 }
1123
1124                         } else {        // global timer event
1125                         }
1126                         break;
1127                 }
1128
1129         case kEplEventTypeHeartbeat:
1130                 {
1131                         tEplHeartbeatEvent *pHeartbeatEvent =
1132                             (tEplHeartbeatEvent *) pEvent_p->m_pArg;
1133
1134                         Ret =
1135                             EplNmtMnuProcessInternalEvent(pHeartbeatEvent->
1136                                                           m_uiNodeId,
1137                                                           pHeartbeatEvent->
1138                                                           m_NmtState,
1139                                                           pHeartbeatEvent->
1140                                                           m_wErrorCode,
1141                                                           kEplNmtMnuIntNodeEventHeartbeat);
1142                         break;
1143                 }
1144
1145         case kEplEventTypeNmtMnuNmtCmdSent:
1146                 {
1147                         tEplFrame *pFrame = (tEplFrame *) pEvent_p->m_pArg;
1148                         unsigned int uiNodeId;
1149                         tEplNmtCommand NmtCommand;
1150                         u8 bNmtState;
1151
1152                         uiNodeId = AmiGetByteFromLe(&pFrame->m_le_bDstNodeId);
1153                         NmtCommand =
1154                             (tEplNmtCommand) AmiGetByteFromLe(&pFrame->m_Data.
1155                                                               m_Asnd.m_Payload.
1156                                                               m_NmtCommandService.
1157                                                               m_le_bNmtCommandId);
1158
1159                         switch (NmtCommand) {
1160                         case kEplNmtCmdStartNode:
1161                                 bNmtState =
1162                                     (u8) (kEplNmtCsOperational & 0xFF);
1163                                 break;
1164
1165                         case kEplNmtCmdStopNode:
1166                                 bNmtState = (u8) (kEplNmtCsStopped & 0xFF);
1167                                 break;
1168
1169                         case kEplNmtCmdEnterPreOperational2:
1170                                 bNmtState =
1171                                     (u8) (kEplNmtCsPreOperational2 & 0xFF);
1172                                 break;
1173
1174                         case kEplNmtCmdEnableReadyToOperate:
1175                                 // d.k. do not change expected node state, because of DS 1.0.0 7.3.1.2.1 Plain NMT State Command
1176                                 //      and because node may not change NMT state within EPL_C_NMT_STATE_TOLERANCE
1177                                 bNmtState =
1178                                     (u8) (kEplNmtCsPreOperational2 & 0xFF);
1179                                 break;
1180
1181                         case kEplNmtCmdResetNode:
1182                         case kEplNmtCmdResetCommunication:
1183                         case kEplNmtCmdResetConfiguration:
1184                         case kEplNmtCmdSwReset:
1185                                 bNmtState = (u8) (kEplNmtCsNotActive & 0xFF);
1186                                 // EplNmtMnuProcessInternalEvent() sets internal node state to kEplNmtMnuNodeStateUnknown
1187                                 // after next unresponded IdentRequest/StatusRequest
1188                                 break;
1189
1190                         default:
1191                                 goto Exit;
1192                         }
1193
1194                         // process as internal event which update expected NMT state in OD
1195                         if (uiNodeId != EPL_C_ADR_BROADCAST) {
1196                                 Ret = EplNmtMnuProcessInternalEvent(uiNodeId,
1197                                                                     (tEplNmtState)
1198                                                                     (bNmtState |
1199                                                                      EPL_NMT_TYPE_CS),
1200                                                                     0,
1201                                                                     kEplNmtMnuIntNodeEventNmtCmdSent);
1202
1203                         } else {        // process internal event for all active nodes (except myself)
1204
1205                                 for (uiNodeId = 1;
1206                                      uiNodeId <=
1207                                      tabentries(EplNmtMnuInstance_g.
1208                                                 m_aNodeInfo); uiNodeId++) {
1209                                         if ((EPL_NMTMNU_GET_NODEINFO(uiNodeId)->
1210                                              m_dwNodeCfg &
1211                                              (EPL_NODEASSIGN_NODE_IS_CN |
1212                                               EPL_NODEASSIGN_NODE_EXISTS)) !=
1213                                             0) {
1214                                                 Ret =
1215                                                     EplNmtMnuProcessInternalEvent
1216                                                     (uiNodeId,
1217                                                      (tEplNmtState) (bNmtState |
1218                                                                      EPL_NMT_TYPE_CS),
1219                                                      0,
1220                                                      kEplNmtMnuIntNodeEventNmtCmdSent);
1221
1222                                                 if (Ret != kEplSuccessful) {
1223                                                         goto Exit;
1224                                                 }
1225                                         }
1226                                 }
1227                         }
1228
1229                         break;
1230                 }
1231
1232         default:
1233                 {
1234                         Ret = kEplNmtInvalidEvent;
1235                 }
1236
1237         }
1238
1239       Exit:
1240         return Ret;
1241 }
1242
1243 //---------------------------------------------------------------------------
1244 //
1245 // Function:    EplNmtMnuGetRunningTimerStatReq
1246 //
1247 // Description: returns a bit field with running StatReq timers
1248 //              just for debugging purposes
1249 //
1250 // Parameters:  (none)
1251 //
1252 // Returns:     tEplKernel              = error code
1253 //
1254 // State:
1255 //
1256 //---------------------------------------------------------------------------
1257
1258 tEplKernel EplNmtMnuGetDiagnosticInfo(unsigned int *puiMandatorySlaveCount_p,
1259                                       unsigned int *puiSignalSlaveCount_p,
1260                                       u16 *pwFlags_p)
1261 {
1262         tEplKernel Ret = kEplSuccessful;
1263
1264         if ((puiMandatorySlaveCount_p == NULL)
1265             || (puiSignalSlaveCount_p == NULL)
1266             || (pwFlags_p == NULL)) {
1267                 Ret = kEplNmtInvalidParam;
1268                 goto Exit;
1269         }
1270
1271         *puiMandatorySlaveCount_p = EplNmtMnuInstance_g.m_uiMandatorySlaveCount;
1272         *puiSignalSlaveCount_p = EplNmtMnuInstance_g.m_uiSignalSlaveCount;
1273         *pwFlags_p = EplNmtMnuInstance_g.m_wFlags;
1274
1275       Exit:
1276         return Ret;
1277 }
1278
1279 //---------------------------------------------------------------------------
1280 //
1281 // Function:    EplNmtMnuGetRunningTimerStatReq
1282 //
1283 // Description: returns a bit field with running StatReq timers
1284 //              just for debugging purposes
1285 //
1286 // Parameters:  (none)
1287 //
1288 // Returns:     tEplKernel              = error code
1289 //
1290 // State:
1291 //
1292 //---------------------------------------------------------------------------
1293 /*
1294 u32 EplNmtMnuGetRunningTimerStatReq(void)
1295 {
1296 tEplKernel      Ret = kEplSuccessful;
1297 unsigned int    uiIndex;
1298 tEplNmtMnuNodeInfo* pNodeInfo;
1299
1300     pNodeInfo = EplNmtMnuInstance_g.m_aNodeInfo;
1301     for (uiIndex = 1; uiIndex <= tabentries(EplNmtMnuInstance_g.m_aNodeInfo); uiIndex++, pNodeInfo++)
1302     {
1303         if (pNodeInfo->m_NodeState == kEplNmtMnuNodeStateConfigured)
1304         {
1305             // reset flag "scanned once"
1306             pNodeInfo->m_wFlags &= ~EPL_NMTMNU_NODE_FLAG_SCANNED;
1307
1308             Ret = EplNmtMnuNodeBootStep2(uiIndex, pNodeInfo);
1309             if (Ret != kEplSuccessful)
1310             {
1311                 goto Exit;
1312             }
1313             EplNmtMnuInstance_g.m_uiSignalSlaveCount++;
1314             // signal slave counter shall be decremented if StatusRequest was sent once to a CN
1315             // mandatory slave counter shall be decremented if mandatory CN is ReadyToOp
1316         }
1317     }
1318
1319 Exit:
1320     return Ret;
1321 }
1322 */
1323
1324 //=========================================================================//
1325 //                                                                         //
1326 //          P R I V A T E   F U N C T I O N S                              //
1327 //                                                                         //
1328 //=========================================================================//
1329
1330 //---------------------------------------------------------------------------
1331 //
1332 // Function:    EplNmtMnuCbNmtRequest
1333 //
1334 // Description: callback funktion for NmtRequest
1335 //
1336 // Parameters:  pFrameInfo_p            = Frame with the NmtRequest
1337 //
1338 // Returns:     tEplKernel              = error code
1339 //
1340 //
1341 // State:
1342 //
1343 //---------------------------------------------------------------------------
1344
1345 static tEplKernel EplNmtMnuCbNmtRequest(tEplFrameInfo *pFrameInfo_p)
1346 {
1347         tEplKernel Ret = kEplSuccessful;
1348
1349         // $$$ perform NMTRequest
1350         return Ret;
1351 }
1352
1353 //---------------------------------------------------------------------------
1354 //
1355 // Function:    EplNmtMnuCbIdentResponse
1356 //
1357 // Description: callback funktion for IdentResponse
1358 //
1359 // Parameters:  uiNodeId_p              = node ID for which IdentReponse was received
1360 //              pIdentResponse_p        = pointer to IdentResponse
1361 //                                        is NULL if node did not answer
1362 //
1363 // Returns:     tEplKernel              = error code
1364 //
1365 // State:
1366 //
1367 //---------------------------------------------------------------------------
1368
1369 static tEplKernel EplNmtMnuCbIdentResponse(unsigned int uiNodeId_p,
1370                                            tEplIdentResponse *pIdentResponse_p)
1371 {
1372         tEplKernel Ret = kEplSuccessful;
1373
1374         if (pIdentResponse_p == NULL) { // node did not answer
1375                 Ret = EplNmtMnuProcessInternalEvent(uiNodeId_p, kEplNmtCsNotActive, EPL_E_NMT_NO_IDENT_RES,     // was EPL_E_NO_ERROR
1376                                                     kEplNmtMnuIntNodeEventNoIdentResponse);
1377         } else {                // node answered IdentRequest
1378                 tEplObdSize ObdSize;
1379                 u32 dwDevType;
1380                 u16 wErrorCode = EPL_E_NO_ERROR;
1381                 tEplNmtState NmtState =
1382                     (tEplNmtState) (AmiGetByteFromLe
1383                                     (&pIdentResponse_p->
1384                                      m_le_bNmtStatus) | EPL_NMT_TYPE_CS);
1385
1386                 // check IdentResponse $$$ move to ProcessIntern, because this function may be called also if CN
1387
1388                 // check DeviceType (0x1F84)
1389                 ObdSize = 4;
1390                 Ret =
1391                     EplObduReadEntry(0x1F84, uiNodeId_p, &dwDevType, &ObdSize);
1392                 if (Ret != kEplSuccessful) {
1393                         goto Exit;
1394                 }
1395                 if (dwDevType != 0L) {  // actually compare it with DeviceType from IdentResponse
1396                         if (AmiGetDwordFromLe(&pIdentResponse_p->m_le_dwDeviceType) != dwDevType) {     // wrong DeviceType
1397                                 NmtState = kEplNmtCsNotActive;
1398                                 wErrorCode = EPL_E_NMT_BPO1_DEVICE_TYPE;
1399                         }
1400                 }
1401
1402                 Ret = EplNmtMnuProcessInternalEvent(uiNodeId_p,
1403                                                     NmtState,
1404                                                     wErrorCode,
1405                                                     kEplNmtMnuIntNodeEventIdentResponse);
1406         }
1407
1408       Exit:
1409         return Ret;
1410 }
1411
1412 //---------------------------------------------------------------------------
1413 //
1414 // Function:    EplNmtMnuCbStatusResponse
1415 //
1416 // Description: callback funktion for StatusResponse
1417 //
1418 // Parameters:  uiNodeId_p              = node ID for which IdentReponse was received
1419 //              pIdentResponse_p        = pointer to IdentResponse
1420 //                                        is NULL if node did not answer
1421 //
1422 // Returns:     tEplKernel              = error code
1423 //
1424 // State:
1425 //
1426 //---------------------------------------------------------------------------
1427
1428 static tEplKernel EplNmtMnuCbStatusResponse(unsigned int uiNodeId_p,
1429                                             tEplStatusResponse *pStatusResponse_p)
1430 {
1431         tEplKernel Ret = kEplSuccessful;
1432
1433         if (pStatusResponse_p == NULL) {        // node did not answer
1434                 Ret = EplNmtMnuProcessInternalEvent(uiNodeId_p, kEplNmtCsNotActive, EPL_E_NMT_NO_STATUS_RES,    // was EPL_E_NO_ERROR
1435                                                     kEplNmtMnuIntNodeEventNoStatusResponse);
1436         } else {                // node answered StatusRequest
1437                 Ret = EplNmtMnuProcessInternalEvent(uiNodeId_p,
1438                                                     (tEplNmtState)
1439                                                     (AmiGetByteFromLe
1440                                                      (&pStatusResponse_p->
1441                                                       m_le_bNmtStatus) |
1442                                                      EPL_NMT_TYPE_CS),
1443                                                     EPL_E_NO_ERROR,
1444                                                     kEplNmtMnuIntNodeEventStatusResponse);
1445         }
1446
1447         return Ret;
1448 }
1449
1450 //---------------------------------------------------------------------------
1451 //
1452 // Function:    EplNmtMnuStartBootStep1
1453 //
1454 // Description: starts BootStep1
1455 //
1456 // Parameters:  (none)
1457 //
1458 // Returns:     tEplKernel              = error code
1459 //
1460 // State:
1461 //
1462 //---------------------------------------------------------------------------
1463
1464 static tEplKernel EplNmtMnuStartBootStep1(void)
1465 {
1466         tEplKernel Ret = kEplSuccessful;
1467         unsigned int uiSubIndex;
1468         unsigned int uiLocalNodeId;
1469         u32 dwNodeCfg;
1470         tEplObdSize ObdSize;
1471
1472         // $$$ d.k.: save current time for 0x1F89/2 MNTimeoutPreOp1_U32
1473
1474         // start network scan
1475         EplNmtMnuInstance_g.m_uiMandatorySlaveCount = 0;
1476         EplNmtMnuInstance_g.m_uiSignalSlaveCount = 0;
1477         // check 0x1F81
1478         uiLocalNodeId = EplObduGetNodeId();
1479         for (uiSubIndex = 1; uiSubIndex <= 254; uiSubIndex++) {
1480                 ObdSize = 4;
1481                 Ret =
1482                     EplObduReadEntry(0x1F81, uiSubIndex, &dwNodeCfg, &ObdSize);
1483                 if (Ret != kEplSuccessful) {
1484                         goto Exit;
1485                 }
1486                 if (uiSubIndex != uiLocalNodeId) {
1487                         // reset flags "not scanned" and "isochronous"
1488                         EPL_NMTMNU_GET_NODEINFO(uiSubIndex)->m_wFlags &=
1489                             ~(EPL_NMTMNU_NODE_FLAG_ISOCHRON |
1490                               EPL_NMTMNU_NODE_FLAG_NOT_SCANNED);
1491
1492                         if (uiSubIndex == EPL_C_ADR_DIAG_DEF_NODE_ID) { // diagnostic node must be scanned by MN in any case
1493                                 dwNodeCfg |=
1494                                     (EPL_NODEASSIGN_NODE_IS_CN |
1495                                      EPL_NODEASSIGN_NODE_EXISTS);
1496                                 // and it must be isochronously accessed
1497                                 dwNodeCfg &= ~EPL_NODEASSIGN_ASYNCONLY_NODE;
1498                         }
1499                         // save node config in local node info structure
1500                         EPL_NMTMNU_GET_NODEINFO(uiSubIndex)->m_dwNodeCfg =
1501                             dwNodeCfg;
1502                         EPL_NMTMNU_GET_NODEINFO(uiSubIndex)->m_NodeState =
1503                             kEplNmtMnuNodeStateUnknown;
1504
1505                         if ((dwNodeCfg & (EPL_NODEASSIGN_NODE_IS_CN | EPL_NODEASSIGN_NODE_EXISTS)) != 0) {      // node is configured as CN
1506                                 // identify the node
1507                                 Ret =
1508                                     EplIdentuRequestIdentResponse(uiSubIndex,
1509                                                                   EplNmtMnuCbIdentResponse);
1510                                 if (Ret != kEplSuccessful) {
1511                                         goto Exit;
1512                                 }
1513                                 // set flag "not scanned"
1514                                 EPL_NMTMNU_GET_NODEINFO(uiSubIndex)->m_wFlags |=
1515                                     EPL_NMTMNU_NODE_FLAG_NOT_SCANNED;
1516                                 EplNmtMnuInstance_g.m_uiSignalSlaveCount++;
1517                                 // signal slave counter shall be decremented if IdentRequest was sent once to a CN
1518
1519                                 if ((dwNodeCfg & EPL_NODEASSIGN_MANDATORY_CN) != 0) {   // node is a mandatory CN
1520                                         EplNmtMnuInstance_g.
1521                                             m_uiMandatorySlaveCount++;
1522                                         // mandatory slave counter shall be decremented if mandatory CN was configured successfully
1523                                 }
1524                         }
1525                 } else {        // subindex of MN
1526                         if ((dwNodeCfg & (EPL_NODEASSIGN_MN_PRES | EPL_NODEASSIGN_NODE_EXISTS)) != 0) { // MN shall send PRes
1527                                 tEplDllNodeInfo DllNodeInfo;
1528
1529                                 EPL_MEMSET(&DllNodeInfo, 0,
1530                                            sizeof(DllNodeInfo));
1531                                 DllNodeInfo.m_uiNodeId = uiLocalNodeId;
1532
1533                                 Ret = EplDlluCalAddNode(&DllNodeInfo);
1534                         }
1535                 }
1536         }
1537
1538       Exit:
1539         return Ret;
1540 }
1541
1542 //---------------------------------------------------------------------------
1543 //
1544 // Function:    EplNmtMnuStartBootStep2
1545 //
1546 // Description: starts BootStep2.
1547 //              That means add nodes to isochronous phase and send
1548 //              NMT EnableReadyToOp.
1549 //
1550 // Parameters:  (none)
1551 //
1552 // Returns:     tEplKernel              = error code
1553 //
1554 // State:
1555 //
1556 //---------------------------------------------------------------------------
1557
1558 static tEplKernel EplNmtMnuStartBootStep2(void)
1559 {
1560         tEplKernel Ret = kEplSuccessful;
1561         unsigned int uiIndex;
1562         tEplNmtMnuNodeInfo *pNodeInfo;
1563
1564         if ((EplNmtMnuInstance_g.m_wFlags & EPL_NMTMNU_FLAG_HALTED) == 0) {     // boot process is not halted
1565                 // add nodes to isochronous phase and send NMT EnableReadyToOp
1566                 EplNmtMnuInstance_g.m_uiMandatorySlaveCount = 0;
1567                 EplNmtMnuInstance_g.m_uiSignalSlaveCount = 0;
1568                 // reset flag that application was informed about possible state change
1569                 EplNmtMnuInstance_g.m_wFlags &= ~EPL_NMTMNU_FLAG_APP_INFORMED;
1570
1571                 pNodeInfo = EplNmtMnuInstance_g.m_aNodeInfo;
1572                 for (uiIndex = 1;
1573                      uiIndex <= tabentries(EplNmtMnuInstance_g.m_aNodeInfo);
1574                      uiIndex++, pNodeInfo++) {
1575                         if (pNodeInfo->m_NodeState ==
1576                             kEplNmtMnuNodeStateConfigured) {
1577                                 Ret =
1578                                     EplNmtMnuNodeBootStep2(uiIndex, pNodeInfo);
1579                                 if (Ret != kEplSuccessful) {
1580                                         goto Exit;
1581                                 }
1582                                 // set flag "not scanned"
1583                                 pNodeInfo->m_wFlags |=
1584                                     EPL_NMTMNU_NODE_FLAG_NOT_SCANNED;
1585
1586                                 EplNmtMnuInstance_g.m_uiSignalSlaveCount++;
1587                                 // signal slave counter shall be decremented if StatusRequest was sent once to a CN
1588
1589                                 if ((pNodeInfo->m_dwNodeCfg & EPL_NODEASSIGN_MANDATORY_CN) != 0) {      // node is a mandatory CN
1590                                         EplNmtMnuInstance_g.
1591                                             m_uiMandatorySlaveCount++;
1592                                 }
1593                                 // mandatory slave counter shall be decremented if mandatory CN is ReadyToOp
1594                         }
1595                 }
1596         }
1597
1598       Exit:
1599         return Ret;
1600 }
1601
1602 //---------------------------------------------------------------------------
1603 //
1604 // Function:    EplNmtMnuNodeBootStep2
1605 //
1606 // Description: starts BootStep2 for the specified node.
1607 //              This means the CN is added to isochronous phase if not
1608 //              async-only and it gets the NMT command EnableReadyToOp.
1609 //              The CN must be in node state Configured, when it enters
1610 //              BootStep2. When BootStep2 finishes, the CN is in node state
1611 //              ReadyToOp.
1612 //              If TimeoutReadyToOp in object 0x1F89/5 is configured,
1613 //              TimerHdlLonger will be started with this timeout.
1614 //
1615 // Parameters:  uiNodeId_p              = node ID
1616 //              pNodeInfo_p             = pointer to internal node info structure
1617 //
1618 // Returns:     tEplKernel              = error code
1619 //
1620 // State:
1621 //
1622 //---------------------------------------------------------------------------
1623
1624 static tEplKernel EplNmtMnuNodeBootStep2(unsigned int uiNodeId_p,
1625                                          tEplNmtMnuNodeInfo * pNodeInfo_p)
1626 {
1627         tEplKernel Ret = kEplSuccessful;
1628         tEplDllNodeInfo DllNodeInfo;
1629         u32 dwNodeCfg;
1630         tEplObdSize ObdSize;
1631         tEplTimerArg TimerArg;
1632
1633         dwNodeCfg = pNodeInfo_p->m_dwNodeCfg;
1634         if ((dwNodeCfg & EPL_NODEASSIGN_ASYNCONLY_NODE) == 0) { // add node to isochronous phase
1635                 DllNodeInfo.m_uiNodeId = uiNodeId_p;
1636                 ObdSize = 4;
1637                 Ret =
1638                     EplObduReadEntry(0x1F92, uiNodeId_p,
1639                                      &DllNodeInfo.m_dwPresTimeout, &ObdSize);
1640                 if (Ret != kEplSuccessful) {
1641                         goto Exit;
1642                 }
1643
1644                 ObdSize = 2;
1645                 Ret =
1646                     EplObduReadEntry(0x1F8B, uiNodeId_p,
1647                                      &DllNodeInfo.m_wPreqPayloadLimit,
1648                                      &ObdSize);
1649                 if (Ret != kEplSuccessful) {
1650                         goto Exit;
1651                 }
1652
1653                 ObdSize = 2;
1654                 Ret =
1655                     EplObduReadEntry(0x1F8D, uiNodeId_p,
1656                                      &DllNodeInfo.m_wPresPayloadLimit,
1657                                      &ObdSize);
1658                 if (Ret != kEplSuccessful) {
1659                         goto Exit;
1660                 }
1661
1662                 pNodeInfo_p->m_wFlags |= EPL_NMTMNU_NODE_FLAG_ISOCHRON;
1663
1664                 Ret = EplDlluCalAddNode(&DllNodeInfo);
1665                 if (Ret != kEplSuccessful) {
1666                         goto Exit;
1667                 }
1668
1669         }
1670
1671         EPL_NMTMNU_DBG_POST_TRACE_VALUE(0,
1672                                         uiNodeId_p,
1673                                         kEplNmtCmdEnableReadyToOperate);
1674
1675         Ret =
1676             EplNmtMnuSendNmtCommand(uiNodeId_p, kEplNmtCmdEnableReadyToOperate);
1677         if (Ret != kEplSuccessful) {
1678                 goto Exit;
1679         }
1680
1681         if (EplNmtMnuInstance_g.m_ulTimeoutReadyToOp != 0L) {   // start timer
1682                 // when the timer expires the CN must be ReadyToOp
1683                 EPL_NMTMNU_SET_FLAGS_TIMERARG_LONGER(pNodeInfo_p, uiNodeId_p,
1684                                                      TimerArg);
1685 //        TimerArg.m_EventSink = kEplEventSinkNmtMnu;
1686 //        TimerArg.m_ulArg = EPL_NMTMNU_TIMERARG_LONGER | uiNodeId_p;
1687                 Ret =
1688                     EplTimeruModifyTimerMs(&pNodeInfo_p->m_TimerHdlLonger,
1689                                            EplNmtMnuInstance_g.
1690                                            m_ulTimeoutReadyToOp, TimerArg);
1691         }
1692
1693       Exit:
1694         return Ret;
1695 }
1696
1697 //---------------------------------------------------------------------------
1698 //
1699 // Function:    EplNmtMnuStartCheckCom
1700 //
1701 // Description: starts CheckCommunication
1702 //
1703 // Parameters:  (none)
1704 //
1705 // Returns:     tEplKernel              = error code
1706 //
1707 // State:
1708 //
1709 //---------------------------------------------------------------------------
1710
1711 static tEplKernel EplNmtMnuStartCheckCom(void)
1712 {
1713         tEplKernel Ret = kEplSuccessful;
1714         unsigned int uiIndex;
1715         tEplNmtMnuNodeInfo *pNodeInfo;
1716
1717         if ((EplNmtMnuInstance_g.m_wFlags & EPL_NMTMNU_FLAG_HALTED) == 0) {     // boot process is not halted
1718                 // wait some time and check that no communication error occurs
1719                 EplNmtMnuInstance_g.m_uiMandatorySlaveCount = 0;
1720                 EplNmtMnuInstance_g.m_uiSignalSlaveCount = 0;
1721                 // reset flag that application was informed about possible state change
1722                 EplNmtMnuInstance_g.m_wFlags &= ~EPL_NMTMNU_FLAG_APP_INFORMED;
1723
1724                 pNodeInfo = EplNmtMnuInstance_g.m_aNodeInfo;
1725                 for (uiIndex = 1;
1726                      uiIndex <= tabentries(EplNmtMnuInstance_g.m_aNodeInfo);
1727                      uiIndex++, pNodeInfo++) {
1728                         if (pNodeInfo->m_NodeState ==
1729                             kEplNmtMnuNodeStateReadyToOp) {
1730                                 Ret = EplNmtMnuNodeCheckCom(uiIndex, pNodeInfo);
1731                                 if (Ret == kEplReject) {        // timer was started
1732                                         // wait until it expires
1733                                         if ((pNodeInfo->m_dwNodeCfg & EPL_NODEASSIGN_MANDATORY_CN) != 0) {      // node is a mandatory CN
1734                                                 EplNmtMnuInstance_g.
1735                                                     m_uiMandatorySlaveCount++;
1736                                         }
1737                                 } else if (Ret != kEplSuccessful) {
1738                                         goto Exit;
1739                                 }
1740                                 // set flag "not scanned"
1741                                 pNodeInfo->m_wFlags |=
1742                                     EPL_NMTMNU_NODE_FLAG_NOT_SCANNED;
1743
1744                                 EplNmtMnuInstance_g.m_uiSignalSlaveCount++;
1745                                 // signal slave counter shall be decremented if timeout elapsed and regardless of an error
1746                                 // mandatory slave counter shall be decremented if timeout elapsed and no error occured
1747                         }
1748                 }
1749         }
1750
1751         Ret = kEplSuccessful;
1752
1753       Exit:
1754         return Ret;
1755 }
1756
1757 //---------------------------------------------------------------------------
1758 //
1759 // Function:    EplNmtMnuNodeCheckCom
1760 //
1761 // Description: checks communication of the specified node.
1762 //              That means wait some time and if no error occured everything
1763 //              is OK.
1764 //
1765 // Parameters:  uiNodeId_p              = node ID
1766 //              pNodeInfo_p             = pointer to internal node info structure
1767 //
1768 // Returns:     tEplKernel              = error code
1769 //
1770 // State:
1771 //
1772 //---------------------------------------------------------------------------
1773
1774 static tEplKernel EplNmtMnuNodeCheckCom(unsigned int uiNodeId_p,
1775                                         tEplNmtMnuNodeInfo * pNodeInfo_p)
1776 {
1777         tEplKernel Ret = kEplSuccessful;
1778         u32 dwNodeCfg;
1779         tEplTimerArg TimerArg;
1780
1781         dwNodeCfg = pNodeInfo_p->m_dwNodeCfg;
1782         if (((dwNodeCfg & EPL_NODEASSIGN_ASYNCONLY_NODE) == 0)
1783             && (EplNmtMnuInstance_g.m_ulTimeoutCheckCom != 0L)) {       // CN is not async-only and timeout for CheckCom was set
1784
1785                 // check communication,
1786                 // that means wait some time and if no error occured everything is OK;
1787
1788                 // start timer (when the timer expires the CN must be still ReadyToOp)
1789                 EPL_NMTMNU_SET_FLAGS_TIMERARG_LONGER(pNodeInfo_p, uiNodeId_p,
1790                                                      TimerArg);
1791 //        TimerArg.m_EventSink = kEplEventSinkNmtMnu;
1792 //        TimerArg.m_ulArg = EPL_NMTMNU_TIMERARG_LONGER | uiNodeId_p;
1793                 Ret =
1794                     EplTimeruModifyTimerMs(&pNodeInfo_p->m_TimerHdlLonger,
1795                                            EplNmtMnuInstance_g.
1796                                            m_ulTimeoutCheckCom, TimerArg);
1797
1798                 // update mandatory slave counter, because timer was started
1799                 if (Ret == kEplSuccessful) {
1800                         Ret = kEplReject;
1801                 }
1802         } else {                // timer was not started
1803                 // assume everything is OK
1804                 pNodeInfo_p->m_NodeState = kEplNmtMnuNodeStateComChecked;
1805         }
1806
1807 //Exit:
1808         return Ret;
1809 }
1810
1811 //---------------------------------------------------------------------------
1812 //
1813 // Function:    EplNmtMnuStartNodes
1814 //
1815 // Description: really starts all nodes which are ReadyToOp and CheckCom did not fail
1816 //
1817 // Parameters:  (none)
1818 //
1819 // Returns:     tEplKernel              = error code
1820 //
1821 // State:
1822 //
1823 //---------------------------------------------------------------------------
1824
1825 static tEplKernel EplNmtMnuStartNodes(void)
1826 {
1827         tEplKernel Ret = kEplSuccessful;
1828         unsigned int uiIndex;
1829         tEplNmtMnuNodeInfo *pNodeInfo;
1830
1831         if ((EplNmtMnuInstance_g.m_wFlags & EPL_NMTMNU_FLAG_HALTED) == 0) {     // boot process is not halted
1832                 // send NMT command Start Node
1833                 EplNmtMnuInstance_g.m_uiMandatorySlaveCount = 0;
1834                 EplNmtMnuInstance_g.m_uiSignalSlaveCount = 0;
1835                 // reset flag that application was informed about possible state change
1836                 EplNmtMnuInstance_g.m_wFlags &= ~EPL_NMTMNU_FLAG_APP_INFORMED;
1837
1838                 pNodeInfo = EplNmtMnuInstance_g.m_aNodeInfo;
1839                 for (uiIndex = 1;
1840                      uiIndex <= tabentries(EplNmtMnuInstance_g.m_aNodeInfo);
1841                      uiIndex++, pNodeInfo++) {
1842                         if (pNodeInfo->m_NodeState ==
1843                             kEplNmtMnuNodeStateComChecked) {
1844                                 if ((EplNmtMnuInstance_g.
1845                                      m_dwNmtStartup & EPL_NMTST_STARTALLNODES)
1846                                     == 0) {
1847                                         EPL_NMTMNU_DBG_POST_TRACE_VALUE(0,
1848                                                                         uiIndex,
1849                                                                         kEplNmtCmdStartNode);
1850
1851                                         Ret =
1852                                             EplNmtMnuSendNmtCommand(uiIndex,
1853                                                                     kEplNmtCmdStartNode);
1854                                         if (Ret != kEplSuccessful) {
1855                                                 goto Exit;
1856                                         }
1857                                 }
1858
1859                                 if ((pNodeInfo->m_dwNodeCfg & EPL_NODEASSIGN_MANDATORY_CN) != 0) {      // node is a mandatory CN
1860                                         EplNmtMnuInstance_g.
1861                                             m_uiMandatorySlaveCount++;
1862                                 }
1863                                 // set flag "not scanned"
1864                                 pNodeInfo->m_wFlags |=
1865                                     EPL_NMTMNU_NODE_FLAG_NOT_SCANNED;
1866
1867                                 EplNmtMnuInstance_g.m_uiSignalSlaveCount++;
1868                                 // signal slave counter shall be decremented if StatusRequest was sent once to a CN
1869                                 // mandatory slave counter shall be decremented if mandatory CN is OPERATIONAL
1870                         }
1871                 }
1872
1873                 // $$$ inform application if EPL_NMTST_NO_STARTNODE is set
1874
1875                 if ((EplNmtMnuInstance_g.
1876                      m_dwNmtStartup & EPL_NMTST_STARTALLNODES) != 0) {
1877                         EPL_NMTMNU_DBG_POST_TRACE_VALUE(0, EPL_C_ADR_BROADCAST,
1878                                                         kEplNmtCmdStartNode);
1879
1880                         Ret =
1881                             EplNmtMnuSendNmtCommand(EPL_C_ADR_BROADCAST,
1882                                                     kEplNmtCmdStartNode);
1883                         if (Ret != kEplSuccessful) {
1884                                 goto Exit;
1885                         }
1886                 }
1887         }
1888
1889       Exit:
1890         return Ret;
1891 }
1892
1893 //---------------------------------------------------------------------------
1894 //
1895 // Function:    EplNmtMnuProcessInternalEvent
1896 //
1897 // Description: processes internal node events
1898 //
1899 // Parameters:  uiNodeId_p              = node ID
1900 //              NodeNmtState_p          = NMT state of CN
1901 //              NodeEvent_p             = occured events
1902 //
1903 // Returns:     tEplKernel              = error code
1904 //
1905 //
1906 // State:
1907 //
1908 //---------------------------------------------------------------------------
1909
1910 static tEplKernel EplNmtMnuProcessInternalEvent(unsigned int uiNodeId_p,
1911                                                 tEplNmtState NodeNmtState_p,
1912                                                 u16 wErrorCode_p,
1913                                                 tEplNmtMnuIntNodeEvent
1914                                                 NodeEvent_p)
1915 {
1916         tEplKernel Ret = kEplSuccessful;
1917         tEplNmtState NmtState;
1918         tEplNmtMnuNodeInfo *pNodeInfo;
1919         tEplTimerArg TimerArg;
1920
1921         pNodeInfo = EPL_NMTMNU_GET_NODEINFO(uiNodeId_p);
1922         NmtState = EplNmtuGetNmtState();
1923         if (NmtState <= kEplNmtMsNotActive) {   // MN is not active
1924                 goto Exit;
1925         }
1926
1927         switch (NodeEvent_p) {
1928         case kEplNmtMnuIntNodeEventIdentResponse:
1929                 {
1930                         u8 bNmtState;
1931
1932                         EPL_NMTMNU_DBG_POST_TRACE_VALUE(NodeEvent_p,
1933                                                         uiNodeId_p,
1934                                                         pNodeInfo->m_NodeState);
1935
1936                         if (pNodeInfo->m_NodeState !=
1937                             kEplNmtMnuNodeStateResetConf) {
1938                                 pNodeInfo->m_NodeState =
1939                                     kEplNmtMnuNodeStateIdentified;
1940                         }
1941                         // reset flags ISOCHRON and NMT_CMD_ISSUED
1942                         pNodeInfo->m_wFlags &= ~(EPL_NMTMNU_NODE_FLAG_ISOCHRON
1943                                                  |
1944                                                  EPL_NMTMNU_NODE_FLAG_NMT_CMD_ISSUED);
1945
1946                         if ((NmtState == kEplNmtMsPreOperational1)
1947                             &&
1948                             ((pNodeInfo->
1949                               m_wFlags & EPL_NMTMNU_NODE_FLAG_NOT_SCANNED) !=
1950                              0)) {
1951                                 // decrement only signal slave count
1952                                 EplNmtMnuInstance_g.m_uiSignalSlaveCount--;
1953                                 pNodeInfo->m_wFlags &=
1954                                     ~EPL_NMTMNU_NODE_FLAG_NOT_SCANNED;
1955                         }
1956                         // update object 0x1F8F NMT_MNNodeExpState_AU8 to PreOp1 (even if local state >= PreOp2)
1957                         bNmtState = (u8) (kEplNmtCsPreOperational1 & 0xFF);
1958                         Ret =
1959                             EplObduWriteEntry(0x1F8F, uiNodeId_p, &bNmtState,
1960                                               1);
1961
1962                         // check NMT state of CN
1963                         Ret =
1964                             EplNmtMnuCheckNmtState(uiNodeId_p, pNodeInfo,
1965                                                    NodeNmtState_p, wErrorCode_p,
1966                                                    NmtState);
1967                         if (Ret != kEplSuccessful) {
1968                                 if (Ret == kEplReject) {
1969                                         Ret = kEplSuccessful;
1970                                 }
1971                                 break;
1972                         }
1973                         // request StatusResponse immediately,
1974                         // because we want a fast boot-up of CNs
1975                         Ret =
1976                             EplStatusuRequestStatusResponse(uiNodeId_p,
1977                                                             EplNmtMnuCbStatusResponse);
1978                         if (Ret != kEplSuccessful) {
1979                                 EPL_NMTMNU_DBG_POST_TRACE_VALUE(NodeEvent_p,
1980                                                                 uiNodeId_p,
1981                                                                 Ret);
1982
1983                                 if (Ret == kEplInvalidOperation) {      // the only situation when this should happen is, when
1984                                         // StatusResponse was already requested from within
1985                                         // the StatReq timer event.
1986                                         // so ignore this error.
1987                                         Ret = kEplSuccessful;
1988                                 } else {
1989                                         break;
1990                                 }
1991                         }
1992
1993                         if (pNodeInfo->m_NodeState !=
1994                             kEplNmtMnuNodeStateResetConf) {
1995                                 // inform application
1996                                 Ret =
1997                                     EplNmtMnuInstance_g.
1998                                     m_pfnCbNodeEvent(uiNodeId_p,
1999                                                      kEplNmtNodeEventFound,
2000                                                      NodeNmtState_p,
2001                                                      EPL_E_NO_ERROR,
2002                                                      (pNodeInfo->
2003                                                       m_dwNodeCfg &
2004                                                       EPL_NODEASSIGN_MANDATORY_CN)
2005                                                      != 0);
2006                                 if (Ret == kEplReject) {        // interrupt boot process on user request
2007                                         EPL_NMTMNU_DBG_POST_TRACE_VALUE
2008                                             (NodeEvent_p, uiNodeId_p,
2009                                              ((pNodeInfo->m_NodeState << 8)
2010                                               | Ret));
2011
2012                                         Ret = kEplSuccessful;
2013                                         break;
2014                                 } else if (Ret != kEplSuccessful) {
2015                                         EPL_NMTMNU_DBG_POST_TRACE_VALUE
2016                                             (NodeEvent_p, uiNodeId_p,
2017                                              ((pNodeInfo->m_NodeState << 8)
2018                                               | Ret));
2019
2020                                         break;
2021                                 }
2022                         }
2023                         // continue BootStep1
2024                 }
2025
2026         case kEplNmtMnuIntNodeEventBoot:
2027                 {
2028
2029                         // $$$ check identification (vendor ID, product code, revision no, serial no)
2030
2031                         if (pNodeInfo->m_NodeState ==
2032                             kEplNmtMnuNodeStateIdentified) {
2033                                 // $$$ check software
2034
2035                                 // check/start configuration
2036                                 // inform application
2037                                 Ret =
2038                                     EplNmtMnuInstance_g.
2039                                     m_pfnCbNodeEvent(uiNodeId_p,
2040                                                      kEplNmtNodeEventCheckConf,
2041                                                      NodeNmtState_p,
2042                                                      EPL_E_NO_ERROR,
2043                                                      (pNodeInfo->
2044                                                       m_dwNodeCfg &
2045                                                       EPL_NODEASSIGN_MANDATORY_CN)
2046                                                      != 0);
2047                                 if (Ret == kEplReject) {        // interrupt boot process on user request
2048                                         EPL_NMTMNU_DBG_POST_TRACE_VALUE
2049                                             (kEplNmtMnuIntNodeEventBoot,
2050                                              uiNodeId_p,
2051                                              ((pNodeInfo->m_NodeState << 8)
2052                                               | Ret));
2053
2054                                         Ret = kEplSuccessful;
2055                                         break;
2056                                 } else if (Ret != kEplSuccessful) {
2057                                         EPL_NMTMNU_DBG_POST_TRACE_VALUE
2058                                             (kEplNmtMnuIntNodeEventBoot,
2059                                              uiNodeId_p,
2060                                              ((pNodeInfo->m_NodeState << 8)
2061                                               | Ret));
2062
2063                                         break;
2064                                 }
2065                         } else if (pNodeInfo->m_NodeState != kEplNmtMnuNodeStateResetConf) {    // wrong CN state
2066                                 // ignore event
2067                                 break;
2068                         }
2069                         // $$$ d.k.: currently we assume configuration is OK
2070
2071                         // continue BootStep1
2072                 }
2073
2074         case kEplNmtMnuIntNodeEventConfigured:
2075                 {
2076                         if ((pNodeInfo->m_NodeState !=
2077                              kEplNmtMnuNodeStateIdentified)
2078                             && (pNodeInfo->m_NodeState != kEplNmtMnuNodeStateResetConf)) {      // wrong CN state
2079                                 // ignore event
2080                                 break;
2081                         }
2082
2083                         pNodeInfo->m_NodeState = kEplNmtMnuNodeStateConfigured;
2084
2085                         if (NmtState == kEplNmtMsPreOperational1) {
2086                                 if ((pNodeInfo->m_dwNodeCfg & EPL_NODEASSIGN_MANDATORY_CN) != 0) {      // decrement mandatory CN counter
2087                                         EplNmtMnuInstance_g.
2088                                             m_uiMandatorySlaveCount--;
2089                                 }
2090                         } else {
2091                                 // put optional node to next step (BootStep2)
2092                                 Ret =
2093                                     EplNmtMnuNodeBootStep2(uiNodeId_p,
2094                                                            pNodeInfo);
2095                         }
2096                         break;
2097                 }
2098
2099         case kEplNmtMnuIntNodeEventNoIdentResponse:
2100                 {
2101                         if ((NmtState == kEplNmtMsPreOperational1)
2102                             &&
2103                             ((pNodeInfo->
2104                               m_wFlags & EPL_NMTMNU_NODE_FLAG_NOT_SCANNED) !=
2105                              0)) {
2106                                 // decrement only signal slave count
2107                                 EplNmtMnuInstance_g.m_uiSignalSlaveCount--;
2108                                 pNodeInfo->m_wFlags &=
2109                                     ~EPL_NMTMNU_NODE_FLAG_NOT_SCANNED;
2110                         }
2111
2112                         if (pNodeInfo->m_NodeState !=
2113                             kEplNmtMnuNodeStateResetConf) {
2114                                 pNodeInfo->m_NodeState =
2115                                     kEplNmtMnuNodeStateUnknown;
2116                         }
2117                         // $$$ d.k. check start time for 0x1F89/2 MNTimeoutPreOp1_U32
2118                         // $$$ d.k. check individual timeout 0x1F89/6 MNIdentificationTimeout_U32
2119                         // if mandatory node and timeout elapsed -> halt boot procedure
2120                         // trigger IdentRequest again (if >= PreOp2, after delay)
2121                         if (NmtState >= kEplNmtMsPreOperational2) {     // start timer
2122                                 EPL_NMTMNU_SET_FLAGS_TIMERARG_IDENTREQ
2123                                     (pNodeInfo, uiNodeId_p, TimerArg);
2124 //                TimerArg.m_EventSink = kEplEventSinkNmtMnu;
2125 //                TimerArg.m_ulArg = EPL_NMTMNU_TIMERARG_IDENTREQ | uiNodeId_p;
2126 /*
2127                 EPL_NMTMNU_DBG_POST_TRACE_VALUE(kEplNmtMnuIntNodeEventNoIdentResponse,
2128                                                 uiNodeId_p,
2129                                                 ((pNodeInfo->m_NodeState << 8)
2130                                                  | 0x80
2131                                                  | ((pNodeInfo->m_wFlags & EPL_NMTMNU_NODE_FLAG_COUNT_STATREQ) >> 6)
2132                                                  | ((TimerArg.m_ulArg & EPL_NMTMNU_TIMERARG_COUNT_SR) >> 8)));
2133 */
2134                                 Ret =
2135                                     EplTimeruModifyTimerMs(&pNodeInfo->
2136                                                            m_TimerHdlStatReq,
2137                                                            EplNmtMnuInstance_g.
2138                                                            m_ulStatusRequestDelay,
2139                                                            TimerArg);
2140                         } else {        // trigger IdentRequest immediately
2141                                 Ret =
2142                                     EplIdentuRequestIdentResponse(uiNodeId_p,
2143                                                                   EplNmtMnuCbIdentResponse);
2144                         }
2145                         break;
2146                 }
2147
2148         case kEplNmtMnuIntNodeEventStatusResponse:
2149                 {
2150                         if ((NmtState >= kEplNmtMsPreOperational2)
2151                             &&
2152                             ((pNodeInfo->
2153                               m_wFlags & EPL_NMTMNU_NODE_FLAG_NOT_SCANNED) !=
2154                              0)) {
2155                                 // decrement only signal slave count if checked once for ReadyToOp, CheckCom, Operational
2156                                 EplNmtMnuInstance_g.m_uiSignalSlaveCount--;
2157                                 pNodeInfo->m_wFlags &=
2158                                     ~EPL_NMTMNU_NODE_FLAG_NOT_SCANNED;
2159                         }
2160                         // check NMT state of CN
2161                         Ret =
2162                             EplNmtMnuCheckNmtState(uiNodeId_p, pNodeInfo,
2163                                                    NodeNmtState_p, wErrorCode_p,
2164                                                    NmtState);
2165                         if (Ret != kEplSuccessful) {
2166                                 if (Ret == kEplReject) {
2167                                         Ret = kEplSuccessful;
2168                                 }
2169                                 break;
2170                         }
2171
2172                         if (NmtState == kEplNmtMsPreOperational1) {
2173                                 // request next StatusResponse immediately
2174                                 Ret =
2175                                     EplStatusuRequestStatusResponse(uiNodeId_p,
2176                                                                     EplNmtMnuCbStatusResponse);
2177                                 if (Ret != kEplSuccessful) {
2178                                         EPL_NMTMNU_DBG_POST_TRACE_VALUE
2179                                             (NodeEvent_p, uiNodeId_p, Ret);
2180                                 }
2181
2182                         } else if ((pNodeInfo->m_wFlags & EPL_NMTMNU_NODE_FLAG_ISOCHRON) == 0) {        // start timer
2183                                 // not isochronously accessed CN (e.g. async-only or stopped CN)
2184                                 EPL_NMTMNU_SET_FLAGS_TIMERARG_STATREQ(pNodeInfo,
2185                                                                       uiNodeId_p,
2186                                                                       TimerArg);
2187 //                TimerArg.m_EventSink = kEplEventSinkNmtMnu;
2188 //                TimerArg.m_ulArg = EPL_NMTMNU_TIMERARG_STATREQ | uiNodeId_p;
2189 /*
2190                 EPL_NMTMNU_DBG_POST_TRACE_VALUE(kEplNmtMnuIntNodeEventStatusResponse,
2191                                                 uiNodeId_p,
2192                                                 ((pNodeInfo->m_NodeState << 8)
2193                                                  | 0x80
2194                                                  | ((pNodeInfo->m_wFlags & EPL_NMTMNU_NODE_FLAG_COUNT_STATREQ) >> 6)
2195                                                  | ((TimerArg.m_ulArg & EPL_NMTMNU_TIMERARG_COUNT_SR) >> 8)));
2196 */
2197                                 Ret =
2198                                     EplTimeruModifyTimerMs(&pNodeInfo->
2199                                                            m_TimerHdlStatReq,
2200                                                            EplNmtMnuInstance_g.
2201                                                            m_ulStatusRequestDelay,
2202                                                            TimerArg);
2203                         }
2204
2205                         break;
2206                 }
2207
2208         case kEplNmtMnuIntNodeEventNoStatusResponse:
2209                 {
2210                         // function CheckNmtState sets node state to unknown if necessary
2211 /*
2212             if ((NmtState >= kEplNmtMsPreOperational2)
2213                 && ((pNodeInfo->m_wFlags & EPL_NMTMNU_NODE_FLAG_NOT_SCANNED) != 0))
2214             {
2215                 // decrement only signal slave count if checked once for ReadyToOp, CheckCom, Operational
2216                 EplNmtMnuInstance_g.m_uiSignalSlaveCount--;
2217                 pNodeInfo->m_wFlags &= ~EPL_NMTMNU_NODE_FLAG_NOT_SCANNED;
2218             }
2219 */
2220                         // check NMT state of CN
2221                         Ret =
2222                             EplNmtMnuCheckNmtState(uiNodeId_p, pNodeInfo,
2223                                                    NodeNmtState_p, wErrorCode_p,
2224                                                    NmtState);
2225                         if (Ret != kEplSuccessful) {
2226                                 if (Ret == kEplReject) {
2227                                         Ret = kEplSuccessful;
2228                                 }
2229                                 break;
2230                         }
2231
2232                         break;
2233                 }
2234
2235         case kEplNmtMnuIntNodeEventError:
2236                 {               // currently only issued on kEplNmtNodeCommandConfErr
2237
2238                         if (pNodeInfo->m_NodeState != kEplNmtMnuNodeStateIdentified) {  // wrong CN state
2239                                 // ignore event
2240                                 break;
2241                         }
2242                         // check NMT state of CN
2243                         Ret =
2244                             EplNmtMnuCheckNmtState(uiNodeId_p, pNodeInfo,
2245                                                    kEplNmtCsNotActive,
2246                                                    wErrorCode_p, NmtState);
2247                         if (Ret != kEplSuccessful) {
2248                                 if (Ret == kEplReject) {
2249                                         Ret = kEplSuccessful;
2250                                 }
2251                                 break;
2252                         }
2253
2254                         break;
2255                 }
2256
2257         case kEplNmtMnuIntNodeEventExecReset:
2258                 {
2259                         if (pNodeInfo->m_NodeState != kEplNmtMnuNodeStateIdentified) {  // wrong CN state
2260                                 // ignore event
2261                                 break;
2262                         }
2263
2264                         pNodeInfo->m_NodeState = kEplNmtMnuNodeStateResetConf;
2265
2266                         EPL_NMTMNU_DBG_POST_TRACE_VALUE(NodeEvent_p,
2267                                                         uiNodeId_p,
2268                                                         (((NodeNmtState_p &
2269                                                            0xFF) << 8)
2270                                                          |
2271                                                          kEplNmtCmdResetConfiguration));
2272
2273                         // send NMT reset configuration to CN for activation of configuration
2274                         Ret =
2275                             EplNmtMnuSendNmtCommand(uiNodeId_p,
2276                                                     kEplNmtCmdResetConfiguration);
2277
2278                         break;
2279                 }
2280
2281         case kEplNmtMnuIntNodeEventHeartbeat:
2282                 {
2283 /*
2284             if ((NmtState >= kEplNmtMsPreOperational2)
2285                 && ((pNodeInfo->m_wFlags & EPL_NMTMNU_NODE_FLAG_NOT_SCANNED) != 0))
2286             {
2287                 // decrement only signal slave count if checked once for ReadyToOp, CheckCom, Operational
2288                 EplNmtMnuInstance_g.m_uiSignalSlaveCount--;
2289                 pNodeInfo->m_wFlags &= ~EPL_NMTMNU_NODE_FLAG_NOT_SCANNED;
2290             }
2291 */
2292                         // check NMT state of CN
2293                         Ret =
2294                             EplNmtMnuCheckNmtState(uiNodeId_p, pNodeInfo,
2295                                                    NodeNmtState_p, wErrorCode_p,
2296                                                    NmtState);
2297                         if (Ret != kEplSuccessful) {
2298                                 if (Ret == kEplReject) {
2299                                         Ret = kEplSuccessful;
2300                                 }
2301                                 break;
2302                         }
2303
2304                         break;
2305                 }
2306
2307         case kEplNmtMnuIntNodeEventTimerIdentReq:
2308                 {
2309                         EPL_DBGLVL_NMTMN_TRACE1
2310                             ("TimerStatReq->IdentReq(%02X)\n", uiNodeId_p);
2311                         // trigger IdentRequest again
2312                         Ret =
2313                             EplIdentuRequestIdentResponse(uiNodeId_p,
2314                                                           EplNmtMnuCbIdentResponse);
2315                         if (Ret != kEplSuccessful) {
2316                                 EPL_NMTMNU_DBG_POST_TRACE_VALUE(NodeEvent_p,
2317                                                                 uiNodeId_p,
2318                                                                 (((NodeNmtState_p & 0xFF) << 8)
2319                                                                  | Ret));
2320                                 if (Ret == kEplInvalidOperation) {      // this can happen because of a bug in EplTimeruLinuxKernel.c
2321                                         // so ignore this error.
2322                                         Ret = kEplSuccessful;
2323                                 }
2324                         }
2325
2326                         break;
2327                 }
2328
2329         case kEplNmtMnuIntNodeEventTimerStateMon:
2330                 {
2331                         // reset NMT state change flag
2332                         // because from now on the CN must have the correct NMT state
2333                         pNodeInfo->m_wFlags &=
2334                             ~EPL_NMTMNU_NODE_FLAG_NMT_CMD_ISSUED;
2335
2336                         // continue with normal StatReq processing
2337                 }
2338
2339         case kEplNmtMnuIntNodeEventTimerStatReq:
2340                 {
2341                         EPL_DBGLVL_NMTMN_TRACE1("TimerStatReq->StatReq(%02X)\n",
2342                                                 uiNodeId_p);
2343                         // request next StatusResponse
2344                         Ret =
2345                             EplStatusuRequestStatusResponse(uiNodeId_p,
2346                                                             EplNmtMnuCbStatusResponse);
2347                         if (Ret != kEplSuccessful) {
2348                                 EPL_NMTMNU_DBG_POST_TRACE_VALUE(NodeEvent_p,
2349                                                                 uiNodeId_p,
2350                                                                 (((NodeNmtState_p & 0xFF) << 8)
2351                                                                  | Ret));
2352                                 if (Ret == kEplInvalidOperation) {      // the only situation when this should happen is, when
2353                                         // StatusResponse was already requested while processing
2354                                         // event IdentResponse.
2355                                         // so ignore this error.
2356                                         Ret = kEplSuccessful;
2357                                 }
2358                         }
2359
2360                         break;
2361                 }
2362
2363         case kEplNmtMnuIntNodeEventTimerLonger:
2364                 {
2365                         switch (pNodeInfo->m_NodeState) {
2366                         case kEplNmtMnuNodeStateConfigured:
2367                                 {       // node should be ReadyToOp but it is not
2368
2369                                         // check NMT state which shall be intentionally wrong, so that ERROR_TREATMENT will be started
2370                                         Ret =
2371                                             EplNmtMnuCheckNmtState(uiNodeId_p,
2372                                                                    pNodeInfo,
2373                                                                    kEplNmtCsNotActive,
2374                                                                    EPL_E_NMT_BPO2,
2375                                                                    NmtState);
2376                                         if (Ret != kEplSuccessful) {
2377                                                 if (Ret == kEplReject) {
2378                                                         Ret = kEplSuccessful;
2379                                                 }
2380                                                 break;
2381                                         }
2382
2383                                         break;
2384                                 }
2385
2386                         case kEplNmtMnuNodeStateReadyToOp:
2387                                 {       // CheckCom finished successfully
2388
2389                                         pNodeInfo->m_NodeState =
2390                                             kEplNmtMnuNodeStateComChecked;
2391
2392                                         if ((pNodeInfo->
2393                                              m_wFlags &
2394                                              EPL_NMTMNU_NODE_FLAG_NOT_SCANNED)
2395                                             != 0) {
2396                                                 // decrement only signal slave count if checked once for ReadyToOp, CheckCom, Operational
2397                                                 EplNmtMnuInstance_g.
2398                                                     m_uiSignalSlaveCount--;
2399                                                 pNodeInfo->m_wFlags &=
2400                                                     ~EPL_NMTMNU_NODE_FLAG_NOT_SCANNED;
2401                                         }
2402
2403                                         if ((pNodeInfo->
2404                                              m_dwNodeCfg &
2405                                              EPL_NODEASSIGN_MANDATORY_CN) !=
2406                                             0) {
2407                                                 // decrement mandatory slave counter
2408                                                 EplNmtMnuInstance_g.
2409                                                     m_uiMandatorySlaveCount--;
2410                                         }
2411                                         if (NmtState != kEplNmtMsReadyToOperate) {
2412                                                 EPL_NMTMNU_DBG_POST_TRACE_VALUE
2413                                                     (NodeEvent_p, uiNodeId_p,
2414                                                      (((NodeNmtState_p & 0xFF)
2415                                                        << 8)
2416                                                       | kEplNmtCmdStartNode));
2417
2418                                                 // start optional CN
2419                                                 Ret =
2420                                                     EplNmtMnuSendNmtCommand
2421                                                     (uiNodeId_p,
2422                                                      kEplNmtCmdStartNode);
2423                                         }
2424                                         break;
2425                                 }
2426
2427                         default:
2428                                 {
2429                                         break;
2430                                 }
2431                         }
2432                         break;
2433                 }
2434
2435         case kEplNmtMnuIntNodeEventNmtCmdSent:
2436                 {
2437                         u8 bNmtState;
2438
2439                         // update expected NMT state with the one that results
2440                         // from the sent NMT command
2441                         bNmtState = (u8) (NodeNmtState_p & 0xFF);
2442
2443                         // write object 0x1F8F NMT_MNNodeExpState_AU8
2444                         Ret =
2445                             EplObduWriteEntry(0x1F8F, uiNodeId_p, &bNmtState,
2446                                               1);
2447                         if (Ret != kEplSuccessful) {
2448                                 goto Exit;
2449                         }
2450
2451                         if (NodeNmtState_p == kEplNmtCsNotActive) {     // restart processing with IdentRequest
2452                                 EPL_NMTMNU_SET_FLAGS_TIMERARG_IDENTREQ
2453                                     (pNodeInfo, uiNodeId_p, TimerArg);
2454                         } else {        // monitor NMT state change with StatusRequest after
2455                                 // the corresponding delay;
2456                                 // until then wrong NMT states will be ignored
2457                                 EPL_NMTMNU_SET_FLAGS_TIMERARG_STATE_MON
2458                                     (pNodeInfo, uiNodeId_p, TimerArg);
2459
2460                                 // set NMT state change flag
2461                                 pNodeInfo->m_wFlags |=
2462                                     EPL_NMTMNU_NODE_FLAG_NMT_CMD_ISSUED;
2463                         }
2464
2465                         Ret =
2466                             EplTimeruModifyTimerMs(&pNodeInfo->
2467                                                    m_TimerHdlStatReq,
2468                                                    EplNmtMnuInstance_g.
2469                                                    m_ulStatusRequestDelay,
2470                                                    TimerArg);
2471
2472                         // finish processing, because NmtState_p is the expected and not the current state
2473                         goto Exit;
2474                 }
2475
2476         default:
2477                 {
2478                         break;
2479                 }
2480         }
2481
2482         // check if network is ready to change local NMT state and this was not done before
2483         if ((EplNmtMnuInstance_g.m_wFlags & (EPL_NMTMNU_FLAG_HALTED | EPL_NMTMNU_FLAG_APP_INFORMED)) == 0) {    // boot process is not halted
2484                 switch (NmtState) {
2485                 case kEplNmtMsPreOperational1:
2486                         {
2487                                 if ((EplNmtMnuInstance_g.m_uiSignalSlaveCount ==
2488                                      0)
2489                                     && (EplNmtMnuInstance_g.m_uiMandatorySlaveCount == 0)) {    // all optional CNs scanned once and all mandatory CNs configured successfully
2490                                         EplNmtMnuInstance_g.m_wFlags |=
2491                                             EPL_NMTMNU_FLAG_APP_INFORMED;
2492                                         // inform application
2493                                         Ret =
2494                                             EplNmtMnuInstance_g.
2495                                             m_pfnCbBootEvent
2496                                             (kEplNmtBootEventBootStep1Finish,
2497                                              NmtState, EPL_E_NO_ERROR);
2498                                         if (Ret != kEplSuccessful) {
2499                                                 if (Ret == kEplReject) {
2500                                                         // wait for application
2501                                                         Ret = kEplSuccessful;
2502                                                 }
2503                                                 break;
2504                                         }
2505                                         // enter PreOp2
2506                                         Ret =
2507                                             EplNmtuNmtEvent
2508                                             (kEplNmtEventAllMandatoryCNIdent);
2509                                 }
2510                                 break;
2511                         }
2512
2513                 case kEplNmtMsPreOperational2:
2514                         {
2515                                 if ((EplNmtMnuInstance_g.m_uiSignalSlaveCount ==
2516                                      0)
2517                                     && (EplNmtMnuInstance_g.m_uiMandatorySlaveCount == 0)) {    // all optional CNs checked once for ReadyToOp and all mandatory CNs are ReadyToOp
2518                                         EplNmtMnuInstance_g.m_wFlags |=
2519                                             EPL_NMTMNU_FLAG_APP_INFORMED;
2520                                         // inform application
2521                                         Ret =
2522                                             EplNmtMnuInstance_g.
2523                                             m_pfnCbBootEvent
2524                                             (kEplNmtBootEventBootStep2Finish,
2525                                              NmtState, EPL_E_NO_ERROR);
2526                                         if (Ret != kEplSuccessful) {
2527                                                 if (Ret == kEplReject) {
2528                                                         // wait for application
2529                                                         Ret = kEplSuccessful;
2530                                                 }
2531                                                 break;
2532                                         }
2533                                         // enter ReadyToOp
2534                                         Ret =
2535                                             EplNmtuNmtEvent
2536                                             (kEplNmtEventEnterReadyToOperate);
2537                                 }
2538                                 break;
2539                         }
2540
2541                 case kEplNmtMsReadyToOperate:
2542                         {
2543                                 if ((EplNmtMnuInstance_g.m_uiSignalSlaveCount ==
2544                                      0)
2545                                     && (EplNmtMnuInstance_g.m_uiMandatorySlaveCount == 0)) {    // all CNs checked for errorless communication
2546                                         EplNmtMnuInstance_g.m_wFlags |=
2547                                             EPL_NMTMNU_FLAG_APP_INFORMED;
2548                                         // inform application
2549                                         Ret =
2550                                             EplNmtMnuInstance_g.
2551                                             m_pfnCbBootEvent
2552                                             (kEplNmtBootEventCheckComFinish,
2553                                              NmtState, EPL_E_NO_ERROR);
2554                                         if (Ret != kEplSuccessful) {
2555                                                 if (Ret == kEplReject) {
2556                                                         // wait for application
2557                                                         Ret = kEplSuccessful;
2558                                                 }
2559                                                 break;
2560                                         }
2561                                         // enter Operational
2562                                         Ret =
2563                                             EplNmtuNmtEvent
2564                                             (kEplNmtEventEnterMsOperational);
2565                                 }
2566                                 break;
2567                         }
2568
2569                 case kEplNmtMsOperational:
2570                         {
2571                                 if ((EplNmtMnuInstance_g.m_uiSignalSlaveCount ==
2572                                      0)
2573                                     && (EplNmtMnuInstance_g.m_uiMandatorySlaveCount == 0)) {    // all optional CNs scanned once and all mandatory CNs are OPERATIONAL
2574                                         EplNmtMnuInstance_g.m_wFlags |=
2575                                             EPL_NMTMNU_FLAG_APP_INFORMED;
2576                                         // inform application
2577                                         Ret =
2578                                             EplNmtMnuInstance_g.
2579                                             m_pfnCbBootEvent
2580                                             (kEplNmtBootEventOperational,
2581                                              NmtState, EPL_E_NO_ERROR);
2582                                         if (Ret != kEplSuccessful) {
2583                                                 if (Ret == kEplReject) {
2584                                                         // ignore error code
2585                                                         Ret = kEplSuccessful;
2586                                                 }
2587                                                 break;
2588                                         }
2589                                 }
2590                                 break;
2591                         }
2592
2593                 default:
2594                         {
2595                                 break;
2596                         }
2597                 }
2598         }
2599
2600       Exit:
2601         return Ret;
2602 }
2603
2604 //---------------------------------------------------------------------------
2605 //
2606 // Function:    EplNmtMnuCheckNmtState
2607 //
2608 // Description: checks the NMT state, i.e. evaluates it with object 0x1F8F
2609 //              NMT_MNNodeExpState_AU8 and updates object 0x1F8E
2610 //              NMT_MNNodeCurrState_AU8.
2611 //              It manipulates m_NodeState in internal node info structure.
2612 //
2613 // Parameters:  uiNodeId_p              = node ID
2614 //              NodeNmtState_p          = NMT state of CN
2615 //
2616 // Returns:     tEplKernel              = error code
2617 //                  kEplReject          = CN was in wrong state and has been reset
2618 //
2619 // State:
2620 //
2621 //---------------------------------------------------------------------------
2622
2623 static tEplKernel EplNmtMnuCheckNmtState(unsigned int uiNodeId_p,
2624                                          tEplNmtMnuNodeInfo * pNodeInfo_p,
2625                                          tEplNmtState NodeNmtState_p,
2626                                          u16 wErrorCode_p,
2627                                          tEplNmtState LocalNmtState_p)
2628 {
2629         tEplKernel Ret = kEplSuccessful;
2630         tEplObdSize ObdSize;
2631         u8 bNmtState;
2632         u8 bNmtStatePrev;
2633         tEplNmtState ExpNmtState;
2634
2635         ObdSize = 1;
2636         // read object 0x1F8F NMT_MNNodeExpState_AU8
2637         Ret = EplObduReadEntry(0x1F8F, uiNodeId_p, &bNmtState, &ObdSize);
2638         if (Ret != kEplSuccessful) {
2639                 goto Exit;
2640         }
2641         // compute expected NMT state
2642         ExpNmtState = (tEplNmtState) (bNmtState | EPL_NMT_TYPE_CS);
2643         // compute u8 of current NMT state
2644         bNmtState = ((u8) NodeNmtState_p & 0xFF);
2645
2646         if (ExpNmtState == kEplNmtCsNotActive) {        // ignore the current state, because the CN shall be not active
2647                 Ret = kEplReject;
2648                 goto Exit;
2649         } else if ((ExpNmtState == kEplNmtCsPreOperational2)
2650                    && (NodeNmtState_p == kEplNmtCsReadyToOperate)) {    // CN switched to ReadyToOp
2651                 // delete timer for timeout handling
2652                 Ret = EplTimeruDeleteTimer(&pNodeInfo_p->m_TimerHdlLonger);
2653                 if (Ret != kEplSuccessful) {
2654                         goto Exit;
2655                 }
2656                 pNodeInfo_p->m_NodeState = kEplNmtMnuNodeStateReadyToOp;
2657
2658                 // update object 0x1F8F NMT_MNNodeExpState_AU8 to ReadyToOp
2659                 Ret = EplObduWriteEntry(0x1F8F, uiNodeId_p, &bNmtState, 1);
2660                 if (Ret != kEplSuccessful) {
2661                         goto Exit;
2662                 }
2663
2664                 if ((pNodeInfo_p->m_dwNodeCfg & EPL_NODEASSIGN_MANDATORY_CN) != 0) {    // node is a mandatory CN -> decrement counter
2665                         EplNmtMnuInstance_g.m_uiMandatorySlaveCount--;
2666                 }
2667                 if (LocalNmtState_p >= kEplNmtMsReadyToOperate) {       // start procedure CheckCommunication for this node
2668                         Ret = EplNmtMnuNodeCheckCom(uiNodeId_p, pNodeInfo_p);
2669                         if (Ret != kEplSuccessful) {
2670                                 goto Exit;
2671                         }
2672
2673                         if ((LocalNmtState_p == kEplNmtMsOperational)
2674                             && (pNodeInfo_p->m_NodeState ==
2675                                 kEplNmtMnuNodeStateComChecked)) {
2676                                 EPL_NMTMNU_DBG_POST_TRACE_VALUE(0, uiNodeId_p,
2677                                                                 (((NodeNmtState_p & 0xFF) << 8)
2678                                                                  |
2679                                                                  kEplNmtCmdStartNode));
2680
2681                                 // immediately start optional CN, because communication is always OK (e.g. async-only CN)
2682                                 Ret =
2683                                     EplNmtMnuSendNmtCommand(uiNodeId_p,
2684                                                             kEplNmtCmdStartNode);
2685                                 if (Ret != kEplSuccessful) {
2686                                         goto Exit;
2687                                 }
2688                         }
2689                 }
2690
2691         } else if ((ExpNmtState == kEplNmtCsReadyToOperate)
2692                    && (NodeNmtState_p == kEplNmtCsOperational)) {       // CN switched to OPERATIONAL
2693                 pNodeInfo_p->m_NodeState = kEplNmtMnuNodeStateOperational;
2694
2695                 if ((pNodeInfo_p->m_dwNodeCfg & EPL_NODEASSIGN_MANDATORY_CN) != 0) {    // node is a mandatory CN -> decrement counter
2696                         EplNmtMnuInstance_g.m_uiMandatorySlaveCount--;
2697                 }
2698
2699         } else if ((ExpNmtState != NodeNmtState_p)
2700                    && !((ExpNmtState == kEplNmtCsPreOperational1)
2701                         && (NodeNmtState_p == kEplNmtCsPreOperational2))) {     // CN is not in expected NMT state (without the exceptions above)
2702                 u16 wbeErrorCode;
2703
2704                 if ((pNodeInfo_p->
2705                      m_wFlags & EPL_NMTMNU_NODE_FLAG_NOT_SCANNED) != 0) {
2706                         // decrement only signal slave count if checked once
2707                         EplNmtMnuInstance_g.m_uiSignalSlaveCount--;
2708                         pNodeInfo_p->m_wFlags &=
2709                             ~EPL_NMTMNU_NODE_FLAG_NOT_SCANNED;
2710                 }
2711
2712                 if (pNodeInfo_p->m_NodeState == kEplNmtMnuNodeStateUnknown) {   // CN is already in state unknown, which means that it got
2713                         // NMT reset command earlier
2714                         goto Exit;
2715                 }
2716                 // -> CN is in wrong NMT state
2717                 pNodeInfo_p->m_NodeState = kEplNmtMnuNodeStateUnknown;
2718
2719                 if (wErrorCode_p == 0) {        // assume wrong NMT state error
2720                         if ((pNodeInfo_p->m_wFlags & EPL_NMTMNU_NODE_FLAG_NMT_CMD_ISSUED) != 0) {       // NMT command has been just issued;
2721                                 // ignore wrong NMT state until timer expires;
2722                                 // other errors like LOSS_PRES_TH are still processed
2723                                 goto Exit;
2724                         }
2725
2726                         wErrorCode_p = EPL_E_NMT_WRONG_STATE;
2727                 }
2728
2729                 BENCHMARK_MOD_07_TOGGLE(9);
2730
2731                 // $$$ start ERROR_TREATMENT and inform application
2732                 Ret = EplNmtMnuInstance_g.m_pfnCbNodeEvent(uiNodeId_p,
2733                                                            kEplNmtNodeEventError,
2734                                                            NodeNmtState_p,
2735                                                            wErrorCode_p,
2736                                                            (pNodeInfo_p->
2737                                                             m_dwNodeCfg &
2738                                                             EPL_NODEASSIGN_MANDATORY_CN)
2739                                                            != 0);
2740                 if (Ret != kEplSuccessful) {
2741                         goto Exit;
2742                 }
2743
2744                 EPL_NMTMNU_DBG_POST_TRACE_VALUE(0,
2745                                                 uiNodeId_p,
2746                                                 (((NodeNmtState_p & 0xFF) << 8)
2747                                                  | kEplNmtCmdResetNode));
2748
2749                 // reset CN
2750                 // store error code in NMT command data for diagnostic purpose
2751                 AmiSetWordToLe(&wbeErrorCode, wErrorCode_p);
2752                 Ret =
2753                     EplNmtMnuSendNmtCommandEx(uiNodeId_p, kEplNmtCmdResetNode,
2754                                               &wbeErrorCode,
2755                                               sizeof(wbeErrorCode));
2756                 if (Ret == kEplSuccessful) {
2757                         Ret = kEplReject;
2758                 }
2759
2760                 goto Exit;
2761         }
2762         // check if NMT_MNNodeCurrState_AU8 has to be changed
2763         ObdSize = 1;
2764         Ret = EplObduReadEntry(0x1F8E, uiNodeId_p, &bNmtStatePrev, &ObdSize);
2765         if (Ret != kEplSuccessful) {
2766                 goto Exit;
2767         }
2768         if (bNmtState != bNmtStatePrev) {
2769                 // update object 0x1F8E NMT_MNNodeCurrState_AU8
2770                 Ret = EplObduWriteEntry(0x1F8E, uiNodeId_p, &bNmtState, 1);
2771                 if (Ret != kEplSuccessful) {
2772                         goto Exit;
2773                 }
2774                 Ret = EplNmtMnuInstance_g.m_pfnCbNodeEvent(uiNodeId_p,
2775                                                            kEplNmtNodeEventNmtState,
2776                                                            NodeNmtState_p,
2777                                                            wErrorCode_p,
2778                                                            (pNodeInfo_p->
2779                                                             m_dwNodeCfg &
2780                                                             EPL_NODEASSIGN_MANDATORY_CN)
2781                                                            != 0);
2782                 if (Ret != kEplSuccessful) {
2783                         goto Exit;
2784                 }
2785         }
2786
2787       Exit:
2788         return Ret;
2789 }
2790
2791 //---------------------------------------------------------------------------
2792 //
2793 // Function:    EplNmtMnuReset
2794 //
2795 // Description: reset internal structures, e.g. timers
2796 //
2797 // Parameters:  void
2798 //
2799 // Returns:     tEplKernel              = error code
2800 //
2801 // State:
2802 //
2803 //---------------------------------------------------------------------------
2804
2805 static tEplKernel EplNmtMnuReset(void)
2806 {
2807         tEplKernel Ret;
2808         int iIndex;
2809
2810         Ret = EplTimeruDeleteTimer(&EplNmtMnuInstance_g.m_TimerHdlNmtState);
2811
2812         for (iIndex = 1; iIndex <= tabentries(EplNmtMnuInstance_g.m_aNodeInfo);
2813              iIndex++) {
2814                 // delete timer handles
2815                 Ret =
2816                     EplTimeruDeleteTimer(&EPL_NMTMNU_GET_NODEINFO(iIndex)->
2817                                          m_TimerHdlStatReq);
2818                 Ret =
2819                     EplTimeruDeleteTimer(&EPL_NMTMNU_GET_NODEINFO(iIndex)->
2820                                          m_TimerHdlLonger);
2821         }
2822
2823         return Ret;
2824 }
2825
2826 #endif // #if(((EPL_MODULE_INTEGRATION) & (EPL_MODULE_NMT_MN)) != 0)
2827
2828 // EOF