blob: de67e5bbee98a814dd72ff9b28bca9e91d9caeb4 [file] [log] [blame]
Daniel Krueger9d7164c2008-12-19 11:41:57 -08001/****************************************************************************
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 Communication Abstraction Layer 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: EplDllkCal.c,v $
53
54 $Author: D.Krueger $
55
56 $Revision: 1.7 $ $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/15 d.k.: start of the implementation, version 1.00
68
69****************************************************************************/
70
71#include "kernel/EplDllkCal.h"
72#include "kernel/EplDllk.h"
73#include "kernel/EplEventk.h"
74
75#include "EplDllCal.h"
76#ifndef EPL_NO_FIFO
77#include "SharedBuff.h"
78#endif
79
80#if(((EPL_MODULE_INTEGRATION) & (EPL_MODULE_DLLK)) != 0)
81/***************************************************************************/
82/* */
83/* */
84/* G L O B A L D E F I N I T I O N S */
85/* */
86/* */
87/***************************************************************************/
88
89//---------------------------------------------------------------------------
90// const defines
91//---------------------------------------------------------------------------
92
93#ifndef min
94#define min(a,b) (((a) < (b)) ? (a) : (b))
95#endif
96
97//---------------------------------------------------------------------------
98// local types
99//---------------------------------------------------------------------------
100
101//---------------------------------------------------------------------------
102// modul globale vars
103//---------------------------------------------------------------------------
104
105//---------------------------------------------------------------------------
106// local function prototypes
107//---------------------------------------------------------------------------
108
109
110/***************************************************************************/
111/* */
112/* */
113/* C L A S S EplDllkCal */
114/* */
115/* */
116/***************************************************************************/
117//
118// Description:
119//
120//
121/***************************************************************************/
122
123
124//=========================================================================//
125// //
126// P R I V A T E D E F I N I T I O N S //
127// //
128//=========================================================================//
129
130//---------------------------------------------------------------------------
131// const defines
132//---------------------------------------------------------------------------
133
134#define EPL_DLLKCAL_MAX_QUEUES 5 // CnGenReq, CnNmtReq, {MnGenReq, MnNmtReq}, MnIdentReq, MnStatusReq
135
136//---------------------------------------------------------------------------
137// local types
138//---------------------------------------------------------------------------
139
140typedef struct
141{
142#ifndef EPL_NO_FIFO
143// tShbInstance m_ShbInstanceRx; // FIFO for Rx ASnd frames
144 tShbInstance m_ShbInstanceTxNmt; // FIFO for Tx frames with NMT request priority
145 tShbInstance m_ShbInstanceTxGen; // FIFO for Tx frames with generic priority
146#else
147 unsigned int m_uiFrameSizeNmt;
148 BYTE m_abFrameNmt[1500];
149 unsigned int m_uiFrameSizeGen;
150 BYTE m_abFrameGen[1500];
151#endif
152
153 tEplDllkCalStatistics m_Statistics;
154
155#if (((EPL_MODULE_INTEGRATION) & (EPL_MODULE_NMT_MN)) != 0)
156 // IdentRequest queue with CN node IDs
157 unsigned int m_auiQueueIdentReq[EPL_D_NMT_MaxCNNumber_U8 + 1]; // 1 entry is reserved to distinguish between full and empty
158 unsigned int m_uiWriteIdentReq;
159 unsigned int m_uiReadIdentReq;
160
161 // StatusRequest queue with CN node IDs
162 unsigned int m_auiQueueStatusReq[EPL_D_NMT_MaxCNNumber_U8 + 1]; // 1 entry is reserved to distinguish between full and empty
163 unsigned int m_uiWriteStatusReq;
164 unsigned int m_uiReadStatusReq;
165
166 unsigned int m_auiQueueCnRequests[254 * 2];
167 // first 254 entries represent the generic requests of the corresponding node
168 // second 254 entries represent the NMT requests of the corresponding node
169 unsigned int m_uiNextQueueCnRequest;
170 unsigned int m_uiNextRequestQueue;
171#endif
172
173} tEplDllkCalInstance;
174
175//---------------------------------------------------------------------------
176// local vars
177//---------------------------------------------------------------------------
178
179// if no dynamic memory allocation shall be used
180// define structures statically
181static tEplDllkCalInstance EplDllkCalInstance_g;
182
183//---------------------------------------------------------------------------
184// local function prototypes
185//---------------------------------------------------------------------------
186
187
188//=========================================================================//
189// //
190// P U B L I C F U N C T I O N S //
191// //
192//=========================================================================//
193
194//---------------------------------------------------------------------------
195//
196// Function: EplDllkCalAddInstance()
197//
198// Description: add and initialize new instance of DLL CAL module
199//
200// Parameters: none
201//
202// Returns: tEplKernel = error code
203//
204//
205// State:
206//
207//---------------------------------------------------------------------------
208
209tEplKernel EplDllkCalAddInstance()
210{
211tEplKernel Ret = kEplSuccessful;
212#ifndef EPL_NO_FIFO
213tShbError ShbError;
214unsigned int fShbNewCreated;
215
216/* ShbError = ShbCirAllocBuffer (EPL_DLLCAL_BUFFER_SIZE_RX, EPL_DLLCAL_BUFFER_ID_RX,
217 &EplDllkCalInstance_g.m_ShbInstanceRx, &fShbNewCreated);
218 // returns kShbOk, kShbOpenMismatch, kShbOutOfMem or kShbInvalidArg
219
220 if (ShbError != kShbOk)
221 {
222 Ret = kEplNoResource;
223 }
224*/
225 ShbError = ShbCirAllocBuffer (EPL_DLLCAL_BUFFER_SIZE_TX_NMT, EPL_DLLCAL_BUFFER_ID_TX_NMT,
226 &EplDllkCalInstance_g.m_ShbInstanceTxNmt, &fShbNewCreated);
227 // returns kShbOk, kShbOpenMismatch, kShbOutOfMem or kShbInvalidArg
228
229 if (ShbError != kShbOk)
230 {
231 Ret = kEplNoResource;
232 }
233
234/* ShbError = ShbCirSetSignalHandlerNewData (EplDllkCalInstance_g.m_ShbInstanceTxNmt, EplDllkCalTxNmtSignalHandler, kShbPriorityNormal);
235 // returns kShbOk, kShbAlreadySignaling or kShbInvalidArg
236
237 if (ShbError != kShbOk)
238 {
239 Ret = kEplNoResource;
240 }
241*/
242 ShbError = ShbCirAllocBuffer (EPL_DLLCAL_BUFFER_SIZE_TX_GEN, EPL_DLLCAL_BUFFER_ID_TX_GEN,
243 &EplDllkCalInstance_g.m_ShbInstanceTxGen, &fShbNewCreated);
244 // returns kShbOk, kShbOpenMismatch, kShbOutOfMem or kShbInvalidArg
245
246 if (ShbError != kShbOk)
247 {
248 Ret = kEplNoResource;
249 }
250
251/* ShbError = ShbCirSetSignalHandlerNewData (EplDllkCalInstance_g.m_ShbInstanceTxGen, EplDllkCalTxGenSignalHandler, kShbPriorityNormal);
252 // returns kShbOk, kShbAlreadySignaling or kShbInvalidArg
253
254 if (ShbError != kShbOk)
255 {
256 Ret = kEplNoResource;
257 }
258*/
259#else
260 EplDllkCalInstance_g.m_uiFrameSizeNmt = 0;
261 EplDllkCalInstance_g.m_uiFrameSizeGen = 0;
262#endif
263
264 return Ret;
265}
266
267//---------------------------------------------------------------------------
268//
269// Function: EplDllkCalDelInstance()
270//
271// Description: deletes instance of DLL CAL module
272//
273// Parameters: none
274//
275// Returns: tEplKernel = error code
276//
277//
278// State:
279//
280//---------------------------------------------------------------------------
281
282tEplKernel EplDllkCalDelInstance()
283{
284tEplKernel Ret = kEplSuccessful;
285#ifndef EPL_NO_FIFO
286tShbError ShbError;
287
288/* ShbError = ShbCirReleaseBuffer (EplDllkCalInstance_g.m_ShbInstanceRx);
289 if (ShbError != kShbOk)
290 {
291 Ret = kEplNoResource;
292 }
293 EplDllkCalInstance_g.m_ShbInstanceRx = NULL;
294*/
295 ShbError = ShbCirReleaseBuffer (EplDllkCalInstance_g.m_ShbInstanceTxNmt);
296 if (ShbError != kShbOk)
297 {
298 Ret = kEplNoResource;
299 }
300 EplDllkCalInstance_g.m_ShbInstanceTxNmt = NULL;
301
302 ShbError = ShbCirReleaseBuffer (EplDllkCalInstance_g.m_ShbInstanceTxGen);
303 if (ShbError != kShbOk)
304 {
305 Ret = kEplNoResource;
306 }
307 EplDllkCalInstance_g.m_ShbInstanceTxGen = NULL;
308
309#else
310 EplDllkCalInstance_g.m_uiFrameSizeNmt = 0;
311 EplDllkCalInstance_g.m_uiFrameSizeGen = 0;
312#endif
313
314 return Ret;
315}
316
317//---------------------------------------------------------------------------
318//
319// Function: EplDllkCalProcess
320//
321// Description: process the passed configuration
322//
323// Parameters: pEvent_p = event containing configuration options
324//
325// Returns: tEplKernel = error code
326//
327//
328// State:
329//
330//---------------------------------------------------------------------------
331
332tEplKernel EplDllkCalProcess(tEplEvent * pEvent_p)
333{
334tEplKernel Ret = kEplSuccessful;
335
336 switch (pEvent_p->m_EventType)
337 {
338 case kEplEventTypeDllkServFilter:
339 {
340 tEplDllCalAsndServiceIdFilter* pServFilter;
341
342 pServFilter = (tEplDllCalAsndServiceIdFilter*) pEvent_p->m_pArg;
343 Ret = EplDllkSetAsndServiceIdFilter(pServFilter->m_ServiceId, pServFilter->m_Filter);
344 break;
345 }
346
347#if (((EPL_MODULE_INTEGRATION) & (EPL_MODULE_NMT_MN)) != 0)
348 case kEplEventTypeDllkIssueReq:
349 {
350 tEplDllCalIssueRequest* pIssueReq;
351
352 pIssueReq = (tEplDllCalIssueRequest*) pEvent_p->m_pArg;
353 Ret = EplDllkCalIssueRequest(pIssueReq->m_Service, pIssueReq->m_uiNodeId, pIssueReq->m_bSoaFlag1);
354 break;
355 }
356
357 case kEplEventTypeDllkAddNode:
358 {
359 tEplDllNodeInfo* pNodeInfo;
360
361 pNodeInfo = (tEplDllNodeInfo*) pEvent_p->m_pArg;
362 Ret = EplDllkAddNode(pNodeInfo);
363 break;
364 }
365
366 case kEplEventTypeDllkDelNode:
367 {
368 unsigned int* puiNodeId;
369
370 puiNodeId = (unsigned int*) pEvent_p->m_pArg;
371 Ret = EplDllkDeleteNode(*puiNodeId);
372 break;
373 }
374
375 case kEplEventTypeDllkSoftDelNode:
376 {
377 unsigned int* puiNodeId;
378
379 puiNodeId = (unsigned int*) pEvent_p->m_pArg;
380 Ret = EplDllkSoftDeleteNode(*puiNodeId);
381 break;
382 }
383#endif
384
385 case kEplEventTypeDllkIdentity:
386 {
387 tEplDllIdentParam* pIdentParam;
388
389 pIdentParam = (tEplDllIdentParam*) pEvent_p->m_pArg;
390 if (pIdentParam->m_uiSizeOfStruct > pEvent_p->m_uiSize)
391 {
392 pIdentParam->m_uiSizeOfStruct = pEvent_p->m_uiSize;
393 }
394 Ret = EplDllkSetIdentity(pIdentParam);
395 break;
396 }
397
398 case kEplEventTypeDllkConfig:
399 {
400 tEplDllConfigParam* pConfigParam;
401
402 pConfigParam = (tEplDllConfigParam*) pEvent_p->m_pArg;
403 if (pConfigParam->m_uiSizeOfStruct > pEvent_p->m_uiSize)
404 {
405 pConfigParam->m_uiSizeOfStruct = pEvent_p->m_uiSize;
406 }
407 Ret = EplDllkConfig(pConfigParam);
408 break;
409 }
410
411 default:
412 break;
413 }
414
415//Exit:
416 return Ret;
417}
418
419
420//---------------------------------------------------------------------------
421//
422// Function: EplDllkCalAsyncGetTxCount()
423//
424// Description: returns count of Tx frames of FIFO with highest priority
425//
426// Parameters: none
427//
428// Returns: tEplKernel = error code
429//
430//
431// State:
432//
433//---------------------------------------------------------------------------
434
435tEplKernel EplDllkCalAsyncGetTxCount(tEplDllAsyncReqPriority * pPriority_p, unsigned int * puiCount_p)
436{
437tEplKernel Ret = kEplSuccessful;
438#ifndef EPL_NO_FIFO
439tShbError ShbError;
440unsigned long ulFrameCount;
441
442 // get frame count of Tx FIFO with NMT request priority
443 ShbError = ShbCirGetReadBlockCount (EplDllkCalInstance_g.m_ShbInstanceTxNmt, &ulFrameCount);
444 // returns kShbOk, kShbInvalidArg
445
446 // error handling
447 if (ShbError != kShbOk)
448 {
449 Ret = kEplNoResource;
450 goto Exit;
451 }
452
453 if (ulFrameCount > EplDllkCalInstance_g.m_Statistics.m_ulMaxTxFrameCountNmt)
454 {
455 EplDllkCalInstance_g.m_Statistics.m_ulMaxTxFrameCountNmt = ulFrameCount;
456 }
457
458 if (ulFrameCount != 0)
459 { // NMT requests are in queue
460 *pPriority_p = kEplDllAsyncReqPrioNmt;
461 *puiCount_p = (unsigned int) ulFrameCount;
462 goto Exit;
463 }
464
465 // get frame count of Tx FIFO with generic priority
466 ShbError = ShbCirGetReadBlockCount (EplDllkCalInstance_g.m_ShbInstanceTxGen, &ulFrameCount);
467 // returns kShbOk, kShbInvalidArg
468
469 // error handling
470 if (ShbError != kShbOk)
471 {
472 Ret = kEplNoResource;
473 goto Exit;
474 }
475
476 if (ulFrameCount > EplDllkCalInstance_g.m_Statistics.m_ulMaxTxFrameCountGen)
477 {
478 EplDllkCalInstance_g.m_Statistics.m_ulMaxTxFrameCountGen = ulFrameCount;
479 }
480
481 *pPriority_p = kEplDllAsyncReqPrioGeneric;
482 *puiCount_p = (unsigned int) ulFrameCount;
483
484Exit:
485#else
486 if (EplDllkCalInstance_g.m_uiFrameSizeNmt > 0)
487 {
488 *pPriority_p = kEplDllAsyncReqPrioNmt;
489 *puiCount_p = 1;
490 }
491 else if (EplDllkCalInstance_g.m_uiFrameSizeGen > 0)
492 {
493 *pPriority_p = kEplDllAsyncReqPrioGeneric;
494 *puiCount_p = 1;
495 }
496 else
497 {
498 *pPriority_p = kEplDllAsyncReqPrioGeneric;
499 *puiCount_p = 0;
500 }
501#endif
502
503 return Ret;
504}
505
506//---------------------------------------------------------------------------
507//
508// Function: EplDllkCalAsyncGetTxFrame()
509//
510// Description: returns Tx frames from FIFO with specified priority
511//
512// Parameters: pFrame_p = IN: pointer to buffer
513// puiFrameSize_p = IN: max size of buffer
514// OUT: actual size of frame
515// Priority_p = IN: priority
516//
517// Returns: tEplKernel = error code
518//
519//
520// State:
521//
522//---------------------------------------------------------------------------
523
524tEplKernel EplDllkCalAsyncGetTxFrame(void * pFrame_p, unsigned int * puiFrameSize_p, tEplDllAsyncReqPriority Priority_p)
525{
526tEplKernel Ret = kEplSuccessful;
527#ifndef EPL_NO_FIFO
528tShbError ShbError;
529unsigned long ulFrameSize;
530
531 switch (Priority_p)
532 {
533 case kEplDllAsyncReqPrioNmt: // NMT request priority
534 ShbError = ShbCirReadDataBlock (EplDllkCalInstance_g.m_ShbInstanceTxNmt, (BYTE *) pFrame_p, *puiFrameSize_p, &ulFrameSize);
535 // returns kShbOk, kShbDataTruncated, kShbInvalidArg, kShbNoReadableData
536 break;
537
538 default: // generic priority
539 ShbError = ShbCirReadDataBlock (EplDllkCalInstance_g.m_ShbInstanceTxGen, (BYTE *) pFrame_p, *puiFrameSize_p, &ulFrameSize);
540 // returns kShbOk, kShbDataTruncated, kShbInvalidArg, kShbNoReadableData
541 break;
542
543 }
544
545 // error handling
546 if (ShbError != kShbOk)
547 {
548 if (ShbError == kShbNoReadableData)
549 {
550 Ret = kEplDllAsyncTxBufferEmpty;
551 }
552 else
553 { // other error
554 Ret = kEplNoResource;
555 }
556 goto Exit;
557 }
558
559 *puiFrameSize_p = (unsigned int) ulFrameSize;
560
561Exit:
562#else
563 switch (Priority_p)
564 {
565 case kEplDllAsyncReqPrioNmt: // NMT request priority
566 *puiFrameSize_p = min(*puiFrameSize_p, EplDllkCalInstance_g.m_uiFrameSizeNmt);
567 EPL_MEMCPY(pFrame_p, EplDllkCalInstance_g.m_abFrameNmt, *puiFrameSize_p);
568 EplDllkCalInstance_g.m_uiFrameSizeNmt = 0;
569 break;
570
571 default: // generic priority
572 *puiFrameSize_p = min(*puiFrameSize_p, EplDllkCalInstance_g.m_uiFrameSizeGen);
573 EPL_MEMCPY(pFrame_p, EplDllkCalInstance_g.m_abFrameGen, *puiFrameSize_p);
574 EplDllkCalInstance_g.m_uiFrameSizeGen = 0;
575 break;
576 }
577
578#endif
579
580 return Ret;
581}
582
583//---------------------------------------------------------------------------
584//
585// Function: EplDllkCalAsyncFrameReceived()
586//
587// Description: passes ASnd frame to receive FIFO.
588// It will be called only for frames with registered AsndServiceIds.
589//
590// Parameters: none
591//
592// Returns: tEplKernel = error code
593//
594//
595// State:
596//
597//---------------------------------------------------------------------------
598
599tEplKernel EplDllkCalAsyncFrameReceived(tEplFrameInfo * pFrameInfo_p)
600{
601tEplKernel Ret = kEplSuccessful;
602tEplEvent Event;
603
604 Event.m_EventSink = kEplEventSinkDlluCal;
605 Event.m_EventType = kEplEventTypeAsndRx;
606 Event.m_pArg = pFrameInfo_p->m_pFrame;
607 Event.m_uiSize = pFrameInfo_p->m_uiFrameSize;
608 // pass NetTime of frame to userspace
609 Event.m_NetTime = pFrameInfo_p->m_NetTime;
610
611 Ret = EplEventkPost(&Event);
612 if (Ret != kEplSuccessful)
613 {
614 EplDllkCalInstance_g.m_Statistics.m_ulCurRxFrameCount++;
615 }
616 else
617 {
618 EplDllkCalInstance_g.m_Statistics.m_ulMaxRxFrameCount++;
619 }
620
621 return Ret;
622}
623
624
625//---------------------------------------------------------------------------
626//
627// Function: EplDllkCalAsyncSend()
628//
629// Description: puts the given frame into the transmit FIFO with the specified
630// priority.
631//
632// Parameters: pFrameInfo_p = frame info structure
633// Priority_p = priority
634//
635// Returns: tEplKernel = error code
636//
637//
638// State:
639//
640//---------------------------------------------------------------------------
641
642tEplKernel EplDllkCalAsyncSend(tEplFrameInfo * pFrameInfo_p, tEplDllAsyncReqPriority Priority_p)
643{
644tEplKernel Ret = kEplSuccessful;
645tEplEvent Event;
646#ifndef EPL_NO_FIFO
647tShbError ShbError;
648
649 switch (Priority_p)
650 {
651 case kEplDllAsyncReqPrioNmt: // NMT request priority
652 ShbError = ShbCirWriteDataBlock (EplDllkCalInstance_g.m_ShbInstanceTxNmt, pFrameInfo_p->m_pFrame, pFrameInfo_p->m_uiFrameSize);
653 // returns kShbOk, kShbExceedDataSizeLimit, kShbBufferFull, kShbInvalidArg
654 break;
655
656 default: // generic priority
657 ShbError = ShbCirWriteDataBlock (EplDllkCalInstance_g.m_ShbInstanceTxGen, pFrameInfo_p->m_pFrame, pFrameInfo_p->m_uiFrameSize);
658 // returns kShbOk, kShbExceedDataSizeLimit, kShbBufferFull, kShbInvalidArg
659 break;
660
661 }
662
663 // error handling
664 switch (ShbError)
665 {
666 case kShbOk:
667 break;
668
669 case kShbExceedDataSizeLimit:
670 Ret = kEplDllAsyncTxBufferFull;
671 break;
672
673 case kShbBufferFull:
674 Ret = kEplDllAsyncTxBufferFull;
675 break;
676
677 case kShbInvalidArg:
678 default:
679 Ret = kEplNoResource;
680 break;
681 }
682
683#else
684
685 switch (Priority_p)
686 {
687 case kEplDllAsyncReqPrioNmt: // NMT request priority
688 if (EplDllkCalInstance_g.m_uiFrameSizeNmt == 0)
689 {
690 EPL_MEMCPY(EplDllkCalInstance_g.m_abFrameNmt, pFrameInfo_p->m_pFrame, pFrameInfo_p->m_uiFrameSize);
691 EplDllkCalInstance_g.m_uiFrameSizeNmt = pFrameInfo_p->m_uiFrameSize;
692 }
693 else
694 {
695 Ret = kEplDllAsyncTxBufferFull;
696 goto Exit;
697 }
698 break;
699
700 default: // generic priority
701 if (EplDllkCalInstance_g.m_uiFrameSizeGen == 0)
702 {
703 EPL_MEMCPY(EplDllkCalInstance_g.m_abFrameGen, pFrameInfo_p->m_pFrame, pFrameInfo_p->m_uiFrameSize);
704 EplDllkCalInstance_g.m_uiFrameSizeGen = pFrameInfo_p->m_uiFrameSize;
705 }
706 else
707 {
708 Ret = kEplDllAsyncTxBufferFull;
709 goto Exit;
710 }
711 break;
712 }
713
714#endif
715
716 // post event to DLL
717 Event.m_EventSink = kEplEventSinkDllk;
718 Event.m_EventType = kEplEventTypeDllkFillTx;
719 EPL_MEMSET(&Event.m_NetTime, 0x00, sizeof(Event.m_NetTime));
720 Event.m_pArg = &Priority_p;
721 Event.m_uiSize = sizeof(Priority_p);
722 Ret = EplEventkPost(&Event);
723
724#ifdef EPL_NO_FIFO
725Exit:
726#endif
727
728 return Ret;
729}
730
731
732//---------------------------------------------------------------------------
733//
734// Function: EplDllkCalAsyncClearBuffer()
735//
736// Description: clears the transmit buffer
737//
738// Parameters: (none)
739//
740// Returns: tEplKernel = error code
741//
742//
743// State:
744//
745//---------------------------------------------------------------------------
746
747tEplKernel EplDllkCalAsyncClearBuffer(void)
748{
749tEplKernel Ret = kEplSuccessful;
750#ifndef EPL_NO_FIFO
751tShbError ShbError;
752
753 ShbError = ShbCirResetBuffer (EplDllkCalInstance_g.m_ShbInstanceTxNmt, 1000, NULL);
754 ShbError = ShbCirResetBuffer (EplDllkCalInstance_g.m_ShbInstanceTxGen, 1000, NULL);
755
756#else
757 EplDllkCalInstance_g.m_uiFrameSizeNmt = 0;
758 EplDllkCalInstance_g.m_uiFrameSizeGen = 0;
759#endif
760
761// EPL_MEMSET(&EplDllkCalInstance_g.m_Statistics, 0, sizeof (tEplDllkCalStatistics));
762 return Ret;
763}
764
765
766//---------------------------------------------------------------------------
767//
768// Function: EplDllkCalAsyncClearQueues()
769//
770// Description: clears the transmit buffer
771//
772// Parameters: (none)
773//
774// Returns: tEplKernel = error code
775//
776//
777// State:
778//
779//---------------------------------------------------------------------------
780
781#if (((EPL_MODULE_INTEGRATION) & (EPL_MODULE_NMT_MN)) != 0)
782tEplKernel EplDllkCalAsyncClearQueues(void)
783{
784tEplKernel Ret = kEplSuccessful;
785
786 // clear MN asynchronous queues
787 EplDllkCalInstance_g.m_uiNextQueueCnRequest = 0;
788 EplDllkCalInstance_g.m_uiNextRequestQueue = 0;
789 EplDllkCalInstance_g.m_uiReadIdentReq = 0;
790 EplDllkCalInstance_g.m_uiWriteIdentReq = 0;
791 EplDllkCalInstance_g.m_uiReadStatusReq = 0;
792 EplDllkCalInstance_g.m_uiWriteStatusReq = 0;
793
794 return Ret;
795}
796#endif
797
798
799//---------------------------------------------------------------------------
800//
801// Function: EplDllkCalGetStatistics()
802//
803// Description: returns statistics of the asynchronous queues.
804//
805// Parameters: ppStatistics = statistics structure
806//
807// Returns: tEplKernel = error code
808//
809//
810// State:
811//
812//---------------------------------------------------------------------------
813
814tEplKernel EplDllkCalGetStatistics(tEplDllkCalStatistics ** ppStatistics)
815{
816tEplKernel Ret = kEplSuccessful;
817#ifndef EPL_NO_FIFO
818tShbError ShbError;
819
820 ShbError = ShbCirGetReadBlockCount (EplDllkCalInstance_g.m_ShbInstanceTxNmt, &EplDllkCalInstance_g.m_Statistics.m_ulCurTxFrameCountNmt);
821 ShbError = ShbCirGetReadBlockCount (EplDllkCalInstance_g.m_ShbInstanceTxGen, &EplDllkCalInstance_g.m_Statistics.m_ulCurTxFrameCountGen);
822// ShbError = ShbCirGetReadBlockCount (EplDllkCalInstance_g.m_ShbInstanceRx, &EplDllkCalInstance_g.m_Statistics.m_ulCurRxFrameCount);
823
824#else
825 if (EplDllkCalInstance_g.m_uiFrameSizeNmt > 0)
826 {
827 EplDllkCalInstance_g.m_Statistics.m_ulCurTxFrameCountNmt = 1;
828 }
829 else
830 {
831 EplDllkCalInstance_g.m_Statistics.m_ulCurTxFrameCountNmt = 0;
832 }
833 if (EplDllkCalInstance_g.m_uiFrameSizeGen > 0)
834 {
835 EplDllkCalInstance_g.m_Statistics.m_ulCurTxFrameCountGen = 1;
836 }
837 else
838 {
839 EplDllkCalInstance_g.m_Statistics.m_ulCurTxFrameCountGen = 0;
840 }
841#endif
842
843 *ppStatistics = &EplDllkCalInstance_g.m_Statistics;
844 return Ret;
845}
846
847
848#if (((EPL_MODULE_INTEGRATION) & (EPL_MODULE_NMT_MN)) != 0)
849
850//---------------------------------------------------------------------------
851//
852// Function: EplDllkCalIssueRequest()
853//
854// Description: issues a StatusRequest or a IdentRequest to the specified node.
855//
856// Parameters: Service_p = request service ID
857// uiNodeId_p = node ID
858// bSoaFlag1_p = flag1 for this node (transmit in SoA and PReq)
859// If 0xFF this flag is ignored.
860//
861// Returns: tEplKernel = error code
862//
863//
864// State:
865//
866//---------------------------------------------------------------------------
867
868tEplKernel EplDllkCalIssueRequest(tEplDllReqServiceId Service_p, unsigned int uiNodeId_p, BYTE bSoaFlag1_p)
869{
870tEplKernel Ret = kEplSuccessful;
871
872 if (bSoaFlag1_p != 0xFF)
873 {
874 Ret = EplDllkSetFlag1OfNode(uiNodeId_p, bSoaFlag1_p);
875 if (Ret != kEplSuccessful)
876 {
877 goto Exit;
878 }
879 }
880
881 // add node to appropriate request queue
882 switch (Service_p)
883 {
884 case kEplDllReqServiceIdent:
885 {
886 if (((EplDllkCalInstance_g.m_uiWriteIdentReq + 1) % tabentries (EplDllkCalInstance_g.m_auiQueueIdentReq))
887 == EplDllkCalInstance_g.m_uiReadIdentReq)
888 { // queue is full
889 Ret = kEplDllAsyncTxBufferFull;
890 goto Exit;
891 }
892 EplDllkCalInstance_g.m_auiQueueIdentReq[EplDllkCalInstance_g.m_uiWriteIdentReq] = uiNodeId_p;
893 EplDllkCalInstance_g.m_uiWriteIdentReq =
894 (EplDllkCalInstance_g.m_uiWriteIdentReq + 1) % tabentries (EplDllkCalInstance_g.m_auiQueueIdentReq);
895 break;
896 }
897
898 case kEplDllReqServiceStatus:
899 {
900 if (((EplDllkCalInstance_g.m_uiWriteStatusReq + 1) % tabentries (EplDllkCalInstance_g.m_auiQueueStatusReq))
901 == EplDllkCalInstance_g.m_uiReadStatusReq)
902 { // queue is full
903 Ret = kEplDllAsyncTxBufferFull;
904 goto Exit;
905 }
906 EplDllkCalInstance_g.m_auiQueueStatusReq[EplDllkCalInstance_g.m_uiWriteStatusReq] = uiNodeId_p;
907 EplDllkCalInstance_g.m_uiWriteStatusReq =
908 (EplDllkCalInstance_g.m_uiWriteStatusReq + 1) % tabentries (EplDllkCalInstance_g.m_auiQueueStatusReq);
909 break;
910 }
911
912 default:
913 {
914 Ret = kEplDllInvalidParam;
915 goto Exit;
916 }
917 }
918
919Exit:
920 return Ret;
921}
922
923
924//---------------------------------------------------------------------------
925//
926// Function: EplDllkCalAsyncGetSoaRequest()
927//
928// Description: returns next request for SoA. This function is called by DLLk module.
929//
930// Parameters: pReqServiceId_p = pointer to request service ID
931// IN: available request for MN NMT or generic request queue (Flag2.PR)
932// or kEplDllReqServiceNo if queues are empty
933// OUT: next request
934// puiNodeId_p = OUT: pointer to node ID of next request
935// = EPL_C_ADR_INVALID, if request is self addressed
936//
937// Returns: tEplKernel = error code
938//
939//
940// State:
941//
942//---------------------------------------------------------------------------
943
944tEplKernel EplDllkCalAsyncGetSoaRequest(tEplDllReqServiceId* pReqServiceId_p, unsigned int* puiNodeId_p)
945{
946tEplKernel Ret = kEplSuccessful;
947unsigned int uiCount;
948
949// *pReqServiceId_p = kEplDllReqServiceNo;
950
951 for (uiCount = EPL_DLLKCAL_MAX_QUEUES; uiCount > 0; uiCount--)
952 {
953 switch (EplDllkCalInstance_g.m_uiNextRequestQueue)
954 {
955 case 0:
956 { // CnGenReq
957 for (;EplDllkCalInstance_g.m_uiNextQueueCnRequest < (tabentries (EplDllkCalInstance_g.m_auiQueueCnRequests) / 2);
958 EplDllkCalInstance_g.m_uiNextQueueCnRequest++)
959 {
960 if (EplDllkCalInstance_g.m_auiQueueCnRequests[EplDllkCalInstance_g.m_uiNextQueueCnRequest] > 0)
961 { // non empty queue found
962 // remove one request from queue
963 EplDllkCalInstance_g.m_auiQueueCnRequests[EplDllkCalInstance_g.m_uiNextQueueCnRequest]--;
964 *puiNodeId_p = EplDllkCalInstance_g.m_uiNextQueueCnRequest + 1;
965 *pReqServiceId_p = kEplDllReqServiceUnspecified;
966 EplDllkCalInstance_g.m_uiNextQueueCnRequest++;
967 if (EplDllkCalInstance_g.m_uiNextQueueCnRequest >= (tabentries (EplDllkCalInstance_g.m_auiQueueCnRequests) / 2))
968 { // last node reached
969 // continue with CnNmtReq queue at next SoA
970 EplDllkCalInstance_g.m_uiNextRequestQueue = 1;
971 }
972 goto Exit;
973 }
974 }
975 // all CnGenReq queues are empty -> continue with CnNmtReq queue
976 EplDllkCalInstance_g.m_uiNextRequestQueue = 1;
977 break;
978 }
979
980 case 1:
981 { // CnNmtReq
982 for (;EplDllkCalInstance_g.m_uiNextQueueCnRequest < tabentries (EplDllkCalInstance_g.m_auiQueueCnRequests);
983 EplDllkCalInstance_g.m_uiNextQueueCnRequest++)
984 {
985 if (EplDllkCalInstance_g.m_auiQueueCnRequests[EplDllkCalInstance_g.m_uiNextQueueCnRequest] > 0)
986 { // non empty queue found
987 // remove one request from queue
988 EplDllkCalInstance_g.m_auiQueueCnRequests[EplDllkCalInstance_g.m_uiNextQueueCnRequest]--;
989 *puiNodeId_p = EplDllkCalInstance_g.m_uiNextQueueCnRequest + 1 - (tabentries (EplDllkCalInstance_g.m_auiQueueCnRequests) / 2);
990 *pReqServiceId_p = kEplDllReqServiceNmtRequest;
991 EplDllkCalInstance_g.m_uiNextQueueCnRequest++;
992 if (EplDllkCalInstance_g.m_uiNextQueueCnRequest > tabentries (EplDllkCalInstance_g.m_auiQueueCnRequests))
993 { // last node reached
994 // restart CnGenReq queue
995 EplDllkCalInstance_g.m_uiNextQueueCnRequest = 0;
996 // continue with MnGenReq queue at next SoA
997 EplDllkCalInstance_g.m_uiNextRequestQueue = 2;
998 }
999 goto Exit;
1000 }
1001 }
1002 // restart CnGenReq queue
1003 EplDllkCalInstance_g.m_uiNextQueueCnRequest = 0;
1004 // all CnNmtReq queues are empty -> continue with MnGenReq queue
1005 EplDllkCalInstance_g.m_uiNextRequestQueue = 2;
1006 break;
1007 }
1008
1009 case 2:
1010 { // MnNmtReq and MnGenReq
1011 // next queue will be MnIdentReq queue
1012 EplDllkCalInstance_g.m_uiNextRequestQueue = 3;
1013 if (*pReqServiceId_p != kEplDllReqServiceNo)
1014 {
1015 *puiNodeId_p = EPL_C_ADR_INVALID; // DLLk must exchange this with the actual node ID
1016 goto Exit;
1017 }
1018 break;
1019 }
1020
1021 case 3:
1022 { // MnIdentReq
1023 // next queue will be MnStatusReq queue
1024 EplDllkCalInstance_g.m_uiNextRequestQueue = 4;
1025 if (EplDllkCalInstance_g.m_uiReadIdentReq != EplDllkCalInstance_g.m_uiWriteIdentReq)
1026 { // queue is not empty
1027 *puiNodeId_p = EplDllkCalInstance_g.m_auiQueueIdentReq[EplDllkCalInstance_g.m_uiReadIdentReq];
1028 EplDllkCalInstance_g.m_uiReadIdentReq =
1029 (EplDllkCalInstance_g.m_uiReadIdentReq + 1) % tabentries (EplDllkCalInstance_g.m_auiQueueIdentReq);
1030 *pReqServiceId_p = kEplDllReqServiceIdent;
1031 goto Exit;
1032 }
1033 break;
1034 }
1035
1036 case 4:
1037 { // MnStatusReq
1038 // next queue will be CnGenReq queue
1039 EplDllkCalInstance_g.m_uiNextRequestQueue = 0;
1040 if (EplDllkCalInstance_g.m_uiReadStatusReq != EplDllkCalInstance_g.m_uiWriteStatusReq)
1041 { // queue is not empty
1042 *puiNodeId_p = EplDllkCalInstance_g.m_auiQueueStatusReq[EplDllkCalInstance_g.m_uiReadStatusReq];
1043 EplDllkCalInstance_g.m_uiReadStatusReq =
1044 (EplDllkCalInstance_g.m_uiReadStatusReq + 1) % tabentries (EplDllkCalInstance_g.m_auiQueueStatusReq);
1045 *pReqServiceId_p = kEplDllReqServiceStatus;
1046 goto Exit;
1047 }
1048 break;
1049 }
1050
1051 }
1052 }
1053
1054Exit:
1055 return Ret;
1056}
1057
1058//---------------------------------------------------------------------------
1059//
1060// Function: EplDllkCalAsyncSetPendingRequests()
1061//
1062// Description: sets the pending asynchronous frame requests of the specified node.
1063// This will add the node to the asynchronous request scheduler.
1064//
1065// Parameters: uiNodeId_p = node ID
1066// AsyncReqPrio_p = asynchronous request priority
1067// uiCount_p = count of asynchronous frames
1068//
1069// Returns: tEplKernel = error code
1070//
1071//
1072// State:
1073//
1074//---------------------------------------------------------------------------
1075
1076tEplKernel EplDllkCalAsyncSetPendingRequests(unsigned int uiNodeId_p, tEplDllAsyncReqPriority AsyncReqPrio_p, unsigned int uiCount_p)
1077{
1078tEplKernel Ret = kEplSuccessful;
1079
1080 // add node to appropriate request queue
1081 switch (AsyncReqPrio_p)
1082 {
1083 case kEplDllAsyncReqPrioNmt:
1084 {
1085 uiNodeId_p--;
1086 if (uiNodeId_p >= (tabentries (EplDllkCalInstance_g.m_auiQueueCnRequests) / 2))
1087 {
1088 Ret = kEplDllInvalidParam;
1089 goto Exit;
1090 }
1091 uiNodeId_p += tabentries (EplDllkCalInstance_g.m_auiQueueCnRequests) / 2;
1092 EplDllkCalInstance_g.m_auiQueueCnRequests[uiNodeId_p] = uiCount_p;
1093 break;
1094 }
1095
1096 default:
1097 {
1098 uiNodeId_p--;
1099 if (uiNodeId_p >= (tabentries (EplDllkCalInstance_g.m_auiQueueCnRequests) / 2))
1100 {
1101 Ret = kEplDllInvalidParam;
1102 goto Exit;
1103 }
1104 EplDllkCalInstance_g.m_auiQueueCnRequests[uiNodeId_p] = uiCount_p;
1105 break;
1106 }
1107 }
1108
1109Exit:
1110 return Ret;
1111}
1112#endif //(((EPL_MODULE_INTEGRATION) & (EPL_MODULE_NMT_MN)) != 0)
1113
1114//=========================================================================//
1115// //
1116// P R I V A T E F U N C T I O N S //
1117// //
1118//=========================================================================//
1119
1120//---------------------------------------------------------------------------
1121// Callback handler for new data signaling
1122//---------------------------------------------------------------------------
1123
1124#ifndef EPL_NO_FIFO
1125/*static void EplDllkCalTxNmtSignalHandler (
1126 tShbInstance pShbRxInstance_p,
1127 unsigned long ulDataSize_p)
1128{
1129tEplKernel Ret = kEplSuccessful;
1130tEplEvent Event;
1131tEplDllAsyncReqPriority Priority;
1132#ifndef EPL_NO_FIFO
1133tShbError ShbError;
1134unsigned long ulBlockCount;
1135
1136
1137 ShbError = ShbCirGetReadBlockCount (EplDllkCalInstance_g.m_ShbInstanceTxNmt, &ulBlockCount);
1138 if (ulBlockCount > EplDllkCalInstance_g.m_Statistics.m_ulMaxTxFrameCountNmt)
1139 {
1140 EplDllkCalInstance_g.m_Statistics.m_ulMaxTxFrameCountNmt = ulBlockCount;
1141 }
1142
1143#endif
1144
1145 // post event to DLL
1146 Priority = kEplDllAsyncReqPrioNmt;
1147 Event.m_EventSink = kEplEventSinkDllk;
1148 Event.m_EventType = kEplEventTypeDllkFillTx;
1149 EPL_MEMSET(&Event.m_NetTime, 0x00, sizeof(Event.m_NetTime));
1150 Event.m_pArg = &Priority;
1151 Event.m_uiSize = sizeof(Priority);
1152 Ret = EplEventkPost(&Event);
1153
1154}
1155
1156static void EplDllkCalTxGenSignalHandler (
1157 tShbInstance pShbRxInstance_p,
1158 unsigned long ulDataSize_p)
1159{
1160tEplKernel Ret = kEplSuccessful;
1161tEplEvent Event;
1162tEplDllAsyncReqPriority Priority;
1163#ifndef EPL_NO_FIFO
1164tShbError ShbError;
1165unsigned long ulBlockCount;
1166
1167
1168 ShbError = ShbCirGetReadBlockCount (EplDllkCalInstance_g.m_ShbInstanceTxGen, &ulBlockCount);
1169 if (ulBlockCount > EplDllkCalInstance_g.m_Statistics.m_ulMaxTxFrameCountGen)
1170 {
1171 EplDllkCalInstance_g.m_Statistics.m_ulMaxTxFrameCountGen = ulBlockCount;
1172 }
1173
1174#endif
1175
1176 // post event to DLL
1177 Priority = kEplDllAsyncReqPrioGeneric;
1178 Event.m_EventSink = kEplEventSinkDllk;
1179 Event.m_EventType = kEplEventTypeDllkFillTx;
1180 EPL_MEMSET(&Event.m_NetTime, 0x00, sizeof(Event.m_NetTime));
1181 Event.m_pArg = &Priority;
1182 Event.m_uiSize = sizeof(Priority);
1183 Ret = EplEventkPost(&Event);
1184
1185}
1186*/
1187#endif
1188
1189
1190#endif // #if(((EPL_MODULE_INTEGRATION) & (EPL_MODULE_DLLK)) != 0)
1191
1192// EOF
1193