Merge remote-tracking branch 'staging/staging-next'
[deliverable/linux.git] / drivers / staging / i4l / pcbit / edss1.c
CommitLineData
1da177e4
LT
1/*
2 * DSS.1 Finite State Machine
3 * base: ITU-T Rec Q.931
4 *
5 * Copyright (C) 1996 Universidade de Lisboa
475be4d8 6 *
1da177e4
LT
7 * Written by Pedro Roque Marques (roque@di.fc.ul.pt)
8 *
475be4d8 9 * This software may be used and distributed according to the terms of
1da177e4
LT
10 * the GNU General Public License, incorporated herein by reference.
11 */
12
13/*
14 * TODO: complete the FSM
15 * move state/event descriptions to a user space logger
16 */
17
1da177e4
LT
18#include <linux/string.h>
19#include <linux/kernel.h>
20
21#include <linux/types.h>
1da177e4
LT
22#include <linux/mm.h>
23#include <linux/skbuff.h>
24
25#include <linux/timer.h>
26#include <asm/io.h>
27
28#include <linux/isdnif.h>
29
30#include "pcbit.h"
31#include "edss1.h"
32#include "layer2.h"
33#include "callbacks.h"
34
35
6f68ad7f 36const char * const isdn_state_table[] = {
475be4d8
JP
37 "Closed",
38 "Call initiated",
39 "Overlap sending",
40 "Outgoing call proceeding",
41 "NOT DEFINED",
42 "Call delivered",
43 "Call present",
44 "Call received",
45 "Connect request",
46 "Incoming call proceeding",
47 "Active",
48 "Disconnect request",
49 "Disconnect indication",
50 "NOT DEFINED",
51 "NOT DEFINED",
52 "Suspend request",
53 "NOT DEFINED",
54 "Resume request",
55 "NOT DEFINED",
56 "Release Request",
57 "NOT DEFINED",
58 "NOT DEFINED",
59 "NOT DEFINED",
60 "NOT DEFINED",
61 "NOT DEFINED",
62 "Overlap receiving",
63 "Select protocol on B-Channel",
64 "Activate B-channel protocol"
1da177e4
LT
65};
66
67#ifdef DEBUG_ERRS
68static
69struct CauseValue {
475be4d8
JP
70 byte nr;
71 char *descr;
72} cvlist[] = {
73 {0x01, "Unallocated (unassigned) number"},
74 {0x02, "No route to specified transit network"},
75 {0x03, "No route to destination"},
76 {0x04, "Send special information tone"},
77 {0x05, "Misdialled trunk prefix"},
78 {0x06, "Channel unacceptable"},
79 {0x07, "Channel awarded and being delivered in an established channel"},
80 {0x08, "Preemption"},
81 {0x09, "Preemption - circuit reserved for reuse"},
82 {0x10, "Normal call clearing"},
83 {0x11, "User busy"},
84 {0x12, "No user responding"},
85 {0x13, "No answer from user (user alerted)"},
86 {0x14, "Subscriber absent"},
87 {0x15, "Call rejected"},
88 {0x16, "Number changed"},
89 {0x1a, "non-selected user clearing"},
90 {0x1b, "Destination out of order"},
91 {0x1c, "Invalid number format (address incomplete)"},
92 {0x1d, "Facility rejected"},
93 {0x1e, "Response to Status enquiry"},
94 {0x1f, "Normal, unspecified"},
95 {0x22, "No circuit/channel available"},
96 {0x26, "Network out of order"},
97 {0x27, "Permanent frame mode connection out-of-service"},
98 {0x28, "Permanent frame mode connection operational"},
99 {0x29, "Temporary failure"},
100 {0x2a, "Switching equipment congestion"},
101 {0x2b, "Access information discarded"},
102 {0x2c, "Requested circuit/channel not available"},
103 {0x2e, "Precedence call blocked"},
104 {0x2f, "Resource unavailable, unspecified"},
105 {0x31, "Quality of service unavailable"},
106 {0x32, "Requested facility not subscribed"},
107 {0x35, "Outgoing calls barred within CUG"},
108 {0x37, "Incoming calls barred within CUG"},
109 {0x39, "Bearer capability not authorized"},
110 {0x3a, "Bearer capability not presently available"},
111 {0x3e, "Inconsistency in designated outgoing access information and subscriber class"},
112 {0x3f, "Service or option not available, unspecified"},
113 {0x41, "Bearer capability not implemented"},
114 {0x42, "Channel type not implemented"},
115 {0x43, "Requested facility not implemented"},
116 {0x44, "Only restricted digital information bearer capability is available"},
117 {0x4f, "Service or option not implemented"},
118 {0x51, "Invalid call reference value"},
119 {0x52, "Identified channel does not exist"},
120 {0x53, "A suspended call exists, but this call identity does not"},
121 {0x54, "Call identity in use"},
122 {0x55, "No call suspended"},
123 {0x56, "Call having the requested call identity has been cleared"},
124 {0x57, "User not member of CUG"},
125 {0x58, "Incompatible destination"},
126 {0x5a, "Non-existent CUG"},
127 {0x5b, "Invalid transit network selection"},
128 {0x5f, "Invalid message, unspecified"},
129 {0x60, "Mandatory information element is missing"},
130 {0x61, "Message type non-existent or not implemented"},
131 {0x62, "Message not compatible with call state or message type non-existent or not implemented"},
132 {0x63, "Information element/parameter non-existent or not implemented"},
133 {0x64, "Invalid information element contents"},
134 {0x65, "Message not compatible with call state"},
135 {0x66, "Recovery on timer expiry"},
136 {0x67, "Parameter non-existent or not implemented - passed on"},
137 {0x6e, "Message with unrecognized parameter discarded"},
138 {0x6f, "Protocol error, unspecified"},
139 {0x7f, "Interworking, unspecified"}
1da177e4
LT
140};
141
142#endif
143
144static struct isdn_event_desc {
475be4d8
JP
145 unsigned short ev;
146 char *desc;
147} isdn_event_table[] = {
148 {EV_USR_SETUP_REQ, "CC->L3: Setup Request"},
149 {EV_USR_SETUP_RESP, "CC->L3: Setup Response"},
150 {EV_USR_PROCED_REQ, "CC->L3: Proceeding Request"},
151 {EV_USR_RELEASE_REQ, "CC->L3: Release Request"},
152
153 {EV_NET_SETUP, "NET->TE: setup "},
154 {EV_NET_CALL_PROC, "NET->TE: call proceeding"},
155 {EV_NET_SETUP_ACK, "NET->TE: setup acknowledge (more info needed)"},
156 {EV_NET_CONN, "NET->TE: connect"},
157 {EV_NET_CONN_ACK, "NET->TE: connect acknowledge"},
158 {EV_NET_DISC, "NET->TE: disconnect indication"},
159 {EV_NET_RELEASE, "NET->TE: release"},
160 {EV_NET_RELEASE_COMP, "NET->TE: release complete"},
161 {EV_NET_SELP_RESP, "Board: Select B-channel protocol ack"},
162 {EV_NET_ACTV_RESP, "Board: Activate B-channel protocol ack"},
163 {EV_TIMER, "Timeout"},
164 {0, "NULL"}
1da177e4
LT
165};
166
475be4d8 167char *strisdnevent(ushort ev)
1da177e4 168{
475be4d8
JP
169 struct isdn_event_desc *entry;
170
171 for (entry = isdn_event_table; entry->ev; entry++)
172 if (entry->ev == ev)
173 break;
1da177e4 174
475be4d8 175 return entry->desc;
1da177e4
LT
176}
177
178/*
179 * Euro ISDN finite state machine
180 */
181
182static struct fsm_timer_entry fsm_timers[] = {
475be4d8
JP
183 {ST_CALL_PROC, 10},
184 {ST_DISC_REQ, 2},
185 {ST_ACTIVE_SELP, 5},
186 {ST_ACTIVE_ACTV, 5},
187 {ST_INCM_PROC, 10},
188 {ST_CONN_REQ, 2},
189 {0xff, 0}
1da177e4
LT
190};
191
192static struct fsm_entry fsm_table[] = {
193/* Connect Phase */
475be4d8
JP
194 /* Outgoing */
195 {ST_NULL, ST_CALL_INIT, EV_USR_SETUP_REQ, cb_out_1},
1da177e4 196
475be4d8
JP
197 {ST_CALL_INIT, ST_OVER_SEND, EV_NET_SETUP_ACK, cb_notdone},
198 {ST_CALL_INIT, ST_CALL_PROC, EV_NET_CALL_PROC, NULL},
199 {ST_CALL_INIT, ST_NULL, EV_NET_DISC, cb_out_2},
1da177e4 200
475be4d8
JP
201 {ST_CALL_PROC, ST_ACTIVE_SELP, EV_NET_CONN, cb_out_2},
202 {ST_CALL_PROC, ST_NULL, EV_NET_DISC, cb_disc_1},
203 {ST_CALL_PROC, ST_DISC_REQ, EV_USR_RELEASE_REQ, cb_disc_2},
1da177e4 204
475be4d8
JP
205 /* Incoming */
206 {ST_NULL, ST_CALL_PRES, EV_NET_SETUP, NULL},
1da177e4 207
475be4d8
JP
208 {ST_CALL_PRES, ST_INCM_PROC, EV_USR_PROCED_REQ, cb_in_1},
209 {ST_CALL_PRES, ST_DISC_REQ, EV_USR_RELEASE_REQ, cb_disc_2},
1da177e4 210
475be4d8
JP
211 {ST_INCM_PROC, ST_CONN_REQ, EV_USR_SETUP_RESP, cb_in_2},
212 {ST_INCM_PROC, ST_DISC_REQ, EV_USR_RELEASE_REQ, cb_disc_2},
1da177e4 213
475be4d8 214 {ST_CONN_REQ, ST_ACTIVE_SELP, EV_NET_CONN_ACK, cb_in_3},
1da177e4 215
475be4d8
JP
216 /* Active */
217 {ST_ACTIVE, ST_NULL, EV_NET_DISC, cb_disc_1},
218 {ST_ACTIVE, ST_DISC_REQ, EV_USR_RELEASE_REQ, cb_disc_2},
219 {ST_ACTIVE, ST_NULL, EV_NET_RELEASE, cb_disc_3},
1da177e4 220
475be4d8 221 /* Disconnect */
1da177e4 222
475be4d8
JP
223 {ST_DISC_REQ, ST_NULL, EV_NET_DISC, cb_disc_1},
224 {ST_DISC_REQ, ST_NULL, EV_NET_RELEASE, cb_disc_3},
1da177e4 225
475be4d8
JP
226 /* protocol selection */
227 {ST_ACTIVE_SELP, ST_ACTIVE_ACTV, EV_NET_SELP_RESP, cb_selp_1},
228 {ST_ACTIVE_SELP, ST_DISC_REQ, EV_USR_RELEASE_REQ, cb_disc_2},
1da177e4 229
475be4d8
JP
230 {ST_ACTIVE_ACTV, ST_ACTIVE, EV_NET_ACTV_RESP, cb_open},
231 {ST_ACTIVE_ACTV, ST_DISC_REQ, EV_USR_RELEASE_REQ, cb_disc_2},
1da177e4 232
475be4d8
JP
233 /* Timers */
234 {ST_CALL_PROC, ST_DISC_REQ, EV_TIMER, cb_disc_2},
235 {ST_DISC_REQ, ST_NULL, EV_TIMER, cb_disc_3},
236 {ST_ACTIVE_SELP, ST_DISC_REQ, EV_TIMER, cb_disc_2},
237 {ST_ACTIVE_ACTV, ST_DISC_REQ, EV_TIMER, cb_disc_2},
238 {ST_INCM_PROC, ST_DISC_REQ, EV_TIMER, cb_disc_2},
239 {ST_CONN_REQ, ST_CONN_REQ, EV_TIMER, cb_in_2},
240
241 {0xff, 0, 0, NULL}
1da177e4
LT
242};
243
244
245static void pcbit_fsm_timer(unsigned long data)
246{
475be4d8
JP
247 struct pcbit_dev *dev;
248 struct pcbit_chan *chan;
1da177e4 249
475be4d8 250 chan = (struct pcbit_chan *) data;
1da177e4 251
475be4d8
JP
252 del_timer(&chan->fsm_timer);
253 chan->fsm_timer.function = NULL;
1da177e4 254
475be4d8 255 dev = chan2dev(chan);
1da177e4 256
f2cef3f2 257 if (!dev) {
475be4d8
JP
258 printk(KERN_WARNING "pcbit: timer for unknown device\n");
259 return;
260 }
1da177e4 261
475be4d8 262 pcbit_fsm_event(dev, chan, EV_TIMER, NULL);
1da177e4
LT
263}
264
265
266void pcbit_fsm_event(struct pcbit_dev *dev, struct pcbit_chan *chan,
475be4d8 267 unsigned short event, struct callb_data *data)
1da177e4 268{
475be4d8 269 struct fsm_entry *action;
1da177e4
LT
270 struct fsm_timer_entry *tentry;
271 unsigned long flags;
272
273 spin_lock_irqsave(&dev->lock, flags);
274
475be4d8
JP
275 for (action = fsm_table; action->init != 0xff; action++)
276 if (action->init == chan->fsm_state && action->event == event)
277 break;
278
1da177e4 279 if (action->init == 0xff) {
475be4d8 280
1da177e4 281 spin_unlock_irqrestore(&dev->lock, flags);
475be4d8
JP
282 printk(KERN_DEBUG "fsm error: event %x on state %x\n",
283 event, chan->fsm_state);
1da177e4
LT
284 return;
285 }
286
475be4d8
JP
287 if (chan->fsm_timer.function) {
288 del_timer(&chan->fsm_timer);
289 chan->fsm_timer.function = NULL;
290 }
1da177e4
LT
291
292 chan->fsm_state = action->final;
475be4d8 293
1da177e4
LT
294 pcbit_state_change(dev, chan, action->init, event, action->final);
295
475be4d8
JP
296 for (tentry = fsm_timers; tentry->init != 0xff; tentry++)
297 if (tentry->init == chan->fsm_state)
298 break;
1da177e4 299
475be4d8 300 if (tentry->init != 0xff) {
8df7a222
MFW
301 setup_timer(&chan->fsm_timer, &pcbit_fsm_timer, (ulong)chan);
302 mod_timer(&chan->fsm_timer, jiffies + tentry->timeout * HZ);
475be4d8 303 }
1da177e4
LT
304
305 spin_unlock_irqrestore(&dev->lock, flags);
306
307 if (action->callb)
308 action->callb(dev, chan, data);
309
310}
This page took 0.976805 seconds and 5 git commands to generate.