• 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 kernel DLL 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: EplDllk.c,v $
53 
54                 $Author: D.Krueger $
55 
56                 $Revision: 1.21 $  $Date: 2008/11/13 17:13:09 $
57 
58                 $State: Exp $
59 
60                 Build Environment:
61                     GCC V3.4
62 
63   -------------------------------------------------------------------------
64 
65   Revision History:
66 
67   2006/06/12 d.k.:   start of the implementation, version 1.00
68 
69 ****************************************************************************/
70 
71 #include "kernel/EplDllk.h"
72 #include "kernel/EplDllkCal.h"
73 #include "kernel/EplEventk.h"
74 #include "kernel/EplNmtk.h"
75 #include "edrv.h"
76 #include "Benchmark.h"
77 
78 #if (((EPL_MODULE_INTEGRATION) & (EPL_MODULE_PDOK)) != 0)
79 #include "kernel/EplPdok.h"
80 #endif
81 
82 #if (((EPL_MODULE_INTEGRATION) & (EPL_MODULE_VETH)) != 0)
83 #include "kernel/VirtualEthernet.h"
84 #endif
85 
86 //#if EPL_TIMER_USE_HIGHRES != FALSE
87 #include "kernel/EplTimerHighResk.h"
88 //#endif
89 
90 #if(((EPL_MODULE_INTEGRATION) & (EPL_MODULE_DLLK)) != 0)
91 
92 #if(((EPL_MODULE_INTEGRATION) & (EPL_MODULE_NMTK)) == 0)
93 #error "EPL module DLLK needs EPL module NMTK!"
94 #endif
95 
96 #if (EPL_DLL_PRES_READY_AFTER_SOA != FALSE) && (EPL_DLL_PRES_READY_AFTER_SOC != FALSE)
97 #error "EPL module DLLK: select only one of EPL_DLL_PRES_READY_AFTER_SOA and EPL_DLL_PRES_READY_AFTER_SOC."
98 #endif
99 
100 #if ((EPL_DLL_PRES_READY_AFTER_SOA != FALSE) || (EPL_DLL_PRES_READY_AFTER_SOC != FALSE)) \
101     && (((EPL_MODULE_INTEGRATION) & (EPL_MODULE_NMT_MN)) == 0)
102 #error "EPL module DLLK: currently, EPL_DLL_PRES_READY_AFTER_* is not supported if EPL_MODULE_NMT_MN is enabled."
103 #endif
104 
105 #if (EDRV_FAST_TXFRAMES == FALSE) && \
106     ((EPL_DLL_PRES_READY_AFTER_SOA != FALSE) || (EPL_DLL_PRES_READY_AFTER_SOC != FALSE))
107 #error "EPL module DLLK: EPL_DLL_PRES_READY_AFTER_* is enabled, but not EDRV_FAST_TXFRAMES."
108 #endif
109 
110 /***************************************************************************/
111 /*                                                                         */
112 /*                                                                         */
113 /*          G L O B A L   D E F I N I T I O N S                            */
114 /*                                                                         */
115 /*                                                                         */
116 /***************************************************************************/
117 
118 //---------------------------------------------------------------------------
119 // const defines
120 //---------------------------------------------------------------------------
121 
122 // TracePoint support for realtime-debugging
123 #ifdef _DBG_TRACE_POINTS_
124 void PUBLIC TgtDbgSignalTracePoint(BYTE bTracePointNumber_p);
125 void PUBLIC TgtDbgPostTraceValue(DWORD dwTraceValue_p);
126 #define TGT_DBG_SIGNAL_TRACE_POINT(p)   TgtDbgSignalTracePoint(p)
127 #define TGT_DBG_POST_TRACE_VALUE(v)     TgtDbgPostTraceValue(v)
128 #else
129 #define TGT_DBG_SIGNAL_TRACE_POINT(p)
130 #define TGT_DBG_POST_TRACE_VALUE(v)
131 #endif
132 #define EPL_DLLK_DBG_POST_TRACE_VALUE(Event_p, uiNodeId_p, wErrorCode_p) \
133     TGT_DBG_POST_TRACE_VALUE((kEplEventSinkDllk << 28) | (Event_p << 24) \
134                              | (uiNodeId_p << 16) | wErrorCode_p)
135 
136 /***************************************************************************/
137 /*                                                                         */
138 /*                                                                         */
139 /*          C L A S S  EplDllk                                             */
140 /*                                                                         */
141 /*                                                                         */
142 /***************************************************************************/
143 //
144 // Description:
145 //
146 //
147 /***************************************************************************/
148 
149 //=========================================================================//
150 //                                                                         //
151 //          P R I V A T E   D E F I N I T I O N S                          //
152 //                                                                         //
153 //=========================================================================//
154 
155 //---------------------------------------------------------------------------
156 // const defines
157 //---------------------------------------------------------------------------
158 
159 // defines for indexes of tEplDllInstance.m_pTxFrameInfo
160 #define EPL_DLLK_TXFRAME_IDENTRES   0	// IdentResponse on CN / MN
161 #define EPL_DLLK_TXFRAME_STATUSRES  1	// StatusResponse on CN / MN
162 #define EPL_DLLK_TXFRAME_NMTREQ     2	// NMT Request from FIFO on CN / MN
163 #define EPL_DLLK_TXFRAME_NONEPL     3	// non-EPL frame from FIFO on CN / MN
164 #define EPL_DLLK_TXFRAME_PRES       4	// PRes on CN / MN
165 #define EPL_DLLK_TXFRAME_SOC        5	// SoC on MN
166 #define EPL_DLLK_TXFRAME_SOA        6	// SoA on MN
167 #define EPL_DLLK_TXFRAME_PREQ       7	// PReq on MN
168 #if(((EPL_MODULE_INTEGRATION) & (EPL_MODULE_NMT_MN)) != 0)
169 #define EPL_DLLK_TXFRAME_COUNT      (7 + EPL_D_NMT_MaxCNNumber_U8 + 2)	// on MN: 7 + MaxPReq of regular CNs + 1 Diag + 1 Router
170 #else
171 #define EPL_DLLK_TXFRAME_COUNT      5	// on CN: 5
172 #endif
173 
174 #define EPL_DLLK_BUFLEN_EMPTY       0	// buffer is empty
175 #define EPL_DLLK_BUFLEN_FILLING     1	// just the buffer is being filled
176 #define EPL_DLLK_BUFLEN_MIN         60	// minimum ethernet frame length
177 
178 //---------------------------------------------------------------------------
179 // local types
180 //---------------------------------------------------------------------------
181 
182 typedef enum {
183 	kEplDllGsInit = 0x00,	// MN/CN: initialisation (< PreOp2)
184 	kEplDllCsWaitPreq = 0x01,	// CN: wait for PReq frame
185 	kEplDllCsWaitSoc = 0x02,	// CN: wait for SoC frame
186 	kEplDllCsWaitSoa = 0x03,	// CN: wait for SoA frame
187 	kEplDllMsNonCyclic = 0x04,	// MN: reduced EPL cycle (PreOp1)
188 	kEplDllMsWaitSocTrig = 0x05,	// MN: wait for SoC trigger (cycle timer)
189 	kEplDllMsWaitPreqTrig = 0x06,	// MN: wait for (first) PReq trigger (WaitSoCPReq_U32)
190 	kEplDllMsWaitPres = 0x07,	// MN: wait for PRes frame from CN
191 	kEplDllMsWaitSoaTrig = 0x08,	// MN: wait for SoA trigger (PRes transmitted)
192 	kEplDllMsWaitAsndTrig = 0x09,	// MN: wait for ASnd trigger (SoA transmitted)
193 	kEplDllMsWaitAsnd = 0x0A,	// MN: wait for ASnd frame if SoA contained invitation
194 
195 } tEplDllState;
196 
197 typedef struct {
198 	BYTE m_be_abSrcMac[6];
199 	tEdrvTxBuffer *m_pTxBuffer;	// Buffers for Tx-Frames
200 	unsigned int m_uiMaxTxFrames;
201 	BYTE m_bFlag1;		// Flag 1 with EN, EC for PRes, StatusRes
202 	BYTE m_bMnFlag1;	// Flag 1 with EA, ER from PReq, SoA of MN
203 	BYTE m_bFlag2;		// Flag 2 with PR and RS for PRes, StatusRes, IdentRes
204 	tEplDllConfigParam m_DllConfigParam;
205 	tEplDllIdentParam m_DllIdentParam;
206 	tEplDllState m_DllState;
207 	tEplDllkCbAsync m_pfnCbAsync;
208 	tEplDllAsndFilter m_aAsndFilter[EPL_DLL_MAX_ASND_SERVICE_ID];
209 
210 #if (((EPL_MODULE_INTEGRATION) & (EPL_MODULE_NMT_MN)) != 0)
211 	tEplDllkNodeInfo *m_pFirstNodeInfo;
212 	tEplDllkNodeInfo *m_pCurNodeInfo;
213 	tEplDllkNodeInfo m_aNodeInfo[EPL_NMT_MAX_NODE_ID];
214 	tEplDllReqServiceId m_LastReqServiceId;
215 	unsigned int m_uiLastTargetNodeId;
216 #endif
217 
218 #if EPL_TIMER_USE_HIGHRES != FALSE
219 	tEplTimerHdl m_TimerHdlCycle;	// used for EPL cycle monitoring on CN and generation on MN
220 #if (((EPL_MODULE_INTEGRATION) & (EPL_MODULE_NMT_MN)) != 0)
221 	tEplTimerHdl m_TimerHdlResponse;	// used for CN response monitoring
222 #endif				//(((EPL_MODULE_INTEGRATION) & (EPL_MODULE_NMT_MN)) != 0)
223 #endif
224 
225 	unsigned int m_uiCycleCount;	// cycle counter (needed for multiplexed cycle support)
226 	unsigned long long m_ullFrameTimeout;	// frame timeout (cycle length + loss of frame tolerance)
227 
228 } tEplDllkInstance;
229 
230 //---------------------------------------------------------------------------
231 // local vars
232 //---------------------------------------------------------------------------
233 
234 // if no dynamic memory allocation shall be used
235 // define structures statically
236 static tEplDllkInstance EplDllkInstance_g;
237 
238 static tEdrvTxBuffer aEplDllkTxBuffer_l[EPL_DLLK_TXFRAME_COUNT];
239 
240 //---------------------------------------------------------------------------
241 // local function prototypes
242 //---------------------------------------------------------------------------
243 
244 // change DLL state on event
245 static tEplKernel EplDllkChangeState(tEplNmtEvent NmtEvent_p,
246 				     tEplNmtState NmtState_p);
247 
248 // called from EdrvInterruptHandler()
249 static void EplDllkCbFrameReceived(tEdrvRxBuffer * pRxBuffer_p);
250 
251 // called from EdrvInterruptHandler()
252 static void EplDllkCbFrameTransmitted(tEdrvTxBuffer * pTxBuffer_p);
253 
254 // check frame and set missing information
255 static tEplKernel EplDllkCheckFrame(tEplFrame * pFrame_p,
256 				    unsigned int uiFrameSize_p);
257 
258 // called by high resolution timer module to monitor EPL cycle as CN
259 #if EPL_TIMER_USE_HIGHRES != FALSE
260 static tEplKernel PUBLIC EplDllkCbCnTimer(tEplTimerEventArg * pEventArg_p);
261 #endif
262 
263 #if (((EPL_MODULE_INTEGRATION) & (EPL_MODULE_NMT_MN)) != 0)
264 // MN: returns internal node info structure
265 static tEplDllkNodeInfo *EplDllkGetNodeInfo(unsigned int uiNodeId_p);
266 
267 // transmit SoA
268 static tEplKernel EplDllkMnSendSoa(tEplNmtState NmtState_p,
269 				   tEplDllState * pDllStateProposed_p,
270 				   BOOL fEnableInvitation_p);
271 
272 static tEplKernel EplDllkMnSendSoc(void);
273 
274 static tEplKernel EplDllkMnSendPreq(tEplNmtState NmtState_p,
275 				    tEplDllState * pDllStateProposed_p);
276 
277 static tEplKernel EplDllkAsyncFrameNotReceived(tEplDllReqServiceId
278 					       ReqServiceId_p,
279 					       unsigned int uiNodeId_p);
280 
281 static tEplKernel PUBLIC EplDllkCbMnTimerCycle(tEplTimerEventArg * pEventArg_p);
282 
283 static tEplKernel PUBLIC EplDllkCbMnTimerResponse(tEplTimerEventArg *
284 						  pEventArg_p);
285 
286 #endif
287 
288 //=========================================================================//
289 //                                                                         //
290 //          P U B L I C   F U N C T I O N S                                //
291 //                                                                         //
292 //=========================================================================//
293 
294 //---------------------------------------------------------------------------
295 //
296 // Function:    EplDllkAddInstance()
297 //
298 // Description: add and initialize new instance of EPL stack
299 //
300 // Parameters:  pInitParam_p            = initialisation parameters like MAC address
301 //
302 // Returns:     tEplKernel              = error code
303 //
304 //
305 // State:
306 //
307 //---------------------------------------------------------------------------
308 
EplDllkAddInstance(tEplDllkInitParam * pInitParam_p)309 tEplKernel EplDllkAddInstance(tEplDllkInitParam * pInitParam_p)
310 {
311 	tEplKernel Ret = kEplSuccessful;
312 	unsigned int uiIndex;
313 	tEdrvInitParam EdrvInitParam;
314 
315 	// reset instance structure
316 	EPL_MEMSET(&EplDllkInstance_g, 0, sizeof(EplDllkInstance_g));
317 
318 #if EPL_TIMER_USE_HIGHRES != FALSE
319 	Ret = EplTimerHighReskInit();
320 	if (Ret != kEplSuccessful) {	// error occured while initializing high resolution timer module
321 		goto Exit;
322 	}
323 #endif
324 
325 	// if dynamic memory allocation available
326 	// allocate instance structure
327 	// allocate TPDO and RPDO table with default size
328 
329 	// initialize and link pointers in instance structure to frame tables
330 	EplDllkInstance_g.m_pTxBuffer = aEplDllkTxBuffer_l;
331 	EplDllkInstance_g.m_uiMaxTxFrames =
332 	    sizeof(aEplDllkTxBuffer_l) / sizeof(tEdrvTxBuffer);
333 
334 	// initialize state
335 	EplDllkInstance_g.m_DllState = kEplDllGsInit;
336 
337 #if (((EPL_MODULE_INTEGRATION) & (EPL_MODULE_NMT_MN)) != 0)
338 	// set up node info structure
339 	for (uiIndex = 0; uiIndex < tabentries(EplDllkInstance_g.m_aNodeInfo);
340 	     uiIndex++) {
341 		EplDllkInstance_g.m_aNodeInfo[uiIndex].m_uiNodeId = uiIndex + 1;
342 		EplDllkInstance_g.m_aNodeInfo[uiIndex].m_wPresPayloadLimit =
343 		    0xFFFF;
344 	}
345 #endif
346 
347 	// initialize Edrv
348 	EPL_MEMCPY(EdrvInitParam.m_abMyMacAddr, pInitParam_p->m_be_abSrcMac, 6);
349 	EdrvInitParam.m_pfnRxHandler = EplDllkCbFrameReceived;
350 	EdrvInitParam.m_pfnTxHandler = EplDllkCbFrameTransmitted;
351 	Ret = EdrvInit(&EdrvInitParam);
352 	if (Ret != kEplSuccessful) {	// error occured while initializing ethernet driver
353 		goto Exit;
354 	}
355 	// copy local MAC address from Ethernet driver back to local instance structure
356 	// because Ethernet driver may have read it from controller EEPROM
357 	EPL_MEMCPY(EplDllkInstance_g.m_be_abSrcMac, EdrvInitParam.m_abMyMacAddr,
358 		   6);
359 	EPL_MEMCPY(pInitParam_p->m_be_abSrcMac, EdrvInitParam.m_abMyMacAddr, 6);
360 
361 	// initialize TxBuffer array
362 	for (uiIndex = 0; uiIndex < EplDllkInstance_g.m_uiMaxTxFrames;
363 	     uiIndex++) {
364 		EplDllkInstance_g.m_pTxBuffer[uiIndex].m_pbBuffer = NULL;
365 	}
366 
367 #if (((EPL_MODULE_INTEGRATION) & (EPL_MODULE_VETH)) != 0)
368 	Ret = VEthAddInstance(pInitParam_p);
369 #endif
370 
371       Exit:
372 	return Ret;
373 }
374 
375 //---------------------------------------------------------------------------
376 //
377 // Function:    EplDllkDelInstance()
378 //
379 // Description: deletes an instance of EPL stack
380 //
381 // Parameters:  (none)
382 //
383 // Returns:     tEplKernel              = error code
384 //
385 //
386 // State:
387 //
388 //---------------------------------------------------------------------------
389 
EplDllkDelInstance(void)390 tEplKernel EplDllkDelInstance(void)
391 {
392 	tEplKernel Ret = kEplSuccessful;
393 
394 	// reset state
395 	EplDllkInstance_g.m_DllState = kEplDllGsInit;
396 
397 #if EPL_TIMER_USE_HIGHRES != FALSE
398 	Ret = EplTimerHighReskDelInstance();
399 #endif
400 
401 #if (((EPL_MODULE_INTEGRATION) & (EPL_MODULE_VETH)) != 0)
402 	Ret = VEthDelInstance();
403 #endif
404 
405 	Ret = EdrvShutdown();
406 	return Ret;
407 }
408 
409 //---------------------------------------------------------------------------
410 //
411 // Function:    EplDllkCreateTxFrame
412 //
413 // Description: creates the buffer for a Tx frame and registers it to the
414 //              ethernet driver
415 //
416 // Parameters:  puiHandle_p             = OUT: handle to frame buffer
417 //              ppFrame_p               = OUT: pointer to pointer of EPL frame
418 //              puiFrameSize_p          = IN/OUT: pointer to size of frame
419 //                                        returned size is always equal or larger than
420 //                                        requested size, if that is not possible
421 //                                        an error will be returned
422 //              MsgType_p               = EPL message type
423 //              ServiceId_p             = Service ID in case of ASnd frame, otherwise
424 //                                        kEplDllAsndNotDefined
425 //
426 // Returns:     tEplKernel              = error code
427 //
428 //
429 // State:
430 //
431 //---------------------------------------------------------------------------
432 
EplDllkCreateTxFrame(unsigned int * puiHandle_p,tEplFrame ** ppFrame_p,unsigned int * puiFrameSize_p,tEplMsgType MsgType_p,tEplDllAsndServiceId ServiceId_p)433 tEplKernel EplDllkCreateTxFrame(unsigned int *puiHandle_p,
434 				tEplFrame ** ppFrame_p,
435 				unsigned int *puiFrameSize_p,
436 				tEplMsgType MsgType_p,
437 				tEplDllAsndServiceId ServiceId_p)
438 {
439 	tEplKernel Ret = kEplSuccessful;
440 	tEplFrame *pTxFrame;
441 	unsigned int uiHandle = EplDllkInstance_g.m_uiMaxTxFrames;
442 	tEdrvTxBuffer *pTxBuffer = NULL;
443 
444 	if (MsgType_p == kEplMsgTypeAsnd) {
445 		// search for fixed Tx buffers
446 		if (ServiceId_p == kEplDllAsndIdentResponse) {
447 			uiHandle = EPL_DLLK_TXFRAME_IDENTRES;
448 		} else if (ServiceId_p == kEplDllAsndStatusResponse) {
449 			uiHandle = EPL_DLLK_TXFRAME_STATUSRES;
450 		} else if ((ServiceId_p == kEplDllAsndNmtRequest)
451 			   || (ServiceId_p == kEplDllAsndNmtCommand)) {
452 			uiHandle = EPL_DLLK_TXFRAME_NMTREQ;
453 		}
454 
455 		if (uiHandle >= EplDllkInstance_g.m_uiMaxTxFrames) {	// look for free entry
456 			uiHandle = EPL_DLLK_TXFRAME_PREQ;
457 			pTxBuffer = &EplDllkInstance_g.m_pTxBuffer[uiHandle];
458 			for (; uiHandle < EplDllkInstance_g.m_uiMaxTxFrames;
459 			     uiHandle++, pTxBuffer++) {
460 				if (pTxBuffer->m_pbBuffer == NULL) {	// free entry found
461 					break;
462 				}
463 			}
464 		}
465 	} else if (MsgType_p == kEplMsgTypeNonEpl) {
466 		uiHandle = EPL_DLLK_TXFRAME_NONEPL;
467 	} else if (MsgType_p == kEplMsgTypePres) {
468 		uiHandle = EPL_DLLK_TXFRAME_PRES;
469 	} else if (MsgType_p == kEplMsgTypeSoc) {
470 		uiHandle = EPL_DLLK_TXFRAME_SOC;
471 	} else if (MsgType_p == kEplMsgTypeSoa) {
472 		uiHandle = EPL_DLLK_TXFRAME_SOA;
473 	} else {		// look for free entry
474 		uiHandle = EPL_DLLK_TXFRAME_PREQ;
475 		pTxBuffer = &EplDllkInstance_g.m_pTxBuffer[uiHandle];
476 		for (; uiHandle < EplDllkInstance_g.m_uiMaxTxFrames;
477 		     uiHandle++, pTxBuffer++) {
478 			if (pTxBuffer->m_pbBuffer == NULL) {	// free entry found
479 				break;
480 			}
481 		}
482 		if (pTxBuffer->m_pbBuffer != NULL) {
483 			Ret = kEplEdrvNoFreeBufEntry;
484 			goto Exit;
485 		}
486 	}
487 
488 	// test if requested entry is free
489 	pTxBuffer = &EplDllkInstance_g.m_pTxBuffer[uiHandle];
490 	if (pTxBuffer->m_pbBuffer != NULL) {	// entry is not free
491 		Ret = kEplEdrvNoFreeBufEntry;
492 		goto Exit;
493 	}
494 	// setup Tx buffer
495 	pTxBuffer->m_EplMsgType = MsgType_p;
496 	pTxBuffer->m_uiMaxBufferLen = *puiFrameSize_p;
497 
498 	Ret = EdrvAllocTxMsgBuffer(pTxBuffer);
499 	if (Ret != kEplSuccessful) {	// error occured while registering Tx frame
500 		goto Exit;
501 	}
502 	// because buffer size may be larger than requested
503 	// memorize real length of frame
504 	pTxBuffer->m_uiTxMsgLen = *puiFrameSize_p;
505 
506 	// fill whole frame with 0
507 	EPL_MEMSET(pTxBuffer->m_pbBuffer, 0, pTxBuffer->m_uiMaxBufferLen);
508 
509 	pTxFrame = (tEplFrame *) pTxBuffer->m_pbBuffer;
510 
511 	if (MsgType_p != kEplMsgTypeNonEpl) {	// fill out Frame only if it is an EPL frame
512 		// ethertype
513 		AmiSetWordToBe(&pTxFrame->m_be_wEtherType,
514 			       EPL_C_DLL_ETHERTYPE_EPL);
515 		// source node ID
516 		AmiSetByteToLe(&pTxFrame->m_le_bSrcNodeId,
517 			       (BYTE) EplDllkInstance_g.m_DllConfigParam.
518 			       m_uiNodeId);
519 		// source MAC address
520 		EPL_MEMCPY(&pTxFrame->m_be_abSrcMac[0],
521 			   &EplDllkInstance_g.m_be_abSrcMac[0], 6);
522 		switch (MsgType_p) {
523 		case kEplMsgTypeAsnd:
524 			// destination MAC address
525 			AmiSetQword48ToBe(&pTxFrame->m_be_abDstMac[0],
526 					  EPL_C_DLL_MULTICAST_ASND);
527 			// destination node ID
528 			switch (ServiceId_p) {
529 			case kEplDllAsndIdentResponse:
530 			case kEplDllAsndStatusResponse:
531 				{	// IdentResponses and StatusResponses are Broadcast
532 					AmiSetByteToLe(&pTxFrame->
533 						       m_le_bDstNodeId,
534 						       (BYTE)
535 						       EPL_C_ADR_BROADCAST);
536 					break;
537 				}
538 
539 			default:
540 				break;
541 			}
542 			// ASnd Service ID
543 			AmiSetByteToLe(&pTxFrame->m_Data.m_Asnd.m_le_bServiceId,
544 				       ServiceId_p);
545 			break;
546 
547 		case kEplMsgTypeSoc:
548 			// destination MAC address
549 			AmiSetQword48ToBe(&pTxFrame->m_be_abDstMac[0],
550 					  EPL_C_DLL_MULTICAST_SOC);
551 			// destination node ID
552 			AmiSetByteToLe(&pTxFrame->m_le_bDstNodeId,
553 				       (BYTE) EPL_C_ADR_BROADCAST);
554 			// reset Flags
555 			//AmiSetByteToLe(&pTxFrame->m_Data.m_Soc.m_le_bFlag1, (BYTE) 0);
556 			//AmiSetByteToLe(&pTxFrame->m_Data.m_Soc.m_le_bFlag2, (BYTE) 0);
557 			break;
558 
559 		case kEplMsgTypeSoa:
560 			// destination MAC address
561 			AmiSetQword48ToBe(&pTxFrame->m_be_abDstMac[0],
562 					  EPL_C_DLL_MULTICAST_SOA);
563 			// destination node ID
564 			AmiSetByteToLe(&pTxFrame->m_le_bDstNodeId,
565 				       (BYTE) EPL_C_ADR_BROADCAST);
566 			// reset Flags
567 			//AmiSetByteToLe(&pTxFrame->m_Data.m_Soa.m_le_bFlag1, (BYTE) 0);
568 			//AmiSetByteToLe(&pTxFrame->m_Data.m_Soa.m_le_bFlag2, (BYTE) 0);
569 			// EPL profile version
570 			AmiSetByteToLe(&pTxFrame->m_Data.m_Soa.m_le_bEplVersion,
571 				       (BYTE) EPL_SPEC_VERSION);
572 			break;
573 
574 		case kEplMsgTypePres:
575 			// destination MAC address
576 			AmiSetQword48ToBe(&pTxFrame->m_be_abDstMac[0],
577 					  EPL_C_DLL_MULTICAST_PRES);
578 			// destination node ID
579 			AmiSetByteToLe(&pTxFrame->m_le_bDstNodeId,
580 				       (BYTE) EPL_C_ADR_BROADCAST);
581 			// reset Flags
582 			//AmiSetByteToLe(&pTxFrame->m_Data.m_Pres.m_le_bFlag1, (BYTE) 0);
583 			//AmiSetByteToLe(&pTxFrame->m_Data.m_Pres.m_le_bFlag2, (BYTE) 0);
584 			// PDO size
585 			//AmiSetWordToLe(&pTxFrame->m_Data.m_Pres.m_le_wSize, 0);
586 			break;
587 
588 		case kEplMsgTypePreq:
589 			// reset Flags
590 			//AmiSetByteToLe(&pTxFrame->m_Data.m_Preq.m_le_bFlag1, (BYTE) 0);
591 			//AmiSetByteToLe(&pTxFrame->m_Data.m_Preq.m_le_bFlag2, (BYTE) 0);
592 			// PDO size
593 			//AmiSetWordToLe(&pTxFrame->m_Data.m_Preq.m_le_wSize, 0);
594 			break;
595 
596 		default:
597 			break;
598 		}
599 		// EPL message type
600 		AmiSetByteToLe(&pTxFrame->m_le_bMessageType, (BYTE) MsgType_p);
601 	}
602 
603 	*ppFrame_p = pTxFrame;
604 	*puiFrameSize_p = pTxBuffer->m_uiMaxBufferLen;
605 	*puiHandle_p = uiHandle;
606 
607       Exit:
608 	return Ret;
609 }
610 
611 //---------------------------------------------------------------------------
612 //
613 // Function:    EplDllkDeleteTxFrame
614 //
615 // Description: deletes the buffer for a Tx frame and frees it in the
616 //              ethernet driver
617 //
618 // Parameters:  uiHandle_p              = IN: handle to frame buffer
619 //
620 // Returns:     tEplKernel              = error code
621 //
622 //
623 // State:
624 //
625 //---------------------------------------------------------------------------
626 
EplDllkDeleteTxFrame(unsigned int uiHandle_p)627 tEplKernel EplDllkDeleteTxFrame(unsigned int uiHandle_p)
628 {
629 	tEplKernel Ret = kEplSuccessful;
630 	tEdrvTxBuffer *pTxBuffer = NULL;
631 
632 	if (uiHandle_p >= EplDllkInstance_g.m_uiMaxTxFrames) {	// handle is not valid
633 		Ret = kEplDllIllegalHdl;
634 		goto Exit;
635 	}
636 
637 	pTxBuffer = &EplDllkInstance_g.m_pTxBuffer[uiHandle_p];
638 
639 	// mark buffer as free so that frame will not be send in future anymore
640 	// $$$ d.k. What's up with running transmissions?
641 	pTxBuffer->m_uiTxMsgLen = EPL_DLLK_BUFLEN_EMPTY;
642 	pTxBuffer->m_pbBuffer = NULL;
643 
644 	// delete Tx buffer
645 	Ret = EdrvReleaseTxMsgBuffer(pTxBuffer);
646 	if (Ret != kEplSuccessful) {	// error occured while releasing Tx frame
647 		goto Exit;
648 	}
649 
650       Exit:
651 	return Ret;
652 }
653 
654 //---------------------------------------------------------------------------
655 //
656 // Function:    EplDllkProcess
657 //
658 // Description: process the passed event
659 //
660 // Parameters:  pEvent_p                = event to be processed
661 //
662 // Returns:     tEplKernel              = error code
663 //
664 //
665 // State:
666 //
667 //---------------------------------------------------------------------------
668 
EplDllkProcess(tEplEvent * pEvent_p)669 tEplKernel EplDllkProcess(tEplEvent * pEvent_p)
670 {
671 	tEplKernel Ret = kEplSuccessful;
672 	tEplFrame *pTxFrame;
673 	tEdrvTxBuffer *pTxBuffer;
674 	unsigned int uiHandle;
675 	unsigned int uiFrameSize;
676 	BYTE abMulticastMac[6];
677 	tEplDllAsyncReqPriority AsyncReqPriority;
678 	unsigned int uiFrameCount;
679 	tEplNmtState NmtState;
680 #if (((EPL_MODULE_INTEGRATION) & (EPL_MODULE_PDOK)) != 0)
681 	tEplFrameInfo FrameInfo;
682 #endif
683 
684 	switch (pEvent_p->m_EventType) {
685 	case kEplEventTypeDllkCreate:
686 		{
687 			// $$$ reset ethernet driver
688 
689 			NmtState = *((tEplNmtState *) pEvent_p->m_pArg);
690 
691 			// initialize flags for PRes and StatusRes
692 			EplDllkInstance_g.m_bFlag1 = EPL_FRAME_FLAG1_EC;
693 			EplDllkInstance_g.m_bMnFlag1 = 0;
694 			EplDllkInstance_g.m_bFlag2 = 0;
695 
696 #if (((EPL_MODULE_INTEGRATION) & (EPL_MODULE_NMT_MN)) != 0)
697 			// initialize linked node list
698 			EplDllkInstance_g.m_pFirstNodeInfo = NULL;
699 #endif
700 
701 			// register TxFrames in Edrv
702 
703 			// IdentResponse
704 			uiFrameSize = EPL_C_DLL_MINSIZE_IDENTRES;
705 			Ret =
706 			    EplDllkCreateTxFrame(&uiHandle, &pTxFrame,
707 						 &uiFrameSize, kEplMsgTypeAsnd,
708 						 kEplDllAsndIdentResponse);
709 			if (Ret != kEplSuccessful) {	// error occured while registering Tx frame
710 				goto Exit;
711 			}
712 			// EPL profile version
713 			AmiSetByteToLe(&pTxFrame->m_Data.m_Asnd.m_Payload.
714 				       m_IdentResponse.m_le_bEplProfileVersion,
715 				       (BYTE) EPL_SPEC_VERSION);
716 			// FeatureFlags
717 			AmiSetDwordToLe(&pTxFrame->m_Data.m_Asnd.m_Payload.
718 					m_IdentResponse.m_le_dwFeatureFlags,
719 					EplDllkInstance_g.m_DllConfigParam.
720 					m_dwFeatureFlags);
721 			// MTU
722 			AmiSetWordToLe(&pTxFrame->m_Data.m_Asnd.m_Payload.
723 				       m_IdentResponse.m_le_wMtu,
724 				       (WORD) EplDllkInstance_g.
725 				       m_DllConfigParam.m_uiAsyncMtu);
726 			// PollInSize
727 			AmiSetWordToLe(&pTxFrame->m_Data.m_Asnd.m_Payload.
728 				       m_IdentResponse.m_le_wPollInSize,
729 				       (WORD) EplDllkInstance_g.
730 				       m_DllConfigParam.
731 				       m_uiPreqActPayloadLimit);
732 			// PollOutSize
733 			AmiSetWordToLe(&pTxFrame->m_Data.m_Asnd.m_Payload.
734 				       m_IdentResponse.m_le_wPollOutSize,
735 				       (WORD) EplDllkInstance_g.
736 				       m_DllConfigParam.
737 				       m_uiPresActPayloadLimit);
738 			// ResponseTime / PresMaxLatency
739 			AmiSetDwordToLe(&pTxFrame->m_Data.m_Asnd.m_Payload.
740 					m_IdentResponse.m_le_dwResponseTime,
741 					EplDllkInstance_g.m_DllConfigParam.
742 					m_dwPresMaxLatency);
743 			// DeviceType
744 			AmiSetDwordToLe(&pTxFrame->m_Data.m_Asnd.m_Payload.
745 					m_IdentResponse.m_le_dwDeviceType,
746 					EplDllkInstance_g.m_DllIdentParam.
747 					m_dwDeviceType);
748 			// VendorId
749 			AmiSetDwordToLe(&pTxFrame->m_Data.m_Asnd.m_Payload.
750 					m_IdentResponse.m_le_dwVendorId,
751 					EplDllkInstance_g.m_DllIdentParam.
752 					m_dwVendorId);
753 			// ProductCode
754 			AmiSetDwordToLe(&pTxFrame->m_Data.m_Asnd.m_Payload.
755 					m_IdentResponse.m_le_dwProductCode,
756 					EplDllkInstance_g.m_DllIdentParam.
757 					m_dwProductCode);
758 			// RevisionNumber
759 			AmiSetDwordToLe(&pTxFrame->m_Data.m_Asnd.m_Payload.
760 					m_IdentResponse.m_le_dwRevisionNumber,
761 					EplDllkInstance_g.m_DllIdentParam.
762 					m_dwRevisionNumber);
763 			// SerialNumber
764 			AmiSetDwordToLe(&pTxFrame->m_Data.m_Asnd.m_Payload.
765 					m_IdentResponse.m_le_dwSerialNumber,
766 					EplDllkInstance_g.m_DllIdentParam.
767 					m_dwSerialNumber);
768 			// VendorSpecificExt1
769 			AmiSetQword64ToLe(&pTxFrame->m_Data.m_Asnd.m_Payload.
770 					  m_IdentResponse.
771 					  m_le_qwVendorSpecificExt1,
772 					  EplDllkInstance_g.m_DllIdentParam.
773 					  m_qwVendorSpecificExt1);
774 			// VerifyConfigurationDate
775 			AmiSetDwordToLe(&pTxFrame->m_Data.m_Asnd.m_Payload.
776 					m_IdentResponse.
777 					m_le_dwVerifyConfigurationDate,
778 					EplDllkInstance_g.m_DllIdentParam.
779 					m_dwVerifyConfigurationDate);
780 			// VerifyConfigurationTime
781 			AmiSetDwordToLe(&pTxFrame->m_Data.m_Asnd.m_Payload.
782 					m_IdentResponse.
783 					m_le_dwVerifyConfigurationTime,
784 					EplDllkInstance_g.m_DllIdentParam.
785 					m_dwVerifyConfigurationTime);
786 			// ApplicationSwDate
787 			AmiSetDwordToLe(&pTxFrame->m_Data.m_Asnd.m_Payload.
788 					m_IdentResponse.
789 					m_le_dwApplicationSwDate,
790 					EplDllkInstance_g.m_DllIdentParam.
791 					m_dwApplicationSwDate);
792 			// ApplicationSwTime
793 			AmiSetDwordToLe(&pTxFrame->m_Data.m_Asnd.m_Payload.
794 					m_IdentResponse.
795 					m_le_dwApplicationSwTime,
796 					EplDllkInstance_g.m_DllIdentParam.
797 					m_dwApplicationSwTime);
798 			// IPAddress
799 			AmiSetDwordToLe(&pTxFrame->m_Data.m_Asnd.m_Payload.
800 					m_IdentResponse.m_le_dwIpAddress,
801 					EplDllkInstance_g.m_DllIdentParam.
802 					m_dwIpAddress);
803 			// SubnetMask
804 			AmiSetDwordToLe(&pTxFrame->m_Data.m_Asnd.m_Payload.
805 					m_IdentResponse.m_le_dwSubnetMask,
806 					EplDllkInstance_g.m_DllIdentParam.
807 					m_dwSubnetMask);
808 			// DefaultGateway
809 			AmiSetDwordToLe(&pTxFrame->m_Data.m_Asnd.m_Payload.
810 					m_IdentResponse.m_le_dwDefaultGateway,
811 					EplDllkInstance_g.m_DllIdentParam.
812 					m_dwDefaultGateway);
813 			// HostName
814 			EPL_MEMCPY(&pTxFrame->m_Data.m_Asnd.m_Payload.
815 				   m_IdentResponse.m_le_sHostname[0],
816 				   &EplDllkInstance_g.m_DllIdentParam.
817 				   m_sHostname[0],
818 				   sizeof(EplDllkInstance_g.m_DllIdentParam.
819 					  m_sHostname));
820 			// VendorSpecificExt2
821 			EPL_MEMCPY(&pTxFrame->m_Data.m_Asnd.m_Payload.
822 				   m_IdentResponse.m_le_abVendorSpecificExt2[0],
823 				   &EplDllkInstance_g.m_DllIdentParam.
824 				   m_abVendorSpecificExt2[0],
825 				   sizeof(EplDllkInstance_g.m_DllIdentParam.
826 					  m_abVendorSpecificExt2));
827 
828 			// StatusResponse
829 			uiFrameSize = EPL_C_DLL_MINSIZE_STATUSRES;
830 			Ret =
831 			    EplDllkCreateTxFrame(&uiHandle, &pTxFrame,
832 						 &uiFrameSize, kEplMsgTypeAsnd,
833 						 kEplDllAsndStatusResponse);
834 			if (Ret != kEplSuccessful) {	// error occured while registering Tx frame
835 				goto Exit;
836 			}
837 			// PRes $$$ maybe move this to PDO module
838 			if ((EplDllkInstance_g.m_DllConfigParam.m_fAsyncOnly ==
839 			     FALSE)
840 			    && (EplDllkInstance_g.m_DllConfigParam.m_uiPresActPayloadLimit >= 36)) {	// it is not configured as async-only CN,
841 				// so take part in isochronous phase and register PRes frame
842 				uiFrameSize =
843 				    EplDllkInstance_g.m_DllConfigParam.
844 				    m_uiPresActPayloadLimit + 24;
845 				Ret =
846 				    EplDllkCreateTxFrame(&uiHandle, &pTxFrame,
847 							 &uiFrameSize,
848 							 kEplMsgTypePres,
849 							 kEplDllAsndNotDefined);
850 				if (Ret != kEplSuccessful) {	// error occured while registering Tx frame
851 					goto Exit;
852 				}
853 #if (((EPL_MODULE_INTEGRATION) & (EPL_MODULE_PDOK)) != 0)
854 				// initially encode TPDO -> inform PDO module
855 				FrameInfo.m_pFrame = pTxFrame;
856 				FrameInfo.m_uiFrameSize = uiFrameSize;
857 				Ret = EplPdokCbPdoTransmitted(&FrameInfo);
858 #endif
859 				// reset cycle counter
860 				EplDllkInstance_g.m_uiCycleCount = 0;
861 			} else {	// it is an async-only CN
862 				// fool EplDllkChangeState() to think that PRes was not expected
863 				EplDllkInstance_g.m_uiCycleCount = 1;
864 			}
865 
866 			// NMT request
867 			uiFrameSize = EPL_C_IP_MAX_MTU;
868 			Ret =
869 			    EplDllkCreateTxFrame(&uiHandle, &pTxFrame,
870 						 &uiFrameSize, kEplMsgTypeAsnd,
871 						 kEplDllAsndNmtRequest);
872 			if (Ret != kEplSuccessful) {	// error occured while registering Tx frame
873 				goto Exit;
874 			}
875 			// mark Tx buffer as empty
876 			EplDllkInstance_g.m_pTxBuffer[uiHandle].m_uiTxMsgLen =
877 			    EPL_DLLK_BUFLEN_EMPTY;
878 
879 			// non-EPL frame
880 			uiFrameSize = EPL_C_IP_MAX_MTU;
881 			Ret =
882 			    EplDllkCreateTxFrame(&uiHandle, &pTxFrame,
883 						 &uiFrameSize,
884 						 kEplMsgTypeNonEpl,
885 						 kEplDllAsndNotDefined);
886 			if (Ret != kEplSuccessful) {	// error occured while registering Tx frame
887 				goto Exit;
888 			}
889 			// mark Tx buffer as empty
890 			EplDllkInstance_g.m_pTxBuffer[uiHandle].m_uiTxMsgLen =
891 			    EPL_DLLK_BUFLEN_EMPTY;
892 
893 			// register multicast MACs in ethernet driver
894 			AmiSetQword48ToBe(&abMulticastMac[0],
895 					  EPL_C_DLL_MULTICAST_SOC);
896 			Ret = EdrvDefineRxMacAddrEntry(abMulticastMac);
897 			AmiSetQword48ToBe(&abMulticastMac[0],
898 					  EPL_C_DLL_MULTICAST_SOA);
899 			Ret = EdrvDefineRxMacAddrEntry(abMulticastMac);
900 			AmiSetQword48ToBe(&abMulticastMac[0],
901 					  EPL_C_DLL_MULTICAST_PRES);
902 			Ret = EdrvDefineRxMacAddrEntry(abMulticastMac);
903 			AmiSetQword48ToBe(&abMulticastMac[0],
904 					  EPL_C_DLL_MULTICAST_ASND);
905 			Ret = EdrvDefineRxMacAddrEntry(abMulticastMac);
906 
907 #if (((EPL_MODULE_INTEGRATION) & (EPL_MODULE_NMT_MN)) != 0)
908 			if (NmtState >= kEplNmtMsNotActive) {	// local node is MN
909 				unsigned int uiIndex;
910 
911 				// SoC
912 				uiFrameSize = EPL_C_DLL_MINSIZE_SOC;
913 				Ret =
914 				    EplDllkCreateTxFrame(&uiHandle, &pTxFrame,
915 							 &uiFrameSize,
916 							 kEplMsgTypeSoc,
917 							 kEplDllAsndNotDefined);
918 				if (Ret != kEplSuccessful) {	// error occured while registering Tx frame
919 					goto Exit;
920 				}
921 				// SoA
922 				uiFrameSize = EPL_C_DLL_MINSIZE_SOA;
923 				Ret =
924 				    EplDllkCreateTxFrame(&uiHandle, &pTxFrame,
925 							 &uiFrameSize,
926 							 kEplMsgTypeSoa,
927 							 kEplDllAsndNotDefined);
928 				if (Ret != kEplSuccessful) {	// error occured while registering Tx frame
929 					goto Exit;
930 				}
931 
932 				for (uiIndex = 0;
933 				     uiIndex <
934 				     tabentries(EplDllkInstance_g.m_aNodeInfo);
935 				     uiIndex++) {
936 //                    EplDllkInstance_g.m_aNodeInfo[uiIndex].m_uiNodeId = uiIndex + 1;
937 					EplDllkInstance_g.m_aNodeInfo[uiIndex].
938 					    m_wPresPayloadLimit =
939 					    (WORD) EplDllkInstance_g.
940 					    m_DllConfigParam.
941 					    m_uiIsochrRxMaxPayload;
942 				}
943 
944 				// calculate cycle length
945 				EplDllkInstance_g.m_ullFrameTimeout = 1000LL
946 				    *
947 				    ((unsigned long long)EplDllkInstance_g.
948 				     m_DllConfigParam.m_dwCycleLen);
949 			}
950 #endif //(((EPL_MODULE_INTEGRATION) & (EPL_MODULE_NMT_MN)) != 0)
951 
952 			Ret = EplDllkCalAsyncClearBuffer();
953 
954 			break;
955 		}
956 
957 	case kEplEventTypeDllkDestroy:
958 		{
959 			// destroy all data structures
960 
961 			NmtState = *((tEplNmtState *) pEvent_p->m_pArg);
962 
963 			// delete Tx frames
964 			Ret = EplDllkDeleteTxFrame(EPL_DLLK_TXFRAME_IDENTRES);
965 			if (Ret != kEplSuccessful) {	// error occured while deregistering Tx frame
966 				goto Exit;
967 			}
968 
969 			Ret = EplDllkDeleteTxFrame(EPL_DLLK_TXFRAME_STATUSRES);
970 			if (Ret != kEplSuccessful) {	// error occured while deregistering Tx frame
971 				goto Exit;
972 			}
973 
974 			Ret = EplDllkDeleteTxFrame(EPL_DLLK_TXFRAME_PRES);
975 			if (Ret != kEplSuccessful) {	// error occured while deregistering Tx frame
976 				goto Exit;
977 			}
978 
979 			Ret = EplDllkDeleteTxFrame(EPL_DLLK_TXFRAME_NMTREQ);
980 			if (Ret != kEplSuccessful) {	// error occured while deregistering Tx frame
981 				goto Exit;
982 			}
983 
984 			Ret = EplDllkDeleteTxFrame(EPL_DLLK_TXFRAME_NONEPL);
985 			if (Ret != kEplSuccessful) {	// error occured while deregistering Tx frame
986 				goto Exit;
987 			}
988 #if (((EPL_MODULE_INTEGRATION) & (EPL_MODULE_NMT_MN)) != 0)
989 			if (NmtState >= kEplNmtMsNotActive) {	// local node was MN
990 				unsigned int uiIndex;
991 
992 				Ret =
993 				    EplDllkDeleteTxFrame(EPL_DLLK_TXFRAME_SOC);
994 				if (Ret != kEplSuccessful) {	// error occured while deregistering Tx frame
995 					goto Exit;
996 				}
997 
998 				Ret =
999 				    EplDllkDeleteTxFrame(EPL_DLLK_TXFRAME_SOA);
1000 				if (Ret != kEplSuccessful) {	// error occured while deregistering Tx frame
1001 					goto Exit;
1002 				}
1003 
1004 				for (uiIndex = 0;
1005 				     uiIndex <
1006 				     tabentries(EplDllkInstance_g.m_aNodeInfo);
1007 				     uiIndex++) {
1008 					if (EplDllkInstance_g.
1009 					    m_aNodeInfo[uiIndex].
1010 					    m_pPreqTxBuffer != NULL) {
1011 						uiHandle =
1012 						    EplDllkInstance_g.
1013 						    m_aNodeInfo[uiIndex].
1014 						    m_pPreqTxBuffer -
1015 						    EplDllkInstance_g.
1016 						    m_pTxBuffer;
1017 						EplDllkInstance_g.
1018 						    m_aNodeInfo[uiIndex].
1019 						    m_pPreqTxBuffer = NULL;
1020 						Ret =
1021 						    EplDllkDeleteTxFrame
1022 						    (uiHandle);
1023 						if (Ret != kEplSuccessful) {	// error occured while deregistering Tx frame
1024 							goto Exit;
1025 						}
1026 
1027 					}
1028 					EplDllkInstance_g.m_aNodeInfo[uiIndex].
1029 					    m_wPresPayloadLimit = 0xFFFF;
1030 				}
1031 			}
1032 #endif //(((EPL_MODULE_INTEGRATION) & (EPL_MODULE_NMT_MN)) != 0)
1033 
1034 			// deregister multicast MACs in ethernet driver
1035 			AmiSetQword48ToBe(&abMulticastMac[0],
1036 					  EPL_C_DLL_MULTICAST_SOC);
1037 			Ret = EdrvUndefineRxMacAddrEntry(abMulticastMac);
1038 			AmiSetQword48ToBe(&abMulticastMac[0],
1039 					  EPL_C_DLL_MULTICAST_SOA);
1040 			Ret = EdrvUndefineRxMacAddrEntry(abMulticastMac);
1041 			AmiSetQword48ToBe(&abMulticastMac[0],
1042 					  EPL_C_DLL_MULTICAST_PRES);
1043 			Ret = EdrvUndefineRxMacAddrEntry(abMulticastMac);
1044 			AmiSetQword48ToBe(&abMulticastMac[0],
1045 					  EPL_C_DLL_MULTICAST_ASND);
1046 			Ret = EdrvUndefineRxMacAddrEntry(abMulticastMac);
1047 
1048 			// delete timer
1049 #if EPL_TIMER_USE_HIGHRES != FALSE
1050 			Ret =
1051 			    EplTimerHighReskDeleteTimer(&EplDllkInstance_g.
1052 							m_TimerHdlCycle);
1053 #endif
1054 
1055 			break;
1056 		}
1057 
1058 	case kEplEventTypeDllkFillTx:
1059 		{
1060 			// fill TxBuffer of specified priority with new frame if empty
1061 
1062 			pTxFrame = NULL;
1063 			AsyncReqPriority =
1064 			    *((tEplDllAsyncReqPriority *) pEvent_p->m_pArg);
1065 			switch (AsyncReqPriority) {
1066 			case kEplDllAsyncReqPrioNmt:	// NMT request priority
1067 				{
1068 					pTxBuffer =
1069 					    &EplDllkInstance_g.
1070 					    m_pTxBuffer
1071 					    [EPL_DLLK_TXFRAME_NMTREQ];
1072 					if (pTxBuffer->m_pbBuffer != NULL) {	// NmtRequest does exist
1073 						// check if frame is empty and not being filled
1074 						if (pTxBuffer->m_uiTxMsgLen ==
1075 						    EPL_DLLK_BUFLEN_EMPTY) {
1076 							// mark Tx buffer as filling is in process
1077 							pTxBuffer->
1078 							    m_uiTxMsgLen =
1079 							    EPL_DLLK_BUFLEN_FILLING;
1080 							// set max buffer size as input parameter
1081 							uiFrameSize =
1082 							    pTxBuffer->
1083 							    m_uiMaxBufferLen;
1084 							// copy frame from shared loop buffer to Tx buffer
1085 							Ret =
1086 							    EplDllkCalAsyncGetTxFrame
1087 							    (pTxBuffer->
1088 							     m_pbBuffer,
1089 							     &uiFrameSize,
1090 							     AsyncReqPriority);
1091 							if (Ret ==
1092 							    kEplSuccessful) {
1093 								pTxFrame =
1094 								    (tEplFrame
1095 								     *)
1096 								    pTxBuffer->
1097 								    m_pbBuffer;
1098 								Ret =
1099 								    EplDllkCheckFrame
1100 								    (pTxFrame,
1101 								     uiFrameSize);
1102 
1103 								// set buffer valid
1104 								pTxBuffer->
1105 								    m_uiTxMsgLen
1106 								    =
1107 								    uiFrameSize;
1108 							} else if (Ret == kEplDllAsyncTxBufferEmpty) {	// empty Tx buffer is not a real problem
1109 								// so just ignore it
1110 								Ret =
1111 								    kEplSuccessful;
1112 								// mark Tx buffer as empty
1113 								pTxBuffer->
1114 								    m_uiTxMsgLen
1115 								    =
1116 								    EPL_DLLK_BUFLEN_EMPTY;
1117 							}
1118 						}
1119 					}
1120 					break;
1121 				}
1122 
1123 			default:	// generic priority
1124 				{
1125 					pTxBuffer =
1126 					    &EplDllkInstance_g.
1127 					    m_pTxBuffer
1128 					    [EPL_DLLK_TXFRAME_NONEPL];
1129 					if (pTxBuffer->m_pbBuffer != NULL) {	// non-EPL frame does exist
1130 						// check if frame is empty and not being filled
1131 						if (pTxBuffer->m_uiTxMsgLen ==
1132 						    EPL_DLLK_BUFLEN_EMPTY) {
1133 							// mark Tx buffer as filling is in process
1134 							pTxBuffer->
1135 							    m_uiTxMsgLen =
1136 							    EPL_DLLK_BUFLEN_FILLING;
1137 							// set max buffer size as input parameter
1138 							uiFrameSize =
1139 							    pTxBuffer->
1140 							    m_uiMaxBufferLen;
1141 							// copy frame from shared loop buffer to Tx buffer
1142 							Ret =
1143 							    EplDllkCalAsyncGetTxFrame
1144 							    (pTxBuffer->
1145 							     m_pbBuffer,
1146 							     &uiFrameSize,
1147 							     AsyncReqPriority);
1148 							if (Ret ==
1149 							    kEplSuccessful) {
1150 								pTxFrame =
1151 								    (tEplFrame
1152 								     *)
1153 								    pTxBuffer->
1154 								    m_pbBuffer;
1155 								Ret =
1156 								    EplDllkCheckFrame
1157 								    (pTxFrame,
1158 								     uiFrameSize);
1159 
1160 								// set buffer valid
1161 								pTxBuffer->
1162 								    m_uiTxMsgLen
1163 								    =
1164 								    uiFrameSize;
1165 							} else if (Ret == kEplDllAsyncTxBufferEmpty) {	// empty Tx buffer is not a real problem
1166 								// so just ignore it
1167 								Ret =
1168 								    kEplSuccessful;
1169 								// mark Tx buffer as empty
1170 								pTxBuffer->
1171 								    m_uiTxMsgLen
1172 								    =
1173 								    EPL_DLLK_BUFLEN_EMPTY;
1174 							}
1175 						}
1176 					}
1177 					break;
1178 				}
1179 			}
1180 
1181 			NmtState = EplNmtkGetNmtState();
1182 
1183 			if ((NmtState == kEplNmtCsBasicEthernet) || (NmtState == kEplNmtMsBasicEthernet)) {	// send frame immediately
1184 				if (pTxFrame != NULL) {	// frame is present
1185 					// padding is done by Edrv or ethernet controller
1186 					Ret = EdrvSendTxMsg(pTxBuffer);
1187 				} else {	// no frame moved to TxBuffer
1188 					// check if TxBuffers contain unsent frames
1189 					if (EplDllkInstance_g.m_pTxBuffer[EPL_DLLK_TXFRAME_NMTREQ].m_uiTxMsgLen > EPL_DLLK_BUFLEN_EMPTY) {	// NMT request Tx buffer contains a frame
1190 						Ret =
1191 						    EdrvSendTxMsg
1192 						    (&EplDllkInstance_g.
1193 						     m_pTxBuffer
1194 						     [EPL_DLLK_TXFRAME_NMTREQ]);
1195 					} else if (EplDllkInstance_g.m_pTxBuffer[EPL_DLLK_TXFRAME_NONEPL].m_uiTxMsgLen > EPL_DLLK_BUFLEN_EMPTY) {	// non-EPL Tx buffer contains a frame
1196 						Ret =
1197 						    EdrvSendTxMsg
1198 						    (&EplDllkInstance_g.
1199 						     m_pTxBuffer
1200 						     [EPL_DLLK_TXFRAME_NONEPL]);
1201 					}
1202 					if (Ret == kEplInvalidOperation) {	// ignore error if caused by already active transmission
1203 						Ret = kEplSuccessful;
1204 					}
1205 				}
1206 				// reset PRes flag 2
1207 				EplDllkInstance_g.m_bFlag2 = 0;
1208 			} else {
1209 				// update Flag 2 (PR, RS)
1210 				Ret =
1211 				    EplDllkCalAsyncGetTxCount(&AsyncReqPriority,
1212 							      &uiFrameCount);
1213 				if (AsyncReqPriority == kEplDllAsyncReqPrioNmt) {	// non-empty FIFO with hightest priority is for NMT requests
1214 					if (EplDllkInstance_g.m_pTxBuffer[EPL_DLLK_TXFRAME_NMTREQ].m_uiTxMsgLen > EPL_DLLK_BUFLEN_EMPTY) {	// NMT request Tx buffer contains a frame
1215 						// add one more frame
1216 						uiFrameCount++;
1217 					}
1218 				} else {	// non-empty FIFO with highest priority is for generic frames
1219 					if (EplDllkInstance_g.m_pTxBuffer[EPL_DLLK_TXFRAME_NMTREQ].m_uiTxMsgLen > EPL_DLLK_BUFLEN_EMPTY) {	// NMT request Tx buffer contains a frame
1220 						// use NMT request FIFO, because of higher priority
1221 						uiFrameCount = 1;
1222 						AsyncReqPriority =
1223 						    kEplDllAsyncReqPrioNmt;
1224 					} else if (EplDllkInstance_g.m_pTxBuffer[EPL_DLLK_TXFRAME_NONEPL].m_uiTxMsgLen > EPL_DLLK_BUFLEN_EMPTY) {	// non-EPL Tx buffer contains a frame
1225 						// use NMT request FIFO, because of higher priority
1226 						// add one more frame
1227 						uiFrameCount++;
1228 					}
1229 				}
1230 
1231 				if (uiFrameCount > 7) {	// limit frame request to send counter to 7
1232 					uiFrameCount = 7;
1233 				}
1234 				if (uiFrameCount > 0) {
1235 					EplDllkInstance_g.m_bFlag2 =
1236 					    (BYTE) (((AsyncReqPriority <<
1237 						      EPL_FRAME_FLAG2_PR_SHIFT)
1238 						     & EPL_FRAME_FLAG2_PR)
1239 						    | (uiFrameCount &
1240 						       EPL_FRAME_FLAG2_RS));
1241 				} else {
1242 					EplDllkInstance_g.m_bFlag2 = 0;
1243 				}
1244 			}
1245 
1246 			break;
1247 		}
1248 
1249 #if (((EPL_MODULE_INTEGRATION) & (EPL_MODULE_NMT_MN)) != 0)
1250 	case kEplEventTypeDllkStartReducedCycle:
1251 		{
1252 			// start the reduced cycle by programming the cycle timer
1253 			// it is issued by NMT MN module, when PreOp1 is entered
1254 
1255 			// clear the asynchronous queues
1256 			Ret = EplDllkCalAsyncClearQueues();
1257 
1258 			// reset cycle counter (everytime a SoA is triggerd in PreOp1 the counter is incremented
1259 			// and when it reaches EPL_C_DLL_PREOP1_START_CYCLES the SoA may contain invitations)
1260 			EplDllkInstance_g.m_uiCycleCount = 0;
1261 
1262 			// remove any CN from isochronous phase
1263 			while (EplDllkInstance_g.m_pFirstNodeInfo != NULL) {
1264 				EplDllkDeleteNode(EplDllkInstance_g.
1265 						  m_pFirstNodeInfo->m_uiNodeId);
1266 			}
1267 
1268 			// change state to NonCyclic,
1269 			// hence EplDllkChangeState() will not ignore the next call
1270 			EplDllkInstance_g.m_DllState = kEplDllMsNonCyclic;
1271 
1272 #if EPL_TIMER_USE_HIGHRES != FALSE
1273 			if (EplDllkInstance_g.m_DllConfigParam.
1274 			    m_dwAsyncSlotTimeout != 0) {
1275 				Ret =
1276 				    EplTimerHighReskModifyTimerNs
1277 				    (&EplDllkInstance_g.m_TimerHdlCycle,
1278 				     EplDllkInstance_g.m_DllConfigParam.
1279 				     m_dwAsyncSlotTimeout,
1280 				     EplDllkCbMnTimerCycle, 0L, FALSE);
1281 			}
1282 #endif
1283 
1284 			break;
1285 		}
1286 #endif
1287 
1288 #if EPL_DLL_PRES_READY_AFTER_SOA != FALSE
1289 	case kEplEventTypeDllkPresReady:
1290 		{
1291 			// post PRes to transmit FIFO
1292 
1293 			NmtState = EplNmtkGetNmtState();
1294 
1295 			if (NmtState != kEplNmtCsBasicEthernet) {
1296 				// Does PRes exist?
1297 				if (EplDllkInstance_g.m_pTxBuffer[EPL_DLLK_TXFRAME_PRES].m_pbBuffer != NULL) {	// PRes does exist
1298 					pTxFrame =
1299 					    (tEplFrame *) EplDllkInstance_g.
1300 					    m_pTxBuffer[EPL_DLLK_TXFRAME_PRES].
1301 					    m_pbBuffer;
1302 					// update frame (NMT state, RD, RS, PR, MS, EN flags)
1303 					if (NmtState < kEplNmtCsPreOperational2) {	// NMT state is not PreOp2, ReadyToOp or Op
1304 						// fake NMT state PreOp2, because PRes will be sent only in PreOp2 or greater
1305 						NmtState =
1306 						    kEplNmtCsPreOperational2;
1307 					}
1308 					AmiSetByteToLe(&pTxFrame->m_Data.m_Pres.
1309 						       m_le_bNmtStatus,
1310 						       (BYTE) NmtState);
1311 					AmiSetByteToLe(&pTxFrame->m_Data.m_Pres.
1312 						       m_le_bFlag2,
1313 						       EplDllkInstance_g.
1314 						       m_bFlag2);
1315 					if (NmtState != kEplNmtCsOperational) {	// mark PDO as invalid in NMT state Op
1316 						// $$$ reset only RD flag; set other flags appropriately
1317 						AmiSetByteToLe(&pTxFrame->
1318 							       m_Data.m_Pres.
1319 							       m_le_bFlag1, 0);
1320 					}
1321 					// $$$ make function that updates Pres, StatusRes
1322 					// mark PRes frame as ready for transmission
1323 					Ret =
1324 					    EdrvTxMsgReady(&EplDllkInstance_g.
1325 							   m_pTxBuffer
1326 							   [EPL_DLLK_TXFRAME_PRES]);
1327 				}
1328 			}
1329 
1330 			break;
1331 		}
1332 #endif
1333 	default:
1334 		{
1335 			ASSERTMSG(FALSE,
1336 				  "EplDllkProcess(): unhandled event type!\n");
1337 		}
1338 	}
1339 
1340       Exit:
1341 	return Ret;
1342 }
1343 
1344 //---------------------------------------------------------------------------
1345 //
1346 // Function:    EplDllkConfig
1347 //
1348 // Description: configure parameters of DLL
1349 //
1350 // Parameters:  pDllConfigParam_p       = configuration parameters
1351 //
1352 // Returns:     tEplKernel              = error code
1353 //
1354 //
1355 // State:
1356 //
1357 //---------------------------------------------------------------------------
1358 
EplDllkConfig(tEplDllConfigParam * pDllConfigParam_p)1359 tEplKernel EplDllkConfig(tEplDllConfigParam * pDllConfigParam_p)
1360 {
1361 	tEplKernel Ret = kEplSuccessful;
1362 
1363 // d.k. check of NMT state disabled, because CycleLen is programmed at run time by MN without reset of CN
1364 /*tEplNmtState    NmtState;
1365 
1366     NmtState = EplNmtkGetNmtState();
1367 
1368     if (NmtState > kEplNmtGsResetConfiguration)
1369     {   // only allowed in state DLL_GS_INIT
1370         Ret = kEplInvalidOperation;
1371         goto Exit;
1372     }
1373 */
1374 	EPL_MEMCPY(&EplDllkInstance_g.m_DllConfigParam, pDllConfigParam_p,
1375 		   (pDllConfigParam_p->m_uiSizeOfStruct <
1376 		    sizeof(tEplDllConfigParam) ? pDllConfigParam_p->
1377 		    m_uiSizeOfStruct : sizeof(tEplDllConfigParam)));
1378 
1379 	if ((EplDllkInstance_g.m_DllConfigParam.m_dwCycleLen != 0)
1380 	    && (EplDllkInstance_g.m_DllConfigParam.m_dwLossOfFrameTolerance != 0)) {	// monitor EPL cycle, calculate frame timeout
1381 		EplDllkInstance_g.m_ullFrameTimeout = (1000LL
1382 						       *
1383 						       ((unsigned long long)
1384 							EplDllkInstance_g.
1385 							m_DllConfigParam.
1386 							m_dwCycleLen))
1387 		    +
1388 		    ((unsigned long long)EplDllkInstance_g.m_DllConfigParam.
1389 		     m_dwLossOfFrameTolerance);
1390 	} else {
1391 		EplDllkInstance_g.m_ullFrameTimeout = 0LL;
1392 	}
1393 
1394 	if (EplDllkInstance_g.m_DllConfigParam.m_fAsyncOnly != FALSE) {	// it is configured as async-only CN
1395 		// disable multiplexed cycle, that m_uiCycleCount will not be incremented spuriously on SoC
1396 		EplDllkInstance_g.m_DllConfigParam.m_uiMultiplCycleCnt = 0;
1397 	}
1398 //Exit:
1399 	return Ret;
1400 }
1401 
1402 //---------------------------------------------------------------------------
1403 //
1404 // Function:    EplDllkSetIdentity
1405 //
1406 // Description: configure identity of local node for IdentResponse
1407 //
1408 // Parameters:  pDllIdentParam_p        = identity
1409 //
1410 // Returns:     tEplKernel              = error code
1411 //
1412 //
1413 // State:
1414 //
1415 //---------------------------------------------------------------------------
1416 
EplDllkSetIdentity(tEplDllIdentParam * pDllIdentParam_p)1417 tEplKernel EplDllkSetIdentity(tEplDllIdentParam * pDllIdentParam_p)
1418 {
1419 	tEplKernel Ret = kEplSuccessful;
1420 
1421 	EPL_MEMCPY(&EplDllkInstance_g.m_DllIdentParam, pDllIdentParam_p,
1422 		   (pDllIdentParam_p->m_uiSizeOfStruct <
1423 		    sizeof(tEplDllIdentParam) ? pDllIdentParam_p->
1424 		    m_uiSizeOfStruct : sizeof(tEplDllIdentParam)));
1425 
1426 	// $$$ if IdentResponse frame exists update it
1427 
1428 	return Ret;
1429 }
1430 
1431 //---------------------------------------------------------------------------
1432 //
1433 // Function:    EplDllkRegAsyncHandler
1434 //
1435 // Description: registers handler for non-EPL frames
1436 //
1437 // Parameters:  pfnDllkCbAsync_p        = pointer to callback function
1438 //
1439 // Returns:     tEplKernel              = error code
1440 //
1441 //
1442 // State:
1443 //
1444 //---------------------------------------------------------------------------
1445 
EplDllkRegAsyncHandler(tEplDllkCbAsync pfnDllkCbAsync_p)1446 tEplKernel EplDllkRegAsyncHandler(tEplDllkCbAsync pfnDllkCbAsync_p)
1447 {
1448 	tEplKernel Ret = kEplSuccessful;
1449 
1450 	if (EplDllkInstance_g.m_pfnCbAsync == NULL) {	// no handler registered yet
1451 		EplDllkInstance_g.m_pfnCbAsync = pfnDllkCbAsync_p;
1452 	} else {		// handler already registered
1453 		Ret = kEplDllCbAsyncRegistered;
1454 	}
1455 
1456 	return Ret;
1457 }
1458 
1459 //---------------------------------------------------------------------------
1460 //
1461 // Function:    EplDllkDeregAsyncHandler
1462 //
1463 // Description: deregisters handler for non-EPL frames
1464 //
1465 // Parameters:  pfnDllkCbAsync_p        = pointer to callback function
1466 //
1467 // Returns:     tEplKernel              = error code
1468 //
1469 //
1470 // State:
1471 //
1472 //---------------------------------------------------------------------------
1473 
EplDllkDeregAsyncHandler(tEplDllkCbAsync pfnDllkCbAsync_p)1474 tEplKernel EplDllkDeregAsyncHandler(tEplDllkCbAsync pfnDllkCbAsync_p)
1475 {
1476 	tEplKernel Ret = kEplSuccessful;
1477 
1478 	if (EplDllkInstance_g.m_pfnCbAsync == pfnDllkCbAsync_p) {	// same handler is registered
1479 		// deregister it
1480 		EplDllkInstance_g.m_pfnCbAsync = NULL;
1481 	} else {		// wrong handler or no handler registered
1482 		Ret = kEplDllCbAsyncRegistered;
1483 	}
1484 
1485 	return Ret;
1486 }
1487 
1488 //---------------------------------------------------------------------------
1489 //
1490 // Function:    EplDllkSetAsndServiceIdFilter()
1491 //
1492 // Description: sets the specified node ID filter for the specified
1493 //              AsndServiceId. It registers C_DLL_MULTICAST_ASND in ethernet
1494 //              driver if any AsndServiceId is open.
1495 //
1496 // Parameters:  ServiceId_p             = ASnd Service ID
1497 //              Filter_p                = node ID filter
1498 //
1499 // Returns:     tEplKernel              = error code
1500 //
1501 //
1502 // State:
1503 //
1504 //---------------------------------------------------------------------------
1505 
EplDllkSetAsndServiceIdFilter(tEplDllAsndServiceId ServiceId_p,tEplDllAsndFilter Filter_p)1506 tEplKernel EplDllkSetAsndServiceIdFilter(tEplDllAsndServiceId ServiceId_p,
1507 					 tEplDllAsndFilter Filter_p)
1508 {
1509 	tEplKernel Ret = kEplSuccessful;
1510 
1511 	if (ServiceId_p < tabentries(EplDllkInstance_g.m_aAsndFilter)) {
1512 		EplDllkInstance_g.m_aAsndFilter[ServiceId_p] = Filter_p;
1513 	}
1514 
1515 	return Ret;
1516 }
1517 
1518 #if (((EPL_MODULE_INTEGRATION) & (EPL_MODULE_NMT_MN)) != 0)
1519 
1520 //---------------------------------------------------------------------------
1521 //
1522 // Function:    EplDllkSetFlag1OfNode()
1523 //
1524 // Description: sets Flag1 (for PReq and SoA) of the specified node ID.
1525 //
1526 // Parameters:  uiNodeId_p              = node ID
1527 //              bSoaFlag1_p             = flag1
1528 //
1529 // Returns:     tEplKernel              = error code
1530 //
1531 //
1532 // State:
1533 //
1534 //---------------------------------------------------------------------------
1535 
EplDllkSetFlag1OfNode(unsigned int uiNodeId_p,BYTE bSoaFlag1_p)1536 tEplKernel EplDllkSetFlag1OfNode(unsigned int uiNodeId_p, BYTE bSoaFlag1_p)
1537 {
1538 	tEplKernel Ret = kEplSuccessful;
1539 	tEplDllkNodeInfo *pNodeInfo;
1540 
1541 	pNodeInfo = EplDllkGetNodeInfo(uiNodeId_p);
1542 	if (pNodeInfo == NULL) {	// no node info structure available
1543 		Ret = kEplDllNoNodeInfo;
1544 		goto Exit;
1545 	}
1546 	// store flag1 in internal node info structure
1547 	pNodeInfo->m_bSoaFlag1 = bSoaFlag1_p;
1548 
1549       Exit:
1550 	return Ret;
1551 }
1552 
1553 //---------------------------------------------------------------------------
1554 //
1555 // Function:    EplDllkGetFirstNodeInfo()
1556 //
1557 // Description: returns first info structure of first node in isochronous phase.
1558 //              It is only useful for ErrorHandlerk module.
1559 //
1560 // Parameters:  ppNodeInfo_p            = pointer to pointer of internal node info structure
1561 //
1562 // Returns:     tEplKernel              = error code
1563 //
1564 //
1565 // State:
1566 //
1567 //---------------------------------------------------------------------------
1568 
EplDllkGetFirstNodeInfo(tEplDllkNodeInfo ** ppNodeInfo_p)1569 tEplKernel EplDllkGetFirstNodeInfo(tEplDllkNodeInfo ** ppNodeInfo_p)
1570 {
1571 	tEplKernel Ret = kEplSuccessful;
1572 
1573 	*ppNodeInfo_p = EplDllkInstance_g.m_pFirstNodeInfo;
1574 
1575 	return Ret;
1576 }
1577 
1578 //---------------------------------------------------------------------------
1579 //
1580 // Function:    EplDllkAddNode()
1581 //
1582 // Description: adds the specified node to the isochronous phase.
1583 //
1584 // Parameters:  pNodeInfo_p             = pointer of node info structure
1585 //
1586 // Returns:     tEplKernel              = error code
1587 //
1588 //
1589 // State:
1590 //
1591 //---------------------------------------------------------------------------
1592 
EplDllkAddNode(tEplDllNodeInfo * pNodeInfo_p)1593 tEplKernel EplDllkAddNode(tEplDllNodeInfo * pNodeInfo_p)
1594 {
1595 	tEplKernel Ret = kEplSuccessful;
1596 	tEplDllkNodeInfo *pIntNodeInfo;
1597 	tEplDllkNodeInfo **ppIntNodeInfo;
1598 	unsigned int uiHandle;
1599 	tEplFrame *pFrame;
1600 	unsigned int uiFrameSize;
1601 
1602 	pIntNodeInfo = EplDllkGetNodeInfo(pNodeInfo_p->m_uiNodeId);
1603 	if (pIntNodeInfo == NULL) {	// no node info structure available
1604 		Ret = kEplDllNoNodeInfo;
1605 		goto Exit;
1606 	}
1607 
1608 	EPL_DLLK_DBG_POST_TRACE_VALUE(kEplEventTypeDllkAddNode,
1609 				      pNodeInfo_p->m_uiNodeId, 0);
1610 
1611 	// copy node configuration
1612 	pIntNodeInfo->m_dwPresTimeout = pNodeInfo_p->m_dwPresTimeout;
1613 	pIntNodeInfo->m_wPresPayloadLimit = pNodeInfo_p->m_wPresPayloadLimit;
1614 
1615 	// $$$ d.k.: actually add node only if MN. On CN it is sufficient to update the node configuration
1616 	if (pNodeInfo_p->m_uiNodeId == EplDllkInstance_g.m_DllConfigParam.m_uiNodeId) {	// we shall send PRes ourself
1617 		// insert our node at the end of the list
1618 		ppIntNodeInfo = &EplDllkInstance_g.m_pFirstNodeInfo;
1619 		while ((*ppIntNodeInfo != NULL)
1620 		       && ((*ppIntNodeInfo)->m_pNextNodeInfo != NULL)) {
1621 			ppIntNodeInfo = &(*ppIntNodeInfo)->m_pNextNodeInfo;
1622 		}
1623 		if (*ppIntNodeInfo != NULL) {
1624 			if ((*ppIntNodeInfo)->m_uiNodeId == pNodeInfo_p->m_uiNodeId) {	// node was already added to list
1625 				// $$$ d.k. maybe this should be an error
1626 				goto Exit;
1627 			} else {	// add our node at the end of the list
1628 				ppIntNodeInfo =
1629 				    &(*ppIntNodeInfo)->m_pNextNodeInfo;
1630 			}
1631 		}
1632 		// set "PReq"-TxBuffer to PRes-TxBuffer
1633 		pIntNodeInfo->m_pPreqTxBuffer =
1634 		    &EplDllkInstance_g.m_pTxBuffer[EPL_DLLK_TXFRAME_PRES];
1635 	} else {		// normal CN shall be added to isochronous phase
1636 		// insert node into list in ascending order
1637 		ppIntNodeInfo = &EplDllkInstance_g.m_pFirstNodeInfo;
1638 		while ((*ppIntNodeInfo != NULL)
1639 		       && ((*ppIntNodeInfo)->m_uiNodeId <
1640 			   pNodeInfo_p->m_uiNodeId)
1641 		       && ((*ppIntNodeInfo)->m_uiNodeId !=
1642 			   EplDllkInstance_g.m_DllConfigParam.m_uiNodeId)) {
1643 			ppIntNodeInfo = &(*ppIntNodeInfo)->m_pNextNodeInfo;
1644 		}
1645 		if ((*ppIntNodeInfo != NULL) && ((*ppIntNodeInfo)->m_uiNodeId == pNodeInfo_p->m_uiNodeId)) {	// node was already added to list
1646 			// $$$ d.k. maybe this should be an error
1647 			goto Exit;
1648 		}
1649 	}
1650 
1651 	// initialize elements of internal node info structure
1652 	pIntNodeInfo->m_bSoaFlag1 = 0;
1653 	pIntNodeInfo->m_fSoftDelete = FALSE;
1654 	pIntNodeInfo->m_NmtState = kEplNmtCsNotActive;
1655 	if (pIntNodeInfo->m_pPreqTxBuffer == NULL) {	// create TxBuffer entry
1656 		uiFrameSize = pNodeInfo_p->m_wPreqPayloadLimit + 24;
1657 		Ret =
1658 		    EplDllkCreateTxFrame(&uiHandle, &pFrame, &uiFrameSize,
1659 					 kEplMsgTypePreq,
1660 					 kEplDllAsndNotDefined);
1661 		if (Ret != kEplSuccessful) {
1662 			goto Exit;
1663 		}
1664 		pIntNodeInfo->m_pPreqTxBuffer =
1665 		    &EplDllkInstance_g.m_pTxBuffer[uiHandle];
1666 		AmiSetByteToLe(&pFrame->m_le_bDstNodeId,
1667 			       (BYTE) pNodeInfo_p->m_uiNodeId);
1668 
1669 		// set up destination MAC address
1670 		EPL_MEMCPY(pFrame->m_be_abDstMac, pIntNodeInfo->m_be_abMacAddr,
1671 			   6);
1672 
1673 #if (((EPL_MODULE_INTEGRATION) & (EPL_MODULE_PDOK)) != 0)
1674 		{
1675 			tEplFrameInfo FrameInfo;
1676 
1677 			// initially encode TPDO -> inform PDO module
1678 			FrameInfo.m_pFrame = pFrame;
1679 			FrameInfo.m_uiFrameSize = uiFrameSize;
1680 			Ret = EplPdokCbPdoTransmitted(&FrameInfo);
1681 		}
1682 #endif
1683 	}
1684 	pIntNodeInfo->m_ulDllErrorEvents = 0L;
1685 	// add node to list
1686 	pIntNodeInfo->m_pNextNodeInfo = *ppIntNodeInfo;
1687 	*ppIntNodeInfo = pIntNodeInfo;
1688 
1689       Exit:
1690 	return Ret;
1691 }
1692 
1693 //---------------------------------------------------------------------------
1694 //
1695 // Function:    EplDllkDeleteNode()
1696 //
1697 // Description: removes the specified node from the isochronous phase.
1698 //
1699 // Parameters:  uiNodeId_p              = node ID
1700 //
1701 // Returns:     tEplKernel              = error code
1702 //
1703 //
1704 // State:
1705 //
1706 //---------------------------------------------------------------------------
1707 
EplDllkDeleteNode(unsigned int uiNodeId_p)1708 tEplKernel EplDllkDeleteNode(unsigned int uiNodeId_p)
1709 {
1710 	tEplKernel Ret = kEplSuccessful;
1711 	tEplDllkNodeInfo *pIntNodeInfo;
1712 	tEplDllkNodeInfo **ppIntNodeInfo;
1713 	unsigned int uiHandle;
1714 
1715 	pIntNodeInfo = EplDllkGetNodeInfo(uiNodeId_p);
1716 	if (pIntNodeInfo == NULL) {	// no node info structure available
1717 		Ret = kEplDllNoNodeInfo;
1718 		goto Exit;
1719 	}
1720 
1721 	EPL_DLLK_DBG_POST_TRACE_VALUE(kEplEventTypeDllkDelNode, uiNodeId_p, 0);
1722 
1723 	// search node in whole list
1724 	ppIntNodeInfo = &EplDllkInstance_g.m_pFirstNodeInfo;
1725 	while ((*ppIntNodeInfo != NULL)
1726 	       && ((*ppIntNodeInfo)->m_uiNodeId != uiNodeId_p)) {
1727 		ppIntNodeInfo = &(*ppIntNodeInfo)->m_pNextNodeInfo;
1728 	}
1729 	if ((*ppIntNodeInfo == NULL) || ((*ppIntNodeInfo)->m_uiNodeId != uiNodeId_p)) {	// node was not found in list
1730 		// $$$ d.k. maybe this should be an error
1731 		goto Exit;
1732 	}
1733 	// remove node from list
1734 	*ppIntNodeInfo = pIntNodeInfo->m_pNextNodeInfo;
1735 
1736 	if ((pIntNodeInfo->m_pPreqTxBuffer != NULL)
1737 	    && (pIntNodeInfo->m_pPreqTxBuffer != &EplDllkInstance_g.m_pTxBuffer[EPL_DLLK_TXFRAME_PRES])) {	// delete TxBuffer entry
1738 		uiHandle =
1739 		    pIntNodeInfo->m_pPreqTxBuffer -
1740 		    EplDllkInstance_g.m_pTxBuffer;
1741 		pIntNodeInfo->m_pPreqTxBuffer = NULL;
1742 		Ret = EplDllkDeleteTxFrame(uiHandle);
1743 /*        if (Ret != kEplSuccessful)
1744         {
1745             goto Exit;
1746         }*/
1747 	}
1748 
1749       Exit:
1750 	return Ret;
1751 }
1752 
1753 //---------------------------------------------------------------------------
1754 //
1755 // Function:    EplDllkSoftDeleteNode()
1756 //
1757 // Description: removes the specified node not immediately from the isochronous phase.
1758 //              Instead the will be removed after error (late/loss PRes) without
1759 //              charging the error.
1760 //
1761 // Parameters:  uiNodeId_p              = node ID
1762 //
1763 // Returns:     tEplKernel              = error code
1764 //
1765 //
1766 // State:
1767 //
1768 //---------------------------------------------------------------------------
1769 
EplDllkSoftDeleteNode(unsigned int uiNodeId_p)1770 tEplKernel EplDllkSoftDeleteNode(unsigned int uiNodeId_p)
1771 {
1772 	tEplKernel Ret = kEplSuccessful;
1773 	tEplDllkNodeInfo *pIntNodeInfo;
1774 
1775 	pIntNodeInfo = EplDllkGetNodeInfo(uiNodeId_p);
1776 	if (pIntNodeInfo == NULL) {	// no node info structure available
1777 		Ret = kEplDllNoNodeInfo;
1778 		goto Exit;
1779 	}
1780 
1781 	EPL_DLLK_DBG_POST_TRACE_VALUE(kEplEventTypeDllkSoftDelNode,
1782 				      uiNodeId_p, 0);
1783 
1784 	pIntNodeInfo->m_fSoftDelete = TRUE;
1785 
1786       Exit:
1787 	return Ret;
1788 }
1789 
1790 #endif //(((EPL_MODULE_INTEGRATION) & (EPL_MODULE_NMT_MN)) != 0)
1791 
1792 //=========================================================================//
1793 //                                                                         //
1794 //          P R I V A T E   F U N C T I O N S                              //
1795 //                                                                         //
1796 //=========================================================================//
1797 
1798 //---------------------------------------------------------------------------
1799 //
1800 // Function:    EplDllkChangeState
1801 //
1802 // Description: change DLL state on event and diagnose some communication errors
1803 //
1804 // Parameters:  NmtEvent_p              = DLL event (wrapped in NMT event)
1805 //
1806 // Returns:     tEplKernel              = error code
1807 //
1808 //
1809 // State:
1810 //
1811 //---------------------------------------------------------------------------
1812 
EplDllkChangeState(tEplNmtEvent NmtEvent_p,tEplNmtState NmtState_p)1813 static tEplKernel EplDllkChangeState(tEplNmtEvent NmtEvent_p,
1814 				     tEplNmtState NmtState_p)
1815 {
1816 	tEplKernel Ret = kEplSuccessful;
1817 	tEplEvent Event;
1818 	tEplErrorHandlerkEvent DllEvent;
1819 
1820 	DllEvent.m_ulDllErrorEvents = 0;
1821 	DllEvent.m_uiNodeId = 0;
1822 	DllEvent.m_NmtState = NmtState_p;
1823 
1824 	switch (NmtState_p) {
1825 	case kEplNmtGsOff:
1826 	case kEplNmtGsInitialising:
1827 	case kEplNmtGsResetApplication:
1828 	case kEplNmtGsResetCommunication:
1829 	case kEplNmtGsResetConfiguration:
1830 	case kEplNmtCsBasicEthernet:
1831 		// enter DLL_GS_INIT
1832 		EplDllkInstance_g.m_DllState = kEplDllGsInit;
1833 		break;
1834 
1835 	case kEplNmtCsNotActive:
1836 	case kEplNmtCsPreOperational1:
1837 		// reduced EPL cycle is active
1838 		if (NmtEvent_p == kEplNmtEventDllCeSoc) {	// SoC received
1839 			// enter DLL_CS_WAIT_PREQ
1840 			EplDllkInstance_g.m_DllState = kEplDllCsWaitPreq;
1841 		} else {
1842 			// enter DLL_GS_INIT
1843 			EplDllkInstance_g.m_DllState = kEplDllGsInit;
1844 		}
1845 		break;
1846 
1847 	case kEplNmtCsPreOperational2:
1848 	case kEplNmtCsReadyToOperate:
1849 	case kEplNmtCsOperational:
1850 		// full EPL cycle is active
1851 
1852 		switch (EplDllkInstance_g.m_DllState) {
1853 		case kEplDllCsWaitPreq:
1854 			switch (NmtEvent_p) {
1855 				// DLL_CT2
1856 			case kEplNmtEventDllCePreq:
1857 				// enter DLL_CS_WAIT_SOA
1858 				DllEvent.m_ulDllErrorEvents |=
1859 				    EPL_DLL_ERR_CN_RECVD_PREQ;
1860 				EplDllkInstance_g.m_DllState = kEplDllCsWaitSoa;
1861 				break;
1862 
1863 				// DLL_CT8
1864 			case kEplNmtEventDllCeFrameTimeout:
1865 				if (NmtState_p == kEplNmtCsPreOperational2) {	// ignore frame timeout in PreOp2,
1866 					// because the previously configured cycle len
1867 					// may be wrong.
1868 					// 2008/10/15 d.k. If it would not be ignored,
1869 					// we would go cyclically to PreOp1 and on next
1870 					// SoC back to PreOp2.
1871 					break;
1872 				}
1873 				// report DLL_CEV_LOSS_SOC and DLL_CEV_LOSS_SOA
1874 				DllEvent.m_ulDllErrorEvents |=
1875 				    EPL_DLL_ERR_CN_LOSS_SOA |
1876 				    EPL_DLL_ERR_CN_LOSS_SOC;
1877 
1878 				// enter DLL_CS_WAIT_SOC
1879 				EplDllkInstance_g.m_DllState = kEplDllCsWaitSoc;
1880 				break;
1881 
1882 			case kEplNmtEventDllCeSoa:
1883 				// check if multiplexed and PReq should have been received in this cycle
1884 				// and if >= NMT_CS_READY_TO_OPERATE
1885 				if ((EplDllkInstance_g.m_uiCycleCount == 0)
1886 				    && (NmtState_p >= kEplNmtCsReadyToOperate)) {	// report DLL_CEV_LOSS_OF_PREQ
1887 					DllEvent.m_ulDllErrorEvents |=
1888 					    EPL_DLL_ERR_CN_LOSS_PREQ;
1889 				}
1890 				// enter DLL_CS_WAIT_SOC
1891 				EplDllkInstance_g.m_DllState = kEplDllCsWaitSoc;
1892 				break;
1893 
1894 				// DLL_CT7
1895 			case kEplNmtEventDllCeSoc:
1896 			case kEplNmtEventDllCeAsnd:
1897 				// report DLL_CEV_LOSS_SOA
1898 				DllEvent.m_ulDllErrorEvents |=
1899 				    EPL_DLL_ERR_CN_LOSS_SOA;
1900 
1901 			case kEplNmtEventDllCePres:
1902 			default:
1903 				// remain in this state
1904 				break;
1905 			}
1906 			break;
1907 
1908 		case kEplDllCsWaitSoc:
1909 			switch (NmtEvent_p) {
1910 				// DLL_CT1
1911 			case kEplNmtEventDllCeSoc:
1912 				// start of cycle and isochronous phase
1913 				// enter DLL_CS_WAIT_PREQ
1914 				EplDllkInstance_g.m_DllState =
1915 				    kEplDllCsWaitPreq;
1916 				break;
1917 
1918 				// DLL_CT4
1919 //                        case kEplNmtEventDllCePres:
1920 			case kEplNmtEventDllCeFrameTimeout:
1921 				if (NmtState_p == kEplNmtCsPreOperational2) {	// ignore frame timeout in PreOp2,
1922 					// because the previously configured cycle len
1923 					// may be wrong.
1924 					// 2008/10/15 d.k. If it would not be ignored,
1925 					// we would go cyclically to PreOp1 and on next
1926 					// SoC back to PreOp2.
1927 					break;
1928 				}
1929 				// fall through
1930 
1931 			case kEplNmtEventDllCePreq:
1932 			case kEplNmtEventDllCeSoa:
1933 				// report DLL_CEV_LOSS_SOC
1934 				DllEvent.m_ulDllErrorEvents |=
1935 				    EPL_DLL_ERR_CN_LOSS_SOC;
1936 
1937 			case kEplNmtEventDllCeAsnd:
1938 			default:
1939 				// remain in this state
1940 				break;
1941 			}
1942 			break;
1943 
1944 		case kEplDllCsWaitSoa:
1945 			switch (NmtEvent_p) {
1946 			case kEplNmtEventDllCeFrameTimeout:
1947 				// DLL_CT3
1948 				if (NmtState_p == kEplNmtCsPreOperational2) {	// ignore frame timeout in PreOp2,
1949 					// because the previously configured cycle len
1950 					// may be wrong.
1951 					// 2008/10/15 d.k. If it would not be ignored,
1952 					// we would go cyclically to PreOp1 and on next
1953 					// SoC back to PreOp2.
1954 					break;
1955 				}
1956 				// fall through
1957 
1958 			case kEplNmtEventDllCePreq:
1959 				// report DLL_CEV_LOSS_SOC and DLL_CEV_LOSS_SOA
1960 				DllEvent.m_ulDllErrorEvents |=
1961 				    EPL_DLL_ERR_CN_LOSS_SOA |
1962 				    EPL_DLL_ERR_CN_LOSS_SOC;
1963 
1964 			case kEplNmtEventDllCeSoa:
1965 				// enter DLL_CS_WAIT_SOC
1966 				EplDllkInstance_g.m_DllState = kEplDllCsWaitSoc;
1967 				break;
1968 
1969 				// DLL_CT9
1970 			case kEplNmtEventDllCeSoc:
1971 				// report DLL_CEV_LOSS_SOA
1972 				DllEvent.m_ulDllErrorEvents |=
1973 				    EPL_DLL_ERR_CN_LOSS_SOA;
1974 
1975 				// enter DLL_CS_WAIT_PREQ
1976 				EplDllkInstance_g.m_DllState =
1977 				    kEplDllCsWaitPreq;
1978 				break;
1979 
1980 				// DLL_CT10
1981 			case kEplNmtEventDllCeAsnd:
1982 				// report DLL_CEV_LOSS_SOA
1983 				DllEvent.m_ulDllErrorEvents |=
1984 				    EPL_DLL_ERR_CN_LOSS_SOA;
1985 
1986 			case kEplNmtEventDllCePres:
1987 			default:
1988 				// remain in this state
1989 				break;
1990 			}
1991 			break;
1992 
1993 		case kEplDllGsInit:
1994 			// enter DLL_CS_WAIT_PREQ
1995 			EplDllkInstance_g.m_DllState = kEplDllCsWaitPreq;
1996 			break;
1997 
1998 		default:
1999 			break;
2000 		}
2001 		break;
2002 
2003 	case kEplNmtCsStopped:
2004 		// full EPL cycle is active, but without PReq/PRes
2005 
2006 		switch (EplDllkInstance_g.m_DllState) {
2007 		case kEplDllCsWaitPreq:
2008 			switch (NmtEvent_p) {
2009 				// DLL_CT2
2010 			case kEplNmtEventDllCePreq:
2011 				// enter DLL_CS_WAIT_SOA
2012 				EplDllkInstance_g.m_DllState = kEplDllCsWaitSoa;
2013 				break;
2014 
2015 				// DLL_CT8
2016 			case kEplNmtEventDllCeFrameTimeout:
2017 				// report DLL_CEV_LOSS_SOC and DLL_CEV_LOSS_SOA
2018 				DllEvent.m_ulDllErrorEvents |=
2019 				    EPL_DLL_ERR_CN_LOSS_SOA |
2020 				    EPL_DLL_ERR_CN_LOSS_SOC;
2021 
2022 			case kEplNmtEventDllCeSoa:
2023 				// NMT_CS_STOPPED active
2024 				// it is Ok if no PReq was received
2025 
2026 				// enter DLL_CS_WAIT_SOC
2027 				EplDllkInstance_g.m_DllState = kEplDllCsWaitSoc;
2028 				break;
2029 
2030 				// DLL_CT7
2031 			case kEplNmtEventDllCeSoc:
2032 			case kEplNmtEventDllCeAsnd:
2033 				// report DLL_CEV_LOSS_SOA
2034 				DllEvent.m_ulDllErrorEvents |=
2035 				    EPL_DLL_ERR_CN_LOSS_SOA;
2036 
2037 			case kEplNmtEventDllCePres:
2038 			default:
2039 				// remain in this state
2040 				break;
2041 			}
2042 			break;
2043 
2044 		case kEplDllCsWaitSoc:
2045 			switch (NmtEvent_p) {
2046 				// DLL_CT1
2047 			case kEplNmtEventDllCeSoc:
2048 				// start of cycle and isochronous phase
2049 				// enter DLL_CS_WAIT_SOA
2050 				EplDllkInstance_g.m_DllState = kEplDllCsWaitSoa;
2051 				break;
2052 
2053 				// DLL_CT4
2054 //                        case kEplNmtEventDllCePres:
2055 			case kEplNmtEventDllCePreq:
2056 			case kEplNmtEventDllCeSoa:
2057 			case kEplNmtEventDllCeFrameTimeout:
2058 				// report DLL_CEV_LOSS_SOC
2059 				DllEvent.m_ulDllErrorEvents |=
2060 				    EPL_DLL_ERR_CN_LOSS_SOC;
2061 
2062 			case kEplNmtEventDllCeAsnd:
2063 			default:
2064 				// remain in this state
2065 				break;
2066 			}
2067 			break;
2068 
2069 		case kEplDllCsWaitSoa:
2070 			switch (NmtEvent_p) {
2071 				// DLL_CT3
2072 			case kEplNmtEventDllCeFrameTimeout:
2073 				// report DLL_CEV_LOSS_SOC and DLL_CEV_LOSS_SOA
2074 				DllEvent.m_ulDllErrorEvents |=
2075 				    EPL_DLL_ERR_CN_LOSS_SOA |
2076 				    EPL_DLL_ERR_CN_LOSS_SOC;
2077 
2078 			case kEplNmtEventDllCeSoa:
2079 				// enter DLL_CS_WAIT_SOC
2080 				EplDllkInstance_g.m_DllState = kEplDllCsWaitSoc;
2081 				break;
2082 
2083 				// DLL_CT9
2084 			case kEplNmtEventDllCeSoc:
2085 				// report DLL_CEV_LOSS_SOA
2086 				DllEvent.m_ulDllErrorEvents |=
2087 				    EPL_DLL_ERR_CN_LOSS_SOA;
2088 				// remain in DLL_CS_WAIT_SOA
2089 				break;
2090 
2091 				// DLL_CT10
2092 			case kEplNmtEventDllCeAsnd:
2093 				// report DLL_CEV_LOSS_SOA
2094 				DllEvent.m_ulDllErrorEvents |=
2095 				    EPL_DLL_ERR_CN_LOSS_SOA;
2096 
2097 			case kEplNmtEventDllCePreq:
2098 				// NMT_CS_STOPPED active and we do not expect any PReq
2099 				// so just ignore it
2100 			case kEplNmtEventDllCePres:
2101 			default:
2102 				// remain in this state
2103 				break;
2104 			}
2105 			break;
2106 
2107 		case kEplDllGsInit:
2108 		default:
2109 			// enter DLL_CS_WAIT_PREQ
2110 			EplDllkInstance_g.m_DllState = kEplDllCsWaitSoa;
2111 			break;
2112 		}
2113 		break;
2114 
2115 #if (((EPL_MODULE_INTEGRATION) & (EPL_MODULE_NMT_MN)) != 0)
2116 	case kEplNmtMsNotActive:
2117 	case kEplNmtMsBasicEthernet:
2118 		break;
2119 
2120 	case kEplNmtMsPreOperational1:
2121 		// reduced EPL cycle is active
2122 		if (EplDllkInstance_g.m_DllState != kEplDllMsNonCyclic) {	// stop cycle timer
2123 #if EPL_TIMER_USE_HIGHRES != FALSE
2124 			Ret =
2125 			    EplTimerHighReskDeleteTimer(&EplDllkInstance_g.
2126 							m_TimerHdlCycle);
2127 #endif
2128 			EplDllkInstance_g.m_DllState = kEplDllMsNonCyclic;
2129 
2130 			// stop further processing,
2131 			// because it will be restarted by NMT MN module
2132 			break;
2133 		}
2134 
2135 		switch (NmtEvent_p) {
2136 		case kEplNmtEventDllMeSocTrig:
2137 		case kEplNmtEventDllCeAsnd:
2138 			{	// because of reduced EPL cycle SoA shall be triggered, not SoC
2139 				tEplDllState DummyDllState;
2140 
2141 				Ret =
2142 				    EplDllkAsyncFrameNotReceived
2143 				    (EplDllkInstance_g.m_LastReqServiceId,
2144 				     EplDllkInstance_g.m_uiLastTargetNodeId);
2145 
2146 				// go ahead and send SoA
2147 				Ret = EplDllkMnSendSoa(NmtState_p,
2148 						       &DummyDllState,
2149 						       (EplDllkInstance_g.
2150 							m_uiCycleCount >=
2151 							EPL_C_DLL_PREOP1_START_CYCLES));
2152 				// increment cycle counter to detect if EPL_C_DLL_PREOP1_START_CYCLES empty cycles are elapsed
2153 				EplDllkInstance_g.m_uiCycleCount++;
2154 
2155 				// reprogram timer
2156 #if EPL_TIMER_USE_HIGHRES != FALSE
2157 				if (EplDllkInstance_g.m_DllConfigParam.
2158 				    m_dwAsyncSlotTimeout != 0) {
2159 					Ret =
2160 					    EplTimerHighReskModifyTimerNs
2161 					    (&EplDllkInstance_g.m_TimerHdlCycle,
2162 					     EplDllkInstance_g.m_DllConfigParam.
2163 					     m_dwAsyncSlotTimeout,
2164 					     EplDllkCbMnTimerCycle, 0L, FALSE);
2165 				}
2166 #endif
2167 				break;
2168 			}
2169 
2170 		default:
2171 			break;
2172 		}
2173 		break;
2174 
2175 	case kEplNmtMsPreOperational2:
2176 	case kEplNmtMsReadyToOperate:
2177 	case kEplNmtMsOperational:
2178 		// full EPL cycle is active
2179 		switch (NmtEvent_p) {
2180 		case kEplNmtEventDllMeSocTrig:
2181 			{
2182 				// update cycle counter
2183 				if (EplDllkInstance_g.m_DllConfigParam.m_uiMultiplCycleCnt > 0) {	// multiplexed cycle active
2184 					EplDllkInstance_g.m_uiCycleCount =
2185 					    (EplDllkInstance_g.m_uiCycleCount +
2186 					     1) %
2187 					    EplDllkInstance_g.m_DllConfigParam.
2188 					    m_uiMultiplCycleCnt;
2189 					// $$$ check multiplexed cycle restart
2190 					//     -> toggle MC flag
2191 					//     -> change node linked list
2192 				} else {	// non-multiplexed cycle active
2193 					// start with first node in isochronous phase
2194 					EplDllkInstance_g.m_pCurNodeInfo = NULL;
2195 				}
2196 
2197 				switch (EplDllkInstance_g.m_DllState) {
2198 				case kEplDllMsNonCyclic:
2199 					{	// start continuous cycle timer
2200 #if EPL_TIMER_USE_HIGHRES != FALSE
2201 						Ret =
2202 						    EplTimerHighReskModifyTimerNs
2203 						    (&EplDllkInstance_g.
2204 						     m_TimerHdlCycle,
2205 						     EplDllkInstance_g.
2206 						     m_ullFrameTimeout,
2207 						     EplDllkCbMnTimerCycle, 0L,
2208 						     TRUE);
2209 #endif
2210 						// continue with sending SoC
2211 					}
2212 
2213 				case kEplDllMsWaitAsnd:
2214 				case kEplDllMsWaitSocTrig:
2215 					{	// if m_LastReqServiceId is still valid,
2216 						// SoA was not correctly answered
2217 						// and user part has to be informed
2218 						Ret =
2219 						    EplDllkAsyncFrameNotReceived
2220 						    (EplDllkInstance_g.
2221 						     m_LastReqServiceId,
2222 						     EplDllkInstance_g.
2223 						     m_uiLastTargetNodeId);
2224 
2225 						// send SoC
2226 						Ret = EplDllkMnSendSoc();
2227 
2228 						// new DLL state
2229 						EplDllkInstance_g.m_DllState =
2230 						    kEplDllMsWaitPreqTrig;
2231 
2232 						// start WaitSoCPReq Timer
2233 #if EPL_TIMER_USE_HIGHRES != FALSE
2234 						Ret =
2235 						    EplTimerHighReskModifyTimerNs
2236 						    (&EplDllkInstance_g.
2237 						     m_TimerHdlResponse,
2238 						     EplDllkInstance_g.
2239 						     m_DllConfigParam.
2240 						     m_dwWaitSocPreq,
2241 						     EplDllkCbMnTimerResponse,
2242 						     0L, FALSE);
2243 #endif
2244 						break;
2245 					}
2246 
2247 				default:
2248 					{	// wrong DLL state / cycle time exceeded
2249 						DllEvent.m_ulDllErrorEvents |=
2250 						    EPL_DLL_ERR_MN_CYCTIMEEXCEED;
2251 						EplDllkInstance_g.m_DllState =
2252 						    kEplDllMsWaitSocTrig;
2253 						break;
2254 					}
2255 				}
2256 
2257 				break;
2258 			}
2259 
2260 		case kEplNmtEventDllMePresTimeout:
2261 			{
2262 
2263 				switch (EplDllkInstance_g.m_DllState) {
2264 				case kEplDllMsWaitPres:
2265 					{	// PRes not received
2266 
2267 						if (EplDllkInstance_g.m_pCurNodeInfo->m_fSoftDelete == FALSE) {	// normal isochronous CN
2268 							DllEvent.
2269 							    m_ulDllErrorEvents
2270 							    |=
2271 							    EPL_DLL_ERR_MN_CN_LOSS_PRES;
2272 							DllEvent.m_uiNodeId =
2273 							    EplDllkInstance_g.
2274 							    m_pCurNodeInfo->
2275 							    m_uiNodeId;
2276 						} else {	// CN shall be deleted softly
2277 							Event.m_EventSink =
2278 							    kEplEventSinkDllkCal;
2279 							Event.m_EventType =
2280 							    kEplEventTypeDllkSoftDelNode;
2281 							// $$$ d.k. set Event.m_NetTime to current time
2282 							Event.m_uiSize =
2283 							    sizeof(unsigned
2284 								   int);
2285 							Event.m_pArg =
2286 							    &EplDllkInstance_g.
2287 							    m_pCurNodeInfo->
2288 							    m_uiNodeId;
2289 							Ret =
2290 							    EplEventkPost
2291 							    (&Event);
2292 						}
2293 
2294 						// continue with sending next PReq
2295 					}
2296 
2297 				case kEplDllMsWaitPreqTrig:
2298 					{
2299 						// send next PReq
2300 						Ret =
2301 						    EplDllkMnSendPreq
2302 						    (NmtState_p,
2303 						     &EplDllkInstance_g.
2304 						     m_DllState);
2305 
2306 						break;
2307 					}
2308 
2309 				default:
2310 					{	// wrong DLL state
2311 						break;
2312 					}
2313 				}
2314 
2315 				break;
2316 			}
2317 
2318 		case kEplNmtEventDllCePres:
2319 			{
2320 
2321 				switch (EplDllkInstance_g.m_DllState) {
2322 				case kEplDllMsWaitPres:
2323 					{	// PRes received
2324 						// send next PReq
2325 						Ret =
2326 						    EplDllkMnSendPreq
2327 						    (NmtState_p,
2328 						     &EplDllkInstance_g.
2329 						     m_DllState);
2330 
2331 						break;
2332 					}
2333 
2334 				default:
2335 					{	// wrong DLL state
2336 						break;
2337 					}
2338 				}
2339 
2340 				break;
2341 			}
2342 
2343 		case kEplNmtEventDllMeSoaTrig:
2344 			{
2345 
2346 				switch (EplDllkInstance_g.m_DllState) {
2347 				case kEplDllMsWaitSoaTrig:
2348 					{	// MN PRes sent
2349 						// send SoA
2350 						Ret =
2351 						    EplDllkMnSendSoa(NmtState_p,
2352 								     &EplDllkInstance_g.
2353 								     m_DllState,
2354 								     TRUE);
2355 
2356 						break;
2357 					}
2358 
2359 				default:
2360 					{	// wrong DLL state
2361 						break;
2362 					}
2363 				}
2364 
2365 				break;
2366 			}
2367 
2368 		case kEplNmtEventDllCeAsnd:
2369 			{	// ASnd has been received, but it may be not the requested one
2370 /*
2371                     // report if SoA was correctly answered
2372                     Ret = EplDllkAsyncFrameNotReceived(EplDllkInstance_g.m_LastReqServiceId,
2373                                                        EplDllkInstance_g.m_uiLastTargetNodeId);
2374 */
2375 				if (EplDllkInstance_g.m_DllState ==
2376 				    kEplDllMsWaitAsnd) {
2377 					EplDllkInstance_g.m_DllState =
2378 					    kEplDllMsWaitSocTrig;
2379 				}
2380 				break;
2381 			}
2382 
2383 		default:
2384 			break;
2385 		}
2386 		break;
2387 #endif //(((EPL_MODULE_INTEGRATION) & (EPL_MODULE_NMT_MN)) != 0)
2388 
2389 	default:
2390 		break;
2391 	}
2392 
2393 	if (DllEvent.m_ulDllErrorEvents != 0) {	// error event set -> post it to error handler
2394 		Event.m_EventSink = kEplEventSinkErrk;
2395 		Event.m_EventType = kEplEventTypeDllError;
2396 		// $$$ d.k. set Event.m_NetTime to current time
2397 		Event.m_uiSize = sizeof(DllEvent);
2398 		Event.m_pArg = &DllEvent;
2399 		Ret = EplEventkPost(&Event);
2400 	}
2401 
2402 	return Ret;
2403 }
2404 
2405 //---------------------------------------------------------------------------
2406 //
2407 // Function:    EplDllkCbFrameReceived()
2408 //
2409 // Description: called from EdrvInterruptHandler()
2410 //
2411 // Parameters:  pRxBuffer_p             = receive buffer structure
2412 //
2413 // Returns:     (none)
2414 //
2415 //
2416 // State:
2417 //
2418 //---------------------------------------------------------------------------
2419 
EplDllkCbFrameReceived(tEdrvRxBuffer * pRxBuffer_p)2420 static void EplDllkCbFrameReceived(tEdrvRxBuffer * pRxBuffer_p)
2421 {
2422 	tEplKernel Ret = kEplSuccessful;
2423 	tEplNmtState NmtState;
2424 	tEplNmtEvent NmtEvent = kEplNmtEventNoEvent;
2425 	tEplEvent Event;
2426 	tEplFrame *pFrame;
2427 	tEplFrame *pTxFrame;
2428 	tEdrvTxBuffer *pTxBuffer = NULL;
2429 	tEplFrameInfo FrameInfo;
2430 	tEplMsgType MsgType;
2431 	tEplDllReqServiceId ReqServiceId;
2432 	unsigned int uiAsndServiceId;
2433 	unsigned int uiNodeId;
2434 	BYTE bFlag1;
2435 
2436 	BENCHMARK_MOD_02_SET(3);
2437 	NmtState = EplNmtkGetNmtState();
2438 
2439 	if (NmtState <= kEplNmtGsResetConfiguration) {
2440 		goto Exit;
2441 	}
2442 
2443 	pFrame = (tEplFrame *) pRxBuffer_p->m_pbBuffer;
2444 
2445 #if EDRV_EARLY_RX_INT != FALSE
2446 	switch (pRxBuffer_p->m_BufferInFrame) {
2447 	case kEdrvBufferFirstInFrame:
2448 		{
2449 			MsgType =
2450 			    (tEplMsgType) AmiGetByteFromLe(&pFrame->
2451 							   m_le_bMessageType);
2452 			if (MsgType == kEplMsgTypePreq) {
2453 				if (EplDllkInstance_g.m_DllState == kEplDllCsWaitPreq) {	// PReq expected and actually received
2454 					// d.k.: The condition above is sufficent, because EPL cycle is active
2455 					//       and no non-EPL frame shall be received in isochronous phase.
2456 					// start transmission PRes
2457 					// $$$ What if Tx buffer is invalid?
2458 					pTxBuffer =
2459 					    &EplDllkInstance_g.
2460 					    m_pTxBuffer[EPL_DLLK_TXFRAME_PRES];
2461 #if (EPL_DLL_PRES_READY_AFTER_SOA != FALSE) || (EPL_DLL_PRES_READY_AFTER_SOC != FALSE)
2462 					Ret = EdrvTxMsgStart(pTxBuffer);
2463 #else
2464 					pTxFrame =
2465 					    (tEplFrame *) pTxBuffer->m_pbBuffer;
2466 					// update frame (NMT state, RD, RS, PR, MS, EN flags)
2467 					AmiSetByteToLe(&pTxFrame->m_Data.m_Pres.
2468 						       m_le_bNmtStatus,
2469 						       (BYTE) NmtState);
2470 					AmiSetByteToLe(&pTxFrame->m_Data.m_Pres.
2471 						       m_le_bFlag2,
2472 						       EplDllkInstance_g.
2473 						       m_bFlag2);
2474 					if (NmtState != kEplNmtCsOperational) {	// mark PDO as invalid in NMT state Op
2475 						// $$$ reset only RD flag; set other flags appropriately
2476 						AmiSetByteToLe(&pTxFrame->
2477 							       m_Data.m_Pres.
2478 							       m_le_bFlag1, 0);
2479 					}
2480 					// $$$ make function that updates Pres, StatusRes
2481 					// send PRes frame
2482 					Ret = EdrvSendTxMsg(pTxBuffer);
2483 #endif
2484 				}
2485 			}
2486 			goto Exit;
2487 		}
2488 
2489 	case kEdrvBufferMiddleInFrame:
2490 		{
2491 			goto Exit;
2492 		}
2493 
2494 	case kEdrvBufferLastInFrame:
2495 		{
2496 			break;
2497 		}
2498 	}
2499 #endif
2500 
2501 	FrameInfo.m_pFrame = pFrame;
2502 	FrameInfo.m_uiFrameSize = pRxBuffer_p->m_uiRxMsgLen;
2503 	FrameInfo.m_NetTime.m_dwNanoSec = pRxBuffer_p->m_NetTime.m_dwNanoSec;
2504 	FrameInfo.m_NetTime.m_dwSec = pRxBuffer_p->m_NetTime.m_dwSec;
2505 
2506 	if (AmiGetWordFromBe(&pFrame->m_be_wEtherType) != EPL_C_DLL_ETHERTYPE_EPL) {	// non-EPL frame
2507 		//TRACE2("EplDllkCbFrameReceived: pfnCbAsync=0x%p SrcMAC=0x%llx\n", EplDllkInstance_g.m_pfnCbAsync, AmiGetQword48FromBe(pFrame->m_be_abSrcMac));
2508 		if (EplDllkInstance_g.m_pfnCbAsync != NULL) {	// handler for async frames is registered
2509 			EplDllkInstance_g.m_pfnCbAsync(&FrameInfo);
2510 		}
2511 
2512 		goto Exit;
2513 	}
2514 
2515 	MsgType = (tEplMsgType) AmiGetByteFromLe(&pFrame->m_le_bMessageType);
2516 	switch (MsgType) {
2517 	case kEplMsgTypePreq:
2518 		{
2519 			// PReq frame
2520 			// d.k.: (we assume that this PReq frame is intended for us and don't check DstNodeId)
2521 			if (AmiGetByteFromLe(&pFrame->m_le_bDstNodeId) != EplDllkInstance_g.m_DllConfigParam.m_uiNodeId) {	// this PReq is not intended for us
2522 				goto Exit;
2523 			}
2524 			NmtEvent = kEplNmtEventDllCePreq;
2525 
2526 			if (NmtState >= kEplNmtMsNotActive) {	// MN is active -> wrong msg type
2527 				break;
2528 			}
2529 #if EDRV_EARLY_RX_INT == FALSE
2530 			if (NmtState >= kEplNmtCsPreOperational2) {	// respond to and process PReq frames only in PreOp2, ReadyToOp and Op
2531 				// Does PRes exist?
2532 				pTxBuffer =
2533 				    &EplDllkInstance_g.
2534 				    m_pTxBuffer[EPL_DLLK_TXFRAME_PRES];
2535 				if (pTxBuffer->m_pbBuffer != NULL) {	// PRes does exist
2536 #if (EPL_DLL_PRES_READY_AFTER_SOA != FALSE) || (EPL_DLL_PRES_READY_AFTER_SOC != FALSE)
2537 					EdrvTxMsgStart(pTxBuffer);
2538 #else
2539 					pTxFrame =
2540 					    (tEplFrame *) pTxBuffer->m_pbBuffer;
2541 					// update frame (NMT state, RD, RS, PR, MS, EN flags)
2542 					AmiSetByteToLe(&pTxFrame->m_Data.m_Pres.
2543 						       m_le_bNmtStatus,
2544 						       (BYTE) NmtState);
2545 					AmiSetByteToLe(&pTxFrame->m_Data.m_Pres.
2546 						       m_le_bFlag2,
2547 						       EplDllkInstance_g.
2548 						       m_bFlag2);
2549 					bFlag1 =
2550 					    AmiGetByteFromLe(&pFrame->m_Data.
2551 							     m_Preq.
2552 							     m_le_bFlag1);
2553 					// save EA flag
2554 					EplDllkInstance_g.m_bMnFlag1 =
2555 					    (EplDllkInstance_g.
2556 					     m_bMnFlag1 & ~EPL_FRAME_FLAG1_EA)
2557 					    | (bFlag1 & EPL_FRAME_FLAG1_EA);
2558 					// preserve MS flag
2559 					bFlag1 &= EPL_FRAME_FLAG1_MS;
2560 					// add EN flag from Error signaling module
2561 					bFlag1 |=
2562 					    EplDllkInstance_g.
2563 					    m_bFlag1 & EPL_FRAME_FLAG1_EN;
2564 					if (NmtState != kEplNmtCsOperational) {	// mark PDO as invalid in NMT state Op
2565 						// reset only RD flag
2566 						AmiSetByteToLe(&pTxFrame->
2567 							       m_Data.m_Pres.
2568 							       m_le_bFlag1,
2569 							       bFlag1);
2570 					} else {	// leave RD flag untouched
2571 						AmiSetByteToLe(&pTxFrame->
2572 							       m_Data.m_Pres.
2573 							       m_le_bFlag1,
2574 							       (AmiGetByteFromLe
2575 								(&pTxFrame->
2576 								 m_Data.m_Pres.
2577 								 m_le_bFlag1) &
2578 								EPL_FRAME_FLAG1_RD)
2579 							       | bFlag1);
2580 					}
2581 					// $$$ update EPL_DLL_PRES_READY_AFTER_* code
2582 					// send PRes frame
2583 					Ret = EdrvSendTxMsg(pTxBuffer);
2584 					if (Ret != kEplSuccessful) {
2585 						goto Exit;
2586 					}
2587 #endif
2588 				}
2589 #endif
2590 				// inform PDO module
2591 #if (((EPL_MODULE_INTEGRATION) & (EPL_MODULE_PDOK)) != 0)
2592 				if (NmtState >= kEplNmtCsReadyToOperate) {	// inform PDO module only in ReadyToOp and Op
2593 					if (NmtState != kEplNmtCsOperational) {
2594 						// reset RD flag and all other flags, but that does not matter, because they were processed above
2595 						AmiSetByteToLe(&pFrame->m_Data.
2596 							       m_Preq.
2597 							       m_le_bFlag1, 0);
2598 					}
2599 					// compares real frame size and PDO size
2600 					if ((unsigned
2601 					     int)(AmiGetWordFromLe(&pFrame->
2602 								   m_Data.
2603 								   m_Preq.
2604 								   m_le_wSize) +
2605 						  24)
2606 					    > FrameInfo.m_uiFrameSize) {	// format error
2607 						tEplErrorHandlerkEvent DllEvent;
2608 
2609 						DllEvent.m_ulDllErrorEvents =
2610 						    EPL_DLL_ERR_INVALID_FORMAT;
2611 						DllEvent.m_uiNodeId =
2612 						    AmiGetByteFromLe(&pFrame->
2613 								     m_le_bSrcNodeId);
2614 						DllEvent.m_NmtState = NmtState;
2615 						Event.m_EventSink =
2616 						    kEplEventSinkErrk;
2617 						Event.m_EventType =
2618 						    kEplEventTypeDllError;
2619 						Event.m_NetTime =
2620 						    FrameInfo.m_NetTime;
2621 						Event.m_uiSize =
2622 						    sizeof(DllEvent);
2623 						Event.m_pArg = &DllEvent;
2624 						Ret = EplEventkPost(&Event);
2625 						break;
2626 					}
2627 					// forward PReq frame as RPDO to PDO module
2628 					Ret = EplPdokCbPdoReceived(&FrameInfo);
2629 
2630 				}
2631 #if (EPL_DLL_PRES_READY_AFTER_SOC != FALSE)
2632 				if (pTxBuffer->m_pbBuffer != NULL) {	// PRes does exist
2633 					// inform PDO module about PRes after PReq
2634 					FrameInfo.m_pFrame =
2635 					    (tEplFrame *) pTxBuffer->m_pbBuffer;
2636 					FrameInfo.m_uiFrameSize =
2637 					    pTxBuffer->m_uiMaxBufferLen;
2638 					Ret =
2639 					    EplPdokCbPdoTransmitted(&FrameInfo);
2640 				}
2641 #endif
2642 #endif
2643 
2644 #if EDRV_EARLY_RX_INT == FALSE
2645 				// $$$ inform emergency protocol handling (error signaling module) about flags
2646 			}
2647 #endif
2648 
2649 			// reset cycle counter
2650 			EplDllkInstance_g.m_uiCycleCount = 0;
2651 
2652 			break;
2653 		}
2654 
2655 	case kEplMsgTypePres:
2656 		{
2657 #if (((EPL_MODULE_INTEGRATION) & (EPL_MODULE_NMT_MN)) != 0)
2658 			tEplDllkNodeInfo *pIntNodeInfo;
2659 			tEplHeartbeatEvent HeartbeatEvent;
2660 #endif
2661 
2662 			// PRes frame
2663 			NmtEvent = kEplNmtEventDllCePres;
2664 
2665 			uiNodeId = AmiGetByteFromLe(&pFrame->m_le_bSrcNodeId);
2666 
2667 			if ((NmtState >= kEplNmtCsPreOperational2)
2668 			    && (NmtState <= kEplNmtCsOperational)) {	// process PRes frames only in PreOp2, ReadyToOp and Op of CN
2669 
2670 #if (((EPL_MODULE_INTEGRATION) & (EPL_MODULE_NMT_MN)) != 0)
2671 				pIntNodeInfo = EplDllkGetNodeInfo(uiNodeId);
2672 				if (pIntNodeInfo == NULL) {	// no node info structure available
2673 					Ret = kEplDllNoNodeInfo;
2674 					goto Exit;
2675 				}
2676 			} else if (EplDllkInstance_g.m_DllState == kEplDllMsWaitPres) {	// or process PRes frames in MsWaitPres
2677 
2678 				pIntNodeInfo = EplDllkInstance_g.m_pCurNodeInfo;
2679 				if ((pIntNodeInfo == NULL) || (pIntNodeInfo->m_uiNodeId != uiNodeId)) {	// ignore PRes, because it is from wrong CN
2680 					// $$$ maybe post event to NmtMn module
2681 					goto Exit;
2682 				}
2683 				// forward Flag2 to asynchronous scheduler
2684 				bFlag1 =
2685 				    AmiGetByteFromLe(&pFrame->m_Data.m_Asnd.
2686 						     m_Payload.m_StatusResponse.
2687 						     m_le_bFlag2);
2688 				Ret =
2689 				    EplDllkCalAsyncSetPendingRequests(uiNodeId,
2690 								      ((tEplDllAsyncReqPriority) ((bFlag1 & EPL_FRAME_FLAG2_PR) >> EPL_FRAME_FLAG2_PR_SHIFT)), (bFlag1 & EPL_FRAME_FLAG2_RS));
2691 
2692 #endif
2693 			} else {	// ignore PRes, because it was received in wrong NMT state
2694 				// but execute EplDllkChangeState() and post event to NMT module
2695 				break;
2696 			}
2697 
2698 #if (((EPL_MODULE_INTEGRATION) & (EPL_MODULE_NMT_MN)) != 0)
2699 			{	// check NMT state of CN
2700 				HeartbeatEvent.m_wErrorCode = EPL_E_NO_ERROR;
2701 				HeartbeatEvent.m_NmtState =
2702 				    (tEplNmtState) (AmiGetByteFromLe
2703 						    (&pFrame->m_Data.m_Pres.
2704 						     m_le_bNmtStatus) |
2705 						    EPL_NMT_TYPE_CS);
2706 				if (pIntNodeInfo->m_NmtState != HeartbeatEvent.m_NmtState) {	// NMT state of CN has changed -> post event to NmtMnu module
2707 					if (pIntNodeInfo->m_fSoftDelete == FALSE) {	// normal isochronous CN
2708 						HeartbeatEvent.m_uiNodeId =
2709 						    uiNodeId;
2710 						Event.m_EventSink =
2711 						    kEplEventSinkNmtMnu;
2712 						Event.m_EventType =
2713 						    kEplEventTypeHeartbeat;
2714 						Event.m_uiSize =
2715 						    sizeof(HeartbeatEvent);
2716 						Event.m_pArg = &HeartbeatEvent;
2717 					} else {	// CN shall be deleted softly
2718 						Event.m_EventSink =
2719 						    kEplEventSinkDllkCal;
2720 						Event.m_EventType =
2721 						    kEplEventTypeDllkSoftDelNode;
2722 						Event.m_uiSize =
2723 						    sizeof(unsigned int);
2724 						Event.m_pArg =
2725 						    &pIntNodeInfo->m_uiNodeId;
2726 					}
2727 					Event.m_NetTime = FrameInfo.m_NetTime;
2728 					Ret = EplEventkPost(&Event);
2729 
2730 					// save current NMT state of CN in internal node structure
2731 					pIntNodeInfo->m_NmtState =
2732 					    HeartbeatEvent.m_NmtState;
2733 				}
2734 			}
2735 #endif
2736 
2737 			// inform PDO module
2738 #if (((EPL_MODULE_INTEGRATION) & (EPL_MODULE_PDOK)) != 0)
2739 			if ((NmtState != kEplNmtCsPreOperational2)
2740 			    && (NmtState != kEplNmtMsPreOperational2)) {	// inform PDO module only in ReadyToOp and Op
2741 				// compare real frame size and PDO size?
2742 				if (((unsigned
2743 				      int)(AmiGetWordFromLe(&pFrame->m_Data.
2744 							    m_Pres.m_le_wSize) +
2745 					   24)
2746 				     > FrameInfo.m_uiFrameSize)
2747 #if (((EPL_MODULE_INTEGRATION) & (EPL_MODULE_NMT_MN)) != 0)
2748 				    ||
2749 				    (AmiGetWordFromLe
2750 				     (&pFrame->m_Data.m_Pres.m_le_wSize) >
2751 				     pIntNodeInfo->m_wPresPayloadLimit)
2752 #endif
2753 				    ) {	// format error
2754 					tEplErrorHandlerkEvent DllEvent;
2755 
2756 					DllEvent.m_ulDllErrorEvents =
2757 					    EPL_DLL_ERR_INVALID_FORMAT;
2758 					DllEvent.m_uiNodeId = uiNodeId;
2759 					DllEvent.m_NmtState = NmtState;
2760 					Event.m_EventSink = kEplEventSinkErrk;
2761 					Event.m_EventType =
2762 					    kEplEventTypeDllError;
2763 					Event.m_NetTime = FrameInfo.m_NetTime;
2764 					Event.m_uiSize = sizeof(DllEvent);
2765 					Event.m_pArg = &DllEvent;
2766 					Ret = EplEventkPost(&Event);
2767 					break;
2768 				}
2769 				if ((NmtState != kEplNmtCsOperational)
2770 				    && (NmtState != kEplNmtMsOperational)) {
2771 					// reset RD flag and all other flags, but that does not matter, because they were processed above
2772 					AmiSetByteToLe(&pFrame->m_Data.m_Pres.
2773 						       m_le_bFlag1, 0);
2774 				}
2775 				Ret = EplPdokCbPdoReceived(&FrameInfo);
2776 			}
2777 #endif
2778 
2779 			break;
2780 		}
2781 
2782 	case kEplMsgTypeSoc:
2783 		{
2784 			// SoC frame
2785 			NmtEvent = kEplNmtEventDllCeSoc;
2786 
2787 			if (NmtState >= kEplNmtMsNotActive) {	// MN is active -> wrong msg type
2788 				break;
2789 			}
2790 #if EPL_DLL_PRES_READY_AFTER_SOC != FALSE
2791 			// post PRes to transmit FIFO of the ethernet controller, but don't start
2792 			// transmission over bus
2793 			pTxBuffer =
2794 			    &EplDllkInstance_g.
2795 			    m_pTxBuffer[EPL_DLLK_TXFRAME_PRES];
2796 			// Does PRes exist?
2797 			if (pTxBuffer->m_pbBuffer != NULL) {	// PRes does exist
2798 				pTxFrame = (tEplFrame *) pTxBuffer->m_pbBuffer;
2799 				// update frame (NMT state, RD, RS, PR, MS, EN flags)
2800 				if (NmtState < kEplNmtCsPreOperational2) {	// NMT state is not PreOp2, ReadyToOp or Op
2801 					// fake NMT state PreOp2, because PRes will be sent only in PreOp2 or greater
2802 					NmtState = kEplNmtCsPreOperational2;
2803 				}
2804 				AmiSetByteToLe(&pTxFrame->m_Data.m_Pres.
2805 					       m_le_bNmtStatus,
2806 					       (BYTE) NmtState);
2807 				AmiSetByteToLe(&pTxFrame->m_Data.m_Pres.
2808 					       m_le_bFlag2,
2809 					       EplDllkInstance_g.m_bFlag2);
2810 				if (NmtState != kEplNmtCsOperational) {	// mark PDO as invalid in NMT state Op
2811 					// $$$ reset only RD flag; set other flags appropriately
2812 					AmiSetByteToLe(&pTxFrame->m_Data.m_Pres.
2813 						       m_le_bFlag1, 0);
2814 				}
2815 				// $$$ make function that updates Pres, StatusRes
2816 				// mark PRes frame as ready for transmission
2817 				Ret = EdrvTxMsgReady(pTxBuffer);
2818 			}
2819 #endif
2820 
2821 			if (NmtState >= kEplNmtCsPreOperational2) {	// SoC frames only in PreOp2, ReadyToOp and Op
2822 				// trigger synchronous task
2823 				Event.m_EventSink = kEplEventSinkSync;
2824 				Event.m_EventType = kEplEventTypeSync;
2825 				Event.m_uiSize = 0;
2826 				Ret = EplEventkPost(&Event);
2827 
2828 				// update cycle counter
2829 				if (EplDllkInstance_g.m_DllConfigParam.m_uiMultiplCycleCnt > 0) {	// multiplexed cycle active
2830 					EplDllkInstance_g.m_uiCycleCount =
2831 					    (EplDllkInstance_g.m_uiCycleCount +
2832 					     1) %
2833 					    EplDllkInstance_g.m_DllConfigParam.
2834 					    m_uiMultiplCycleCnt;
2835 				}
2836 			}
2837 			// reprogram timer
2838 #if EPL_TIMER_USE_HIGHRES != FALSE
2839 			if (EplDllkInstance_g.m_ullFrameTimeout != 0) {
2840 				Ret =
2841 				    EplTimerHighReskModifyTimerNs
2842 				    (&EplDllkInstance_g.m_TimerHdlCycle,
2843 				     EplDllkInstance_g.m_ullFrameTimeout,
2844 				     EplDllkCbCnTimer, 0L, FALSE);
2845 			}
2846 #endif
2847 
2848 			break;
2849 		}
2850 
2851 	case kEplMsgTypeSoa:
2852 		{
2853 			// SoA frame
2854 			NmtEvent = kEplNmtEventDllCeSoa;
2855 
2856 			if (NmtState >= kEplNmtMsNotActive) {	// MN is active -> wrong msg type
2857 				break;
2858 			}
2859 
2860 			pTxFrame = NULL;
2861 
2862 			if ((NmtState & EPL_NMT_SUPERSTATE_MASK) != EPL_NMT_CS_EPLMODE) {	// do not respond, if NMT state is < PreOp1 (i.e. not EPL_MODE)
2863 				break;
2864 			}
2865 			// check TargetNodeId
2866 			uiNodeId =
2867 			    AmiGetByteFromLe(&pFrame->m_Data.m_Soa.
2868 					     m_le_bReqServiceTarget);
2869 			if (uiNodeId == EplDllkInstance_g.m_DllConfigParam.m_uiNodeId) {	// local node is the target of the current request
2870 
2871 				// check ServiceId
2872 				ReqServiceId =
2873 				    (tEplDllReqServiceId)
2874 				    AmiGetByteFromLe(&pFrame->m_Data.m_Soa.
2875 						     m_le_bReqServiceId);
2876 				if (ReqServiceId == kEplDllReqServiceStatus) {	// StatusRequest
2877 					if (EplDllkInstance_g.m_pTxBuffer[EPL_DLLK_TXFRAME_STATUSRES].m_pbBuffer != NULL) {	// StatusRes does exist
2878 
2879 						pTxFrame =
2880 						    (tEplFrame *)
2881 						    EplDllkInstance_g.
2882 						    m_pTxBuffer
2883 						    [EPL_DLLK_TXFRAME_STATUSRES].
2884 						    m_pbBuffer;
2885 						// update StatusRes frame (NMT state, EN, EC, RS, PR flags)
2886 						AmiSetByteToLe(&pTxFrame->
2887 							       m_Data.m_Asnd.
2888 							       m_Payload.
2889 							       m_StatusResponse.
2890 							       m_le_bNmtStatus,
2891 							       (BYTE) NmtState);
2892 						AmiSetByteToLe(&pTxFrame->
2893 							       m_Data.m_Asnd.
2894 							       m_Payload.
2895 							       m_StatusResponse.
2896 							       m_le_bFlag1,
2897 							       EplDllkInstance_g.
2898 							       m_bFlag1);
2899 						AmiSetByteToLe(&pTxFrame->
2900 							       m_Data.m_Asnd.
2901 							       m_Payload.
2902 							       m_StatusResponse.
2903 							       m_le_bFlag2,
2904 							       EplDllkInstance_g.
2905 							       m_bFlag2);
2906 						// send StatusRes
2907 						Ret =
2908 						    EdrvSendTxMsg
2909 						    (&EplDllkInstance_g.
2910 						     m_pTxBuffer
2911 						     [EPL_DLLK_TXFRAME_STATUSRES]);
2912 						if (Ret != kEplSuccessful) {
2913 							goto Exit;
2914 						}
2915 						TGT_DBG_SIGNAL_TRACE_POINT(8);
2916 
2917 						// update error signaling
2918 						bFlag1 =
2919 						    AmiGetByteFromLe(&pFrame->
2920 								     m_Data.
2921 								     m_Soa.
2922 								     m_le_bFlag1);
2923 						if (((bFlag1 ^ EplDllkInstance_g.m_bMnFlag1) & EPL_FRAME_FLAG1_ER) != 0) {	// exception reset flag was changed by MN
2924 							// assume same state for EC in next cycle (clear all other bits)
2925 							if ((bFlag1 &
2926 							     EPL_FRAME_FLAG1_ER)
2927 							    != 0) {
2928 								// set EC and reset rest
2929 								EplDllkInstance_g.
2930 								    m_bFlag1 =
2931 								    EPL_FRAME_FLAG1_EC;
2932 							} else {
2933 								// reset complete flag 1 (including EC and EN)
2934 								EplDllkInstance_g.
2935 								    m_bFlag1 =
2936 								    0;
2937 							}
2938 						}
2939 						// save flag 1 from MN for Status request response cycle
2940 						EplDllkInstance_g.m_bMnFlag1 =
2941 						    bFlag1;
2942 					}
2943 				} else if (ReqServiceId == kEplDllReqServiceIdent) {	// IdentRequest
2944 					if (EplDllkInstance_g.m_pTxBuffer[EPL_DLLK_TXFRAME_IDENTRES].m_pbBuffer != NULL) {	// IdentRes does exist
2945 						pTxFrame =
2946 						    (tEplFrame *)
2947 						    EplDllkInstance_g.
2948 						    m_pTxBuffer
2949 						    [EPL_DLLK_TXFRAME_IDENTRES].
2950 						    m_pbBuffer;
2951 						// update IdentRes frame (NMT state, RS, PR flags)
2952 						AmiSetByteToLe(&pTxFrame->
2953 							       m_Data.m_Asnd.
2954 							       m_Payload.
2955 							       m_IdentResponse.
2956 							       m_le_bNmtStatus,
2957 							       (BYTE) NmtState);
2958 						AmiSetByteToLe(&pTxFrame->
2959 							       m_Data.m_Asnd.
2960 							       m_Payload.
2961 							       m_IdentResponse.
2962 							       m_le_bFlag2,
2963 							       EplDllkInstance_g.
2964 							       m_bFlag2);
2965 						// send IdentRes
2966 						Ret =
2967 						    EdrvSendTxMsg
2968 						    (&EplDllkInstance_g.
2969 						     m_pTxBuffer
2970 						     [EPL_DLLK_TXFRAME_IDENTRES]);
2971 						if (Ret != kEplSuccessful) {
2972 							goto Exit;
2973 						}
2974 						TGT_DBG_SIGNAL_TRACE_POINT(7);
2975 					}
2976 				} else if (ReqServiceId == kEplDllReqServiceNmtRequest) {	// NmtRequest
2977 					if (EplDllkInstance_g.m_pTxBuffer[EPL_DLLK_TXFRAME_NMTREQ].m_pbBuffer != NULL) {	// NmtRequest does exist
2978 						// check if frame is not empty and not being filled
2979 						if (EplDllkInstance_g.
2980 						    m_pTxBuffer
2981 						    [EPL_DLLK_TXFRAME_NMTREQ].
2982 						    m_uiTxMsgLen >
2983 						    EPL_DLLK_BUFLEN_FILLING) {
2984 							/*if (EplDllkInstance_g.m_pTxBuffer[EPL_DLLK_TXFRAME_NMTREQ].m_uiTxMsgLen < EPL_DLLK_BUFLEN_MIN)
2985 							   {   // pad frame
2986 							   EplDllkInstance_g.m_pTxBuffer[EPL_DLLK_TXFRAME_NMTREQ].m_uiTxMsgLen = EPL_DLLK_BUFLEN_MIN;
2987 							   } */
2988 							// memorize transmission
2989 							pTxFrame =
2990 							    (tEplFrame *) 1;
2991 							// send NmtRequest
2992 							Ret =
2993 							    EdrvSendTxMsg
2994 							    (&EplDllkInstance_g.
2995 							     m_pTxBuffer
2996 							     [EPL_DLLK_TXFRAME_NMTREQ]);
2997 							if (Ret !=
2998 							    kEplSuccessful) {
2999 								goto Exit;
3000 							}
3001 
3002 						}
3003 					}
3004 
3005 				} else if (ReqServiceId == kEplDllReqServiceUnspecified) {	// unspecified invite
3006 					if (EplDllkInstance_g.m_pTxBuffer[EPL_DLLK_TXFRAME_NONEPL].m_pbBuffer != NULL) {	// non-EPL frame does exist
3007 						// check if frame is not empty and not being filled
3008 						if (EplDllkInstance_g.
3009 						    m_pTxBuffer
3010 						    [EPL_DLLK_TXFRAME_NONEPL].
3011 						    m_uiTxMsgLen >
3012 						    EPL_DLLK_BUFLEN_FILLING) {
3013 							/*if (EplDllkInstance_g.m_pTxBuffer[EPL_DLLK_TXFRAME_NMTREQ].m_uiTxMsgLen < EPL_DLLK_BUFLEN_MIN)
3014 							   {   // pad frame
3015 							   EplDllkInstance_g.m_pTxBuffer[EPL_DLLK_TXFRAME_NMTREQ].m_uiTxMsgLen = EPL_DLLK_BUFLEN_MIN;
3016 							   } */
3017 							// memorize transmission
3018 							pTxFrame =
3019 							    (tEplFrame *) 1;
3020 							// send non-EPL frame
3021 							Ret =
3022 							    EdrvSendTxMsg
3023 							    (&EplDllkInstance_g.
3024 							     m_pTxBuffer
3025 							     [EPL_DLLK_TXFRAME_NONEPL]);
3026 							if (Ret !=
3027 							    kEplSuccessful) {
3028 								goto Exit;
3029 							}
3030 
3031 						}
3032 					}
3033 
3034 				} else if (ReqServiceId == kEplDllReqServiceNo) {	// no async service requested -> do nothing
3035 				}
3036 			}
3037 #if EPL_DLL_PRES_READY_AFTER_SOA != FALSE
3038 			if (pTxFrame == NULL) {	// signal process function readiness of PRes frame
3039 				Event.m_EventSink = kEplEventSinkDllk;
3040 				Event.m_EventType = kEplEventTypeDllkPresReady;
3041 				Event.m_uiSize = 0;
3042 				Event.m_pArg = NULL;
3043 				Ret = EplEventkPost(&Event);
3044 			}
3045 #endif
3046 
3047 			// inform PDO module
3048 #if (((EPL_MODULE_INTEGRATION) & (EPL_MODULE_PDOK)) != 0)
3049 //            Ret = EplPdokCbSoa(&FrameInfo);
3050 #endif
3051 
3052 			// $$$ put SrcNodeId, NMT state and NetTime as HeartbeatEvent into eventqueue
3053 
3054 			// $$$ inform emergency protocol handling about flags
3055 			break;
3056 		}
3057 
3058 	case kEplMsgTypeAsnd:
3059 		{
3060 			// ASnd frame
3061 			NmtEvent = kEplNmtEventDllCeAsnd;
3062 
3063 			// ASnd service registered?
3064 			uiAsndServiceId =
3065 			    (unsigned int)AmiGetByteFromLe(&pFrame->m_Data.
3066 							   m_Asnd.
3067 							   m_le_bServiceId);
3068 
3069 #if (((EPL_MODULE_INTEGRATION) & (EPL_MODULE_NMT_MN)) != 0)
3070 			if ((EplDllkInstance_g.m_DllState >= kEplDllMsNonCyclic)
3071 			    &&
3072 			    ((((tEplDllAsndServiceId) uiAsndServiceId) ==
3073 			      kEplDllAsndStatusResponse)
3074 			     || (((tEplDllAsndServiceId) uiAsndServiceId) == kEplDllAsndIdentResponse))) {	// StatusRes or IdentRes received
3075 				uiNodeId =
3076 				    AmiGetByteFromLe(&pFrame->m_le_bSrcNodeId);
3077 				if ((EplDllkInstance_g.m_LastReqServiceId ==
3078 				     ((tEplDllReqServiceId) uiAsndServiceId))
3079 				    && (uiNodeId == EplDllkInstance_g.m_uiLastTargetNodeId)) {	// mark request as responded
3080 					EplDllkInstance_g.m_LastReqServiceId =
3081 					    kEplDllReqServiceNo;
3082 				}
3083 				if (((tEplDllAsndServiceId) uiAsndServiceId) == kEplDllAsndIdentResponse) {	// memorize MAC address of CN for PReq
3084 					tEplDllkNodeInfo *pIntNodeInfo;
3085 
3086 					pIntNodeInfo =
3087 					    EplDllkGetNodeInfo(uiNodeId);
3088 					if (pIntNodeInfo == NULL) {	// no node info structure available
3089 						Ret = kEplDllNoNodeInfo;
3090 					} else {
3091 						EPL_MEMCPY(pIntNodeInfo->
3092 							   m_be_abMacAddr,
3093 							   pFrame->
3094 							   m_be_abSrcMac, 6);
3095 					}
3096 				}
3097 				// forward Flag2 to asynchronous scheduler
3098 				bFlag1 =
3099 				    AmiGetByteFromLe(&pFrame->m_Data.m_Asnd.
3100 						     m_Payload.m_StatusResponse.
3101 						     m_le_bFlag2);
3102 				Ret =
3103 				    EplDllkCalAsyncSetPendingRequests(uiNodeId,
3104 								      ((tEplDllAsyncReqPriority) ((bFlag1 & EPL_FRAME_FLAG2_PR) >> EPL_FRAME_FLAG2_PR_SHIFT)), (bFlag1 & EPL_FRAME_FLAG2_RS));
3105 			}
3106 #endif
3107 
3108 			if (uiAsndServiceId < EPL_DLL_MAX_ASND_SERVICE_ID) {	// ASnd service ID is valid
3109 				if (EplDllkInstance_g.m_aAsndFilter[uiAsndServiceId] == kEplDllAsndFilterAny) {	// ASnd service ID is registered
3110 					// forward frame via async receive FIFO to userspace
3111 					Ret =
3112 					    EplDllkCalAsyncFrameReceived
3113 					    (&FrameInfo);
3114 				} else if (EplDllkInstance_g.m_aAsndFilter[uiAsndServiceId] == kEplDllAsndFilterLocal) {	// ASnd service ID is registered, but only local node ID or broadcasts
3115 					// shall be forwarded
3116 					uiNodeId =
3117 					    AmiGetByteFromLe(&pFrame->
3118 							     m_le_bDstNodeId);
3119 					if ((uiNodeId ==
3120 					     EplDllkInstance_g.m_DllConfigParam.
3121 					     m_uiNodeId)
3122 					    || (uiNodeId == EPL_C_ADR_BROADCAST)) {	// ASnd frame is intended for us
3123 						// forward frame via async receive FIFO to userspace
3124 						Ret =
3125 						    EplDllkCalAsyncFrameReceived
3126 						    (&FrameInfo);
3127 					}
3128 				}
3129 			}
3130 			break;
3131 		}
3132 
3133 	default:
3134 		{
3135 			break;
3136 		}
3137 	}
3138 
3139 	if (NmtEvent != kEplNmtEventNoEvent) {	// event for DLL and NMT state machine generated
3140 		Ret = EplDllkChangeState(NmtEvent, NmtState);
3141 		if (Ret != kEplSuccessful) {
3142 			goto Exit;
3143 		}
3144 
3145 		if ((NmtEvent != kEplNmtEventDllCeAsnd)
3146 		    && ((NmtState <= kEplNmtCsPreOperational1) || (NmtEvent != kEplNmtEventDllCePres))) {	// NMT state machine is not interested in ASnd frames and PRes frames when not CsNotActive or CsPreOp1
3147 			// inform NMT module
3148 			Event.m_EventSink = kEplEventSinkNmtk;
3149 			Event.m_EventType = kEplEventTypeNmtEvent;
3150 			Event.m_uiSize = sizeof(NmtEvent);
3151 			Event.m_pArg = &NmtEvent;
3152 			Ret = EplEventkPost(&Event);
3153 		}
3154 	}
3155 
3156       Exit:
3157 	if (Ret != kEplSuccessful) {
3158 		DWORD dwArg;
3159 
3160 		BENCHMARK_MOD_02_TOGGLE(9);
3161 
3162 		dwArg = EplDllkInstance_g.m_DllState | (NmtEvent << 8);
3163 
3164 		// Error event for API layer
3165 		Ret = EplEventkPostError(kEplEventSourceDllk,
3166 					 Ret, sizeof(dwArg), &dwArg);
3167 	}
3168 	BENCHMARK_MOD_02_RESET(3);
3169 	return;
3170 }
3171 
3172 //---------------------------------------------------------------------------
3173 //
3174 // Function:    EplDllkCbFrameTransmitted()
3175 //
3176 // Description: called from EdrvInterruptHandler().
3177 //              It signals
3178 //
3179 // Parameters:  pRxBuffer_p             = receive buffer structure
3180 //
3181 // Returns:     (none)
3182 //
3183 //
3184 // State:
3185 //
3186 //---------------------------------------------------------------------------
3187 
EplDllkCbFrameTransmitted(tEdrvTxBuffer * pTxBuffer_p)3188 static void EplDllkCbFrameTransmitted(tEdrvTxBuffer * pTxBuffer_p)
3189 {
3190 	tEplKernel Ret = kEplSuccessful;
3191 	tEplEvent Event;
3192 	tEplDllAsyncReqPriority Priority;
3193 	tEplNmtState NmtState;
3194 
3195 #if (((EPL_MODULE_INTEGRATION) & (EPL_MODULE_PDOK)) != 0) \
3196     && (EPL_DLL_PRES_READY_AFTER_SOC == FALSE)
3197 	tEplFrameInfo FrameInfo;
3198 #endif
3199 
3200 	NmtState = EplNmtkGetNmtState();
3201 
3202 	if (NmtState <= kEplNmtGsResetConfiguration) {
3203 		goto Exit;
3204 	}
3205 
3206 	if ((pTxBuffer_p - EplDllkInstance_g.m_pTxBuffer) == EPL_DLLK_TXFRAME_NMTREQ) {	// frame from NMT request FIFO sent
3207 		// mark Tx-buffer as empty
3208 		pTxBuffer_p->m_uiTxMsgLen = EPL_DLLK_BUFLEN_EMPTY;
3209 
3210 		// post event to DLL
3211 		Priority = kEplDllAsyncReqPrioNmt;
3212 		Event.m_EventSink = kEplEventSinkDllk;
3213 		Event.m_EventType = kEplEventTypeDllkFillTx;
3214 		EPL_MEMSET(&Event.m_NetTime, 0x00, sizeof(Event.m_NetTime));
3215 		Event.m_pArg = &Priority;
3216 		Event.m_uiSize = sizeof(Priority);
3217 		Ret = EplEventkPost(&Event);
3218 	} else if ((pTxBuffer_p - EplDllkInstance_g.m_pTxBuffer) == EPL_DLLK_TXFRAME_NONEPL) {	// frame from generic priority FIFO sent
3219 		// mark Tx-buffer as empty
3220 		pTxBuffer_p->m_uiTxMsgLen = EPL_DLLK_BUFLEN_EMPTY;
3221 
3222 		// post event to DLL
3223 		Priority = kEplDllAsyncReqPrioGeneric;
3224 		Event.m_EventSink = kEplEventSinkDllk;
3225 		Event.m_EventType = kEplEventTypeDllkFillTx;
3226 		EPL_MEMSET(&Event.m_NetTime, 0x00, sizeof(Event.m_NetTime));
3227 		Event.m_pArg = &Priority;
3228 		Event.m_uiSize = sizeof(Priority);
3229 		Ret = EplEventkPost(&Event);
3230 	}
3231 #if ((((EPL_MODULE_INTEGRATION) & (EPL_MODULE_PDOK)) != 0) \
3232     && (EPL_DLL_PRES_READY_AFTER_SOC == FALSE)) \
3233     || (((EPL_MODULE_INTEGRATION) & (EPL_MODULE_NMT_MN)) != 0)
3234 	else if ((pTxBuffer_p->m_EplMsgType == kEplMsgTypePreq)
3235 		 || (pTxBuffer_p->m_EplMsgType == kEplMsgTypePres)) {	// PRes resp. PReq frame sent
3236 
3237 #if ((((EPL_MODULE_INTEGRATION) & (EPL_MODULE_PDOK)) != 0) \
3238             && (EPL_DLL_PRES_READY_AFTER_SOC == FALSE))
3239 		{
3240 			// inform PDO module
3241 			FrameInfo.m_pFrame =
3242 			    (tEplFrame *) pTxBuffer_p->m_pbBuffer;
3243 			FrameInfo.m_uiFrameSize = pTxBuffer_p->m_uiMaxBufferLen;
3244 			Ret = EplPdokCbPdoTransmitted(&FrameInfo);
3245 		}
3246 #endif
3247 
3248 #if (((EPL_MODULE_INTEGRATION) & (EPL_MODULE_NMT_MN)) != 0)
3249 		{
3250 			// if own Pres on MN, trigger SoA
3251 			if ((NmtState >= kEplNmtMsPreOperational2)
3252 			    && (pTxBuffer_p ==
3253 				&EplDllkInstance_g.
3254 				m_pTxBuffer[EPL_DLLK_TXFRAME_PRES])) {
3255 				Ret =
3256 				    EplDllkChangeState(kEplNmtEventDllMeSoaTrig,
3257 						       NmtState);
3258 			}
3259 		}
3260 #endif
3261 
3262 #if EPL_DLL_PRES_READY_AFTER_SOA != FALSE
3263 		goto Exit;
3264 #endif
3265 	}
3266 #endif
3267 #if (((EPL_MODULE_INTEGRATION) & (EPL_MODULE_NMT_MN)) != 0)
3268 	else if (pTxBuffer_p->m_EplMsgType == kEplMsgTypeSoa) {	// SoA frame sent
3269 		tEplNmtEvent NmtEvent = kEplNmtEventDllMeSoaSent;
3270 
3271 		// check if we are invited
3272 		if (EplDllkInstance_g.m_uiLastTargetNodeId ==
3273 		    EplDllkInstance_g.m_DllConfigParam.m_uiNodeId) {
3274 			tEplFrame *pTxFrame;
3275 
3276 			if (EplDllkInstance_g.m_LastReqServiceId == kEplDllReqServiceStatus) {	// StatusRequest
3277 				if (EplDllkInstance_g.m_pTxBuffer[EPL_DLLK_TXFRAME_STATUSRES].m_pbBuffer != NULL) {	// StatusRes does exist
3278 
3279 					pTxFrame =
3280 					    (tEplFrame *) EplDllkInstance_g.
3281 					    m_pTxBuffer
3282 					    [EPL_DLLK_TXFRAME_STATUSRES].
3283 					    m_pbBuffer;
3284 					// update StatusRes frame (NMT state, EN, EC, RS, PR flags)
3285 					AmiSetByteToLe(&pTxFrame->m_Data.m_Asnd.
3286 						       m_Payload.
3287 						       m_StatusResponse.
3288 						       m_le_bNmtStatus,
3289 						       (BYTE) NmtState);
3290 					AmiSetByteToLe(&pTxFrame->m_Data.m_Asnd.
3291 						       m_Payload.
3292 						       m_StatusResponse.
3293 						       m_le_bFlag1,
3294 						       EplDllkInstance_g.
3295 						       m_bFlag1);
3296 					AmiSetByteToLe(&pTxFrame->m_Data.m_Asnd.
3297 						       m_Payload.
3298 						       m_StatusResponse.
3299 						       m_le_bFlag2,
3300 						       EplDllkInstance_g.
3301 						       m_bFlag2);
3302 					// send StatusRes
3303 					Ret =
3304 					    EdrvSendTxMsg(&EplDllkInstance_g.
3305 							  m_pTxBuffer
3306 							  [EPL_DLLK_TXFRAME_STATUSRES]);
3307 					if (Ret != kEplSuccessful) {
3308 						goto Exit;
3309 					}
3310 					TGT_DBG_SIGNAL_TRACE_POINT(8);
3311 
3312 				}
3313 			} else if (EplDllkInstance_g.m_LastReqServiceId == kEplDllReqServiceIdent) {	// IdentRequest
3314 				if (EplDllkInstance_g.m_pTxBuffer[EPL_DLLK_TXFRAME_IDENTRES].m_pbBuffer != NULL) {	// IdentRes does exist
3315 					pTxFrame =
3316 					    (tEplFrame *) EplDllkInstance_g.
3317 					    m_pTxBuffer
3318 					    [EPL_DLLK_TXFRAME_IDENTRES].
3319 					    m_pbBuffer;
3320 					// update IdentRes frame (NMT state, RS, PR flags)
3321 					AmiSetByteToLe(&pTxFrame->m_Data.m_Asnd.
3322 						       m_Payload.
3323 						       m_IdentResponse.
3324 						       m_le_bNmtStatus,
3325 						       (BYTE) NmtState);
3326 					AmiSetByteToLe(&pTxFrame->m_Data.m_Asnd.
3327 						       m_Payload.
3328 						       m_IdentResponse.
3329 						       m_le_bFlag2,
3330 						       EplDllkInstance_g.
3331 						       m_bFlag2);
3332 					// send IdentRes
3333 					Ret =
3334 					    EdrvSendTxMsg(&EplDllkInstance_g.
3335 							  m_pTxBuffer
3336 							  [EPL_DLLK_TXFRAME_IDENTRES]);
3337 					if (Ret != kEplSuccessful) {
3338 						goto Exit;
3339 					}
3340 					TGT_DBG_SIGNAL_TRACE_POINT(7);
3341 				}
3342 			} else if (EplDllkInstance_g.m_LastReqServiceId == kEplDllReqServiceNmtRequest) {	// NmtRequest
3343 				if (EplDllkInstance_g.m_pTxBuffer[EPL_DLLK_TXFRAME_NMTREQ].m_pbBuffer != NULL) {	// NmtRequest does exist
3344 					// check if frame is not empty and not being filled
3345 					if (EplDllkInstance_g.
3346 					    m_pTxBuffer
3347 					    [EPL_DLLK_TXFRAME_NMTREQ].
3348 					    m_uiTxMsgLen >
3349 					    EPL_DLLK_BUFLEN_FILLING) {
3350 						// check if this frame is a NMT command,
3351 						// then forward this frame back to NmtMnu module,
3352 						// because it needs the time, when this frame is
3353 						// actually sent, to start the timer for monitoring
3354 						// the NMT state change.
3355 
3356 						pTxFrame =
3357 						    (tEplFrame *)
3358 						    EplDllkInstance_g.
3359 						    m_pTxBuffer
3360 						    [EPL_DLLK_TXFRAME_NMTREQ].
3361 						    m_pbBuffer;
3362 						if ((AmiGetByteFromLe
3363 						     (&pTxFrame->
3364 						      m_le_bMessageType)
3365 						     == (BYTE) kEplMsgTypeAsnd)
3366 						    &&
3367 						    (AmiGetByteFromLe
3368 						     (&pTxFrame->m_Data.m_Asnd.
3369 						      m_le_bServiceId)
3370 						     == (BYTE) kEplDllAsndNmtCommand)) {	// post event directly to NmtMnu module
3371 							Event.m_EventSink =
3372 							    kEplEventSinkNmtMnu;
3373 							Event.m_EventType =
3374 							    kEplEventTypeNmtMnuNmtCmdSent;
3375 							Event.m_uiSize =
3376 							    EplDllkInstance_g.
3377 							    m_pTxBuffer
3378 							    [EPL_DLLK_TXFRAME_NMTREQ].
3379 							    m_uiTxMsgLen;
3380 							Event.m_pArg = pTxFrame;
3381 							Ret =
3382 							    EplEventkPost
3383 							    (&Event);
3384 
3385 						}
3386 						// send NmtRequest
3387 						Ret =
3388 						    EdrvSendTxMsg
3389 						    (&EplDllkInstance_g.
3390 						     m_pTxBuffer
3391 						     [EPL_DLLK_TXFRAME_NMTREQ]);
3392 						if (Ret != kEplSuccessful) {
3393 							goto Exit;
3394 						}
3395 
3396 					}
3397 				}
3398 
3399 			} else if (EplDllkInstance_g.m_LastReqServiceId == kEplDllReqServiceUnspecified) {	// unspecified invite
3400 				if (EplDllkInstance_g.m_pTxBuffer[EPL_DLLK_TXFRAME_NONEPL].m_pbBuffer != NULL) {	// non-EPL frame does exist
3401 					// check if frame is not empty and not being filled
3402 					if (EplDllkInstance_g.
3403 					    m_pTxBuffer
3404 					    [EPL_DLLK_TXFRAME_NONEPL].
3405 					    m_uiTxMsgLen >
3406 					    EPL_DLLK_BUFLEN_FILLING) {
3407 						// send non-EPL frame
3408 						Ret =
3409 						    EdrvSendTxMsg
3410 						    (&EplDllkInstance_g.
3411 						     m_pTxBuffer
3412 						     [EPL_DLLK_TXFRAME_NONEPL]);
3413 						if (Ret != kEplSuccessful) {
3414 							goto Exit;
3415 						}
3416 
3417 					}
3418 				}
3419 			}
3420 			// ASnd frame was sent, remove the request
3421 			EplDllkInstance_g.m_LastReqServiceId =
3422 			    kEplDllReqServiceNo;
3423 		}
3424 		// forward event to ErrorHandler and PDO module
3425 		Event.m_EventSink = kEplEventSinkNmtk;
3426 		Event.m_EventType = kEplEventTypeNmtEvent;
3427 		Event.m_uiSize = sizeof(NmtEvent);
3428 		Event.m_pArg = &NmtEvent;
3429 		Ret = EplEventkPost(&Event);
3430 		if (Ret != kEplSuccessful) {
3431 			goto Exit;
3432 		}
3433 	}
3434 #endif
3435 
3436 #if EPL_DLL_PRES_READY_AFTER_SOA != FALSE
3437 	else {			// d.k.: Why that else? on CN it is entered on IdentRes and StatusRes
3438 		goto Exit;
3439 	}
3440 
3441 	// signal process function readiness of PRes frame
3442 	Event.m_EventSink = kEplEventSinkDllk;
3443 	Event.m_EventType = kEplEventTypeDllkPresReady;
3444 	Event.m_uiSize = 0;
3445 	Event.m_pArg = NULL;
3446 	Ret = EplEventkPost(&Event);
3447 
3448 #endif
3449 
3450       Exit:
3451 	if (Ret != kEplSuccessful) {
3452 		DWORD dwArg;
3453 
3454 		BENCHMARK_MOD_02_TOGGLE(9);
3455 
3456 		dwArg =
3457 		    EplDllkInstance_g.m_DllState | (pTxBuffer_p->
3458 						    m_EplMsgType << 16);
3459 
3460 		// Error event for API layer
3461 		Ret = EplEventkPostError(kEplEventSourceDllk,
3462 					 Ret, sizeof(dwArg), &dwArg);
3463 	}
3464 
3465 	return;
3466 }
3467 
3468 //---------------------------------------------------------------------------
3469 //
3470 // Function:    EplDllkCheckFrame()
3471 //
3472 // Description: check frame and set missing information
3473 //
3474 // Parameters:  pFrame_p                = ethernet frame
3475 //              uiFrameSize_p           = size of frame
3476 //
3477 // Returns:     tEplKernel              = error code
3478 //
3479 //
3480 // State:
3481 //
3482 //---------------------------------------------------------------------------
3483 
EplDllkCheckFrame(tEplFrame * pFrame_p,unsigned int uiFrameSize_p)3484 static tEplKernel EplDllkCheckFrame(tEplFrame * pFrame_p,
3485 				    unsigned int uiFrameSize_p)
3486 {
3487 	tEplMsgType MsgType;
3488 	WORD wEtherType;
3489 
3490 	// check frame
3491 	if (pFrame_p != NULL) {
3492 		// check SrcMAC
3493 		if (AmiGetQword48FromBe(pFrame_p->m_be_abSrcMac) == 0) {
3494 			// source MAC address
3495 			EPL_MEMCPY(&pFrame_p->m_be_abSrcMac[0],
3496 				   &EplDllkInstance_g.m_be_abSrcMac[0], 6);
3497 		}
3498 		// check ethertype
3499 		wEtherType = AmiGetWordFromBe(&pFrame_p->m_be_wEtherType);
3500 		if (wEtherType == 0) {
3501 			// assume EPL frame
3502 			wEtherType = EPL_C_DLL_ETHERTYPE_EPL;
3503 			AmiSetWordToBe(&pFrame_p->m_be_wEtherType, wEtherType);
3504 		}
3505 
3506 		if (wEtherType == EPL_C_DLL_ETHERTYPE_EPL) {
3507 			// source node ID
3508 			AmiSetByteToLe(&pFrame_p->m_le_bSrcNodeId,
3509 				       (BYTE) EplDllkInstance_g.
3510 				       m_DllConfigParam.m_uiNodeId);
3511 
3512 			// check message type
3513 			MsgType =
3514 			    AmiGetByteFromLe(&pFrame_p->m_le_bMessageType);
3515 			if (MsgType == 0) {
3516 				MsgType = kEplMsgTypeAsnd;
3517 				AmiSetByteToLe(&pFrame_p->m_le_bMessageType,
3518 					       (BYTE) MsgType);
3519 			}
3520 
3521 			if (MsgType == kEplMsgTypeAsnd) {
3522 				// destination MAC address
3523 				AmiSetQword48ToBe(&pFrame_p->m_be_abDstMac[0],
3524 						  EPL_C_DLL_MULTICAST_ASND);
3525 			}
3526 
3527 		}
3528 	}
3529 
3530 	return kEplSuccessful;
3531 }
3532 
3533 //---------------------------------------------------------------------------
3534 //
3535 // Function:    EplDllkCbCnTimer()
3536 //
3537 // Description: called by timer module. It monitors the EPL cycle when it is a CN.
3538 //
3539 // Parameters:  pEventArg_p             = timer event argument
3540 //
3541 // Returns:     tEplKernel              = error code
3542 //
3543 //
3544 // State:
3545 //
3546 //---------------------------------------------------------------------------
3547 
3548 #if EPL_TIMER_USE_HIGHRES != FALSE
EplDllkCbCnTimer(tEplTimerEventArg * pEventArg_p)3549 static tEplKernel PUBLIC EplDllkCbCnTimer(tEplTimerEventArg * pEventArg_p)
3550 {
3551 	tEplKernel Ret = kEplSuccessful;
3552 	tEplNmtState NmtState;
3553 
3554 #if EPL_TIMER_USE_HIGHRES != FALSE
3555 	if (pEventArg_p->m_TimerHdl != EplDllkInstance_g.m_TimerHdlCycle) {	// zombie callback
3556 		// just exit
3557 		goto Exit;
3558 	}
3559 #endif
3560 
3561 	NmtState = EplNmtkGetNmtState();
3562 
3563 	if (NmtState <= kEplNmtGsResetConfiguration) {
3564 		goto Exit;
3565 	}
3566 
3567 	Ret = EplDllkChangeState(kEplNmtEventDllCeFrameTimeout, NmtState);
3568 	if (Ret != kEplSuccessful) {
3569 		goto Exit;
3570 	}
3571 	// 2008/10/15 d.k. reprogramming of timer not necessary,
3572 	// because it will be programmed, when SoC is received.
3573 /*
3574     // reprogram timer
3575 #if EPL_TIMER_USE_HIGHRES != FALSE
3576     if ((NmtState > kEplNmtCsPreOperational1)
3577         && (EplDllkInstance_g.m_ullFrameTimeout != 0))
3578     {
3579         Ret = EplTimerHighReskModifyTimerNs(&EplDllkInstance_g.m_TimerHdlCycle, EplDllkInstance_g.m_ullFrameTimeout, EplDllkCbCnTimer, 0L, FALSE);
3580     }
3581 #endif
3582 */
3583 
3584       Exit:
3585 	if (Ret != kEplSuccessful) {
3586 		DWORD dwArg;
3587 
3588 		BENCHMARK_MOD_02_TOGGLE(9);
3589 
3590 		dwArg =
3591 		    EplDllkInstance_g.
3592 		    m_DllState | (kEplNmtEventDllCeFrameTimeout << 8);
3593 
3594 		// Error event for API layer
3595 		Ret = EplEventkPostError(kEplEventSourceDllk,
3596 					 Ret, sizeof(dwArg), &dwArg);
3597 	}
3598 
3599 	return Ret;
3600 }
3601 #endif
3602 
3603 #if (((EPL_MODULE_INTEGRATION) & (EPL_MODULE_NMT_MN)) != 0)
3604 
3605 //---------------------------------------------------------------------------
3606 //
3607 // Function:    EplDllkCbMnTimerCycle()
3608 //
3609 // Description: called by timer module. It triggers the SoC when it is a MN.
3610 //
3611 // Parameters:  pEventArg_p             = timer event argument
3612 //
3613 // Returns:     tEplKernel              = error code
3614 //
3615 //
3616 // State:
3617 //
3618 //---------------------------------------------------------------------------
3619 
EplDllkCbMnTimerCycle(tEplTimerEventArg * pEventArg_p)3620 static tEplKernel PUBLIC EplDllkCbMnTimerCycle(tEplTimerEventArg * pEventArg_p)
3621 {
3622 	tEplKernel Ret = kEplSuccessful;
3623 	tEplNmtState NmtState;
3624 
3625 #if EPL_TIMER_USE_HIGHRES != FALSE
3626 	if (pEventArg_p->m_TimerHdl != EplDllkInstance_g.m_TimerHdlCycle) {	// zombie callback
3627 		// just exit
3628 		goto Exit;
3629 	}
3630 #endif
3631 
3632 	NmtState = EplNmtkGetNmtState();
3633 
3634 	if (NmtState <= kEplNmtGsResetConfiguration) {
3635 		goto Exit;
3636 	}
3637 
3638 	Ret = EplDllkChangeState(kEplNmtEventDllMeSocTrig, NmtState);
3639 
3640       Exit:
3641 	if (Ret != kEplSuccessful) {
3642 		DWORD dwArg;
3643 
3644 		BENCHMARK_MOD_02_TOGGLE(9);
3645 
3646 		dwArg =
3647 		    EplDllkInstance_g.
3648 		    m_DllState | (kEplNmtEventDllMeSocTrig << 8);
3649 
3650 		// Error event for API layer
3651 		Ret = EplEventkPostError(kEplEventSourceDllk,
3652 					 Ret, sizeof(dwArg), &dwArg);
3653 	}
3654 
3655 	return Ret;
3656 }
3657 
3658 //---------------------------------------------------------------------------
3659 //
3660 // Function:    EplDllkCbMnTimerResponse()
3661 //
3662 // Description: called by timer module. It monitors the PRes timeout.
3663 //
3664 // Parameters:  pEventArg_p             = timer event argument
3665 //
3666 // Returns:     tEplKernel              = error code
3667 //
3668 //
3669 // State:
3670 //
3671 //---------------------------------------------------------------------------
3672 
EplDllkCbMnTimerResponse(tEplTimerEventArg * pEventArg_p)3673 static tEplKernel PUBLIC EplDllkCbMnTimerResponse(tEplTimerEventArg *
3674 						  pEventArg_p)
3675 {
3676 	tEplKernel Ret = kEplSuccessful;
3677 	tEplNmtState NmtState;
3678 
3679 #if EPL_TIMER_USE_HIGHRES != FALSE
3680 	if (pEventArg_p->m_TimerHdl != EplDllkInstance_g.m_TimerHdlResponse) {	// zombie callback
3681 		// just exit
3682 		goto Exit;
3683 	}
3684 #endif
3685 
3686 	NmtState = EplNmtkGetNmtState();
3687 
3688 	if (NmtState <= kEplNmtGsResetConfiguration) {
3689 		goto Exit;
3690 	}
3691 
3692 	Ret = EplDllkChangeState(kEplNmtEventDllMePresTimeout, NmtState);
3693 
3694       Exit:
3695 	if (Ret != kEplSuccessful) {
3696 		DWORD dwArg;
3697 
3698 		BENCHMARK_MOD_02_TOGGLE(9);
3699 
3700 		dwArg =
3701 		    EplDllkInstance_g.
3702 		    m_DllState | (kEplNmtEventDllMePresTimeout << 8);
3703 
3704 		// Error event for API layer
3705 		Ret = EplEventkPostError(kEplEventSourceDllk,
3706 					 Ret, sizeof(dwArg), &dwArg);
3707 	}
3708 
3709 	return Ret;
3710 }
3711 
3712 //---------------------------------------------------------------------------
3713 //
3714 // Function:    EplDllkGetNodeInfo()
3715 //
3716 // Description: returns node info structure of the specified node.
3717 //
3718 // Parameters:  uiNodeId_p              = node ID
3719 //
3720 // Returns:     tEplDllkNodeInfo*       = pointer to internal node info structure
3721 //
3722 //
3723 // State:
3724 //
3725 //---------------------------------------------------------------------------
3726 
EplDllkGetNodeInfo(unsigned int uiNodeId_p)3727 static tEplDllkNodeInfo *EplDllkGetNodeInfo(unsigned int uiNodeId_p)
3728 {
3729 	// $$$ d.k.: use hash algorithm to retrieve the appropriate node info structure
3730 	//           if size of array is less than 254.
3731 	uiNodeId_p--;		// node ID starts at 1 but array at 0
3732 	if (uiNodeId_p >= tabentries(EplDllkInstance_g.m_aNodeInfo)) {
3733 		return NULL;
3734 	} else {
3735 		return &EplDllkInstance_g.m_aNodeInfo[uiNodeId_p];
3736 	}
3737 }
3738 
3739 //---------------------------------------------------------------------------
3740 //
3741 // Function:    EplDllkMnSendSoa()
3742 //
3743 // Description: it updates and transmits the SoA.
3744 //
3745 // Parameters:  NmtState_p              = current NMT state
3746 //              pDllStateProposed_p     = proposed DLL state
3747 //              fEnableInvitation_p     = enable invitation for asynchronous phase
3748 //                                        it will be disabled for EPL_C_DLL_PREOP1_START_CYCLES SoAs
3749 //
3750 // Returns:     tEplKernel              = error code
3751 //
3752 //
3753 // State:
3754 //
3755 //---------------------------------------------------------------------------
3756 
EplDllkMnSendSoa(tEplNmtState NmtState_p,tEplDllState * pDllStateProposed_p,BOOL fEnableInvitation_p)3757 static tEplKernel EplDllkMnSendSoa(tEplNmtState NmtState_p,
3758 				   tEplDllState * pDllStateProposed_p,
3759 				   BOOL fEnableInvitation_p)
3760 {
3761 	tEplKernel Ret = kEplSuccessful;
3762 	tEdrvTxBuffer *pTxBuffer = NULL;
3763 	tEplFrame *pTxFrame;
3764 	tEplDllkNodeInfo *pNodeInfo;
3765 
3766 	*pDllStateProposed_p = kEplDllMsNonCyclic;
3767 
3768 	pTxBuffer = &EplDllkInstance_g.m_pTxBuffer[EPL_DLLK_TXFRAME_SOA];
3769 	if (pTxBuffer->m_pbBuffer != NULL) {	// SoA does exist
3770 		pTxFrame = (tEplFrame *) pTxBuffer->m_pbBuffer;
3771 
3772 		if (fEnableInvitation_p != FALSE) {	// fetch target of asynchronous phase
3773 			if (EplDllkInstance_g.m_bFlag2 == 0) {	// own queues are empty
3774 				EplDllkInstance_g.m_LastReqServiceId =
3775 				    kEplDllReqServiceNo;
3776 			} else if (((tEplDllAsyncReqPriority) (EplDllkInstance_g.m_bFlag2 >> EPL_FRAME_FLAG2_PR_SHIFT)) == kEplDllAsyncReqPrioNmt) {	// frames in own NMT request queue available
3777 				EplDllkInstance_g.m_LastReqServiceId =
3778 				    kEplDllReqServiceNmtRequest;
3779 			} else {
3780 				EplDllkInstance_g.m_LastReqServiceId =
3781 				    kEplDllReqServiceUnspecified;
3782 			}
3783 			Ret =
3784 			    EplDllkCalAsyncGetSoaRequest(&EplDllkInstance_g.
3785 							 m_LastReqServiceId,
3786 							 &EplDllkInstance_g.
3787 							 m_uiLastTargetNodeId);
3788 			if (Ret != kEplSuccessful) {
3789 				goto Exit;
3790 			}
3791 			if (EplDllkInstance_g.m_LastReqServiceId != kEplDllReqServiceNo) {	// asynchronous phase will be assigned to one node
3792 				if (EplDllkInstance_g.m_uiLastTargetNodeId == EPL_C_ADR_INVALID) {	// exchange invalid node ID with local node ID
3793 					EplDllkInstance_g.m_uiLastTargetNodeId =
3794 					    EplDllkInstance_g.m_DllConfigParam.
3795 					    m_uiNodeId;
3796 					// d.k. DLL state WaitAsndTrig is not helpful;
3797 					//      so just step over to WaitSocTrig,
3798 					//      because own ASnd is sent automatically in CbFrameTransmitted() after SoA.
3799 					//*pDllStateProposed_p = kEplDllMsWaitAsndTrig;
3800 					*pDllStateProposed_p =
3801 					    kEplDllMsWaitSocTrig;
3802 				} else {	// assignment to CN
3803 					*pDllStateProposed_p =
3804 					    kEplDllMsWaitAsnd;
3805 				}
3806 
3807 				pNodeInfo =
3808 				    EplDllkGetNodeInfo(EplDllkInstance_g.
3809 						       m_uiLastTargetNodeId);
3810 				if (pNodeInfo == NULL) {	// no node info structure available
3811 					Ret = kEplDllNoNodeInfo;
3812 					goto Exit;
3813 				}
3814 				// update frame (EA, ER flags)
3815 				AmiSetByteToLe(&pTxFrame->m_Data.m_Soa.
3816 					       m_le_bFlag1,
3817 					       pNodeInfo->
3818 					       m_bSoaFlag1 & (EPL_FRAME_FLAG1_EA
3819 							      |
3820 							      EPL_FRAME_FLAG1_ER));
3821 			} else {	// no assignment of asynchronous phase
3822 				*pDllStateProposed_p = kEplDllMsWaitSocTrig;
3823 				EplDllkInstance_g.m_uiLastTargetNodeId =
3824 				    EPL_C_ADR_INVALID;
3825 			}
3826 
3827 			// update frame (target)
3828 			AmiSetByteToLe(&pTxFrame->m_Data.m_Soa.
3829 				       m_le_bReqServiceId,
3830 				       (BYTE) EplDllkInstance_g.
3831 				       m_LastReqServiceId);
3832 			AmiSetByteToLe(&pTxFrame->m_Data.m_Soa.
3833 				       m_le_bReqServiceTarget,
3834 				       (BYTE) EplDllkInstance_g.
3835 				       m_uiLastTargetNodeId);
3836 
3837 		} else {	// invite nobody
3838 			// update frame (target)
3839 			AmiSetByteToLe(&pTxFrame->m_Data.m_Soa.
3840 				       m_le_bReqServiceId, (BYTE) 0);
3841 			AmiSetByteToLe(&pTxFrame->m_Data.m_Soa.
3842 				       m_le_bReqServiceTarget, (BYTE) 0);
3843 		}
3844 
3845 		// update frame (NMT state)
3846 		AmiSetByteToLe(&pTxFrame->m_Data.m_Soa.m_le_bNmtStatus,
3847 			       (BYTE) NmtState_p);
3848 
3849 		// send SoA frame
3850 		Ret = EdrvSendTxMsg(pTxBuffer);
3851 	}
3852 
3853       Exit:
3854 	return Ret;
3855 }
3856 
3857 //---------------------------------------------------------------------------
3858 //
3859 // Function:    EplDllkMnSendSoc()
3860 //
3861 // Description: it updates and transmits the SoA.
3862 //
3863 // Parameters:  (none)
3864 //
3865 // Returns:     tEplKernel              = error code
3866 //
3867 //
3868 // State:
3869 //
3870 //---------------------------------------------------------------------------
3871 
EplDllkMnSendSoc(void)3872 static tEplKernel EplDllkMnSendSoc(void)
3873 {
3874 	tEplKernel Ret = kEplSuccessful;
3875 	tEdrvTxBuffer *pTxBuffer = NULL;
3876 	tEplFrame *pTxFrame;
3877 	tEplEvent Event;
3878 
3879 	pTxBuffer = &EplDllkInstance_g.m_pTxBuffer[EPL_DLLK_TXFRAME_SOC];
3880 	if (pTxBuffer->m_pbBuffer != NULL) {	// SoC does exist
3881 		pTxFrame = (tEplFrame *) pTxBuffer->m_pbBuffer;
3882 
3883 		// $$$ update NetTime
3884 
3885 		// send SoC frame
3886 		Ret = EdrvSendTxMsg(pTxBuffer);
3887 		if (Ret != kEplSuccessful) {
3888 			goto Exit;
3889 		}
3890 		// trigger synchronous task
3891 		Event.m_EventSink = kEplEventSinkSync;
3892 		Event.m_EventType = kEplEventTypeSync;
3893 		Event.m_uiSize = 0;
3894 		Ret = EplEventkPost(&Event);
3895 	}
3896 
3897       Exit:
3898 	return Ret;
3899 }
3900 
3901 //---------------------------------------------------------------------------
3902 //
3903 // Function:    EplDllkMnSendPreq()
3904 //
3905 // Description: it updates and transmits the PReq for the next isochronous CN
3906 //              or own PRes if enabled.
3907 //
3908 // Parameters:  NmtState_p              = current NMT state
3909 //              pDllStateProposed_p     = proposed DLL state
3910 //
3911 // Returns:     tEplKernel              = error code
3912 //
3913 //
3914 // State:
3915 //
3916 //---------------------------------------------------------------------------
3917 
EplDllkMnSendPreq(tEplNmtState NmtState_p,tEplDllState * pDllStateProposed_p)3918 static tEplKernel EplDllkMnSendPreq(tEplNmtState NmtState_p,
3919 				    tEplDllState * pDllStateProposed_p)
3920 {
3921 	tEplKernel Ret = kEplSuccessful;
3922 	tEdrvTxBuffer *pTxBuffer = NULL;
3923 	tEplFrame *pTxFrame;
3924 	BYTE bFlag1 = 0;
3925 
3926 	if (EplDllkInstance_g.m_pCurNodeInfo == NULL) {	// start with first isochronous CN
3927 		EplDllkInstance_g.m_pCurNodeInfo =
3928 		    EplDllkInstance_g.m_pFirstNodeInfo;
3929 	} else {		// iterate to next isochronous CN
3930 		EplDllkInstance_g.m_pCurNodeInfo =
3931 		    EplDllkInstance_g.m_pCurNodeInfo->m_pNextNodeInfo;
3932 	}
3933 
3934 	if (EplDllkInstance_g.m_pCurNodeInfo == NULL) {	// last isochronous CN reached
3935 		Ret = EplDllkMnSendSoa(NmtState_p, pDllStateProposed_p, TRUE);
3936 		goto Exit;
3937 	} else {
3938 		pTxBuffer = EplDllkInstance_g.m_pCurNodeInfo->m_pPreqTxBuffer;
3939 		bFlag1 =
3940 		    EplDllkInstance_g.m_pCurNodeInfo->
3941 		    m_bSoaFlag1 & EPL_FRAME_FLAG1_EA;
3942 		*pDllStateProposed_p = kEplDllMsWaitPres;
3943 
3944 		// start PRes Timer
3945 		// $$$ d.k.: maybe move this call to CbFrameTransmitted(), because the time should run from there
3946 #if EPL_TIMER_USE_HIGHRES != FALSE
3947 		Ret =
3948 		    EplTimerHighReskModifyTimerNs(&EplDllkInstance_g.
3949 						  m_TimerHdlResponse,
3950 						  EplDllkInstance_g.
3951 						  m_pCurNodeInfo->
3952 						  m_dwPresTimeout,
3953 						  EplDllkCbMnTimerResponse, 0L,
3954 						  FALSE);
3955 #endif
3956 	}
3957 
3958 	if (pTxBuffer == NULL) {	// PReq does not exist
3959 		Ret = kEplDllTxBufNotReady;
3960 		goto Exit;
3961 	}
3962 
3963 	pTxFrame = (tEplFrame *) pTxBuffer->m_pbBuffer;
3964 
3965 	if (pTxFrame != NULL) {	// PReq does exist
3966 		if (NmtState_p == kEplNmtMsOperational) {	// leave RD flag untouched
3967 			bFlag1 |=
3968 			    AmiGetByteFromLe(&pTxFrame->m_Data.m_Preq.
3969 					     m_le_bFlag1) & EPL_FRAME_FLAG1_RD;
3970 		}
3971 
3972 		if (pTxBuffer == &EplDllkInstance_g.m_pTxBuffer[EPL_DLLK_TXFRAME_PRES]) {	// PRes of MN will be sent
3973 			// update NMT state
3974 			AmiSetByteToLe(&pTxFrame->m_Data.m_Pres.m_le_bNmtStatus,
3975 				       (BYTE) NmtState_p);
3976 			*pDllStateProposed_p = kEplDllMsWaitSoaTrig;
3977 		}
3978 		// $$$ d.k. set EPL_FRAME_FLAG1_MS if necessary
3979 		// update frame (Flag1)
3980 		AmiSetByteToLe(&pTxFrame->m_Data.m_Preq.m_le_bFlag1, bFlag1);
3981 
3982 		// calculate frame size from payload size
3983 		pTxBuffer->m_uiTxMsgLen =
3984 		    AmiGetWordFromLe(&pTxFrame->m_Data.m_Preq.m_le_wSize) + 24;
3985 
3986 		// send PReq frame
3987 		Ret = EdrvSendTxMsg(pTxBuffer);
3988 	} else {
3989 		Ret = kEplDllTxFrameInvalid;
3990 	}
3991 
3992       Exit:
3993 	return Ret;
3994 }
3995 
3996 //---------------------------------------------------------------------------
3997 //
3998 // Function:    EplDllkAsyncFrameNotReceived()
3999 //
4000 // Description: passes empty ASnd frame to receive FIFO.
4001 //              It will be called only for frames with registered AsndServiceIds
4002 //              (only kEplDllAsndFilterAny).
4003 //
4004 // Parameters:  none
4005 //
4006 // Returns:     tEplKernel              = error code
4007 //
4008 //
4009 // State:
4010 //
4011 //---------------------------------------------------------------------------
4012 
EplDllkAsyncFrameNotReceived(tEplDllReqServiceId ReqServiceId_p,unsigned int uiNodeId_p)4013 static tEplKernel EplDllkAsyncFrameNotReceived(tEplDllReqServiceId
4014 					       ReqServiceId_p,
4015 					       unsigned int uiNodeId_p)
4016 {
4017 	tEplKernel Ret = kEplSuccessful;
4018 	BYTE abBuffer[18];
4019 	tEplFrame *pFrame = (tEplFrame *) abBuffer;
4020 	tEplFrameInfo FrameInfo;
4021 
4022 	// check if previous SoA invitation was not answered
4023 	switch (ReqServiceId_p) {
4024 	case kEplDllReqServiceIdent:
4025 	case kEplDllReqServiceStatus:
4026 		// ASnd service registered?
4027 		if (EplDllkInstance_g.m_aAsndFilter[ReqServiceId_p] == kEplDllAsndFilterAny) {	// ASnd service ID is registered
4028 			AmiSetByteToLe(&pFrame->m_le_bSrcNodeId,
4029 				       (BYTE) uiNodeId_p);
4030 			// EPL MsgType ASnd
4031 			AmiSetByteToLe(&pFrame->m_le_bMessageType,
4032 				       (BYTE) kEplMsgTypeAsnd);
4033 			// ASnd Service ID
4034 			AmiSetByteToLe(&pFrame->m_Data.m_Asnd.m_le_bServiceId,
4035 				       (BYTE) ReqServiceId_p);
4036 			// create frame info structure
4037 			FrameInfo.m_pFrame = pFrame;
4038 			FrameInfo.m_uiFrameSize = 18;	// empty non existing ASnd frame
4039 			// forward frame via async receive FIFO to userspace
4040 			Ret = EplDllkCalAsyncFrameReceived(&FrameInfo);
4041 		}
4042 		break;
4043 	default:
4044 		// no invitation issued or it was successfully answered or it is uninteresting
4045 		break;
4046 	}
4047 
4048 	return Ret;
4049 }
4050 
4051 #endif //(((EPL_MODULE_INTEGRATION) & (EPL_MODULE_NMT_MN)) != 0)
4052 
4053 #endif // #if(((EPL_MODULE_INTEGRATION) & (EPL_MODULE_DLLK)) != 0)
4054 // EOF
4055