Book a Demo!
CoCalc Logo Icon
StoreFeaturesDocsShareSupportNewsAboutPoliciesSign UpSign In
awilliam
GitHub Repository: awilliam/linux-vfio
Path: blob/master/drivers/isdn/mISDN/fsm.c
15111 views
1
/*
2
* finite state machine implementation
3
*
4
* Author Karsten Keil <[email protected]>
5
*
6
* Thanks to Jan den Ouden
7
* Fritz Elfert
8
* Copyright 2008 by Karsten Keil <[email protected]>
9
*
10
* This program is free software; you can redistribute it and/or modify
11
* it under the terms of the GNU General Public License version 2 as
12
* published by the Free Software Foundation.
13
*
14
* This program is distributed in the hope that it will be useful,
15
* but WITHOUT ANY WARRANTY; without even the implied warranty of
16
* MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the
17
* GNU General Public License for more details.
18
*
19
*/
20
21
#include <linux/kernel.h>
22
#include <linux/slab.h>
23
#include <linux/module.h>
24
#include <linux/string.h>
25
#include "fsm.h"
26
27
#define FSM_TIMER_DEBUG 0
28
29
void
30
mISDN_FsmNew(struct Fsm *fsm,
31
struct FsmNode *fnlist, int fncount)
32
{
33
int i;
34
35
fsm->jumpmatrix = kzalloc(sizeof(FSMFNPTR) * fsm->state_count *
36
fsm->event_count, GFP_KERNEL);
37
38
for (i = 0; i < fncount; i++)
39
if ((fnlist[i].state >= fsm->state_count) ||
40
(fnlist[i].event >= fsm->event_count)) {
41
printk(KERN_ERR
42
"mISDN_FsmNew Error: %d st(%ld/%ld) ev(%ld/%ld)\n",
43
i, (long)fnlist[i].state, (long)fsm->state_count,
44
(long)fnlist[i].event, (long)fsm->event_count);
45
} else
46
fsm->jumpmatrix[fsm->state_count * fnlist[i].event +
47
fnlist[i].state] = (FSMFNPTR) fnlist[i].routine;
48
}
49
EXPORT_SYMBOL(mISDN_FsmNew);
50
51
void
52
mISDN_FsmFree(struct Fsm *fsm)
53
{
54
kfree((void *) fsm->jumpmatrix);
55
}
56
EXPORT_SYMBOL(mISDN_FsmFree);
57
58
int
59
mISDN_FsmEvent(struct FsmInst *fi, int event, void *arg)
60
{
61
FSMFNPTR r;
62
63
if ((fi->state >= fi->fsm->state_count) ||
64
(event >= fi->fsm->event_count)) {
65
printk(KERN_ERR
66
"mISDN_FsmEvent Error st(%ld/%ld) ev(%d/%ld)\n",
67
(long)fi->state, (long)fi->fsm->state_count, event,
68
(long)fi->fsm->event_count);
69
return 1;
70
}
71
r = fi->fsm->jumpmatrix[fi->fsm->state_count * event + fi->state];
72
if (r) {
73
if (fi->debug)
74
fi->printdebug(fi, "State %s Event %s",
75
fi->fsm->strState[fi->state],
76
fi->fsm->strEvent[event]);
77
r(fi, event, arg);
78
return 0;
79
} else {
80
if (fi->debug)
81
fi->printdebug(fi, "State %s Event %s no action",
82
fi->fsm->strState[fi->state],
83
fi->fsm->strEvent[event]);
84
return 1;
85
}
86
}
87
EXPORT_SYMBOL(mISDN_FsmEvent);
88
89
void
90
mISDN_FsmChangeState(struct FsmInst *fi, int newstate)
91
{
92
fi->state = newstate;
93
if (fi->debug)
94
fi->printdebug(fi, "ChangeState %s",
95
fi->fsm->strState[newstate]);
96
}
97
EXPORT_SYMBOL(mISDN_FsmChangeState);
98
99
static void
100
FsmExpireTimer(struct FsmTimer *ft)
101
{
102
#if FSM_TIMER_DEBUG
103
if (ft->fi->debug)
104
ft->fi->printdebug(ft->fi, "FsmExpireTimer %lx", (long) ft);
105
#endif
106
mISDN_FsmEvent(ft->fi, ft->event, ft->arg);
107
}
108
109
void
110
mISDN_FsmInitTimer(struct FsmInst *fi, struct FsmTimer *ft)
111
{
112
ft->fi = fi;
113
ft->tl.function = (void *) FsmExpireTimer;
114
ft->tl.data = (long) ft;
115
#if FSM_TIMER_DEBUG
116
if (ft->fi->debug)
117
ft->fi->printdebug(ft->fi, "mISDN_FsmInitTimer %lx", (long) ft);
118
#endif
119
init_timer(&ft->tl);
120
}
121
EXPORT_SYMBOL(mISDN_FsmInitTimer);
122
123
void
124
mISDN_FsmDelTimer(struct FsmTimer *ft, int where)
125
{
126
#if FSM_TIMER_DEBUG
127
if (ft->fi->debug)
128
ft->fi->printdebug(ft->fi, "mISDN_FsmDelTimer %lx %d",
129
(long) ft, where);
130
#endif
131
del_timer(&ft->tl);
132
}
133
EXPORT_SYMBOL(mISDN_FsmDelTimer);
134
135
int
136
mISDN_FsmAddTimer(struct FsmTimer *ft,
137
int millisec, int event, void *arg, int where)
138
{
139
140
#if FSM_TIMER_DEBUG
141
if (ft->fi->debug)
142
ft->fi->printdebug(ft->fi, "mISDN_FsmAddTimer %lx %d %d",
143
(long) ft, millisec, where);
144
#endif
145
146
if (timer_pending(&ft->tl)) {
147
if (ft->fi->debug) {
148
printk(KERN_WARNING
149
"mISDN_FsmAddTimer: timer already active!\n");
150
ft->fi->printdebug(ft->fi,
151
"mISDN_FsmAddTimer already active!");
152
}
153
return -1;
154
}
155
init_timer(&ft->tl);
156
ft->event = event;
157
ft->arg = arg;
158
ft->tl.expires = jiffies + (millisec * HZ) / 1000;
159
add_timer(&ft->tl);
160
return 0;
161
}
162
EXPORT_SYMBOL(mISDN_FsmAddTimer);
163
164
void
165
mISDN_FsmRestartTimer(struct FsmTimer *ft,
166
int millisec, int event, void *arg, int where)
167
{
168
169
#if FSM_TIMER_DEBUG
170
if (ft->fi->debug)
171
ft->fi->printdebug(ft->fi, "mISDN_FsmRestartTimer %lx %d %d",
172
(long) ft, millisec, where);
173
#endif
174
175
if (timer_pending(&ft->tl))
176
del_timer(&ft->tl);
177
init_timer(&ft->tl);
178
ft->event = event;
179
ft->arg = arg;
180
ft->tl.expires = jiffies + (millisec * HZ) / 1000;
181
add_timer(&ft->tl);
182
}
183
EXPORT_SYMBOL(mISDN_FsmRestartTimer);
184
185