blob: 08820d184055219b89038fb1a278a6d533494b98 [file] [log] [blame]
Daniel Krueger9d7164c2008-12-19 11:41:57 -08001/****************************************************************************
2
3 (c) SYSTEC electronic GmbH, D-07973 Greiz, August-Bebel-Str. 29
4 www.systec-electronic.com
5
6 Project: openPOWERLINK
7
8 Description: source file for EPL User Timermodule for Linux kernel 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: EplTimeruLinuxKernel.c,v $
53
54 $Author: D.Krueger $
55
56 $Revision: 1.6 $ $Date: 2008/04/17 21:36:32 $
57
58 $State: Exp $
59
60 Build Environment:
61 KEIL uVision 2
62
63 -------------------------------------------------------------------------
64
65 Revision History:
66
67 2006/09/12 d.k.: start of the implementation
68
69****************************************************************************/
70
71#include "user/EplTimeru.h"
72#include <linux/timer.h>
73
74/***************************************************************************/
75/* */
76/* */
77/* G L O B A L D E F I N I T I O N S */
78/* */
79/* */
80/***************************************************************************/
81
82//---------------------------------------------------------------------------
83// const defines
84//---------------------------------------------------------------------------
85
86//---------------------------------------------------------------------------
87// local types
88//---------------------------------------------------------------------------
Greg Kroah-Hartman833dfbe2008-12-19 17:11:52 -080089typedef struct {
90 struct timer_list m_Timer;
91 tEplTimerArg TimerArgument;
Daniel Krueger9d7164c2008-12-19 11:41:57 -080092
93} tEplTimeruData;
94
95//---------------------------------------------------------------------------
96// modul globale vars
97//---------------------------------------------------------------------------
98
99//---------------------------------------------------------------------------
100// local function prototypes
101//---------------------------------------------------------------------------
102static void PUBLIC EplTimeruCbMs(unsigned long ulParameter_p);
103
104/***************************************************************************/
105/* */
106/* */
107/* C L A S S <Epl Userspace-Timermodule for Linux Kernel> */
108/* */
109/* */
110/***************************************************************************/
111//
112// Description: Epl Userspace-Timermodule for Linux Kernel
113//
114//
115/***************************************************************************/
116
117//=========================================================================//
118// //
119// P U B L I C F U N C T I O N S //
120// //
121//=========================================================================//
122
123//---------------------------------------------------------------------------
124//
125// Function: EplTimeruInit
126//
127// Description: function inits first instance
128//
129// Parameters: void
130//
131// Returns: tEplKernel = errorcode
132//
133// State:
134//
135//---------------------------------------------------------------------------
136
137tEplKernel PUBLIC EplTimeruInit()
138{
Greg Kroah-Hartman833dfbe2008-12-19 17:11:52 -0800139 tEplKernel Ret;
Daniel Krueger9d7164c2008-12-19 11:41:57 -0800140
Greg Kroah-Hartman833dfbe2008-12-19 17:11:52 -0800141 Ret = EplTimeruAddInstance();
Daniel Krueger9d7164c2008-12-19 11:41:57 -0800142
Greg Kroah-Hartman833dfbe2008-12-19 17:11:52 -0800143 return Ret;
Daniel Krueger9d7164c2008-12-19 11:41:57 -0800144}
145
Daniel Krueger9d7164c2008-12-19 11:41:57 -0800146//---------------------------------------------------------------------------
147//
148// Function: EplTimeruAddInstance
149//
150// Description: function inits additional instance
151//
152// Parameters: void
153//
154// Returns: tEplKernel = errorcode
155//
156// State:
157//
158//---------------------------------------------------------------------------
159
160tEplKernel PUBLIC EplTimeruAddInstance()
161{
Greg Kroah-Hartman833dfbe2008-12-19 17:11:52 -0800162 tEplKernel Ret;
Daniel Krueger9d7164c2008-12-19 11:41:57 -0800163
Greg Kroah-Hartman833dfbe2008-12-19 17:11:52 -0800164 Ret = kEplSuccessful;
Daniel Krueger9d7164c2008-12-19 11:41:57 -0800165
Greg Kroah-Hartman833dfbe2008-12-19 17:11:52 -0800166 return Ret;
Daniel Krueger9d7164c2008-12-19 11:41:57 -0800167}
168
Daniel Krueger9d7164c2008-12-19 11:41:57 -0800169//---------------------------------------------------------------------------
170//
171// Function: EplTimeruDelInstance
172//
173// Description: function deletes instance
174// -> under Linux nothing to do
175// -> no instance table needed
176//
177// Parameters: void
178//
179// Returns: tEplKernel = errorcode
180//
181// State:
182//
183//---------------------------------------------------------------------------
184
185tEplKernel PUBLIC EplTimeruDelInstance()
186{
Greg Kroah-Hartman833dfbe2008-12-19 17:11:52 -0800187 tEplKernel Ret;
Daniel Krueger9d7164c2008-12-19 11:41:57 -0800188
Greg Kroah-Hartman833dfbe2008-12-19 17:11:52 -0800189 Ret = kEplSuccessful;
Daniel Krueger9d7164c2008-12-19 11:41:57 -0800190
Greg Kroah-Hartman833dfbe2008-12-19 17:11:52 -0800191 return Ret;
Daniel Krueger9d7164c2008-12-19 11:41:57 -0800192}
193
Daniel Krueger9d7164c2008-12-19 11:41:57 -0800194//---------------------------------------------------------------------------
195//
196// Function: EplTimeruSetTimerMs
197//
198// Description: function creates a timer and returns the corresponding handle
199//
200// Parameters: pTimerHdl_p = pointer to a buffer to fill in the handle
201// ulTime_p = time for timer in ms
202// Argument_p = argument for timer
203//
204// Returns: tEplKernel = errorcode
205//
206// State:
207//
208//---------------------------------------------------------------------------
209
Greg Kroah-Hartman833dfbe2008-12-19 17:11:52 -0800210tEplKernel PUBLIC EplTimeruSetTimerMs(tEplTimerHdl * pTimerHdl_p,
211 unsigned long ulTime_p,
212 tEplTimerArg Argument_p)
Daniel Krueger9d7164c2008-12-19 11:41:57 -0800213{
Greg Kroah-Hartman833dfbe2008-12-19 17:11:52 -0800214 tEplKernel Ret = kEplSuccessful;
215 tEplTimeruData *pData;
Daniel Krueger9d7164c2008-12-19 11:41:57 -0800216
Greg Kroah-Hartman833dfbe2008-12-19 17:11:52 -0800217 // check pointer to handle
218 if (pTimerHdl_p == NULL) {
219 Ret = kEplTimerInvalidHandle;
220 goto Exit;
221 }
Daniel Krueger9d7164c2008-12-19 11:41:57 -0800222
Greg Kroah-Hartman833dfbe2008-12-19 17:11:52 -0800223 pData = (tEplTimeruData *) EPL_MALLOC(sizeof(tEplTimeruData));
224 if (pData == NULL) {
225 Ret = kEplNoResource;
226 goto Exit;
227 }
Daniel Krueger9d7164c2008-12-19 11:41:57 -0800228
Greg Kroah-Hartman833dfbe2008-12-19 17:11:52 -0800229 init_timer(&pData->m_Timer);
230 pData->m_Timer.function = EplTimeruCbMs;
231 pData->m_Timer.data = (unsigned long)pData;
232 pData->m_Timer.expires = jiffies + ulTime_p * HZ / 1000;
Daniel Krueger9d7164c2008-12-19 11:41:57 -0800233
Greg Kroah-Hartman833dfbe2008-12-19 17:11:52 -0800234 EPL_MEMCPY(&pData->TimerArgument, &Argument_p, sizeof(tEplTimerArg));
Daniel Krueger9d7164c2008-12-19 11:41:57 -0800235
Greg Kroah-Hartman833dfbe2008-12-19 17:11:52 -0800236 add_timer(&pData->m_Timer);
Daniel Krueger9d7164c2008-12-19 11:41:57 -0800237
Greg Kroah-Hartman833dfbe2008-12-19 17:11:52 -0800238 *pTimerHdl_p = (tEplTimerHdl) pData;
Daniel Krueger9d7164c2008-12-19 11:41:57 -0800239
Greg Kroah-Hartman833dfbe2008-12-19 17:11:52 -0800240 Exit:
241 return Ret;
Daniel Krueger9d7164c2008-12-19 11:41:57 -0800242}
243
Daniel Krueger9d7164c2008-12-19 11:41:57 -0800244//---------------------------------------------------------------------------
245//
246// Function: EplTimeruModifyTimerMs
247//
248// Description: function changes a timer and returns the corresponding handle
249//
250// Parameters: pTimerHdl_p = pointer to a buffer to fill in the handle
251// ulTime_p = time for timer in ms
252// Argument_p = argument for timer
253//
254// Returns: tEplKernel = errorcode
255//
256// State:
257//
258//---------------------------------------------------------------------------
259
Greg Kroah-Hartman833dfbe2008-12-19 17:11:52 -0800260tEplKernel PUBLIC EplTimeruModifyTimerMs(tEplTimerHdl * pTimerHdl_p,
261 unsigned long ulTime_p,
262 tEplTimerArg Argument_p)
Daniel Krueger9d7164c2008-12-19 11:41:57 -0800263{
Greg Kroah-Hartman833dfbe2008-12-19 17:11:52 -0800264 tEplKernel Ret = kEplSuccessful;
265 tEplTimeruData *pData;
Daniel Krueger9d7164c2008-12-19 11:41:57 -0800266
Greg Kroah-Hartman833dfbe2008-12-19 17:11:52 -0800267 // check pointer to handle
268 if (pTimerHdl_p == NULL) {
269 Ret = kEplTimerInvalidHandle;
270 goto Exit;
271 }
272 // check handle itself, i.e. was the handle initialized before
273 if (*pTimerHdl_p == 0) {
274 Ret = EplTimeruSetTimerMs(pTimerHdl_p, ulTime_p, Argument_p);
275 goto Exit;
276 }
277 pData = (tEplTimeruData *) * pTimerHdl_p;
278 if ((tEplTimeruData *) pData->m_Timer.data != pData) {
279 Ret = kEplTimerInvalidHandle;
280 goto Exit;
281 }
Daniel Krueger9d7164c2008-12-19 11:41:57 -0800282
Greg Kroah-Hartman833dfbe2008-12-19 17:11:52 -0800283 mod_timer(&pData->m_Timer, (jiffies + ulTime_p * HZ / 1000));
Daniel Krueger9d7164c2008-12-19 11:41:57 -0800284
Greg Kroah-Hartman833dfbe2008-12-19 17:11:52 -0800285 // copy the TimerArg after the timer is restarted,
286 // so that a timer occured immediately before mod_timer
287 // won't use the new TimerArg and
288 // therefore the old timer cannot be distinguished from the new one.
289 // But if the new timer is too fast, it may get lost.
290 EPL_MEMCPY(&pData->TimerArgument, &Argument_p, sizeof(tEplTimerArg));
Daniel Krueger9d7164c2008-12-19 11:41:57 -0800291
Greg Kroah-Hartman833dfbe2008-12-19 17:11:52 -0800292 // check if timer is really running
293 if (timer_pending(&pData->m_Timer) == 0) { // timer is not running
294 // retry starting it
295 add_timer(&pData->m_Timer);
296 }
297 // set handle to pointer of tEplTimeruData
Daniel Krueger9d7164c2008-12-19 11:41:57 -0800298// *pTimerHdl_p = (tEplTimerHdl) pData;
299
Greg Kroah-Hartman833dfbe2008-12-19 17:11:52 -0800300 Exit:
301 return Ret;
Daniel Krueger9d7164c2008-12-19 11:41:57 -0800302}
303
Daniel Krueger9d7164c2008-12-19 11:41:57 -0800304//---------------------------------------------------------------------------
305//
306// Function: EplTimeruDeleteTimer
307//
308// Description: function deletes a timer
309//
310// Parameters: pTimerHdl_p = pointer to a buffer to fill in the handle
311//
312// Returns: tEplKernel = errorcode
313//
314// State:
315//
316//---------------------------------------------------------------------------
317
Greg Kroah-Hartman833dfbe2008-12-19 17:11:52 -0800318tEplKernel PUBLIC EplTimeruDeleteTimer(tEplTimerHdl * pTimerHdl_p)
Daniel Krueger9d7164c2008-12-19 11:41:57 -0800319{
Greg Kroah-Hartman833dfbe2008-12-19 17:11:52 -0800320 tEplKernel Ret = kEplSuccessful;
321 tEplTimeruData *pData;
Daniel Krueger9d7164c2008-12-19 11:41:57 -0800322
Greg Kroah-Hartman833dfbe2008-12-19 17:11:52 -0800323 // check pointer to handle
324 if (pTimerHdl_p == NULL) {
325 Ret = kEplTimerInvalidHandle;
326 goto Exit;
327 }
328 // check handle itself, i.e. was the handle initialized before
329 if (*pTimerHdl_p == 0) {
330 Ret = kEplSuccessful;
331 goto Exit;
332 }
333 pData = (tEplTimeruData *) * pTimerHdl_p;
334 if ((tEplTimeruData *) pData->m_Timer.data != pData) {
335 Ret = kEplTimerInvalidHandle;
336 goto Exit;
337 }
Daniel Krueger9d7164c2008-12-19 11:41:57 -0800338
339/* if (del_timer(&pData->m_Timer) == 1)
340 {
341 kfree(pData);
342 }
343*/
Greg Kroah-Hartman833dfbe2008-12-19 17:11:52 -0800344 // try to delete the timer
345 del_timer(&pData->m_Timer);
346 // free memory in any case
347 kfree(pData);
Daniel Krueger9d7164c2008-12-19 11:41:57 -0800348
Greg Kroah-Hartman833dfbe2008-12-19 17:11:52 -0800349 // uninitialize handle
350 *pTimerHdl_p = 0;
Daniel Krueger9d7164c2008-12-19 11:41:57 -0800351
Greg Kroah-Hartman833dfbe2008-12-19 17:11:52 -0800352 Exit:
353 return Ret;
Daniel Krueger9d7164c2008-12-19 11:41:57 -0800354
355}
356
Daniel Krueger9d7164c2008-12-19 11:41:57 -0800357//---------------------------------------------------------------------------
358//
359// Function: EplTimeruIsTimerActive
360//
361// Description: checks if the timer referenced by the handle is currently
362// active.
363//
364// Parameters: TimerHdl_p = handle of the timer to check
365//
366// Returns: BOOL = TRUE, if active;
367// FALSE, otherwise
368//
369// State:
370//
371//---------------------------------------------------------------------------
372
373BOOL PUBLIC EplTimeruIsTimerActive(tEplTimerHdl TimerHdl_p)
374{
Greg Kroah-Hartman833dfbe2008-12-19 17:11:52 -0800375 BOOL fActive = FALSE;
376 tEplTimeruData *pData;
Daniel Krueger9d7164c2008-12-19 11:41:57 -0800377
Greg Kroah-Hartman833dfbe2008-12-19 17:11:52 -0800378 // check handle itself, i.e. was the handle initialized before
379 if (TimerHdl_p == 0) { // timer was not created yet, so it is not active
380 goto Exit;
381 }
382 pData = (tEplTimeruData *) TimerHdl_p;
383 if ((tEplTimeruData *) pData->m_Timer.data != pData) { // invalid timer
384 goto Exit;
385 }
386 // check if timer is running
387 if (timer_pending(&pData->m_Timer) == 0) { // timer is not running
388 goto Exit;
389 }
Daniel Krueger9d7164c2008-12-19 11:41:57 -0800390
Greg Kroah-Hartman833dfbe2008-12-19 17:11:52 -0800391 fActive = TRUE;
Daniel Krueger9d7164c2008-12-19 11:41:57 -0800392
Greg Kroah-Hartman833dfbe2008-12-19 17:11:52 -0800393 Exit:
394 return fActive;
Daniel Krueger9d7164c2008-12-19 11:41:57 -0800395}
396
Daniel Krueger9d7164c2008-12-19 11:41:57 -0800397//=========================================================================//
398// //
399// P R I V A T E F U N C T I O N S //
400// //
401//=========================================================================//
402
403//---------------------------------------------------------------------------
404//
405// Function: EplTimeruCbMs
406//
407// Description: function to process timer
408//
409//
410//
411// Parameters: lpParameter = pointer to structur of type tEplTimeruData
412//
413//
414// Returns: (none)
415//
416//
417// State:
418//
419//---------------------------------------------------------------------------
420static void PUBLIC EplTimeruCbMs(unsigned long ulParameter_p)
421{
Greg Kroah-Hartman833dfbe2008-12-19 17:11:52 -0800422 tEplKernel Ret = kEplSuccessful;
423 tEplTimeruData *pData;
424 tEplEvent EplEvent;
425 tEplTimerEventArg TimerEventArg;
Daniel Krueger9d7164c2008-12-19 11:41:57 -0800426
Greg Kroah-Hartman833dfbe2008-12-19 17:11:52 -0800427 pData = (tEplTimeruData *) ulParameter_p;
Daniel Krueger9d7164c2008-12-19 11:41:57 -0800428
Greg Kroah-Hartman833dfbe2008-12-19 17:11:52 -0800429 // call event function
430 TimerEventArg.m_TimerHdl = (tEplTimerHdl) pData;
431 TimerEventArg.m_ulArg = pData->TimerArgument.m_ulArg;
Daniel Krueger9d7164c2008-12-19 11:41:57 -0800432
Greg Kroah-Hartman833dfbe2008-12-19 17:11:52 -0800433 EplEvent.m_EventSink = pData->TimerArgument.m_EventSink;
434 EplEvent.m_EventType = kEplEventTypeTimer;
435 EPL_MEMSET(&EplEvent.m_NetTime, 0x00, sizeof(tEplNetTime));
436 EplEvent.m_pArg = &TimerEventArg;
437 EplEvent.m_uiSize = sizeof(TimerEventArg);
Daniel Krueger9d7164c2008-12-19 11:41:57 -0800438
Greg Kroah-Hartman833dfbe2008-12-19 17:11:52 -0800439 Ret = EplEventuPost(&EplEvent);
Daniel Krueger9d7164c2008-12-19 11:41:57 -0800440
Greg Kroah-Hartman833dfbe2008-12-19 17:11:52 -0800441 // d.k. do not free memory, user has to call EplTimeruDeleteTimer()
442 //kfree(pData);
Daniel Krueger9d7164c2008-12-19 11:41:57 -0800443
444}
445
Daniel Krueger9d7164c2008-12-19 11:41:57 -0800446// EOF