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