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