Merge commit 'v2.6.30-rc5' into sched/core
[linux-2.6] / drivers / staging / epl / EplNmtu.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 NMT-Userspace-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: EplNmtu.c,v $
53
54                 $Author: D.Krueger $
55
56                 $Revision: 1.8 $  $Date: 2008/11/10 17:17:42 $
57
58                 $State: Exp $
59
60                 Build Environment:
61                     GCC V3.4
62
63   -------------------------------------------------------------------------
64
65   Revision History:
66
67   2006/06/09 k.t.:   start of the implementation
68
69 ****************************************************************************/
70
71 #include "EplInc.h"
72 #include "user/EplNmtu.h"
73 #include "user/EplObdu.h"
74 #include "user/EplTimeru.h"
75 #if(((EPL_MODULE_INTEGRATION) & (EPL_MODULE_NMTK)) != 0)
76 #include "kernel/EplNmtk.h"
77 #endif
78
79 #if(((EPL_MODULE_INTEGRATION) & (EPL_MODULE_NMTU)) != 0)
80 /***************************************************************************/
81 /*                                                                         */
82 /*                                                                         */
83 /*          G L O B A L   D E F I N I T I O N S                            */
84 /*                                                                         */
85 /*                                                                         */
86 /***************************************************************************/
87
88 //---------------------------------------------------------------------------
89 // const defines
90 //---------------------------------------------------------------------------
91
92 //---------------------------------------------------------------------------
93 // local types
94 //---------------------------------------------------------------------------
95
96 typedef struct {
97         tEplNmtuStateChangeCallback m_pfnNmtChangeCb;
98         tEplTimerHdl m_TimerHdl;
99
100 } tEplNmtuInstance;
101
102 //---------------------------------------------------------------------------
103 // modul globale vars
104 //---------------------------------------------------------------------------
105
106 static tEplNmtuInstance EplNmtuInstance_g;
107
108 //---------------------------------------------------------------------------
109 // local function prototypes
110 //---------------------------------------------------------------------------
111
112 //=========================================================================//
113 //                                                                         //
114 //          P U B L I C   F U N C T I O N S                                //
115 //                                                                         //
116 //=========================================================================//
117
118 //---------------------------------------------------------------------------
119 //
120 // Function:    EplNmtuInit
121 //
122 // Description: init first instance of the module
123 //
124 //
125 //
126 // Parameters:
127 //
128 //
129 // Returns:     tEplKernel  = errorcode
130 //
131 //
132 // State:
133 //
134 //---------------------------------------------------------------------------
135 tEplKernel EplNmtuInit(void)
136 {
137         tEplKernel Ret;
138
139         Ret = EplNmtuAddInstance();
140
141         return Ret;
142 }
143
144 //---------------------------------------------------------------------------
145 //
146 // Function:    EplNmtuAddInstance
147 //
148 // Description: init other instances of the module
149 //
150 //
151 //
152 // Parameters:
153 //
154 //
155 // Returns:     tEplKernel  = errorcode
156 //
157 //
158 // State:
159 //
160 //---------------------------------------------------------------------------
161 tEplKernel EplNmtuAddInstance(void)
162 {
163         tEplKernel Ret;
164
165         Ret = kEplSuccessful;
166
167         EplNmtuInstance_g.m_pfnNmtChangeCb = NULL;
168
169         return Ret;
170
171 }
172
173 //---------------------------------------------------------------------------
174 //
175 // Function:    EplNmtuDelInstance
176 //
177 // Description: delete instance
178 //
179 //
180 //
181 // Parameters:
182 //
183 //
184 // Returns:     tEplKernel  = errorcode
185 //
186 //
187 // State:
188 //
189 //---------------------------------------------------------------------------
190 tEplKernel EplNmtuDelInstance(void)
191 {
192         tEplKernel Ret;
193
194         Ret = kEplSuccessful;
195
196         EplNmtuInstance_g.m_pfnNmtChangeCb = NULL;
197
198         // delete timer
199         Ret = EplTimeruDeleteTimer(&EplNmtuInstance_g.m_TimerHdl);
200
201         return Ret;
202
203 }
204
205 //---------------------------------------------------------------------------
206 //
207 // Function:    EplNmtuNmtEvent
208 //
209 // Description: sends the NMT-Event to the NMT-State-Maschine
210 //
211 //
212 //
213 // Parameters:  NmtEvent_p  = NMT-Event to send
214 //
215 //
216 // Returns:     tEplKernel  = errorcode
217 //
218 //
219 // State:
220 //
221 //---------------------------------------------------------------------------
222 tEplKernel EplNmtuNmtEvent(tEplNmtEvent NmtEvent_p)
223 {
224         tEplKernel Ret;
225         tEplEvent Event;
226
227         Event.m_EventSink = kEplEventSinkNmtk;
228         Event.m_NetTime.m_dwNanoSec = 0;
229         Event.m_NetTime.m_dwSec = 0;
230         Event.m_EventType = kEplEventTypeNmtEvent;
231         Event.m_pArg = &NmtEvent_p;
232         Event.m_uiSize = sizeof(NmtEvent_p);
233
234         Ret = EplEventuPost(&Event);
235
236         return Ret;
237 }
238
239 //---------------------------------------------------------------------------
240 //
241 // Function:    EplNmtuGetNmtState
242 //
243 // Description: returns the actuell NMT-State
244 //
245 //
246 //
247 // Parameters:
248 //
249 //
250 // Returns:     tEplNmtState  = NMT-State
251 //
252 //
253 // State:
254 //
255 //---------------------------------------------------------------------------
256 tEplNmtState EplNmtuGetNmtState(void)
257 {
258         tEplNmtState NmtState;
259
260         // $$$ call function of communication abstraction layer
261 #if(((EPL_MODULE_INTEGRATION) & (EPL_MODULE_NMTK)) != 0)
262         NmtState = EplNmtkGetNmtState();
263 #else
264         NmtState = 0;
265 #endif
266
267         return NmtState;
268 }
269
270 //---------------------------------------------------------------------------
271 //
272 // Function:    EplNmtuProcessEvent
273 //
274 // Description: processes events from event queue
275 //
276 //
277 //
278 // Parameters:  pEplEvent_p =   pointer to event
279 //
280 //
281 // Returns:     tEplKernel  = errorcode
282 //
283 //
284 // State:
285 //
286 //---------------------------------------------------------------------------
287 tEplKernel EplNmtuProcessEvent(tEplEvent *pEplEvent_p)
288 {
289         tEplKernel Ret;
290
291         Ret = kEplSuccessful;
292
293         // process event
294         switch (pEplEvent_p->m_EventType) {
295                 // state change of NMT-Module
296         case kEplEventTypeNmtStateChange:
297                 {
298                         tEplEventNmtStateChange *pNmtStateChange;
299
300                         // delete timer
301                         Ret =
302                             EplTimeruDeleteTimer(&EplNmtuInstance_g.m_TimerHdl);
303
304                         pNmtStateChange =
305                             (tEplEventNmtStateChange *) pEplEvent_p->m_pArg;
306
307                         // call cb-functions to inform higher layer
308                         if (EplNmtuInstance_g.m_pfnNmtChangeCb != NULL) {
309                                 Ret =
310                                     EplNmtuInstance_g.
311                                     m_pfnNmtChangeCb(*pNmtStateChange);
312                         }
313
314                         if (Ret == kEplSuccessful) {    // everything is OK, so switch to next state if necessary
315                                 switch (pNmtStateChange->m_NewNmtState) {
316                                         // EPL stack is not running
317                                 case kEplNmtGsOff:
318                                         break;
319
320                                         // first init of the hardware
321                                 case kEplNmtGsInitialising:
322                                         {
323                                                 Ret =
324                                                     EplNmtuNmtEvent
325                                                     (kEplNmtEventEnterResetApp);
326                                                 break;
327                                         }
328
329                                         // init of the manufacturer-specific profile area and the
330                                         // standardised device profile area
331                                 case kEplNmtGsResetApplication:
332                                         {
333                                                 Ret =
334                                                     EplNmtuNmtEvent
335                                                     (kEplNmtEventEnterResetCom);
336                                                 break;
337                                         }
338
339                                         // init of the communication profile area
340                                 case kEplNmtGsResetCommunication:
341                                         {
342                                                 Ret =
343                                                     EplNmtuNmtEvent
344                                                     (kEplNmtEventEnterResetConfig);
345                                                 break;
346                                         }
347
348                                         // build the configuration with infos from OD
349                                 case kEplNmtGsResetConfiguration:
350                                         {
351                                                 unsigned int uiNodeId;
352
353                                                 // get node ID from OD
354 #if (((EPL_MODULE_INTEGRATION) & (EPL_MODULE_OBDU)) != 0) || (EPL_OBD_USE_KERNEL != FALSE)
355                                                 uiNodeId =
356                                                     EplObduGetNodeId
357                                                     (EPL_MCO_PTR_INSTANCE_PTR);
358 #else
359                                                 uiNodeId = 0;
360 #endif
361                                                 //check node ID if not should be master or slave
362                                                 if (uiNodeId == EPL_C_ADR_MN_DEF_NODE_ID) {     // node shall be MN
363 #if (((EPL_MODULE_INTEGRATION) & (EPL_MODULE_NMT_MN)) != 0)
364                                                         Ret =
365                                                             EplNmtuNmtEvent
366                                                             (kEplNmtEventEnterMsNotActive);
367 #else
368                                                         TRACE0
369                                                             ("EplNmtuProcess(): no MN functionality implemented\n");
370 #endif
371                                                 } else {        // node shall be CN
372                                                         Ret =
373                                                             EplNmtuNmtEvent
374                                                             (kEplNmtEventEnterCsNotActive);
375                                                 }
376                                                 break;
377                                         }
378
379                                         //-----------------------------------------------------------
380                                         // CN part of the state machine
381
382                                         // node listens for EPL-Frames and check timeout
383                                 case kEplNmtCsNotActive:
384                                         {
385                                                 u32 dwBuffer;
386                                                 tEplObdSize ObdSize;
387                                                 tEplTimerArg TimerArg;
388
389                                                 // create timer to switch automatically to BasicEthernet if no MN available in network
390
391                                                 // read NMT_CNBasicEthernetTimerout_U32 from OD
392                                                 ObdSize = sizeof(dwBuffer);
393 #if (((EPL_MODULE_INTEGRATION) & (EPL_MODULE_OBDU)) != 0) || (EPL_OBD_USE_KERNEL != FALSE)
394                                                 Ret =
395                                                     EplObduReadEntry
396                                                     (EPL_MCO_PTR_INSTANCE_PTR_
397                                                      0x1F99, 0x00, &dwBuffer,
398                                                      &ObdSize);
399 #else
400                                                 Ret = kEplObdIndexNotExist;
401 #endif
402                                                 if (Ret != kEplSuccessful) {
403                                                         break;
404                                                 }
405                                                 if (dwBuffer != 0) {    // BasicEthernet is enabled
406                                                         // convert us into ms
407                                                         dwBuffer =
408                                                             dwBuffer / 1000;
409                                                         if (dwBuffer == 0) {    // timer was below one ms
410                                                                 // set one ms
411                                                                 dwBuffer = 1;
412                                                         }
413                                                         TimerArg.m_EventSink =
414                                                             kEplEventSinkNmtk;
415                                                         TimerArg.m_ulArg =
416                                                             (unsigned long)
417                                                             kEplNmtEventTimerBasicEthernet;
418                                                         Ret =
419                                                             EplTimeruModifyTimerMs
420                                                             (&EplNmtuInstance_g.
421                                                              m_TimerHdl,
422                                                              (unsigned long)
423                                                              dwBuffer,
424                                                              TimerArg);
425                                                         // potential error is forwarded to event queue which generates error event
426                                                 }
427                                                 break;
428                                         }
429
430                                         // node processes only async frames
431                                 case kEplNmtCsPreOperational1:
432                                         {
433                                                 break;
434                                         }
435
436                                         // node processes isochronous and asynchronous frames
437                                 case kEplNmtCsPreOperational2:
438                                         {
439                                                 Ret =
440                                                     EplNmtuNmtEvent
441                                                     (kEplNmtEventEnterReadyToOperate);
442                                                 break;
443                                         }
444
445                                         // node should be configured und application is ready
446                                 case kEplNmtCsReadyToOperate:
447                                         {
448                                                 break;
449                                         }
450
451                                         // normal work state
452                                 case kEplNmtCsOperational:
453                                         {
454                                                 break;
455                                         }
456
457                                         // node stopped by MN
458                                         // -> only process asynchronous frames
459                                 case kEplNmtCsStopped:
460                                         {
461                                                 break;
462                                         }
463
464                                         // no EPL cycle
465                                         // -> normal ethernet communication
466                                 case kEplNmtCsBasicEthernet:
467                                         {
468                                                 break;
469                                         }
470
471                                         //-----------------------------------------------------------
472                                         // MN part of the state machine
473
474 #if (((EPL_MODULE_INTEGRATION) & (EPL_MODULE_NMT_MN)) != 0)
475                                         // node listens for EPL-Frames and check timeout
476                                 case kEplNmtMsNotActive:
477                                         {
478                                                 u32 dwBuffer;
479                                                 tEplObdSize ObdSize;
480                                                 tEplTimerArg TimerArg;
481
482                                                 // create timer to switch automatically to BasicEthernet/PreOp1 if no other MN active in network
483
484                                                 // check NMT_StartUp_U32.Bit13
485                                                 // read NMT_StartUp_U32 from OD
486                                                 ObdSize = sizeof(dwBuffer);
487 #if (((EPL_MODULE_INTEGRATION) & (EPL_MODULE_OBDU)) != 0) || (EPL_OBD_USE_KERNEL != FALSE)
488                                                 Ret =
489                                                     EplObduReadEntry
490                                                     (EPL_MCO_PTR_INSTANCE_PTR_
491                                                      0x1F80, 0x00, &dwBuffer,
492                                                      &ObdSize);
493 #else
494                                                 Ret = kEplObdIndexNotExist;
495 #endif
496                                                 if (Ret != kEplSuccessful) {
497                                                         break;
498                                                 }
499
500                                                 if ((dwBuffer & EPL_NMTST_BASICETHERNET) == 0) {        // NMT_StartUp_U32.Bit13 == 0
501                                                         // new state PreOperational1
502                                                         TimerArg.m_ulArg =
503                                                             (unsigned long)
504                                                             kEplNmtEventTimerMsPreOp1;
505                                                 } else {        // NMT_StartUp_U32.Bit13 == 1
506                                                         // new state BasicEthernet
507                                                         TimerArg.m_ulArg =
508                                                             (unsigned long)
509                                                             kEplNmtEventTimerBasicEthernet;
510                                                 }
511
512                                                 // read NMT_BootTime_REC.MNWaitNotAct_U32 from OD
513                                                 ObdSize = sizeof(dwBuffer);
514 #if (((EPL_MODULE_INTEGRATION) & (EPL_MODULE_OBDU)) != 0) || (EPL_OBD_USE_KERNEL != FALSE)
515                                                 Ret =
516                                                     EplObduReadEntry
517                                                     (EPL_MCO_PTR_INSTANCE_PTR_
518                                                      0x1F89, 0x01, &dwBuffer,
519                                                      &ObdSize);
520 #else
521                                                 Ret = kEplObdIndexNotExist;
522 #endif
523                                                 if (Ret != kEplSuccessful) {
524                                                         break;
525                                                 }
526                                                 // convert us into ms
527                                                 dwBuffer = dwBuffer / 1000;
528                                                 if (dwBuffer == 0) {    // timer was below one ms
529                                                         // set one ms
530                                                         dwBuffer = 1;
531                                                 }
532                                                 TimerArg.m_EventSink =
533                                                     kEplEventSinkNmtk;
534                                                 Ret =
535                                                     EplTimeruModifyTimerMs
536                                                     (&EplNmtuInstance_g.
537                                                      m_TimerHdl,
538                                                      (unsigned long)dwBuffer,
539                                                      TimerArg);
540                                                 // potential error is forwarded to event queue which generates error event
541                                                 break;
542                                         }
543
544                                         // node processes only async frames
545                                 case kEplNmtMsPreOperational1:
546                                         {
547                                                 u32 dwBuffer = 0;
548                                                 tEplObdSize ObdSize;
549                                                 tEplTimerArg TimerArg;
550
551                                                 // create timer to switch automatically to PreOp2 if MN identified all mandatory CNs
552
553                                                 // read NMT_BootTime_REC.MNWaitPreOp1_U32 from OD
554                                                 ObdSize = sizeof(dwBuffer);
555 #if (((EPL_MODULE_INTEGRATION) & (EPL_MODULE_OBDU)) != 0) || (EPL_OBD_USE_KERNEL != FALSE)
556                                                 Ret =
557                                                     EplObduReadEntry
558                                                     (EPL_MCO_PTR_INSTANCE_PTR_
559                                                      0x1F89, 0x03, &dwBuffer,
560                                                      &ObdSize);
561                                                 if (Ret != kEplSuccessful) {
562                                                         // ignore error, because this timeout is optional
563                                                         dwBuffer = 0;
564                                                 }
565 #endif
566                                                 if (dwBuffer == 0) {    // delay is deactivated
567                                                         // immediately post timer event
568                                                         Ret =
569                                                             EplNmtuNmtEvent
570                                                             (kEplNmtEventTimerMsPreOp2);
571                                                         break;
572                                                 }
573                                                 // convert us into ms
574                                                 dwBuffer = dwBuffer / 1000;
575                                                 if (dwBuffer == 0) {    // timer was below one ms
576                                                         // set one ms
577                                                         dwBuffer = 1;
578                                                 }
579                                                 TimerArg.m_EventSink =
580                                                     kEplEventSinkNmtk;
581                                                 TimerArg.m_ulArg =
582                                                     (unsigned long)
583                                                     kEplNmtEventTimerMsPreOp2;
584                                                 Ret =
585                                                     EplTimeruModifyTimerMs
586                                                     (&EplNmtuInstance_g.
587                                                      m_TimerHdl,
588                                                      (unsigned long)dwBuffer,
589                                                      TimerArg);
590                                                 // potential error is forwarded to event queue which generates error event
591                                                 break;
592                                         }
593
594                                         // node processes isochronous and asynchronous frames
595                                 case kEplNmtMsPreOperational2:
596                                         {
597                                                 break;
598                                         }
599
600                                         // node should be configured und application is ready
601                                 case kEplNmtMsReadyToOperate:
602                                         {
603                                                 break;
604                                         }
605
606                                         // normal work state
607                                 case kEplNmtMsOperational:
608                                         {
609                                                 break;
610                                         }
611
612                                         // no EPL cycle
613                                         // -> normal ethernet communication
614                                 case kEplNmtMsBasicEthernet:
615                                         {
616                                                 break;
617                                         }
618 #endif // (((EPL_MODULE_INTEGRATION) & (EPL_MODULE_NMT_MN)) != 0)
619
620                                 default:
621                                         {
622                                                 TRACE1
623                                                     ("EplNmtuProcess(): unhandled NMT state 0x%X\n",
624                                                      pNmtStateChange->
625                                                      m_NewNmtState);
626                                         }
627                                 }
628                         } else if (Ret == kEplReject) { // application wants to change NMT state itself
629                                 // it's OK
630                                 Ret = kEplSuccessful;
631                         }
632
633                         EPL_DBGLVL_NMTU_TRACE0
634                             ("EplNmtuProcessEvent(): NMT-State-Maschine announce change of NMT State\n");
635                         break;
636                 }
637
638         default:
639                 {
640                         Ret = kEplNmtInvalidEvent;
641                 }
642
643         }
644
645 //Exit:
646         return Ret;
647 }
648
649 //---------------------------------------------------------------------------
650 //
651 // Function:    EplNmtuRegisterStateChangeCb
652 //
653 // Description: register Callback-function go get informed about a
654 //              NMT-Change-State-Event
655 //
656 //
657 //
658 // Parameters:  pfnEplNmtStateChangeCb_p = functionpointer
659 //
660 //
661 // Returns:     tEplKernel  = errorcode
662 //
663 //
664 // State:
665 //
666 //---------------------------------------------------------------------------
667 tEplKernel EplNmtuRegisterStateChangeCb(tEplNmtuStateChangeCallback pfnEplNmtStateChangeCb_p)
668 {
669         tEplKernel Ret;
670
671         Ret = kEplSuccessful;
672
673         // save callback-function in modul global var
674         EplNmtuInstance_g.m_pfnNmtChangeCb = pfnEplNmtStateChangeCb_p;
675
676         return Ret;
677
678 }
679
680 //=========================================================================//
681 //                                                                         //
682 //          P R I V A T E   F U N C T I O N S                              //
683 //                                                                         //
684 //=========================================================================//
685
686 //---------------------------------------------------------------------------
687 //
688 // Function:
689 //
690 // Description:
691 //
692 //
693 //
694 // Parameters:
695 //
696 //
697 // Returns:
698 //
699 //
700 // State:
701 //
702 //---------------------------------------------------------------------------
703
704 #endif // #if(((EPL_MODULE_INTEGRATION) & (EPL_MODULE_NMTU)) != 0)
705
706 // EOF