ALSA: hda - Tweak OLPC XO-1.5 microphone bias
[linux-2.6/linux-acpi-2.6/ibm-acpi-2.6.git] / drivers / staging / epl / EplDllk.c
blob25d2c34325db27b6e1d5801c0e52d77bac115184
1 /****************************************************************************
3 (c) SYSTEC electronic GmbH, D-07973 Greiz, August-Bebel-Str. 29
4 www.systec-electronic.com
6 Project: openPOWERLINK
8 Description: source file for kernel DLL module
10 License:
12 Redistribution and use in source and binary forms, with or without
13 modification, are permitted provided that the following conditions
14 are met:
16 1. Redistributions of source code must retain the above copyright
17 notice, this list of conditions and the following disclaimer.
19 2. Redistributions in binary form must reproduce the above copyright
20 notice, this list of conditions and the following disclaimer in the
21 documentation and/or other materials provided with the distribution.
23 3. Neither the name of SYSTEC electronic GmbH nor the names of its
24 contributors may be used to endorse or promote products derived
25 from this software without prior written permission. For written
26 permission, please contact info@systec-electronic.com.
28 THIS SOFTWARE IS PROVIDED BY THE COPYRIGHT HOLDERS AND CONTRIBUTORS
29 "AS IS" AND ANY EXPRESS OR IMPLIED WARRANTIES, INCLUDING, BUT NOT
30 LIMITED TO, THE IMPLIED WARRANTIES OF MERCHANTABILITY AND FITNESS
31 FOR A PARTICULAR PURPOSE ARE DISCLAIMED. IN NO EVENT SHALL THE
32 COPYRIGHT HOLDERS OR CONTRIBUTORS BE LIABLE FOR ANY DIRECT, INDIRECT,
33 INCIDENTAL, SPECIAL, EXEMPLARY, OR CONSEQUENTIAL DAMAGES (INCLUDING,
34 BUT NOT LIMITED TO, PROCUREMENT OF SUBSTITUTE GOODS OR SERVICES;
35 LOSS OF USE, DATA, OR PROFITS; OR BUSINESS INTERRUPTION) HOWEVER
36 CAUSED AND ON ANY THEORY OF LIABILITY, WHETHER IN CONTRACT, STRICT
37 LIABILITY, OR TORT (INCLUDING NEGLIGENCE OR OTHERWISE) ARISING IN
38 ANY WAY OUT OF THE USE OF THIS SOFTWARE, EVEN IF ADVISED OF THE
39 POSSIBILITY OF SUCH DAMAGE.
41 Severability Clause:
43 If a provision of this License is or becomes illegal, invalid or
44 unenforceable in any jurisdiction, that shall not affect:
45 1. the validity or enforceability in that jurisdiction of any other
46 provision of this License; or
47 2. the validity or enforceability in other jurisdictions of that or
48 any other provision of this License.
50 -------------------------------------------------------------------------
52 $RCSfile: EplDllk.c,v $
54 $Author: D.Krueger $
56 $Revision: 1.21 $ $Date: 2008/11/13 17:13:09 $
58 $State: Exp $
60 Build Environment:
61 GCC V3.4
63 -------------------------------------------------------------------------
65 Revision History:
67 2006/06/12 d.k.: start of the implementation, version 1.00
69 ****************************************************************************/
71 #include "kernel/EplDllk.h"
72 #include "kernel/EplDllkCal.h"
73 #include "kernel/EplEventk.h"
74 #include "kernel/EplNmtk.h"
75 #include "edrv.h"
76 #include "Benchmark.h"
78 #if (((EPL_MODULE_INTEGRATION) & (EPL_MODULE_PDOK)) != 0)
79 #include "kernel/EplPdok.h"
80 #endif
82 #if (((EPL_MODULE_INTEGRATION) & (EPL_MODULE_VETH)) != 0)
83 #include "kernel/VirtualEthernet.h"
84 #endif
86 //#if EPL_TIMER_USE_HIGHRES != FALSE
87 #include "kernel/EplTimerHighResk.h"
88 //#endif
90 #if(((EPL_MODULE_INTEGRATION) & (EPL_MODULE_DLLK)) != 0)
92 #if(((EPL_MODULE_INTEGRATION) & (EPL_MODULE_NMTK)) == 0)
93 #error "EPL module DLLK needs EPL module NMTK!"
94 #endif
96 #if (EPL_DLL_PRES_READY_AFTER_SOA != FALSE) && (EPL_DLL_PRES_READY_AFTER_SOC != FALSE)
97 #error "EPL module DLLK: select only one of EPL_DLL_PRES_READY_AFTER_SOA and EPL_DLL_PRES_READY_AFTER_SOC."
98 #endif
100 #if ((EPL_DLL_PRES_READY_AFTER_SOA != FALSE) || (EPL_DLL_PRES_READY_AFTER_SOC != FALSE)) \
101 && (((EPL_MODULE_INTEGRATION) & (EPL_MODULE_NMT_MN)) == 0)
102 #error "EPL module DLLK: currently, EPL_DLL_PRES_READY_AFTER_* is not supported if EPL_MODULE_NMT_MN is enabled."
103 #endif
105 #if (EDRV_FAST_TXFRAMES == FALSE) && \
106 ((EPL_DLL_PRES_READY_AFTER_SOA != FALSE) || (EPL_DLL_PRES_READY_AFTER_SOC != FALSE))
107 #error "EPL module DLLK: EPL_DLL_PRES_READY_AFTER_* is enabled, but not EDRV_FAST_TXFRAMES."
108 #endif
110 /***************************************************************************/
111 /* */
112 /* */
113 /* G L O B A L D E F I N I T I O N S */
114 /* */
115 /* */
116 /***************************************************************************/
118 //---------------------------------------------------------------------------
119 // const defines
120 //---------------------------------------------------------------------------
122 // TracePoint support for realtime-debugging
123 #ifdef _DBG_TRACE_POINTS_
124 void 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)
136 /***************************************************************************/
137 /* */
138 /* */
139 /* C L A S S EplDllk */
140 /* */
141 /* */
142 /***************************************************************************/
144 // Description:
147 /***************************************************************************/
149 //=========================================================================//
150 // //
151 // P R I V A T E D E F I N I T I O N S //
152 // //
153 //=========================================================================//
155 //---------------------------------------------------------------------------
156 // const defines
157 //---------------------------------------------------------------------------
159 // defines for indexes of tEplDllInstance.m_pTxFrameInfo
160 #define EPL_DLLK_TXFRAME_IDENTRES 0 // IdentResponse on CN / MN
161 #define EPL_DLLK_TXFRAME_STATUSRES 1 // StatusResponse on CN / MN
162 #define EPL_DLLK_TXFRAME_NMTREQ 2 // NMT Request from FIFO on CN / MN
163 #define EPL_DLLK_TXFRAME_NONEPL 3 // non-EPL frame from FIFO on CN / MN
164 #define EPL_DLLK_TXFRAME_PRES 4 // PRes on CN / MN
165 #define EPL_DLLK_TXFRAME_SOC 5 // SoC on MN
166 #define EPL_DLLK_TXFRAME_SOA 6 // SoA on MN
167 #define EPL_DLLK_TXFRAME_PREQ 7 // PReq on MN
168 #if(((EPL_MODULE_INTEGRATION) & (EPL_MODULE_NMT_MN)) != 0)
169 #define EPL_DLLK_TXFRAME_COUNT (7 + EPL_D_NMT_MaxCNNumber_U8 + 2) // on MN: 7 + MaxPReq of regular CNs + 1 Diag + 1 Router
170 #else
171 #define EPL_DLLK_TXFRAME_COUNT 5 // on CN: 5
172 #endif
174 #define EPL_DLLK_BUFLEN_EMPTY 0 // buffer is empty
175 #define EPL_DLLK_BUFLEN_FILLING 1 // just the buffer is being filled
176 #define EPL_DLLK_BUFLEN_MIN 60 // minimum ethernet frame length
178 //---------------------------------------------------------------------------
179 // local types
180 //---------------------------------------------------------------------------
182 typedef enum {
183 kEplDllGsInit = 0x00, // MN/CN: initialisation (< PreOp2)
184 kEplDllCsWaitPreq = 0x01, // CN: wait for PReq frame
185 kEplDllCsWaitSoc = 0x02, // CN: wait for SoC frame
186 kEplDllCsWaitSoa = 0x03, // CN: wait for SoA frame
187 kEplDllMsNonCyclic = 0x04, // MN: reduced EPL cycle (PreOp1)
188 kEplDllMsWaitSocTrig = 0x05, // MN: wait for SoC trigger (cycle timer)
189 kEplDllMsWaitPreqTrig = 0x06, // MN: wait for (first) PReq trigger (WaitSoCPReq_U32)
190 kEplDllMsWaitPres = 0x07, // MN: wait for PRes frame from CN
191 kEplDllMsWaitSoaTrig = 0x08, // MN: wait for SoA trigger (PRes transmitted)
192 kEplDllMsWaitAsndTrig = 0x09, // MN: wait for ASnd trigger (SoA transmitted)
193 kEplDllMsWaitAsnd = 0x0A, // MN: wait for ASnd frame if SoA contained invitation
195 } tEplDllState;
197 typedef struct {
198 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];
210 #if (((EPL_MODULE_INTEGRATION) & (EPL_MODULE_NMT_MN)) != 0)
211 tEplDllkNodeInfo *m_pFirstNodeInfo;
212 tEplDllkNodeInfo *m_pCurNodeInfo;
213 tEplDllkNodeInfo m_aNodeInfo[EPL_NMT_MAX_NODE_ID];
214 tEplDllReqServiceId m_LastReqServiceId;
215 unsigned int m_uiLastTargetNodeId;
216 #endif
218 #if EPL_TIMER_USE_HIGHRES != FALSE
219 tEplTimerHdl m_TimerHdlCycle; // used for EPL cycle monitoring on CN and generation on MN
220 #if (((EPL_MODULE_INTEGRATION) & (EPL_MODULE_NMT_MN)) != 0)
221 tEplTimerHdl m_TimerHdlResponse; // used for CN response monitoring
222 #endif //(((EPL_MODULE_INTEGRATION) & (EPL_MODULE_NMT_MN)) != 0)
223 #endif
225 unsigned int m_uiCycleCount; // cycle counter (needed for multiplexed cycle support)
226 unsigned long long m_ullFrameTimeout; // frame timeout (cycle length + loss of frame tolerance)
228 } tEplDllkInstance;
230 //---------------------------------------------------------------------------
231 // local vars
232 //---------------------------------------------------------------------------
234 // if no dynamic memory allocation shall be used
235 // define structures statically
236 static tEplDllkInstance EplDllkInstance_g;
238 static tEdrvTxBuffer aEplDllkTxBuffer_l[EPL_DLLK_TXFRAME_COUNT];
240 //---------------------------------------------------------------------------
241 // local function prototypes
242 //---------------------------------------------------------------------------
244 // change DLL state on event
245 static tEplKernel EplDllkChangeState(tEplNmtEvent NmtEvent_p,
246 tEplNmtState NmtState_p);
248 // called from EdrvInterruptHandler()
249 static void EplDllkCbFrameReceived(tEdrvRxBuffer * pRxBuffer_p);
251 // called from EdrvInterruptHandler()
252 static void EplDllkCbFrameTransmitted(tEdrvTxBuffer * pTxBuffer_p);
254 // check frame and set missing information
255 static tEplKernel EplDllkCheckFrame(tEplFrame * pFrame_p,
256 unsigned int uiFrameSize_p);
258 // called by high resolution timer module to monitor EPL cycle as CN
259 #if EPL_TIMER_USE_HIGHRES != FALSE
260 static tEplKernel EplDllkCbCnTimer(tEplTimerEventArg *pEventArg_p);
261 #endif
263 #if (((EPL_MODULE_INTEGRATION) & (EPL_MODULE_NMT_MN)) != 0)
264 // MN: returns internal node info structure
265 static tEplDllkNodeInfo *EplDllkGetNodeInfo(unsigned int uiNodeId_p);
267 // transmit SoA
268 static tEplKernel EplDllkMnSendSoa(tEplNmtState NmtState_p,
269 tEplDllState * pDllStateProposed_p,
270 BOOL fEnableInvitation_p);
272 static tEplKernel EplDllkMnSendSoc(void);
274 static tEplKernel EplDllkMnSendPreq(tEplNmtState NmtState_p,
275 tEplDllState * pDllStateProposed_p);
277 static tEplKernel EplDllkAsyncFrameNotReceived(tEplDllReqServiceId
278 ReqServiceId_p,
279 unsigned int uiNodeId_p);
281 static tEplKernel EplDllkCbMnTimerCycle(tEplTimerEventArg *pEventArg_p);
283 static tEplKernel EplDllkCbMnTimerResponse(tEplTimerEventArg *pEventArg_p);
285 #endif
287 //=========================================================================//
288 // //
289 // P U B L I C F U N C T I O N S //
290 // //
291 //=========================================================================//
293 //---------------------------------------------------------------------------
295 // Function: EplDllkAddInstance()
297 // Description: add and initialize new instance of EPL stack
299 // Parameters: pInitParam_p = initialisation parameters like MAC address
301 // Returns: tEplKernel = error code
304 // State:
306 //---------------------------------------------------------------------------
308 tEplKernel EplDllkAddInstance(tEplDllkInitParam * pInitParam_p)
310 tEplKernel Ret = kEplSuccessful;
311 unsigned int uiIndex;
312 tEdrvInitParam EdrvInitParam;
314 // reset instance structure
315 EPL_MEMSET(&EplDllkInstance_g, 0, sizeof(EplDllkInstance_g));
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;
322 #endif
324 // if dynamic memory allocation available
325 // allocate instance structure
326 // allocate TPDO and RPDO table with default size
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);
333 // initialize state
334 EplDllkInstance_g.m_DllState = kEplDllGsInit;
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;
344 #endif
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;
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,
358 EPL_MEMCPY(pInitParam_p->m_be_abSrcMac, EdrvInitParam.m_abMyMacAddr, 6);
360 // initialize TxBuffer array
361 for (uiIndex = 0; uiIndex < EplDllkInstance_g.m_uiMaxTxFrames;
362 uiIndex++) {
363 EplDllkInstance_g.m_pTxBuffer[uiIndex].m_pbBuffer = NULL;
366 #if (((EPL_MODULE_INTEGRATION) & (EPL_MODULE_VETH)) != 0)
367 Ret = VEthAddInstance(pInitParam_p);
368 #endif
370 Exit:
371 return Ret;
374 //---------------------------------------------------------------------------
376 // Function: EplDllkDelInstance()
378 // Description: deletes an instance of EPL stack
380 // Parameters: (none)
382 // Returns: tEplKernel = error code
385 // State:
387 //---------------------------------------------------------------------------
389 tEplKernel EplDllkDelInstance(void)
391 tEplKernel Ret = kEplSuccessful;
393 // reset state
394 EplDllkInstance_g.m_DllState = kEplDllGsInit;
396 #if EPL_TIMER_USE_HIGHRES != FALSE
397 Ret = EplTimerHighReskDelInstance();
398 #endif
400 #if (((EPL_MODULE_INTEGRATION) & (EPL_MODULE_VETH)) != 0)
401 Ret = VEthDelInstance();
402 #endif
404 Ret = EdrvShutdown();
405 return Ret;
408 //---------------------------------------------------------------------------
410 // Function: EplDllkCreateTxFrame
412 // Description: creates the buffer for a Tx frame and registers it to the
413 // ethernet driver
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
425 // Returns: tEplKernel = error code
428 // State:
430 //---------------------------------------------------------------------------
432 tEplKernel EplDllkCreateTxFrame(unsigned int *puiHandle_p,
433 tEplFrame ** ppFrame_p,
434 unsigned int *puiFrameSize_p,
435 tEplMsgType MsgType_p,
436 tEplDllAsndServiceId ServiceId_p)
438 tEplKernel Ret = kEplSuccessful;
439 tEplFrame *pTxFrame;
440 unsigned int uiHandle = EplDllkInstance_g.m_uiMaxTxFrames;
441 tEdrvTxBuffer *pTxBuffer = NULL;
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;
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;
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;
481 if (pTxBuffer->m_pbBuffer != NULL) {
482 Ret = kEplEdrvNoFreeBufEntry;
483 goto Exit;
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;
493 // setup Tx buffer
494 pTxBuffer->m_EplMsgType = MsgType_p;
495 pTxBuffer->m_uiMaxBufferLen = *puiFrameSize_p;
497 Ret = EdrvAllocTxMsgBuffer(pTxBuffer);
498 if (Ret != kEplSuccessful) { // error occured while registering Tx frame
499 goto Exit;
501 // because buffer size may be larger than requested
502 // memorize real length of frame
503 pTxBuffer->m_uiTxMsgLen = *puiFrameSize_p;
505 // fill whole frame with 0
506 EPL_MEMSET(pTxBuffer->m_pbBuffer, 0, pTxBuffer->m_uiMaxBufferLen);
508 pTxFrame = (tEplFrame *) pTxBuffer->m_pbBuffer;
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;
538 default:
539 break;
541 // ASnd Service ID
542 AmiSetByteToLe(&pTxFrame->m_Data.m_Asnd.m_le_bServiceId,
543 ServiceId_p);
544 break;
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;
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;
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;
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;
595 default:
596 break;
598 // EPL message type
599 AmiSetByteToLe(&pTxFrame->m_le_bMessageType, (u8) MsgType_p);
602 *ppFrame_p = pTxFrame;
603 *puiFrameSize_p = pTxBuffer->m_uiMaxBufferLen;
604 *puiHandle_p = uiHandle;
606 Exit:
607 return Ret;
610 //---------------------------------------------------------------------------
612 // Function: EplDllkDeleteTxFrame
614 // Description: deletes the buffer for a Tx frame and frees it in the
615 // ethernet driver
617 // Parameters: uiHandle_p = IN: handle to frame buffer
619 // Returns: tEplKernel = error code
622 // State:
624 //---------------------------------------------------------------------------
626 tEplKernel EplDllkDeleteTxFrame(unsigned int uiHandle_p)
628 tEplKernel Ret = kEplSuccessful;
629 tEdrvTxBuffer *pTxBuffer = NULL;
631 if (uiHandle_p >= EplDllkInstance_g.m_uiMaxTxFrames) { // handle is not valid
632 Ret = kEplDllIllegalHdl;
633 goto Exit;
636 pTxBuffer = &EplDllkInstance_g.m_pTxBuffer[uiHandle_p];
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;
643 // delete Tx buffer
644 Ret = EdrvReleaseTxMsgBuffer(pTxBuffer);
645 if (Ret != kEplSuccessful) { // error occured while releasing Tx frame
646 goto Exit;
649 Exit:
650 return Ret;
653 //---------------------------------------------------------------------------
655 // Function: EplDllkProcess
657 // Description: process the passed event
659 // Parameters: pEvent_p = event to be processed
661 // Returns: tEplKernel = error code
664 // State:
666 //---------------------------------------------------------------------------
668 tEplKernel EplDllkProcess(tEplEvent * pEvent_p)
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
683 switch (pEvent_p->m_EventType) {
684 case kEplEventTypeDllkCreate:
686 // $$$ reset ethernet driver
688 NmtState = *((tEplNmtState *) pEvent_p->m_pArg);
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;
695 #if (((EPL_MODULE_INTEGRATION) & (EPL_MODULE_NMT_MN)) != 0)
696 // initialize linked node list
697 EplDllkInstance_g.m_pFirstNodeInfo = NULL;
698 #endif
700 // register TxFrames in Edrv
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;
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));
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;
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;
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;
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;
874 // mark Tx buffer as empty
875 EplDllkInstance_g.m_pTxBuffer[uiHandle].m_uiTxMsgLen =
876 EPL_DLLK_BUFLEN_EMPTY;
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;
888 // mark Tx buffer as empty
889 EplDllkInstance_g.m_pTxBuffer[uiHandle].m_uiTxMsgLen =
890 EPL_DLLK_BUFLEN_EMPTY;
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);
906 #if (((EPL_MODULE_INTEGRATION) & (EPL_MODULE_NMT_MN)) != 0)
907 if (NmtState >= kEplNmtMsNotActive) { // local node is MN
908 unsigned int uiIndex;
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;
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;
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;
943 // calculate cycle length
944 EplDllkInstance_g.m_ullFrameTimeout = 1000LL
946 ((unsigned long long)EplDllkInstance_g.
947 m_DllConfigParam.m_dwCycleLen);
949 #endif //(((EPL_MODULE_INTEGRATION) & (EPL_MODULE_NMT_MN)) != 0)
951 Ret = EplDllkCalAsyncClearBuffer();
953 break;
956 case kEplEventTypeDllkDestroy:
958 // destroy all data structures
960 NmtState = *((tEplNmtState *) pEvent_p->m_pArg);
962 // delete Tx frames
963 Ret = EplDllkDeleteTxFrame(EPL_DLLK_TXFRAME_IDENTRES);
964 if (Ret != kEplSuccessful) { // error occured while deregistering Tx frame
965 goto Exit;
968 Ret = EplDllkDeleteTxFrame(EPL_DLLK_TXFRAME_STATUSRES);
969 if (Ret != kEplSuccessful) { // error occured while deregistering Tx frame
970 goto Exit;
973 Ret = EplDllkDeleteTxFrame(EPL_DLLK_TXFRAME_PRES);
974 if (Ret != kEplSuccessful) { // error occured while deregistering Tx frame
975 goto Exit;
978 Ret = EplDllkDeleteTxFrame(EPL_DLLK_TXFRAME_NMTREQ);
979 if (Ret != kEplSuccessful) { // error occured while deregistering Tx frame
980 goto Exit;
983 Ret = EplDllkDeleteTxFrame(EPL_DLLK_TXFRAME_NONEPL);
984 if (Ret != kEplSuccessful) { // error occured while deregistering Tx frame
985 goto Exit;
987 #if (((EPL_MODULE_INTEGRATION) & (EPL_MODULE_NMT_MN)) != 0)
988 if (NmtState >= kEplNmtMsNotActive) { // local node was MN
989 unsigned int uiIndex;
991 Ret =
992 EplDllkDeleteTxFrame(EPL_DLLK_TXFRAME_SOC);
993 if (Ret != kEplSuccessful) { // error occured while deregistering Tx frame
994 goto Exit;
997 Ret =
998 EplDllkDeleteTxFrame(EPL_DLLK_TXFRAME_SOA);
999 if (Ret != kEplSuccessful) { // error occured while deregistering Tx frame
1000 goto Exit;
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;
1027 EplDllkInstance_g.m_aNodeInfo[uiIndex].
1028 m_wPresPayloadLimit = 0xFFFF;
1031 #endif //(((EPL_MODULE_INTEGRATION) & (EPL_MODULE_NMT_MN)) != 0)
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);
1047 // delete timer
1048 #if EPL_TIMER_USE_HIGHRES != FALSE
1049 Ret =
1050 EplTimerHighReskDeleteTimer(&EplDllkInstance_g.
1051 m_TimerHdlCycle);
1052 #endif
1054 break;
1057 case kEplEventTypeDllkFillTx:
1059 // fill TxBuffer of specified priority with new frame if empty
1061 pTxFrame = NULL;
1062 AsyncReqPriority =
1063 *((tEplDllAsyncReqPriority *) pEvent_p->m_pArg);
1064 switch (AsyncReqPriority) {
1065 case kEplDllAsyncReqPrioNmt: // NMT request priority
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
1095 pTxBuffer->
1096 m_pbBuffer;
1097 Ret =
1098 EplDllkCheckFrame
1099 (pTxFrame,
1100 uiFrameSize);
1102 // set buffer valid
1103 pTxBuffer->
1104 m_uiTxMsgLen
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
1115 EPL_DLLK_BUFLEN_EMPTY;
1119 break;
1122 default: // generic priority
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
1152 pTxBuffer->
1153 m_pbBuffer;
1154 Ret =
1155 EplDllkCheckFrame
1156 (pTxFrame,
1157 uiFrameSize);
1159 // set buffer valid
1160 pTxBuffer->
1161 m_uiTxMsgLen
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
1172 EPL_DLLK_BUFLEN_EMPTY;
1176 break;
1180 NmtState = EplNmtkGetNmtState();
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]);
1201 if (Ret == kEplInvalidOperation) { // ignore error if caused by already active transmission
1202 Ret = kEplSuccessful;
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++;
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++;
1230 if (uiFrameCount > 7) { // limit frame request to send counter to 7
1231 uiFrameCount = 7;
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;
1245 break;
1248 #if (((EPL_MODULE_INTEGRATION) & (EPL_MODULE_NMT_MN)) != 0)
1249 case kEplEventTypeDllkStartReducedCycle:
1251 // start the reduced cycle by programming the cycle timer
1252 // it is issued by NMT MN module, when PreOp1 is entered
1254 // clear the asynchronous queues
1255 Ret = EplDllkCalAsyncClearQueues();
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;
1261 // remove any CN from isochronous phase
1262 while (EplDllkInstance_g.m_pFirstNodeInfo != NULL) {
1263 EplDllkDeleteNode(EplDllkInstance_g.
1264 m_pFirstNodeInfo->m_uiNodeId);
1267 // change state to NonCyclic,
1268 // hence EplDllkChangeState() will not ignore the next call
1269 EplDllkInstance_g.m_DllState = kEplDllMsNonCyclic;
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);
1281 #endif
1283 break;
1285 #endif
1287 #if EPL_DLL_PRES_READY_AFTER_SOA != FALSE
1288 case kEplEventTypeDllkPresReady:
1290 // post PRes to transmit FIFO
1292 NmtState = EplNmtkGetNmtState();
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;
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);
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]);
1329 break;
1331 #endif
1332 default:
1334 ASSERTMSG(FALSE,
1335 "EplDllkProcess(): unhandled event type!\n");
1339 Exit:
1340 return Ret;
1343 //---------------------------------------------------------------------------
1345 // Function: EplDllkConfig
1347 // Description: configure parameters of DLL
1349 // Parameters: pDllConfigParam_p = configuration parameters
1351 // Returns: tEplKernel = error code
1354 // State:
1356 //---------------------------------------------------------------------------
1358 tEplKernel EplDllkConfig(tEplDllConfigParam * pDllConfigParam_p)
1360 tEplKernel Ret = kEplSuccessful;
1362 // d.k. check of NMT state disabled, because CycleLen is programmed at run time by MN without reset of CN
1363 /*tEplNmtState NmtState;
1365 NmtState = EplNmtkGetNmtState();
1367 if (NmtState > kEplNmtGsResetConfiguration)
1368 { // only allowed in state DLL_GS_INIT
1369 Ret = kEplInvalidOperation;
1370 goto Exit;
1373 EPL_MEMCPY(&EplDllkInstance_g.m_DllConfigParam, pDllConfigParam_p,
1374 (pDllConfigParam_p->m_uiSizeOfStruct <
1375 sizeof(tEplDllConfigParam) ? pDllConfigParam_p->
1376 m_uiSizeOfStruct : sizeof(tEplDllConfigParam)));
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
1382 ((unsigned long long)
1383 EplDllkInstance_g.
1384 m_DllConfigParam.
1385 m_dwCycleLen))
1387 ((unsigned long long)EplDllkInstance_g.m_DllConfigParam.
1388 m_dwLossOfFrameTolerance);
1389 } else {
1390 EplDllkInstance_g.m_ullFrameTimeout = 0LL;
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;
1397 //Exit:
1398 return Ret;
1401 //---------------------------------------------------------------------------
1403 // Function: EplDllkSetIdentity
1405 // Description: configure identity of local node for IdentResponse
1407 // Parameters: pDllIdentParam_p = identity
1409 // Returns: tEplKernel = error code
1412 // State:
1414 //---------------------------------------------------------------------------
1416 tEplKernel EplDllkSetIdentity(tEplDllIdentParam * pDllIdentParam_p)
1418 tEplKernel Ret = kEplSuccessful;
1420 EPL_MEMCPY(&EplDllkInstance_g.m_DllIdentParam, pDllIdentParam_p,
1421 (pDllIdentParam_p->m_uiSizeOfStruct <
1422 sizeof(tEplDllIdentParam) ? pDllIdentParam_p->
1423 m_uiSizeOfStruct : sizeof(tEplDllIdentParam)));
1425 // $$$ if IdentResponse frame exists update it
1427 return Ret;
1430 //---------------------------------------------------------------------------
1432 // Function: EplDllkRegAsyncHandler
1434 // Description: registers handler for non-EPL frames
1436 // Parameters: pfnDllkCbAsync_p = pointer to callback function
1438 // Returns: tEplKernel = error code
1441 // State:
1443 //---------------------------------------------------------------------------
1445 tEplKernel EplDllkRegAsyncHandler(tEplDllkCbAsync pfnDllkCbAsync_p)
1447 tEplKernel Ret = kEplSuccessful;
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;
1455 return Ret;
1458 //---------------------------------------------------------------------------
1460 // Function: EplDllkDeregAsyncHandler
1462 // Description: deregisters handler for non-EPL frames
1464 // Parameters: pfnDllkCbAsync_p = pointer to callback function
1466 // Returns: tEplKernel = error code
1469 // State:
1471 //---------------------------------------------------------------------------
1473 tEplKernel EplDllkDeregAsyncHandler(tEplDllkCbAsync pfnDllkCbAsync_p)
1475 tEplKernel Ret = kEplSuccessful;
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;
1484 return Ret;
1487 //---------------------------------------------------------------------------
1489 // Function: EplDllkSetAsndServiceIdFilter()
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.
1495 // Parameters: ServiceId_p = ASnd Service ID
1496 // Filter_p = node ID filter
1498 // Returns: tEplKernel = error code
1501 // State:
1503 //---------------------------------------------------------------------------
1505 tEplKernel EplDllkSetAsndServiceIdFilter(tEplDllAsndServiceId ServiceId_p,
1506 tEplDllAsndFilter Filter_p)
1508 tEplKernel Ret = kEplSuccessful;
1510 if (ServiceId_p < tabentries(EplDllkInstance_g.m_aAsndFilter)) {
1511 EplDllkInstance_g.m_aAsndFilter[ServiceId_p] = Filter_p;
1514 return Ret;
1517 #if (((EPL_MODULE_INTEGRATION) & (EPL_MODULE_NMT_MN)) != 0)
1519 //---------------------------------------------------------------------------
1521 // Function: EplDllkSetFlag1OfNode()
1523 // Description: sets Flag1 (for PReq and SoA) of the specified node ID.
1525 // Parameters: uiNodeId_p = node ID
1526 // bSoaFlag1_p = flag1
1528 // Returns: tEplKernel = error code
1531 // State:
1533 //---------------------------------------------------------------------------
1535 tEplKernel EplDllkSetFlag1OfNode(unsigned int uiNodeId_p, u8 bSoaFlag1_p)
1537 tEplKernel Ret = kEplSuccessful;
1538 tEplDllkNodeInfo *pNodeInfo;
1540 pNodeInfo = EplDllkGetNodeInfo(uiNodeId_p);
1541 if (pNodeInfo == NULL) { // no node info structure available
1542 Ret = kEplDllNoNodeInfo;
1543 goto Exit;
1545 // store flag1 in internal node info structure
1546 pNodeInfo->m_bSoaFlag1 = bSoaFlag1_p;
1548 Exit:
1549 return Ret;
1552 //---------------------------------------------------------------------------
1554 // Function: EplDllkGetFirstNodeInfo()
1556 // Description: returns first info structure of first node in isochronous phase.
1557 // It is only useful for ErrorHandlerk module.
1559 // Parameters: ppNodeInfo_p = pointer to pointer of internal node info structure
1561 // Returns: tEplKernel = error code
1564 // State:
1566 //---------------------------------------------------------------------------
1568 tEplKernel EplDllkGetFirstNodeInfo(tEplDllkNodeInfo ** ppNodeInfo_p)
1570 tEplKernel Ret = kEplSuccessful;
1572 *ppNodeInfo_p = EplDllkInstance_g.m_pFirstNodeInfo;
1574 return Ret;
1577 //---------------------------------------------------------------------------
1579 // Function: EplDllkAddNode()
1581 // Description: adds the specified node to the isochronous phase.
1583 // Parameters: pNodeInfo_p = pointer of node info structure
1585 // Returns: tEplKernel = error code
1588 // State:
1590 //---------------------------------------------------------------------------
1592 tEplKernel EplDllkAddNode(tEplDllNodeInfo * pNodeInfo_p)
1594 tEplKernel Ret = kEplSuccessful;
1595 tEplDllkNodeInfo *pIntNodeInfo;
1596 tEplDllkNodeInfo **ppIntNodeInfo;
1597 unsigned int uiHandle;
1598 tEplFrame *pFrame;
1599 unsigned int uiFrameSize;
1601 pIntNodeInfo = EplDllkGetNodeInfo(pNodeInfo_p->m_uiNodeId);
1602 if (pIntNodeInfo == NULL) { // no node info structure available
1603 Ret = kEplDllNoNodeInfo;
1604 goto Exit;
1607 EPL_DLLK_DBG_POST_TRACE_VALUE(kEplEventTypeDllkAddNode,
1608 pNodeInfo_p->m_uiNodeId, 0);
1610 // copy node configuration
1611 pIntNodeInfo->m_dwPresTimeout = pNodeInfo_p->m_dwPresTimeout;
1612 pIntNodeInfo->m_wPresPayloadLimit = pNodeInfo_p->m_wPresPayloadLimit;
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;
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;
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;
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;
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;
1663 pIntNodeInfo->m_pPreqTxBuffer =
1664 &EplDllkInstance_g.m_pTxBuffer[uiHandle];
1665 AmiSetByteToLe(&pFrame->m_le_bDstNodeId,
1666 (u8) pNodeInfo_p->m_uiNodeId);
1668 // set up destination MAC address
1669 EPL_MEMCPY(pFrame->m_be_abDstMac, pIntNodeInfo->m_be_abMacAddr,
1672 #if (((EPL_MODULE_INTEGRATION) & (EPL_MODULE_PDOK)) != 0)
1674 tEplFrameInfo FrameInfo;
1676 // initially encode TPDO -> inform PDO module
1677 FrameInfo.m_pFrame = pFrame;
1678 FrameInfo.m_uiFrameSize = uiFrameSize;
1679 Ret = EplPdokCbPdoTransmitted(&FrameInfo);
1681 #endif
1683 pIntNodeInfo->m_ulDllErrorEvents = 0L;
1684 // add node to list
1685 pIntNodeInfo->m_pNextNodeInfo = *ppIntNodeInfo;
1686 *ppIntNodeInfo = pIntNodeInfo;
1688 Exit:
1689 return Ret;
1692 //---------------------------------------------------------------------------
1694 // Function: EplDllkDeleteNode()
1696 // Description: removes the specified node from the isochronous phase.
1698 // Parameters: uiNodeId_p = node ID
1700 // Returns: tEplKernel = error code
1703 // State:
1705 //---------------------------------------------------------------------------
1707 tEplKernel EplDllkDeleteNode(unsigned int uiNodeId_p)
1709 tEplKernel Ret = kEplSuccessful;
1710 tEplDllkNodeInfo *pIntNodeInfo;
1711 tEplDllkNodeInfo **ppIntNodeInfo;
1712 unsigned int uiHandle;
1714 pIntNodeInfo = EplDllkGetNodeInfo(uiNodeId_p);
1715 if (pIntNodeInfo == NULL) { // no node info structure available
1716 Ret = kEplDllNoNodeInfo;
1717 goto Exit;
1720 EPL_DLLK_DBG_POST_TRACE_VALUE(kEplEventTypeDllkDelNode, uiNodeId_p, 0);
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;
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;
1732 // remove node from list
1733 *ppIntNodeInfo = pIntNodeInfo->m_pNextNodeInfo;
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)
1744 goto Exit;
1748 Exit:
1749 return Ret;
1752 //---------------------------------------------------------------------------
1754 // Function: EplDllkSoftDeleteNode()
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.
1760 // Parameters: uiNodeId_p = node ID
1762 // Returns: tEplKernel = error code
1765 // State:
1767 //---------------------------------------------------------------------------
1769 tEplKernel EplDllkSoftDeleteNode(unsigned int uiNodeId_p)
1771 tEplKernel Ret = kEplSuccessful;
1772 tEplDllkNodeInfo *pIntNodeInfo;
1774 pIntNodeInfo = EplDllkGetNodeInfo(uiNodeId_p);
1775 if (pIntNodeInfo == NULL) { // no node info structure available
1776 Ret = kEplDllNoNodeInfo;
1777 goto Exit;
1780 EPL_DLLK_DBG_POST_TRACE_VALUE(kEplEventTypeDllkSoftDelNode,
1781 uiNodeId_p, 0);
1783 pIntNodeInfo->m_fSoftDelete = TRUE;
1785 Exit:
1786 return Ret;
1789 #endif //(((EPL_MODULE_INTEGRATION) & (EPL_MODULE_NMT_MN)) != 0)
1791 //=========================================================================//
1792 // //
1793 // P R I V A T E F U N C T I O N S //
1794 // //
1795 //=========================================================================//
1797 //---------------------------------------------------------------------------
1799 // Function: EplDllkChangeState
1801 // Description: change DLL state on event and diagnose some communication errors
1803 // Parameters: NmtEvent_p = DLL event (wrapped in NMT event)
1805 // Returns: tEplKernel = error code
1808 // State:
1810 //---------------------------------------------------------------------------
1812 static tEplKernel EplDllkChangeState(tEplNmtEvent NmtEvent_p,
1813 tEplNmtState NmtState_p)
1815 tEplKernel Ret = kEplSuccessful;
1816 tEplEvent Event;
1817 tEplErrorHandlerkEvent DllEvent;
1819 DllEvent.m_ulDllErrorEvents = 0;
1820 DllEvent.m_uiNodeId = 0;
1821 DllEvent.m_NmtState = NmtState_p;
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;
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;
1844 break;
1846 case kEplNmtCsPreOperational2:
1847 case kEplNmtCsReadyToOperate:
1848 case kEplNmtCsOperational:
1849 // full EPL cycle is active
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;
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;
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;
1877 // enter DLL_CS_WAIT_SOC
1878 EplDllkInstance_g.m_DllState = kEplDllCsWaitSoc;
1879 break;
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;
1889 // enter DLL_CS_WAIT_SOC
1890 EplDllkInstance_g.m_DllState = kEplDllCsWaitSoc;
1891 break;
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;
1900 case kEplNmtEventDllCePres:
1901 default:
1902 // remain in this state
1903 break;
1905 break;
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;
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;
1928 // fall through
1930 case kEplNmtEventDllCePreq:
1931 case kEplNmtEventDllCeSoa:
1932 // report DLL_CEV_LOSS_SOC
1933 DllEvent.m_ulDllErrorEvents |=
1934 EPL_DLL_ERR_CN_LOSS_SOC;
1936 case kEplNmtEventDllCeAsnd:
1937 default:
1938 // remain in this state
1939 break;
1941 break;
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;
1955 // fall through
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;
1963 case kEplNmtEventDllCeSoa:
1964 // enter DLL_CS_WAIT_SOC
1965 EplDllkInstance_g.m_DllState = kEplDllCsWaitSoc;
1966 break;
1968 // DLL_CT9
1969 case kEplNmtEventDllCeSoc:
1970 // report DLL_CEV_LOSS_SOA
1971 DllEvent.m_ulDllErrorEvents |=
1972 EPL_DLL_ERR_CN_LOSS_SOA;
1974 // enter DLL_CS_WAIT_PREQ
1975 EplDllkInstance_g.m_DllState =
1976 kEplDllCsWaitPreq;
1977 break;
1979 // DLL_CT10
1980 case kEplNmtEventDllCeAsnd:
1981 // report DLL_CEV_LOSS_SOA
1982 DllEvent.m_ulDllErrorEvents |=
1983 EPL_DLL_ERR_CN_LOSS_SOA;
1985 case kEplNmtEventDllCePres:
1986 default:
1987 // remain in this state
1988 break;
1990 break;
1992 case kEplDllGsInit:
1993 // enter DLL_CS_WAIT_PREQ
1994 EplDllkInstance_g.m_DllState = kEplDllCsWaitPreq;
1995 break;
1997 default:
1998 break;
2000 break;
2002 case kEplNmtCsStopped:
2003 // full EPL cycle is active, but without PReq/PRes
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;
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;
2021 case kEplNmtEventDllCeSoa:
2022 // NMT_CS_STOPPED active
2023 // it is Ok if no PReq was received
2025 // enter DLL_CS_WAIT_SOC
2026 EplDllkInstance_g.m_DllState = kEplDllCsWaitSoc;
2027 break;
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;
2036 case kEplNmtEventDllCePres:
2037 default:
2038 // remain in this state
2039 break;
2041 break;
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;
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;
2061 case kEplNmtEventDllCeAsnd:
2062 default:
2063 // remain in this state
2064 break;
2066 break;
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;
2077 case kEplNmtEventDllCeSoa:
2078 // enter DLL_CS_WAIT_SOC
2079 EplDllkInstance_g.m_DllState = kEplDllCsWaitSoc;
2080 break;
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;
2090 // DLL_CT10
2091 case kEplNmtEventDllCeAsnd:
2092 // report DLL_CEV_LOSS_SOA
2093 DllEvent.m_ulDllErrorEvents |=
2094 EPL_DLL_ERR_CN_LOSS_SOA;
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;
2104 break;
2106 case kEplDllGsInit:
2107 default:
2108 // enter DLL_CS_WAIT_PREQ
2109 EplDllkInstance_g.m_DllState = kEplDllCsWaitSoa;
2110 break;
2112 break;
2114 #if (((EPL_MODULE_INTEGRATION) & (EPL_MODULE_NMT_MN)) != 0)
2115 case kEplNmtMsNotActive:
2116 case kEplNmtMsBasicEthernet:
2117 break;
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;
2129 // stop further processing,
2130 // because it will be restarted by NMT MN module
2131 break;
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;
2140 Ret =
2141 EplDllkAsyncFrameNotReceived
2142 (EplDllkInstance_g.m_LastReqServiceId,
2143 EplDllkInstance_g.m_uiLastTargetNodeId);
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++;
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);
2165 #endif
2166 break;
2169 default:
2170 break;
2172 break;
2174 case kEplNmtMsPreOperational2:
2175 case kEplNmtMsReadyToOperate:
2176 case kEplNmtMsOperational:
2177 // full EPL cycle is active
2178 switch (NmtEvent_p) {
2179 case kEplNmtEventDllMeSocTrig:
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;
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
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);
2224 // send SoC
2225 Ret = EplDllkMnSendSoc();
2227 // new DLL state
2228 EplDllkInstance_g.m_DllState =
2229 kEplDllMsWaitPreqTrig;
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;
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;
2256 break;
2259 case kEplNmtEventDllMePresTimeout:
2262 switch (EplDllkInstance_g.m_DllState) {
2263 case kEplDllMsWaitPres:
2264 { // PRes not received
2266 if (EplDllkInstance_g.m_pCurNodeInfo->m_fSoftDelete == FALSE) { // normal isochronous CN
2267 DllEvent.
2268 m_ulDllErrorEvents
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);
2293 // continue with sending next PReq
2296 case kEplDllMsWaitPreqTrig:
2298 // send next PReq
2299 Ret =
2300 EplDllkMnSendPreq
2301 (NmtState_p,
2302 &EplDllkInstance_g.
2303 m_DllState);
2305 break;
2308 default:
2309 { // wrong DLL state
2310 break;
2314 break;
2317 case kEplNmtEventDllCePres:
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);
2330 break;
2333 default:
2334 { // wrong DLL state
2335 break;
2339 break;
2342 case kEplNmtEventDllMeSoaTrig:
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);
2355 break;
2358 default:
2359 { // wrong DLL state
2360 break;
2364 break;
2367 case kEplNmtEventDllCeAsnd:
2368 { // ASnd has been received, but it may be not the requested one
2370 // report if SoA was correctly answered
2371 Ret = EplDllkAsyncFrameNotReceived(EplDllkInstance_g.m_LastReqServiceId,
2372 EplDllkInstance_g.m_uiLastTargetNodeId);
2374 if (EplDllkInstance_g.m_DllState ==
2375 kEplDllMsWaitAsnd) {
2376 EplDllkInstance_g.m_DllState =
2377 kEplDllMsWaitSocTrig;
2379 break;
2382 default:
2383 break;
2385 break;
2386 #endif //(((EPL_MODULE_INTEGRATION) & (EPL_MODULE_NMT_MN)) != 0)
2388 default:
2389 break;
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);
2401 return Ret;
2404 //---------------------------------------------------------------------------
2406 // Function: EplDllkCbFrameReceived()
2408 // Description: called from EdrvInterruptHandler()
2410 // Parameters: pRxBuffer_p = receive buffer structure
2412 // Returns: (none)
2415 // State:
2417 //---------------------------------------------------------------------------
2419 static void EplDllkCbFrameReceived(tEdrvRxBuffer * pRxBuffer_p)
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;
2435 BENCHMARK_MOD_02_SET(3);
2436 NmtState = EplNmtkGetNmtState();
2438 if (NmtState <= kEplNmtGsResetConfiguration) {
2439 goto Exit;
2442 pFrame = (tEplFrame *) pRxBuffer_p->m_pbBuffer;
2444 #if EDRV_EARLY_RX_INT != FALSE
2445 switch (pRxBuffer_p->m_BufferInFrame) {
2446 case kEdrvBufferFirstInFrame:
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);
2479 // $$$ make function that updates Pres, StatusRes
2480 // send PRes frame
2481 Ret = EdrvSendTxMsg(pTxBuffer);
2482 #endif
2485 goto Exit;
2488 case kEdrvBufferMiddleInFrame:
2490 goto Exit;
2493 case kEdrvBufferLastInFrame:
2495 break;
2498 #endif
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;
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);
2511 goto Exit;
2514 MsgType = (tEplMsgType) AmiGetByteFromLe(&pFrame->m_le_bMessageType);
2515 switch (MsgType) {
2516 case kEplMsgTypePreq:
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;
2523 NmtEvent = kEplNmtEventDllCePreq;
2525 if (NmtState >= kEplNmtMsNotActive) { // MN is active -> wrong msg type
2526 break;
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);
2580 // $$$ update EPL_DLL_PRES_READY_AFTER_* code
2581 // send PRes frame
2582 Ret = EdrvSendTxMsg(pTxBuffer);
2583 if (Ret != kEplSuccessful) {
2584 goto Exit;
2586 #endif
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);
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) +
2605 > FrameInfo.m_uiFrameSize) { // format error
2606 tEplErrorHandlerkEvent DllEvent;
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;
2626 // forward PReq frame as RPDO to PDO module
2627 Ret = EplPdokCbPdoReceived(&FrameInfo);
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);
2640 #endif
2641 #endif
2643 #if EDRV_EARLY_RX_INT == FALSE
2644 // $$$ inform emergency protocol handling (error signaling module) about flags
2646 #endif
2648 // reset cycle counter
2649 EplDllkInstance_g.m_uiCycleCount = 0;
2651 break;
2654 case kEplMsgTypePres:
2656 #if (((EPL_MODULE_INTEGRATION) & (EPL_MODULE_NMT_MN)) != 0)
2657 tEplDllkNodeInfo *pIntNodeInfo;
2658 tEplHeartbeatEvent HeartbeatEvent;
2659 #endif
2661 // PRes frame
2662 NmtEvent = kEplNmtEventDllCePres;
2664 uiNodeId = AmiGetByteFromLe(&pFrame->m_le_bSrcNodeId);
2666 if ((NmtState >= kEplNmtCsPreOperational2)
2667 && (NmtState <= kEplNmtCsOperational)) { // process PRes frames only in PreOp2, ReadyToOp and Op of CN
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;
2675 } else if (EplDllkInstance_g.m_DllState == kEplDllMsWaitPres) { // or process PRes frames in MsWaitPres
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;
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));
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;
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;
2726 Event.m_NetTime = FrameInfo.m_NetTime;
2727 Ret = EplEventkPost(&Event);
2729 // save current NMT state of CN in internal node structure
2730 pIntNodeInfo->m_NmtState =
2731 HeartbeatEvent.m_NmtState;
2734 #endif
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) +
2745 > FrameInfo.m_uiFrameSize)
2746 #if (((EPL_MODULE_INTEGRATION) & (EPL_MODULE_NMT_MN)) != 0)
2748 (AmiGetWordFromLe
2749 (&pFrame->m_Data.m_Pres.m_le_wSize) >
2750 pIntNodeInfo->m_wPresPayloadLimit)
2751 #endif
2752 ) { // format error
2753 tEplErrorHandlerkEvent DllEvent;
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;
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);
2774 Ret = EplPdokCbPdoReceived(&FrameInfo);
2776 #endif
2778 break;
2781 case kEplMsgTypeSoc:
2783 // SoC frame
2784 NmtEvent = kEplNmtEventDllCeSoc;
2786 if (NmtState >= kEplNmtMsNotActive) { // MN is active -> wrong msg type
2787 break;
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;
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);
2814 // $$$ make function that updates Pres, StatusRes
2815 // mark PRes frame as ready for transmission
2816 Ret = EdrvTxMsgReady(pTxBuffer);
2818 #endif
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);
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;
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);
2845 #endif
2847 break;
2850 case kEplMsgTypeSoa:
2852 // SoA frame
2853 NmtEvent = kEplNmtEventDllCeSoa;
2855 if (NmtState >= kEplNmtMsNotActive) { // MN is active -> wrong msg type
2856 break;
2859 pTxFrame = NULL;
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;
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
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
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;
2914 TGT_DBG_SIGNAL_TRACE_POINT(8);
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 =
2938 // save flag 1 from MN for Status request response cycle
2939 EplDllkInstance_g.m_bMnFlag1 =
2940 bFlag1;
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;
2973 TGT_DBG_SIGNAL_TRACE_POINT(7);
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;
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;
3033 } else if (ReqServiceId == kEplDllReqServiceNo) { // no async service requested -> do nothing
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);
3044 #endif
3046 // inform PDO module
3047 #if (((EPL_MODULE_INTEGRATION) & (EPL_MODULE_PDOK)) != 0)
3048 // Ret = EplPdokCbSoa(&FrameInfo);
3049 #endif
3051 // $$$ put SrcNodeId, NMT state and NetTime as HeartbeatEvent into eventqueue
3053 // $$$ inform emergency protocol handling about flags
3054 break;
3057 case kEplMsgTypeAsnd:
3059 // ASnd frame
3060 NmtEvent = kEplNmtEventDllCeAsnd;
3062 // ASnd service registered?
3063 uiAsndServiceId =
3064 (unsigned int)AmiGetByteFromLe(&pFrame->m_Data.
3065 m_Asnd.
3066 m_le_bServiceId);
3068 #if (((EPL_MODULE_INTEGRATION) & (EPL_MODULE_NMT_MN)) != 0)
3069 if ((EplDllkInstance_g.m_DllState >= kEplDllMsNonCyclic)
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;
3082 if (((tEplDllAsndServiceId) uiAsndServiceId) == kEplDllAsndIdentResponse) { // memorize MAC address of CN for PReq
3083 tEplDllkNodeInfo *pIntNodeInfo;
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);
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));
3105 #endif
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);
3129 break;
3132 default:
3134 break;
3138 if (NmtEvent != kEplNmtEventNoEvent) { // event for DLL and NMT state machine generated
3139 Ret = EplDllkChangeState(NmtEvent, NmtState);
3140 if (Ret != kEplSuccessful) {
3141 goto Exit;
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);
3155 Exit:
3156 if (Ret != kEplSuccessful) {
3157 u32 dwArg;
3159 BENCHMARK_MOD_02_TOGGLE(9);
3161 dwArg = EplDllkInstance_g.m_DllState | (NmtEvent << 8);
3163 // Error event for API layer
3164 Ret = EplEventkPostError(kEplEventSourceDllk,
3165 Ret, sizeof(dwArg), &dwArg);
3167 BENCHMARK_MOD_02_RESET(3);
3168 return;
3171 //---------------------------------------------------------------------------
3173 // Function: EplDllkCbFrameTransmitted()
3175 // Description: called from EdrvInterruptHandler().
3176 // It signals
3178 // Parameters: pRxBuffer_p = receive buffer structure
3180 // Returns: (none)
3183 // State:
3185 //---------------------------------------------------------------------------
3187 static void EplDllkCbFrameTransmitted(tEdrvTxBuffer * pTxBuffer_p)
3189 tEplKernel Ret = kEplSuccessful;
3190 tEplEvent Event;
3191 tEplDllAsyncReqPriority Priority;
3192 tEplNmtState NmtState;
3194 #if (((EPL_MODULE_INTEGRATION) & (EPL_MODULE_PDOK)) != 0) \
3195 && (EPL_DLL_PRES_READY_AFTER_SOC == FALSE)
3196 tEplFrameInfo FrameInfo;
3197 #endif
3199 NmtState = EplNmtkGetNmtState();
3201 if (NmtState <= kEplNmtGsResetConfiguration) {
3202 goto Exit;
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;
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;
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);
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
3236 #if ((((EPL_MODULE_INTEGRATION) & (EPL_MODULE_PDOK)) != 0) \
3237 && (EPL_DLL_PRES_READY_AFTER_SOC == FALSE))
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);
3245 #endif
3247 #if (((EPL_MODULE_INTEGRATION) & (EPL_MODULE_NMT_MN)) != 0)
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);
3259 #endif
3261 #if EPL_DLL_PRES_READY_AFTER_SOA != FALSE
3262 goto Exit;
3263 #endif
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;
3270 // check if we are invited
3271 if (EplDllkInstance_g.m_uiLastTargetNodeId ==
3272 EplDllkInstance_g.m_DllConfigParam.m_uiNodeId) {
3273 tEplFrame *pTxFrame;
3275 if (EplDllkInstance_g.m_LastReqServiceId == kEplDllReqServiceStatus) { // StatusRequest
3276 if (EplDllkInstance_g.m_pTxBuffer[EPL_DLLK_TXFRAME_STATUSRES].m_pbBuffer != NULL) { // StatusRes does exist
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;
3309 TGT_DBG_SIGNAL_TRACE_POINT(8);
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;
3339 TGT_DBG_SIGNAL_TRACE_POINT(7);
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.
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)
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);
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;
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;
3419 // ASnd frame was sent, remove the request
3420 EplDllkInstance_g.m_LastReqServiceId =
3421 kEplDllReqServiceNo;
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;
3433 #endif
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;
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);
3447 #endif
3449 Exit:
3450 if (Ret != kEplSuccessful) {
3451 u32 dwArg;
3453 BENCHMARK_MOD_02_TOGGLE(9);
3455 dwArg =
3456 EplDllkInstance_g.m_DllState | (pTxBuffer_p->
3457 m_EplMsgType << 16);
3459 // Error event for API layer
3460 Ret = EplEventkPostError(kEplEventSourceDllk,
3461 Ret, sizeof(dwArg), &dwArg);
3464 return;
3467 //---------------------------------------------------------------------------
3469 // Function: EplDllkCheckFrame()
3471 // Description: check frame and set missing information
3473 // Parameters: pFrame_p = ethernet frame
3474 // uiFrameSize_p = size of frame
3476 // Returns: tEplKernel = error code
3479 // State:
3481 //---------------------------------------------------------------------------
3483 static tEplKernel EplDllkCheckFrame(tEplFrame * pFrame_p,
3484 unsigned int uiFrameSize_p)
3486 tEplMsgType MsgType;
3487 u16 wEtherType;
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);
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);
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);
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);
3520 if (MsgType == kEplMsgTypeAsnd) {
3521 // destination MAC address
3522 AmiSetQword48ToBe(&pFrame_p->m_be_abDstMac[0],
3523 EPL_C_DLL_MULTICAST_ASND);
3529 return kEplSuccessful;
3532 //---------------------------------------------------------------------------
3534 // Function: EplDllkCbCnTimer()
3536 // Description: called by timer module. It monitors the EPL cycle when it is a CN.
3538 // Parameters: pEventArg_p = timer event argument
3540 // Returns: tEplKernel = error code
3543 // State:
3545 //---------------------------------------------------------------------------
3547 #if EPL_TIMER_USE_HIGHRES != FALSE
3548 static tEplKernel EplDllkCbCnTimer(tEplTimerEventArg *pEventArg_p)
3550 tEplKernel Ret = kEplSuccessful;
3551 tEplNmtState NmtState;
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;
3558 #endif
3560 NmtState = EplNmtkGetNmtState();
3562 if (NmtState <= kEplNmtGsResetConfiguration) {
3563 goto Exit;
3566 Ret = EplDllkChangeState(kEplNmtEventDllCeFrameTimeout, NmtState);
3567 if (Ret != kEplSuccessful) {
3568 goto Exit;
3570 // 2008/10/15 d.k. reprogramming of timer not necessary,
3571 // because it will be programmed, when SoC is received.
3573 // reprogram timer
3574 #if EPL_TIMER_USE_HIGHRES != FALSE
3575 if ((NmtState > kEplNmtCsPreOperational1)
3576 && (EplDllkInstance_g.m_ullFrameTimeout != 0))
3578 Ret = EplTimerHighReskModifyTimerNs(&EplDllkInstance_g.m_TimerHdlCycle, EplDllkInstance_g.m_ullFrameTimeout, EplDllkCbCnTimer, 0L, FALSE);
3580 #endif
3583 Exit:
3584 if (Ret != kEplSuccessful) {
3585 u32 dwArg;
3587 BENCHMARK_MOD_02_TOGGLE(9);
3589 dwArg =
3590 EplDllkInstance_g.
3591 m_DllState | (kEplNmtEventDllCeFrameTimeout << 8);
3593 // Error event for API layer
3594 Ret = EplEventkPostError(kEplEventSourceDllk,
3595 Ret, sizeof(dwArg), &dwArg);
3598 return Ret;
3600 #endif
3602 #if (((EPL_MODULE_INTEGRATION) & (EPL_MODULE_NMT_MN)) != 0)
3604 //---------------------------------------------------------------------------
3606 // Function: EplDllkCbMnTimerCycle()
3608 // Description: called by timer module. It triggers the SoC when it is a MN.
3610 // Parameters: pEventArg_p = timer event argument
3612 // Returns: tEplKernel = error code
3615 // State:
3617 //---------------------------------------------------------------------------
3619 static tEplKernel EplDllkCbMnTimerCycle(tEplTimerEventArg *pEventArg_p)
3621 tEplKernel Ret = kEplSuccessful;
3622 tEplNmtState NmtState;
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;
3629 #endif
3631 NmtState = EplNmtkGetNmtState();
3633 if (NmtState <= kEplNmtGsResetConfiguration) {
3634 goto Exit;
3637 Ret = EplDllkChangeState(kEplNmtEventDllMeSocTrig, NmtState);
3639 Exit:
3640 if (Ret != kEplSuccessful) {
3641 u32 dwArg;
3643 BENCHMARK_MOD_02_TOGGLE(9);
3645 dwArg =
3646 EplDllkInstance_g.
3647 m_DllState | (kEplNmtEventDllMeSocTrig << 8);
3649 // Error event for API layer
3650 Ret = EplEventkPostError(kEplEventSourceDllk,
3651 Ret, sizeof(dwArg), &dwArg);
3654 return Ret;
3657 //---------------------------------------------------------------------------
3659 // Function: EplDllkCbMnTimerResponse()
3661 // Description: called by timer module. It monitors the PRes timeout.
3663 // Parameters: pEventArg_p = timer event argument
3665 // Returns: tEplKernel = error code
3668 // State:
3670 //---------------------------------------------------------------------------
3672 static tEplKernel EplDllkCbMnTimerResponse(tEplTimerEventArg *pEventArg_p)
3674 tEplKernel Ret = kEplSuccessful;
3675 tEplNmtState NmtState;
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;
3682 #endif
3684 NmtState = EplNmtkGetNmtState();
3686 if (NmtState <= kEplNmtGsResetConfiguration) {
3687 goto Exit;
3690 Ret = EplDllkChangeState(kEplNmtEventDllMePresTimeout, NmtState);
3692 Exit:
3693 if (Ret != kEplSuccessful) {
3694 u32 dwArg;
3696 BENCHMARK_MOD_02_TOGGLE(9);
3698 dwArg =
3699 EplDllkInstance_g.
3700 m_DllState | (kEplNmtEventDllMePresTimeout << 8);
3702 // Error event for API layer
3703 Ret = EplEventkPostError(kEplEventSourceDllk,
3704 Ret, sizeof(dwArg), &dwArg);
3707 return Ret;
3710 //---------------------------------------------------------------------------
3712 // Function: EplDllkGetNodeInfo()
3714 // Description: returns node info structure of the specified node.
3716 // Parameters: uiNodeId_p = node ID
3718 // Returns: tEplDllkNodeInfo* = pointer to internal node info structure
3721 // State:
3723 //---------------------------------------------------------------------------
3725 static tEplDllkNodeInfo *EplDllkGetNodeInfo(unsigned int uiNodeId_p)
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];
3737 //---------------------------------------------------------------------------
3739 // Function: EplDllkMnSendSoa()
3741 // Description: it updates and transmits the SoA.
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
3748 // Returns: tEplKernel = error code
3751 // State:
3753 //---------------------------------------------------------------------------
3755 static tEplKernel EplDllkMnSendSoa(tEplNmtState NmtState_p,
3756 tEplDllState * pDllStateProposed_p,
3757 BOOL fEnableInvitation_p)
3759 tEplKernel Ret = kEplSuccessful;
3760 tEdrvTxBuffer *pTxBuffer = NULL;
3761 tEplFrame *pTxFrame;
3762 tEplDllkNodeInfo *pNodeInfo;
3764 *pDllStateProposed_p = kEplDllMsNonCyclic;
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;
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;
3781 Ret =
3782 EplDllkCalAsyncGetSoaRequest(&EplDllkInstance_g.
3783 m_LastReqServiceId,
3784 &EplDllkInstance_g.
3785 m_uiLastTargetNodeId);
3786 if (Ret != kEplSuccessful) {
3787 goto Exit;
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;
3805 pNodeInfo =
3806 EplDllkGetNodeInfo(EplDllkInstance_g.
3807 m_uiLastTargetNodeId);
3808 if (pNodeInfo == NULL) { // no node info structure available
3809 Ret = kEplDllNoNodeInfo;
3810 goto Exit;
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
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;
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);
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);
3843 // update frame (NMT state)
3844 AmiSetByteToLe(&pTxFrame->m_Data.m_Soa.m_le_bNmtStatus,
3845 (u8) NmtState_p);
3847 // send SoA frame
3848 Ret = EdrvSendTxMsg(pTxBuffer);
3851 Exit:
3852 return Ret;
3855 //---------------------------------------------------------------------------
3857 // Function: EplDllkMnSendSoc()
3859 // Description: it updates and transmits the SoA.
3861 // Parameters: (none)
3863 // Returns: tEplKernel = error code
3866 // State:
3868 //---------------------------------------------------------------------------
3870 static tEplKernel EplDllkMnSendSoc(void)
3872 tEplKernel Ret = kEplSuccessful;
3873 tEdrvTxBuffer *pTxBuffer = NULL;
3874 tEplFrame *pTxFrame;
3875 tEplEvent Event;
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;
3881 // $$$ update NetTime
3883 // send SoC frame
3884 Ret = EdrvSendTxMsg(pTxBuffer);
3885 if (Ret != kEplSuccessful) {
3886 goto Exit;
3888 // trigger synchronous task
3889 Event.m_EventSink = kEplEventSinkSync;
3890 Event.m_EventType = kEplEventTypeSync;
3891 Event.m_uiSize = 0;
3892 Ret = EplEventkPost(&Event);
3895 Exit:
3896 return Ret;
3899 //---------------------------------------------------------------------------
3901 // Function: EplDllkMnSendPreq()
3903 // Description: it updates and transmits the PReq for the next isochronous CN
3904 // or own PRes if enabled.
3906 // Parameters: NmtState_p = current NMT state
3907 // pDllStateProposed_p = proposed DLL state
3909 // Returns: tEplKernel = error code
3912 // State:
3914 //---------------------------------------------------------------------------
3916 static tEplKernel EplDllkMnSendPreq(tEplNmtState NmtState_p,
3917 tEplDllState * pDllStateProposed_p)
3919 tEplKernel Ret = kEplSuccessful;
3920 tEdrvTxBuffer *pTxBuffer = NULL;
3921 tEplFrame *pTxFrame;
3922 u8 bFlag1 = 0;
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;
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;
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
3956 if (pTxBuffer == NULL) { // PReq does not exist
3957 Ret = kEplDllTxBufNotReady;
3958 goto Exit;
3961 pTxFrame = (tEplFrame *) pTxBuffer->m_pbBuffer;
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;
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;
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);
3980 // calculate frame size from payload size
3981 pTxBuffer->m_uiTxMsgLen =
3982 AmiGetWordFromLe(&pTxFrame->m_Data.m_Preq.m_le_wSize) + 24;
3984 // send PReq frame
3985 Ret = EdrvSendTxMsg(pTxBuffer);
3986 } else {
3987 Ret = kEplDllTxFrameInvalid;
3990 Exit:
3991 return Ret;
3994 //---------------------------------------------------------------------------
3996 // Function: EplDllkAsyncFrameNotReceived()
3998 // Description: passes empty ASnd frame to receive FIFO.
3999 // It will be called only for frames with registered AsndServiceIds
4000 // (only kEplDllAsndFilterAny).
4002 // Parameters: none
4004 // Returns: tEplKernel = error code
4007 // State:
4009 //---------------------------------------------------------------------------
4011 static tEplKernel EplDllkAsyncFrameNotReceived(tEplDllReqServiceId
4012 ReqServiceId_p,
4013 unsigned int uiNodeId_p)
4015 tEplKernel Ret = kEplSuccessful;
4016 u8 abBuffer[18];
4017 tEplFrame *pFrame = (tEplFrame *) abBuffer;
4018 tEplFrameInfo FrameInfo;
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);
4040 break;
4041 default:
4042 // no invitation issued or it was successfully answered or it is uninteresting
4043 break;
4046 return Ret;
4049 #endif //(((EPL_MODULE_INTEGRATION) & (EPL_MODULE_NMT_MN)) != 0)
4051 #endif // #if(((EPL_MODULE_INTEGRATION) & (EPL_MODULE_DLLK)) != 0)
4052 // EOF