• Home
  • Line#
  • Scopes#
  • Navigate#
  • Raw
  • Download
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 
EplNmtMnuInit(tEplNmtMnuCbNodeEvent pfnCbNodeEvent_p,tEplNmtMnuCbBootEvent pfnCbBootEvent_p)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 
EplNmtMnuAddInstance(tEplNmtMnuCbNodeEvent pfnCbNodeEvent_p,tEplNmtMnuCbBootEvent pfnCbBootEvent_p)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 
EplNmtMnuDelInstance()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 
EplNmtMnuSendNmtCommandEx(unsigned int uiNodeId_p,tEplNmtCommand NmtCommand_p,void * pNmtCommandData_p,unsigned int uiDataSize_p)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 
EplNmtMnuSendNmtCommand(unsigned int uiNodeId_p,tEplNmtCommand NmtCommand_p)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 
EplNmtMnuTriggerStateChange(unsigned int uiNodeId_p,tEplNmtNodeCommand NodeCommand_p)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 
EplNmtMnuCbNmtStateChange(tEplEventNmtStateChange NmtStateChange_p)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 
EplNmtMnuCbCheckEvent(tEplNmtEvent NmtEvent_p)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 
EplNmtMnuProcessEvent(tEplEvent * pEvent_p)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 
EplNmtMnuGetDiagnosticInfo(unsigned int * puiMandatorySlaveCount_p,unsigned int * puiSignalSlaveCount_p,WORD * pwFlags_p)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 
EplNmtMnuCbNmtRequest(tEplFrameInfo * pFrameInfo_p)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 
EplNmtMnuCbIdentResponse(unsigned int uiNodeId_p,tEplIdentResponse * pIdentResponse_p)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 
EplNmtMnuCbStatusResponse(unsigned int uiNodeId_p,tEplStatusResponse * pStatusResponse_p)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 
EplNmtMnuStartBootStep1(void)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 
EplNmtMnuStartBootStep2(void)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 
EplNmtMnuNodeBootStep2(unsigned int uiNodeId_p,tEplNmtMnuNodeInfo * pNodeInfo_p)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 
EplNmtMnuStartCheckCom(void)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 
EplNmtMnuNodeCheckCom(unsigned int uiNodeId_p,tEplNmtMnuNodeInfo * pNodeInfo_p)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 
EplNmtMnuStartNodes(void)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 
EplNmtMnuProcessInternalEvent(unsigned int uiNodeId_p,tEplNmtState NodeNmtState_p,WORD wErrorCode_p,tEplNmtMnuIntNodeEvent NodeEvent_p)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 
EplNmtMnuCheckNmtState(unsigned int uiNodeId_p,tEplNmtMnuNodeInfo * pNodeInfo_p,tEplNmtState NodeNmtState_p,WORD wErrorCode_p,tEplNmtState LocalNmtState_p)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 
EplNmtMnuReset(void)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
2836