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