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