]> git.proxmox.com Git - mirror_ubuntu-bionic-kernel.git/blob - drivers/staging/epl/EplNmtu.c
Staging: epl: remove EPLDLLEXPORT
[mirror_ubuntu-bionic-kernel.git] / 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