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