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