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