added 2.6.29.6 aldebaran kernel
[nao-ulib.git] / kernel / 2.6.29.6-aldebaran-rt / drivers / staging / epl / EplDllk.c
blob9e22641055c61cd7066410603c73d74e99d198fa
1 /****************************************************************************
3 (c) SYSTEC electronic GmbH, D-07973 Greiz, August-Bebel-Str. 29
4 www.systec-electronic.com
6 Project: openPOWERLINK
8 Description: source file for kernel DLL module
10 License:
12 Redistribution and use in source and binary forms, with or without
13 modification, are permitted provided that the following conditions
14 are met:
16 1. Redistributions of source code must retain the above copyright
17 notice, this list of conditions and the following disclaimer.
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.
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.
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.
41 Severability Clause:
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.
50 -------------------------------------------------------------------------
52 $RCSfile: EplDllk.c,v $
54 $Author: D.Krueger $
56 $Revision: 1.21 $ $Date: 2008/11/13 17:13:09 $
58 $State: Exp $
60 Build Environment:
61 GCC V3.4
63 -------------------------------------------------------------------------
65 Revision History:
67 2006/06/12 d.k.: start of the implementation, version 1.00
69 ****************************************************************************/
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"
78 #if (((EPL_MODULE_INTEGRATION) & (EPL_MODULE_PDOK)) != 0)
79 #include "kernel/EplPdok.h"
80 #endif
82 #if (((EPL_MODULE_INTEGRATION) & (EPL_MODULE_VETH)) != 0)
83 #include "kernel/VirtualEthernet.h"
84 #endif
86 //#if EPL_TIMER_USE_HIGHRES != FALSE
87 #include "kernel/EplTimerHighResk.h"
88 //#endif
90 #if(((EPL_MODULE_INTEGRATION) & (EPL_MODULE_DLLK)) != 0)
92 #if(((EPL_MODULE_INTEGRATION) & (EPL_MODULE_NMTK)) == 0)
93 #error "EPL module DLLK needs EPL module NMTK!"
94 #endif
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
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
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
110 /***************************************************************************/
111 /* */
112 /* */
113 /* G L O B A L D E F I N I T I O N S */
114 /* */
115 /* */
116 /***************************************************************************/
118 //---------------------------------------------------------------------------
119 // const defines
120 //---------------------------------------------------------------------------
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)
136 /***************************************************************************/
137 /* */
138 /* */
139 /* C L A S S EplDllk */
140 /* */
141 /* */
142 /***************************************************************************/
144 // Description:
147 /***************************************************************************/
149 //=========================================================================//
150 // //
151 // P R I V A T E D E F I N I T I O N S //
152 // //
153 //=========================================================================//
155 //---------------------------------------------------------------------------
156 // const defines
157 //---------------------------------------------------------------------------
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
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
178 //---------------------------------------------------------------------------
179 // local types
180 //---------------------------------------------------------------------------
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
195 } tEplDllState;
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];
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
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
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)
228 } tEplDllkInstance;
230 //---------------------------------------------------------------------------
231 // local vars
232 //---------------------------------------------------------------------------
234 // if no dynamic memory allocation shall be used
235 // define structures statically
236 static tEplDllkInstance EplDllkInstance_g;
238 static tEdrvTxBuffer aEplDllkTxBuffer_l[EPL_DLLK_TXFRAME_COUNT];
240 //---------------------------------------------------------------------------
241 // local function prototypes
242 //---------------------------------------------------------------------------
244 // change DLL state on event
245 static tEplKernel EplDllkChangeState(tEplNmtEvent NmtEvent_p,
246 tEplNmtState NmtState_p);
248 // called from EdrvInterruptHandler()
249 static void EplDllkCbFrameReceived(tEdrvRxBuffer * pRxBuffer_p);
251 // called from EdrvInterruptHandler()
252 static void EplDllkCbFrameTransmitted(tEdrvTxBuffer * pTxBuffer_p);
254 // check frame and set missing information
255 static tEplKernel EplDllkCheckFrame(tEplFrame * pFrame_p,
256 unsigned int uiFrameSize_p);
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
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);
267 // transmit SoA
268 static tEplKernel EplDllkMnSendSoa(tEplNmtState NmtState_p,
269 tEplDllState * pDllStateProposed_p,
270 BOOL fEnableInvitation_p);
272 static tEplKernel EplDllkMnSendSoc(void);
274 static tEplKernel EplDllkMnSendPreq(tEplNmtState NmtState_p,
275 tEplDllState * pDllStateProposed_p);
277 static tEplKernel EplDllkAsyncFrameNotReceived(tEplDllReqServiceId
278 ReqServiceId_p,
279 unsigned int uiNodeId_p);
281 static tEplKernel PUBLIC EplDllkCbMnTimerCycle(tEplTimerEventArg * pEventArg_p);
283 static tEplKernel PUBLIC EplDllkCbMnTimerResponse(tEplTimerEventArg *
284 pEventArg_p);
286 #endif
288 //=========================================================================//
289 // //
290 // P U B L I C F U N C T I O N S //
291 // //
292 //=========================================================================//
294 //---------------------------------------------------------------------------
296 // Function: EplDllkAddInstance()
298 // Description: add and initialize new instance of EPL stack
300 // Parameters: pInitParam_p = initialisation parameters like MAC address
302 // Returns: tEplKernel = error code
305 // State:
307 //---------------------------------------------------------------------------
309 tEplKernel EplDllkAddInstance(tEplDllkInitParam * pInitParam_p)
311 tEplKernel Ret = kEplSuccessful;
312 unsigned int uiIndex;
313 tEdrvInitParam EdrvInitParam;
315 // reset instance structure
316 EPL_MEMSET(&EplDllkInstance_g, 0, sizeof(EplDllkInstance_g));
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;
323 #endif
325 // if dynamic memory allocation available
326 // allocate instance structure
327 // allocate TPDO and RPDO table with default size
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);
334 // initialize state
335 EplDllkInstance_g.m_DllState = kEplDllGsInit;
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;
345 #endif
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;
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,
359 EPL_MEMCPY(pInitParam_p->m_be_abSrcMac, EdrvInitParam.m_abMyMacAddr, 6);
361 // initialize TxBuffer array
362 for (uiIndex = 0; uiIndex < EplDllkInstance_g.m_uiMaxTxFrames;
363 uiIndex++) {
364 EplDllkInstance_g.m_pTxBuffer[uiIndex].m_pbBuffer = NULL;
367 #if (((EPL_MODULE_INTEGRATION) & (EPL_MODULE_VETH)) != 0)
368 Ret = VEthAddInstance(pInitParam_p);
369 #endif
371 Exit:
372 return Ret;
375 //---------------------------------------------------------------------------
377 // Function: EplDllkDelInstance()
379 // Description: deletes an instance of EPL stack
381 // Parameters: (none)
383 // Returns: tEplKernel = error code
386 // State:
388 //---------------------------------------------------------------------------
390 tEplKernel EplDllkDelInstance(void)
392 tEplKernel Ret = kEplSuccessful;
394 // reset state
395 EplDllkInstance_g.m_DllState = kEplDllGsInit;
397 #if EPL_TIMER_USE_HIGHRES != FALSE
398 Ret = EplTimerHighReskDelInstance();
399 #endif
401 #if (((EPL_MODULE_INTEGRATION) & (EPL_MODULE_VETH)) != 0)
402 Ret = VEthDelInstance();
403 #endif
405 Ret = EdrvShutdown();
406 return Ret;
409 //---------------------------------------------------------------------------
411 // Function: EplDllkCreateTxFrame
413 // Description: creates the buffer for a Tx frame and registers it to the
414 // ethernet driver
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
426 // Returns: tEplKernel = error code
429 // State:
431 //---------------------------------------------------------------------------
433 tEplKernel EplDllkCreateTxFrame(unsigned int *puiHandle_p,
434 tEplFrame ** ppFrame_p,
435 unsigned int *puiFrameSize_p,
436 tEplMsgType MsgType_p,
437 tEplDllAsndServiceId ServiceId_p)
439 tEplKernel Ret = kEplSuccessful;
440 tEplFrame *pTxFrame;
441 unsigned int uiHandle = EplDllkInstance_g.m_uiMaxTxFrames;
442 tEdrvTxBuffer *pTxBuffer = NULL;
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;
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;
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;
482 if (pTxBuffer->m_pbBuffer != NULL) {
483 Ret = kEplEdrvNoFreeBufEntry;
484 goto Exit;
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;
494 // setup Tx buffer
495 pTxBuffer->m_EplMsgType = MsgType_p;
496 pTxBuffer->m_uiMaxBufferLen = *puiFrameSize_p;
498 Ret = EdrvAllocTxMsgBuffer(pTxBuffer);
499 if (Ret != kEplSuccessful) { // error occured while registering Tx frame
500 goto Exit;
502 // because buffer size may be larger than requested
503 // memorize real length of frame
504 pTxBuffer->m_uiTxMsgLen = *puiFrameSize_p;
506 // fill whole frame with 0
507 EPL_MEMSET(pTxBuffer->m_pbBuffer, 0, pTxBuffer->m_uiMaxBufferLen);
509 pTxFrame = (tEplFrame *) pTxBuffer->m_pbBuffer;
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;
539 default:
540 break;
542 // ASnd Service ID
543 AmiSetByteToLe(&pTxFrame->m_Data.m_Asnd.m_le_bServiceId,
544 ServiceId_p);
545 break;
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;
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;
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;
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;
596 default:
597 break;
599 // EPL message type
600 AmiSetByteToLe(&pTxFrame->m_le_bMessageType, (BYTE) MsgType_p);
603 *ppFrame_p = pTxFrame;
604 *puiFrameSize_p = pTxBuffer->m_uiMaxBufferLen;
605 *puiHandle_p = uiHandle;
607 Exit:
608 return Ret;
611 //---------------------------------------------------------------------------
613 // Function: EplDllkDeleteTxFrame
615 // Description: deletes the buffer for a Tx frame and frees it in the
616 // ethernet driver
618 // Parameters: uiHandle_p = IN: handle to frame buffer
620 // Returns: tEplKernel = error code
623 // State:
625 //---------------------------------------------------------------------------
627 tEplKernel EplDllkDeleteTxFrame(unsigned int uiHandle_p)
629 tEplKernel Ret = kEplSuccessful;
630 tEdrvTxBuffer *pTxBuffer = NULL;
632 if (uiHandle_p >= EplDllkInstance_g.m_uiMaxTxFrames) { // handle is not valid
633 Ret = kEplDllIllegalHdl;
634 goto Exit;
637 pTxBuffer = &EplDllkInstance_g.m_pTxBuffer[uiHandle_p];
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;
644 // delete Tx buffer
645 Ret = EdrvReleaseTxMsgBuffer(pTxBuffer);
646 if (Ret != kEplSuccessful) { // error occured while releasing Tx frame
647 goto Exit;
650 Exit:
651 return Ret;
654 //---------------------------------------------------------------------------
656 // Function: EplDllkProcess
658 // Description: process the passed event
660 // Parameters: pEvent_p = event to be processed
662 // Returns: tEplKernel = error code
665 // State:
667 //---------------------------------------------------------------------------
669 tEplKernel EplDllkProcess(tEplEvent * pEvent_p)
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
684 switch (pEvent_p->m_EventType) {
685 case kEplEventTypeDllkCreate:
687 // $$$ reset ethernet driver
689 NmtState = *((tEplNmtState *) pEvent_p->m_pArg);
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;
696 #if (((EPL_MODULE_INTEGRATION) & (EPL_MODULE_NMT_MN)) != 0)
697 // initialize linked node list
698 EplDllkInstance_g.m_pFirstNodeInfo = NULL;
699 #endif
701 // register TxFrames in Edrv
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;
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));
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;
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;
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;
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;
875 // mark Tx buffer as empty
876 EplDllkInstance_g.m_pTxBuffer[uiHandle].m_uiTxMsgLen =
877 EPL_DLLK_BUFLEN_EMPTY;
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;
889 // mark Tx buffer as empty
890 EplDllkInstance_g.m_pTxBuffer[uiHandle].m_uiTxMsgLen =
891 EPL_DLLK_BUFLEN_EMPTY;
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);
907 #if (((EPL_MODULE_INTEGRATION) & (EPL_MODULE_NMT_MN)) != 0)
908 if (NmtState >= kEplNmtMsNotActive) { // local node is MN
909 unsigned int uiIndex;
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;
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;
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;
944 // calculate cycle length
945 EplDllkInstance_g.m_ullFrameTimeout = 1000LL
947 ((unsigned long long)EplDllkInstance_g.
948 m_DllConfigParam.m_dwCycleLen);
950 #endif //(((EPL_MODULE_INTEGRATION) & (EPL_MODULE_NMT_MN)) != 0)
952 Ret = EplDllkCalAsyncClearBuffer();
954 break;
957 case kEplEventTypeDllkDestroy:
959 // destroy all data structures
961 NmtState = *((tEplNmtState *) pEvent_p->m_pArg);
963 // delete Tx frames
964 Ret = EplDllkDeleteTxFrame(EPL_DLLK_TXFRAME_IDENTRES);
965 if (Ret != kEplSuccessful) { // error occured while deregistering Tx frame
966 goto Exit;
969 Ret = EplDllkDeleteTxFrame(EPL_DLLK_TXFRAME_STATUSRES);
970 if (Ret != kEplSuccessful) { // error occured while deregistering Tx frame
971 goto Exit;
974 Ret = EplDllkDeleteTxFrame(EPL_DLLK_TXFRAME_PRES);
975 if (Ret != kEplSuccessful) { // error occured while deregistering Tx frame
976 goto Exit;
979 Ret = EplDllkDeleteTxFrame(EPL_DLLK_TXFRAME_NMTREQ);
980 if (Ret != kEplSuccessful) { // error occured while deregistering Tx frame
981 goto Exit;
984 Ret = EplDllkDeleteTxFrame(EPL_DLLK_TXFRAME_NONEPL);
985 if (Ret != kEplSuccessful) { // error occured while deregistering Tx frame
986 goto Exit;
988 #if (((EPL_MODULE_INTEGRATION) & (EPL_MODULE_NMT_MN)) != 0)
989 if (NmtState >= kEplNmtMsNotActive) { // local node was MN
990 unsigned int uiIndex;
992 Ret =
993 EplDllkDeleteTxFrame(EPL_DLLK_TXFRAME_SOC);
994 if (Ret != kEplSuccessful) { // error occured while deregistering Tx frame
995 goto Exit;
998 Ret =
999 EplDllkDeleteTxFrame(EPL_DLLK_TXFRAME_SOA);
1000 if (Ret != kEplSuccessful) { // error occured while deregistering Tx frame
1001 goto Exit;
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;
1028 EplDllkInstance_g.m_aNodeInfo[uiIndex].
1029 m_wPresPayloadLimit = 0xFFFF;
1032 #endif //(((EPL_MODULE_INTEGRATION) & (EPL_MODULE_NMT_MN)) != 0)
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);
1048 // delete timer
1049 #if EPL_TIMER_USE_HIGHRES != FALSE
1050 Ret =
1051 EplTimerHighReskDeleteTimer(&EplDllkInstance_g.
1052 m_TimerHdlCycle);
1053 #endif
1055 break;
1058 case kEplEventTypeDllkFillTx:
1060 // fill TxBuffer of specified priority with new frame if empty
1062 pTxFrame = NULL;
1063 AsyncReqPriority =
1064 *((tEplDllAsyncReqPriority *) pEvent_p->m_pArg);
1065 switch (AsyncReqPriority) {
1066 case kEplDllAsyncReqPrioNmt: // NMT request priority
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
1096 pTxBuffer->
1097 m_pbBuffer;
1098 Ret =
1099 EplDllkCheckFrame
1100 (pTxFrame,
1101 uiFrameSize);
1103 // set buffer valid
1104 pTxBuffer->
1105 m_uiTxMsgLen
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
1116 EPL_DLLK_BUFLEN_EMPTY;
1120 break;
1123 default: // generic priority
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
1153 pTxBuffer->
1154 m_pbBuffer;
1155 Ret =
1156 EplDllkCheckFrame
1157 (pTxFrame,
1158 uiFrameSize);
1160 // set buffer valid
1161 pTxBuffer->
1162 m_uiTxMsgLen
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
1173 EPL_DLLK_BUFLEN_EMPTY;
1177 break;
1181 NmtState = EplNmtkGetNmtState();
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]);
1202 if (Ret == kEplInvalidOperation) { // ignore error if caused by already active transmission
1203 Ret = kEplSuccessful;
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++;
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++;
1231 if (uiFrameCount > 7) { // limit frame request to send counter to 7
1232 uiFrameCount = 7;
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;
1246 break;
1249 #if (((EPL_MODULE_INTEGRATION) & (EPL_MODULE_NMT_MN)) != 0)
1250 case kEplEventTypeDllkStartReducedCycle:
1252 // start the reduced cycle by programming the cycle timer
1253 // it is issued by NMT MN module, when PreOp1 is entered
1255 // clear the asynchronous queues
1256 Ret = EplDllkCalAsyncClearQueues();
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;
1262 // remove any CN from isochronous phase
1263 while (EplDllkInstance_g.m_pFirstNodeInfo != NULL) {
1264 EplDllkDeleteNode(EplDllkInstance_g.
1265 m_pFirstNodeInfo->m_uiNodeId);
1268 // change state to NonCyclic,
1269 // hence EplDllkChangeState() will not ignore the next call
1270 EplDllkInstance_g.m_DllState = kEplDllMsNonCyclic;
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);
1282 #endif
1284 break;
1286 #endif
1288 #if EPL_DLL_PRES_READY_AFTER_SOA != FALSE
1289 case kEplEventTypeDllkPresReady:
1291 // post PRes to transmit FIFO
1293 NmtState = EplNmtkGetNmtState();
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;
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);
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]);
1330 break;
1332 #endif
1333 default:
1335 ASSERTMSG(FALSE,
1336 "EplDllkProcess(): unhandled event type!\n");
1340 Exit:
1341 return Ret;
1344 //---------------------------------------------------------------------------
1346 // Function: EplDllkConfig
1348 // Description: configure parameters of DLL
1350 // Parameters: pDllConfigParam_p = configuration parameters
1352 // Returns: tEplKernel = error code
1355 // State:
1357 //---------------------------------------------------------------------------
1359 tEplKernel EplDllkConfig(tEplDllConfigParam * pDllConfigParam_p)
1361 tEplKernel Ret = kEplSuccessful;
1363 // d.k. check of NMT state disabled, because CycleLen is programmed at run time by MN without reset of CN
1364 /*tEplNmtState NmtState;
1366 NmtState = EplNmtkGetNmtState();
1368 if (NmtState > kEplNmtGsResetConfiguration)
1369 { // only allowed in state DLL_GS_INIT
1370 Ret = kEplInvalidOperation;
1371 goto Exit;
1374 EPL_MEMCPY(&EplDllkInstance_g.m_DllConfigParam, pDllConfigParam_p,
1375 (pDllConfigParam_p->m_uiSizeOfStruct <
1376 sizeof(tEplDllConfigParam) ? pDllConfigParam_p->
1377 m_uiSizeOfStruct : sizeof(tEplDllConfigParam)));
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
1383 ((unsigned long long)
1384 EplDllkInstance_g.
1385 m_DllConfigParam.
1386 m_dwCycleLen))
1388 ((unsigned long long)EplDllkInstance_g.m_DllConfigParam.
1389 m_dwLossOfFrameTolerance);
1390 } else {
1391 EplDllkInstance_g.m_ullFrameTimeout = 0LL;
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;
1398 //Exit:
1399 return Ret;
1402 //---------------------------------------------------------------------------
1404 // Function: EplDllkSetIdentity
1406 // Description: configure identity of local node for IdentResponse
1408 // Parameters: pDllIdentParam_p = identity
1410 // Returns: tEplKernel = error code
1413 // State:
1415 //---------------------------------------------------------------------------
1417 tEplKernel EplDllkSetIdentity(tEplDllIdentParam * pDllIdentParam_p)
1419 tEplKernel Ret = kEplSuccessful;
1421 EPL_MEMCPY(&EplDllkInstance_g.m_DllIdentParam, pDllIdentParam_p,
1422 (pDllIdentParam_p->m_uiSizeOfStruct <
1423 sizeof(tEplDllIdentParam) ? pDllIdentParam_p->
1424 m_uiSizeOfStruct : sizeof(tEplDllIdentParam)));
1426 // $$$ if IdentResponse frame exists update it
1428 return Ret;
1431 //---------------------------------------------------------------------------
1433 // Function: EplDllkRegAsyncHandler
1435 // Description: registers handler for non-EPL frames
1437 // Parameters: pfnDllkCbAsync_p = pointer to callback function
1439 // Returns: tEplKernel = error code
1442 // State:
1444 //---------------------------------------------------------------------------
1446 tEplKernel EplDllkRegAsyncHandler(tEplDllkCbAsync pfnDllkCbAsync_p)
1448 tEplKernel Ret = kEplSuccessful;
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;
1456 return Ret;
1459 //---------------------------------------------------------------------------
1461 // Function: EplDllkDeregAsyncHandler
1463 // Description: deregisters handler for non-EPL frames
1465 // Parameters: pfnDllkCbAsync_p = pointer to callback function
1467 // Returns: tEplKernel = error code
1470 // State:
1472 //---------------------------------------------------------------------------
1474 tEplKernel EplDllkDeregAsyncHandler(tEplDllkCbAsync pfnDllkCbAsync_p)
1476 tEplKernel Ret = kEplSuccessful;
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;
1485 return Ret;
1488 //---------------------------------------------------------------------------
1490 // Function: EplDllkSetAsndServiceIdFilter()
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.
1496 // Parameters: ServiceId_p = ASnd Service ID
1497 // Filter_p = node ID filter
1499 // Returns: tEplKernel = error code
1502 // State:
1504 //---------------------------------------------------------------------------
1506 tEplKernel EplDllkSetAsndServiceIdFilter(tEplDllAsndServiceId ServiceId_p,
1507 tEplDllAsndFilter Filter_p)
1509 tEplKernel Ret = kEplSuccessful;
1511 if (ServiceId_p < tabentries(EplDllkInstance_g.m_aAsndFilter)) {
1512 EplDllkInstance_g.m_aAsndFilter[ServiceId_p] = Filter_p;
1515 return Ret;
1518 #if (((EPL_MODULE_INTEGRATION) & (EPL_MODULE_NMT_MN)) != 0)
1520 //---------------------------------------------------------------------------
1522 // Function: EplDllkSetFlag1OfNode()
1524 // Description: sets Flag1 (for PReq and SoA) of the specified node ID.
1526 // Parameters: uiNodeId_p = node ID
1527 // bSoaFlag1_p = flag1
1529 // Returns: tEplKernel = error code
1532 // State:
1534 //---------------------------------------------------------------------------
1536 tEplKernel EplDllkSetFlag1OfNode(unsigned int uiNodeId_p, BYTE bSoaFlag1_p)
1538 tEplKernel Ret = kEplSuccessful;
1539 tEplDllkNodeInfo *pNodeInfo;
1541 pNodeInfo = EplDllkGetNodeInfo(uiNodeId_p);
1542 if (pNodeInfo == NULL) { // no node info structure available
1543 Ret = kEplDllNoNodeInfo;
1544 goto Exit;
1546 // store flag1 in internal node info structure
1547 pNodeInfo->m_bSoaFlag1 = bSoaFlag1_p;
1549 Exit:
1550 return Ret;
1553 //---------------------------------------------------------------------------
1555 // Function: EplDllkGetFirstNodeInfo()
1557 // Description: returns first info structure of first node in isochronous phase.
1558 // It is only useful for ErrorHandlerk module.
1560 // Parameters: ppNodeInfo_p = pointer to pointer of internal node info structure
1562 // Returns: tEplKernel = error code
1565 // State:
1567 //---------------------------------------------------------------------------
1569 tEplKernel EplDllkGetFirstNodeInfo(tEplDllkNodeInfo ** ppNodeInfo_p)
1571 tEplKernel Ret = kEplSuccessful;
1573 *ppNodeInfo_p = EplDllkInstance_g.m_pFirstNodeInfo;
1575 return Ret;
1578 //---------------------------------------------------------------------------
1580 // Function: EplDllkAddNode()
1582 // Description: adds the specified node to the isochronous phase.
1584 // Parameters: pNodeInfo_p = pointer of node info structure
1586 // Returns: tEplKernel = error code
1589 // State:
1591 //---------------------------------------------------------------------------
1593 tEplKernel EplDllkAddNode(tEplDllNodeInfo * pNodeInfo_p)
1595 tEplKernel Ret = kEplSuccessful;
1596 tEplDllkNodeInfo *pIntNodeInfo;
1597 tEplDllkNodeInfo **ppIntNodeInfo;
1598 unsigned int uiHandle;
1599 tEplFrame *pFrame;
1600 unsigned int uiFrameSize;
1602 pIntNodeInfo = EplDllkGetNodeInfo(pNodeInfo_p->m_uiNodeId);
1603 if (pIntNodeInfo == NULL) { // no node info structure available
1604 Ret = kEplDllNoNodeInfo;
1605 goto Exit;
1608 EPL_DLLK_DBG_POST_TRACE_VALUE(kEplEventTypeDllkAddNode,
1609 pNodeInfo_p->m_uiNodeId, 0);
1611 // copy node configuration
1612 pIntNodeInfo->m_dwPresTimeout = pNodeInfo_p->m_dwPresTimeout;
1613 pIntNodeInfo->m_wPresPayloadLimit = pNodeInfo_p->m_wPresPayloadLimit;
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;
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;
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;
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;
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;
1664 pIntNodeInfo->m_pPreqTxBuffer =
1665 &EplDllkInstance_g.m_pTxBuffer[uiHandle];
1666 AmiSetByteToLe(&pFrame->m_le_bDstNodeId,
1667 (BYTE) pNodeInfo_p->m_uiNodeId);
1669 // set up destination MAC address
1670 EPL_MEMCPY(pFrame->m_be_abDstMac, pIntNodeInfo->m_be_abMacAddr,
1673 #if (((EPL_MODULE_INTEGRATION) & (EPL_MODULE_PDOK)) != 0)
1675 tEplFrameInfo FrameInfo;
1677 // initially encode TPDO -> inform PDO module
1678 FrameInfo.m_pFrame = pFrame;
1679 FrameInfo.m_uiFrameSize = uiFrameSize;
1680 Ret = EplPdokCbPdoTransmitted(&FrameInfo);
1682 #endif
1684 pIntNodeInfo->m_ulDllErrorEvents = 0L;
1685 // add node to list
1686 pIntNodeInfo->m_pNextNodeInfo = *ppIntNodeInfo;
1687 *ppIntNodeInfo = pIntNodeInfo;
1689 Exit:
1690 return Ret;
1693 //---------------------------------------------------------------------------
1695 // Function: EplDllkDeleteNode()
1697 // Description: removes the specified node from the isochronous phase.
1699 // Parameters: uiNodeId_p = node ID
1701 // Returns: tEplKernel = error code
1704 // State:
1706 //---------------------------------------------------------------------------
1708 tEplKernel EplDllkDeleteNode(unsigned int uiNodeId_p)
1710 tEplKernel Ret = kEplSuccessful;
1711 tEplDllkNodeInfo *pIntNodeInfo;
1712 tEplDllkNodeInfo **ppIntNodeInfo;
1713 unsigned int uiHandle;
1715 pIntNodeInfo = EplDllkGetNodeInfo(uiNodeId_p);
1716 if (pIntNodeInfo == NULL) { // no node info structure available
1717 Ret = kEplDllNoNodeInfo;
1718 goto Exit;
1721 EPL_DLLK_DBG_POST_TRACE_VALUE(kEplEventTypeDllkDelNode, uiNodeId_p, 0);
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;
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;
1733 // remove node from list
1734 *ppIntNodeInfo = pIntNodeInfo->m_pNextNodeInfo;
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)
1745 goto Exit;
1749 Exit:
1750 return Ret;
1753 //---------------------------------------------------------------------------
1755 // Function: EplDllkSoftDeleteNode()
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.
1761 // Parameters: uiNodeId_p = node ID
1763 // Returns: tEplKernel = error code
1766 // State:
1768 //---------------------------------------------------------------------------
1770 tEplKernel EplDllkSoftDeleteNode(unsigned int uiNodeId_p)
1772 tEplKernel Ret = kEplSuccessful;
1773 tEplDllkNodeInfo *pIntNodeInfo;
1775 pIntNodeInfo = EplDllkGetNodeInfo(uiNodeId_p);
1776 if (pIntNodeInfo == NULL) { // no node info structure available
1777 Ret = kEplDllNoNodeInfo;
1778 goto Exit;
1781 EPL_DLLK_DBG_POST_TRACE_VALUE(kEplEventTypeDllkSoftDelNode,
1782 uiNodeId_p, 0);
1784 pIntNodeInfo->m_fSoftDelete = TRUE;
1786 Exit:
1787 return Ret;
1790 #endif //(((EPL_MODULE_INTEGRATION) & (EPL_MODULE_NMT_MN)) != 0)
1792 //=========================================================================//
1793 // //
1794 // P R I V A T E F U N C T I O N S //
1795 // //
1796 //=========================================================================//
1798 //---------------------------------------------------------------------------
1800 // Function: EplDllkChangeState
1802 // Description: change DLL state on event and diagnose some communication errors
1804 // Parameters: NmtEvent_p = DLL event (wrapped in NMT event)
1806 // Returns: tEplKernel = error code
1809 // State:
1811 //---------------------------------------------------------------------------
1813 static tEplKernel EplDllkChangeState(tEplNmtEvent NmtEvent_p,
1814 tEplNmtState NmtState_p)
1816 tEplKernel Ret = kEplSuccessful;
1817 tEplEvent Event;
1818 tEplErrorHandlerkEvent DllEvent;
1820 DllEvent.m_ulDllErrorEvents = 0;
1821 DllEvent.m_uiNodeId = 0;
1822 DllEvent.m_NmtState = NmtState_p;
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;
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;
1845 break;
1847 case kEplNmtCsPreOperational2:
1848 case kEplNmtCsReadyToOperate:
1849 case kEplNmtCsOperational:
1850 // full EPL cycle is active
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;
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;
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;
1878 // enter DLL_CS_WAIT_SOC
1879 EplDllkInstance_g.m_DllState = kEplDllCsWaitSoc;
1880 break;
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;
1890 // enter DLL_CS_WAIT_SOC
1891 EplDllkInstance_g.m_DllState = kEplDllCsWaitSoc;
1892 break;
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;
1901 case kEplNmtEventDllCePres:
1902 default:
1903 // remain in this state
1904 break;
1906 break;
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;
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;
1929 // fall through
1931 case kEplNmtEventDllCePreq:
1932 case kEplNmtEventDllCeSoa:
1933 // report DLL_CEV_LOSS_SOC
1934 DllEvent.m_ulDllErrorEvents |=
1935 EPL_DLL_ERR_CN_LOSS_SOC;
1937 case kEplNmtEventDllCeAsnd:
1938 default:
1939 // remain in this state
1940 break;
1942 break;
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;
1956 // fall through
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;
1964 case kEplNmtEventDllCeSoa:
1965 // enter DLL_CS_WAIT_SOC
1966 EplDllkInstance_g.m_DllState = kEplDllCsWaitSoc;
1967 break;
1969 // DLL_CT9
1970 case kEplNmtEventDllCeSoc:
1971 // report DLL_CEV_LOSS_SOA
1972 DllEvent.m_ulDllErrorEvents |=
1973 EPL_DLL_ERR_CN_LOSS_SOA;
1975 // enter DLL_CS_WAIT_PREQ
1976 EplDllkInstance_g.m_DllState =
1977 kEplDllCsWaitPreq;
1978 break;
1980 // DLL_CT10
1981 case kEplNmtEventDllCeAsnd:
1982 // report DLL_CEV_LOSS_SOA
1983 DllEvent.m_ulDllErrorEvents |=
1984 EPL_DLL_ERR_CN_LOSS_SOA;
1986 case kEplNmtEventDllCePres:
1987 default:
1988 // remain in this state
1989 break;
1991 break;
1993 case kEplDllGsInit:
1994 // enter DLL_CS_WAIT_PREQ
1995 EplDllkInstance_g.m_DllState = kEplDllCsWaitPreq;
1996 break;
1998 default:
1999 break;
2001 break;
2003 case kEplNmtCsStopped:
2004 // full EPL cycle is active, but without PReq/PRes
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;
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;
2022 case kEplNmtEventDllCeSoa:
2023 // NMT_CS_STOPPED active
2024 // it is Ok if no PReq was received
2026 // enter DLL_CS_WAIT_SOC
2027 EplDllkInstance_g.m_DllState = kEplDllCsWaitSoc;
2028 break;
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;
2037 case kEplNmtEventDllCePres:
2038 default:
2039 // remain in this state
2040 break;
2042 break;
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;
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;
2062 case kEplNmtEventDllCeAsnd:
2063 default:
2064 // remain in this state
2065 break;
2067 break;
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;
2078 case kEplNmtEventDllCeSoa:
2079 // enter DLL_CS_WAIT_SOC
2080 EplDllkInstance_g.m_DllState = kEplDllCsWaitSoc;
2081 break;
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;
2091 // DLL_CT10
2092 case kEplNmtEventDllCeAsnd:
2093 // report DLL_CEV_LOSS_SOA
2094 DllEvent.m_ulDllErrorEvents |=
2095 EPL_DLL_ERR_CN_LOSS_SOA;
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;
2105 break;
2107 case kEplDllGsInit:
2108 default:
2109 // enter DLL_CS_WAIT_PREQ
2110 EplDllkInstance_g.m_DllState = kEplDllCsWaitSoa;
2111 break;
2113 break;
2115 #if (((EPL_MODULE_INTEGRATION) & (EPL_MODULE_NMT_MN)) != 0)
2116 case kEplNmtMsNotActive:
2117 case kEplNmtMsBasicEthernet:
2118 break;
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;
2130 // stop further processing,
2131 // because it will be restarted by NMT MN module
2132 break;
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;
2141 Ret =
2142 EplDllkAsyncFrameNotReceived
2143 (EplDllkInstance_g.m_LastReqServiceId,
2144 EplDllkInstance_g.m_uiLastTargetNodeId);
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++;
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);
2166 #endif
2167 break;
2170 default:
2171 break;
2173 break;
2175 case kEplNmtMsPreOperational2:
2176 case kEplNmtMsReadyToOperate:
2177 case kEplNmtMsOperational:
2178 // full EPL cycle is active
2179 switch (NmtEvent_p) {
2180 case kEplNmtEventDllMeSocTrig:
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;
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
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);
2225 // send SoC
2226 Ret = EplDllkMnSendSoc();
2228 // new DLL state
2229 EplDllkInstance_g.m_DllState =
2230 kEplDllMsWaitPreqTrig;
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;
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;
2257 break;
2260 case kEplNmtEventDllMePresTimeout:
2263 switch (EplDllkInstance_g.m_DllState) {
2264 case kEplDllMsWaitPres:
2265 { // PRes not received
2267 if (EplDllkInstance_g.m_pCurNodeInfo->m_fSoftDelete == FALSE) { // normal isochronous CN
2268 DllEvent.
2269 m_ulDllErrorEvents
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);
2294 // continue with sending next PReq
2297 case kEplDllMsWaitPreqTrig:
2299 // send next PReq
2300 Ret =
2301 EplDllkMnSendPreq
2302 (NmtState_p,
2303 &EplDllkInstance_g.
2304 m_DllState);
2306 break;
2309 default:
2310 { // wrong DLL state
2311 break;
2315 break;
2318 case kEplNmtEventDllCePres:
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);
2331 break;
2334 default:
2335 { // wrong DLL state
2336 break;
2340 break;
2343 case kEplNmtEventDllMeSoaTrig:
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);
2356 break;
2359 default:
2360 { // wrong DLL state
2361 break;
2365 break;
2368 case kEplNmtEventDllCeAsnd:
2369 { // ASnd has been received, but it may be not the requested one
2371 // report if SoA was correctly answered
2372 Ret = EplDllkAsyncFrameNotReceived(EplDllkInstance_g.m_LastReqServiceId,
2373 EplDllkInstance_g.m_uiLastTargetNodeId);
2375 if (EplDllkInstance_g.m_DllState ==
2376 kEplDllMsWaitAsnd) {
2377 EplDllkInstance_g.m_DllState =
2378 kEplDllMsWaitSocTrig;
2380 break;
2383 default:
2384 break;
2386 break;
2387 #endif //(((EPL_MODULE_INTEGRATION) & (EPL_MODULE_NMT_MN)) != 0)
2389 default:
2390 break;
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);
2402 return Ret;
2405 //---------------------------------------------------------------------------
2407 // Function: EplDllkCbFrameReceived()
2409 // Description: called from EdrvInterruptHandler()
2411 // Parameters: pRxBuffer_p = receive buffer structure
2413 // Returns: (none)
2416 // State:
2418 //---------------------------------------------------------------------------
2420 static void EplDllkCbFrameReceived(tEdrvRxBuffer * pRxBuffer_p)
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;
2436 BENCHMARK_MOD_02_SET(3);
2437 NmtState = EplNmtkGetNmtState();
2439 if (NmtState <= kEplNmtGsResetConfiguration) {
2440 goto Exit;
2443 pFrame = (tEplFrame *) pRxBuffer_p->m_pbBuffer;
2445 #if EDRV_EARLY_RX_INT != FALSE
2446 switch (pRxBuffer_p->m_BufferInFrame) {
2447 case kEdrvBufferFirstInFrame:
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);
2480 // $$$ make function that updates Pres, StatusRes
2481 // send PRes frame
2482 Ret = EdrvSendTxMsg(pTxBuffer);
2483 #endif
2486 goto Exit;
2489 case kEdrvBufferMiddleInFrame:
2491 goto Exit;
2494 case kEdrvBufferLastInFrame:
2496 break;
2499 #endif
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;
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);
2512 goto Exit;
2515 MsgType = (tEplMsgType) AmiGetByteFromLe(&pFrame->m_le_bMessageType);
2516 switch (MsgType) {
2517 case kEplMsgTypePreq:
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;
2524 NmtEvent = kEplNmtEventDllCePreq;
2526 if (NmtState >= kEplNmtMsNotActive) { // MN is active -> wrong msg type
2527 break;
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);
2581 // $$$ update EPL_DLL_PRES_READY_AFTER_* code
2582 // send PRes frame
2583 Ret = EdrvSendTxMsg(pTxBuffer);
2584 if (Ret != kEplSuccessful) {
2585 goto Exit;
2587 #endif
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);
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) +
2606 > FrameInfo.m_uiFrameSize) { // format error
2607 tEplErrorHandlerkEvent DllEvent;
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;
2627 // forward PReq frame as RPDO to PDO module
2628 Ret = EplPdokCbPdoReceived(&FrameInfo);
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);
2641 #endif
2642 #endif
2644 #if EDRV_EARLY_RX_INT == FALSE
2645 // $$$ inform emergency protocol handling (error signaling module) about flags
2647 #endif
2649 // reset cycle counter
2650 EplDllkInstance_g.m_uiCycleCount = 0;
2652 break;
2655 case kEplMsgTypePres:
2657 #if (((EPL_MODULE_INTEGRATION) & (EPL_MODULE_NMT_MN)) != 0)
2658 tEplDllkNodeInfo *pIntNodeInfo;
2659 tEplHeartbeatEvent HeartbeatEvent;
2660 #endif
2662 // PRes frame
2663 NmtEvent = kEplNmtEventDllCePres;
2665 uiNodeId = AmiGetByteFromLe(&pFrame->m_le_bSrcNodeId);
2667 if ((NmtState >= kEplNmtCsPreOperational2)
2668 && (NmtState <= kEplNmtCsOperational)) { // process PRes frames only in PreOp2, ReadyToOp and Op of CN
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;
2676 } else if (EplDllkInstance_g.m_DllState == kEplDllMsWaitPres) { // or process PRes frames in MsWaitPres
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;
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));
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;
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;
2727 Event.m_NetTime = FrameInfo.m_NetTime;
2728 Ret = EplEventkPost(&Event);
2730 // save current NMT state of CN in internal node structure
2731 pIntNodeInfo->m_NmtState =
2732 HeartbeatEvent.m_NmtState;
2735 #endif
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) +
2746 > FrameInfo.m_uiFrameSize)
2747 #if (((EPL_MODULE_INTEGRATION) & (EPL_MODULE_NMT_MN)) != 0)
2749 (AmiGetWordFromLe
2750 (&pFrame->m_Data.m_Pres.m_le_wSize) >
2751 pIntNodeInfo->m_wPresPayloadLimit)
2752 #endif
2753 ) { // format error
2754 tEplErrorHandlerkEvent DllEvent;
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;
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);
2775 Ret = EplPdokCbPdoReceived(&FrameInfo);
2777 #endif
2779 break;
2782 case kEplMsgTypeSoc:
2784 // SoC frame
2785 NmtEvent = kEplNmtEventDllCeSoc;
2787 if (NmtState >= kEplNmtMsNotActive) { // MN is active -> wrong msg type
2788 break;
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;
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);
2815 // $$$ make function that updates Pres, StatusRes
2816 // mark PRes frame as ready for transmission
2817 Ret = EdrvTxMsgReady(pTxBuffer);
2819 #endif
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);
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;
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);
2846 #endif
2848 break;
2851 case kEplMsgTypeSoa:
2853 // SoA frame
2854 NmtEvent = kEplNmtEventDllCeSoa;
2856 if (NmtState >= kEplNmtMsNotActive) { // MN is active -> wrong msg type
2857 break;
2860 pTxFrame = NULL;
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;
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
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
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;
2915 TGT_DBG_SIGNAL_TRACE_POINT(8);
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 =
2939 // save flag 1 from MN for Status request response cycle
2940 EplDllkInstance_g.m_bMnFlag1 =
2941 bFlag1;
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;
2974 TGT_DBG_SIGNAL_TRACE_POINT(7);
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;
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;
3034 } else if (ReqServiceId == kEplDllReqServiceNo) { // no async service requested -> do nothing
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);
3045 #endif
3047 // inform PDO module
3048 #if (((EPL_MODULE_INTEGRATION) & (EPL_MODULE_PDOK)) != 0)
3049 // Ret = EplPdokCbSoa(&FrameInfo);
3050 #endif
3052 // $$$ put SrcNodeId, NMT state and NetTime as HeartbeatEvent into eventqueue
3054 // $$$ inform emergency protocol handling about flags
3055 break;
3058 case kEplMsgTypeAsnd:
3060 // ASnd frame
3061 NmtEvent = kEplNmtEventDllCeAsnd;
3063 // ASnd service registered?
3064 uiAsndServiceId =
3065 (unsigned int)AmiGetByteFromLe(&pFrame->m_Data.
3066 m_Asnd.
3067 m_le_bServiceId);
3069 #if (((EPL_MODULE_INTEGRATION) & (EPL_MODULE_NMT_MN)) != 0)
3070 if ((EplDllkInstance_g.m_DllState >= kEplDllMsNonCyclic)
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;
3083 if (((tEplDllAsndServiceId) uiAsndServiceId) == kEplDllAsndIdentResponse) { // memorize MAC address of CN for PReq
3084 tEplDllkNodeInfo *pIntNodeInfo;
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);
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));
3106 #endif
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);
3130 break;
3133 default:
3135 break;
3139 if (NmtEvent != kEplNmtEventNoEvent) { // event for DLL and NMT state machine generated
3140 Ret = EplDllkChangeState(NmtEvent, NmtState);
3141 if (Ret != kEplSuccessful) {
3142 goto Exit;
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);
3156 Exit:
3157 if (Ret != kEplSuccessful) {
3158 DWORD dwArg;
3160 BENCHMARK_MOD_02_TOGGLE(9);
3162 dwArg = EplDllkInstance_g.m_DllState | (NmtEvent << 8);
3164 // Error event for API layer
3165 Ret = EplEventkPostError(kEplEventSourceDllk,
3166 Ret, sizeof(dwArg), &dwArg);
3168 BENCHMARK_MOD_02_RESET(3);
3169 return;
3172 //---------------------------------------------------------------------------
3174 // Function: EplDllkCbFrameTransmitted()
3176 // Description: called from EdrvInterruptHandler().
3177 // It signals
3179 // Parameters: pRxBuffer_p = receive buffer structure
3181 // Returns: (none)
3184 // State:
3186 //---------------------------------------------------------------------------
3188 static void EplDllkCbFrameTransmitted(tEdrvTxBuffer * pTxBuffer_p)
3190 tEplKernel Ret = kEplSuccessful;
3191 tEplEvent Event;
3192 tEplDllAsyncReqPriority Priority;
3193 tEplNmtState NmtState;
3195 #if (((EPL_MODULE_INTEGRATION) & (EPL_MODULE_PDOK)) != 0) \
3196 && (EPL_DLL_PRES_READY_AFTER_SOC == FALSE)
3197 tEplFrameInfo FrameInfo;
3198 #endif
3200 NmtState = EplNmtkGetNmtState();
3202 if (NmtState <= kEplNmtGsResetConfiguration) {
3203 goto Exit;
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;
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;
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);
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
3237 #if ((((EPL_MODULE_INTEGRATION) & (EPL_MODULE_PDOK)) != 0) \
3238 && (EPL_DLL_PRES_READY_AFTER_SOC == FALSE))
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);
3246 #endif
3248 #if (((EPL_MODULE_INTEGRATION) & (EPL_MODULE_NMT_MN)) != 0)
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);
3260 #endif
3262 #if EPL_DLL_PRES_READY_AFTER_SOA != FALSE
3263 goto Exit;
3264 #endif
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;
3271 // check if we are invited
3272 if (EplDllkInstance_g.m_uiLastTargetNodeId ==
3273 EplDllkInstance_g.m_DllConfigParam.m_uiNodeId) {
3274 tEplFrame *pTxFrame;
3276 if (EplDllkInstance_g.m_LastReqServiceId == kEplDllReqServiceStatus) { // StatusRequest
3277 if (EplDllkInstance_g.m_pTxBuffer[EPL_DLLK_TXFRAME_STATUSRES].m_pbBuffer != NULL) { // StatusRes does exist
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;
3310 TGT_DBG_SIGNAL_TRACE_POINT(8);
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;
3340 TGT_DBG_SIGNAL_TRACE_POINT(7);
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.
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)
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);
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;
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;
3420 // ASnd frame was sent, remove the request
3421 EplDllkInstance_g.m_LastReqServiceId =
3422 kEplDllReqServiceNo;
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;
3434 #endif
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;
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);
3448 #endif
3450 Exit:
3451 if (Ret != kEplSuccessful) {
3452 DWORD dwArg;
3454 BENCHMARK_MOD_02_TOGGLE(9);
3456 dwArg =
3457 EplDllkInstance_g.m_DllState | (pTxBuffer_p->
3458 m_EplMsgType << 16);
3460 // Error event for API layer
3461 Ret = EplEventkPostError(kEplEventSourceDllk,
3462 Ret, sizeof(dwArg), &dwArg);
3465 return;
3468 //---------------------------------------------------------------------------
3470 // Function: EplDllkCheckFrame()
3472 // Description: check frame and set missing information
3474 // Parameters: pFrame_p = ethernet frame
3475 // uiFrameSize_p = size of frame
3477 // Returns: tEplKernel = error code
3480 // State:
3482 //---------------------------------------------------------------------------
3484 static tEplKernel EplDllkCheckFrame(tEplFrame * pFrame_p,
3485 unsigned int uiFrameSize_p)
3487 tEplMsgType MsgType;
3488 WORD wEtherType;
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);
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);
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);
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);
3521 if (MsgType == kEplMsgTypeAsnd) {
3522 // destination MAC address
3523 AmiSetQword48ToBe(&pFrame_p->m_be_abDstMac[0],
3524 EPL_C_DLL_MULTICAST_ASND);
3530 return kEplSuccessful;
3533 //---------------------------------------------------------------------------
3535 // Function: EplDllkCbCnTimer()
3537 // Description: called by timer module. It monitors the EPL cycle when it is a CN.
3539 // Parameters: pEventArg_p = timer event argument
3541 // Returns: tEplKernel = error code
3544 // State:
3546 //---------------------------------------------------------------------------
3548 #if EPL_TIMER_USE_HIGHRES != FALSE
3549 static tEplKernel PUBLIC EplDllkCbCnTimer(tEplTimerEventArg * pEventArg_p)
3551 tEplKernel Ret = kEplSuccessful;
3552 tEplNmtState NmtState;
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;
3559 #endif
3561 NmtState = EplNmtkGetNmtState();
3563 if (NmtState <= kEplNmtGsResetConfiguration) {
3564 goto Exit;
3567 Ret = EplDllkChangeState(kEplNmtEventDllCeFrameTimeout, NmtState);
3568 if (Ret != kEplSuccessful) {
3569 goto Exit;
3571 // 2008/10/15 d.k. reprogramming of timer not necessary,
3572 // because it will be programmed, when SoC is received.
3574 // reprogram timer
3575 #if EPL_TIMER_USE_HIGHRES != FALSE
3576 if ((NmtState > kEplNmtCsPreOperational1)
3577 && (EplDllkInstance_g.m_ullFrameTimeout != 0))
3579 Ret = EplTimerHighReskModifyTimerNs(&EplDllkInstance_g.m_TimerHdlCycle, EplDllkInstance_g.m_ullFrameTimeout, EplDllkCbCnTimer, 0L, FALSE);
3581 #endif
3584 Exit:
3585 if (Ret != kEplSuccessful) {
3586 DWORD dwArg;
3588 BENCHMARK_MOD_02_TOGGLE(9);
3590 dwArg =
3591 EplDllkInstance_g.
3592 m_DllState | (kEplNmtEventDllCeFrameTimeout << 8);
3594 // Error event for API layer
3595 Ret = EplEventkPostError(kEplEventSourceDllk,
3596 Ret, sizeof(dwArg), &dwArg);
3599 return Ret;
3601 #endif
3603 #if (((EPL_MODULE_INTEGRATION) & (EPL_MODULE_NMT_MN)) != 0)
3605 //---------------------------------------------------------------------------
3607 // Function: EplDllkCbMnTimerCycle()
3609 // Description: called by timer module. It triggers the SoC when it is a MN.
3611 // Parameters: pEventArg_p = timer event argument
3613 // Returns: tEplKernel = error code
3616 // State:
3618 //---------------------------------------------------------------------------
3620 static tEplKernel PUBLIC EplDllkCbMnTimerCycle(tEplTimerEventArg * pEventArg_p)
3622 tEplKernel Ret = kEplSuccessful;
3623 tEplNmtState NmtState;
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;
3630 #endif
3632 NmtState = EplNmtkGetNmtState();
3634 if (NmtState <= kEplNmtGsResetConfiguration) {
3635 goto Exit;
3638 Ret = EplDllkChangeState(kEplNmtEventDllMeSocTrig, NmtState);
3640 Exit:
3641 if (Ret != kEplSuccessful) {
3642 DWORD dwArg;
3644 BENCHMARK_MOD_02_TOGGLE(9);
3646 dwArg =
3647 EplDllkInstance_g.
3648 m_DllState | (kEplNmtEventDllMeSocTrig << 8);
3650 // Error event for API layer
3651 Ret = EplEventkPostError(kEplEventSourceDllk,
3652 Ret, sizeof(dwArg), &dwArg);
3655 return Ret;
3658 //---------------------------------------------------------------------------
3660 // Function: EplDllkCbMnTimerResponse()
3662 // Description: called by timer module. It monitors the PRes timeout.
3664 // Parameters: pEventArg_p = timer event argument
3666 // Returns: tEplKernel = error code
3669 // State:
3671 //---------------------------------------------------------------------------
3673 static tEplKernel PUBLIC EplDllkCbMnTimerResponse(tEplTimerEventArg *
3674 pEventArg_p)
3676 tEplKernel Ret = kEplSuccessful;
3677 tEplNmtState NmtState;
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;
3684 #endif
3686 NmtState = EplNmtkGetNmtState();
3688 if (NmtState <= kEplNmtGsResetConfiguration) {
3689 goto Exit;
3692 Ret = EplDllkChangeState(kEplNmtEventDllMePresTimeout, NmtState);
3694 Exit:
3695 if (Ret != kEplSuccessful) {
3696 DWORD dwArg;
3698 BENCHMARK_MOD_02_TOGGLE(9);
3700 dwArg =
3701 EplDllkInstance_g.
3702 m_DllState | (kEplNmtEventDllMePresTimeout << 8);
3704 // Error event for API layer
3705 Ret = EplEventkPostError(kEplEventSourceDllk,
3706 Ret, sizeof(dwArg), &dwArg);
3709 return Ret;
3712 //---------------------------------------------------------------------------
3714 // Function: EplDllkGetNodeInfo()
3716 // Description: returns node info structure of the specified node.
3718 // Parameters: uiNodeId_p = node ID
3720 // Returns: tEplDllkNodeInfo* = pointer to internal node info structure
3723 // State:
3725 //---------------------------------------------------------------------------
3727 static tEplDllkNodeInfo *EplDllkGetNodeInfo(unsigned int uiNodeId_p)
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];
3739 //---------------------------------------------------------------------------
3741 // Function: EplDllkMnSendSoa()
3743 // Description: it updates and transmits the SoA.
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
3750 // Returns: tEplKernel = error code
3753 // State:
3755 //---------------------------------------------------------------------------
3757 static tEplKernel EplDllkMnSendSoa(tEplNmtState NmtState_p,
3758 tEplDllState * pDllStateProposed_p,
3759 BOOL fEnableInvitation_p)
3761 tEplKernel Ret = kEplSuccessful;
3762 tEdrvTxBuffer *pTxBuffer = NULL;
3763 tEplFrame *pTxFrame;
3764 tEplDllkNodeInfo *pNodeInfo;
3766 *pDllStateProposed_p = kEplDllMsNonCyclic;
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;
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;
3783 Ret =
3784 EplDllkCalAsyncGetSoaRequest(&EplDllkInstance_g.
3785 m_LastReqServiceId,
3786 &EplDllkInstance_g.
3787 m_uiLastTargetNodeId);
3788 if (Ret != kEplSuccessful) {
3789 goto Exit;
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;
3807 pNodeInfo =
3808 EplDllkGetNodeInfo(EplDllkInstance_g.
3809 m_uiLastTargetNodeId);
3810 if (pNodeInfo == NULL) { // no node info structure available
3811 Ret = kEplDllNoNodeInfo;
3812 goto Exit;
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
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;
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);
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);
3845 // update frame (NMT state)
3846 AmiSetByteToLe(&pTxFrame->m_Data.m_Soa.m_le_bNmtStatus,
3847 (BYTE) NmtState_p);
3849 // send SoA frame
3850 Ret = EdrvSendTxMsg(pTxBuffer);
3853 Exit:
3854 return Ret;
3857 //---------------------------------------------------------------------------
3859 // Function: EplDllkMnSendSoc()
3861 // Description: it updates and transmits the SoA.
3863 // Parameters: (none)
3865 // Returns: tEplKernel = error code
3868 // State:
3870 //---------------------------------------------------------------------------
3872 static tEplKernel EplDllkMnSendSoc(void)
3874 tEplKernel Ret = kEplSuccessful;
3875 tEdrvTxBuffer *pTxBuffer = NULL;
3876 tEplFrame *pTxFrame;
3877 tEplEvent Event;
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;
3883 // $$$ update NetTime
3885 // send SoC frame
3886 Ret = EdrvSendTxMsg(pTxBuffer);
3887 if (Ret != kEplSuccessful) {
3888 goto Exit;
3890 // trigger synchronous task
3891 Event.m_EventSink = kEplEventSinkSync;
3892 Event.m_EventType = kEplEventTypeSync;
3893 Event.m_uiSize = 0;
3894 Ret = EplEventkPost(&Event);
3897 Exit:
3898 return Ret;
3901 //---------------------------------------------------------------------------
3903 // Function: EplDllkMnSendPreq()
3905 // Description: it updates and transmits the PReq for the next isochronous CN
3906 // or own PRes if enabled.
3908 // Parameters: NmtState_p = current NMT state
3909 // pDllStateProposed_p = proposed DLL state
3911 // Returns: tEplKernel = error code
3914 // State:
3916 //---------------------------------------------------------------------------
3918 static tEplKernel EplDllkMnSendPreq(tEplNmtState NmtState_p,
3919 tEplDllState * pDllStateProposed_p)
3921 tEplKernel Ret = kEplSuccessful;
3922 tEdrvTxBuffer *pTxBuffer = NULL;
3923 tEplFrame *pTxFrame;
3924 BYTE bFlag1 = 0;
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;
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;
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
3958 if (pTxBuffer == NULL) { // PReq does not exist
3959 Ret = kEplDllTxBufNotReady;
3960 goto Exit;
3963 pTxFrame = (tEplFrame *) pTxBuffer->m_pbBuffer;
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;
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;
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);
3982 // calculate frame size from payload size
3983 pTxBuffer->m_uiTxMsgLen =
3984 AmiGetWordFromLe(&pTxFrame->m_Data.m_Preq.m_le_wSize) + 24;
3986 // send PReq frame
3987 Ret = EdrvSendTxMsg(pTxBuffer);
3988 } else {
3989 Ret = kEplDllTxFrameInvalid;
3992 Exit:
3993 return Ret;
3996 //---------------------------------------------------------------------------
3998 // Function: EplDllkAsyncFrameNotReceived()
4000 // Description: passes empty ASnd frame to receive FIFO.
4001 // It will be called only for frames with registered AsndServiceIds
4002 // (only kEplDllAsndFilterAny).
4004 // Parameters: none
4006 // Returns: tEplKernel = error code
4009 // State:
4011 //---------------------------------------------------------------------------
4013 static tEplKernel EplDllkAsyncFrameNotReceived(tEplDllReqServiceId
4014 ReqServiceId_p,
4015 unsigned int uiNodeId_p)
4017 tEplKernel Ret = kEplSuccessful;
4018 BYTE abBuffer[18];
4019 tEplFrame *pFrame = (tEplFrame *) abBuffer;
4020 tEplFrameInfo FrameInfo;
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);
4042 break;
4043 default:
4044 // no invitation issued or it was successfully answered or it is uninteresting
4045 break;
4048 return Ret;
4051 #endif //(((EPL_MODULE_INTEGRATION) & (EPL_MODULE_NMT_MN)) != 0)
4053 #endif // #if(((EPL_MODULE_INTEGRATION) & (EPL_MODULE_DLLK)) != 0)
4054 // EOF