[PATCH] fix semaphore handling in __unregister_chrdev_region
[linux/fpc-iii.git] / drivers / isdn / hisax / tei.c
blob082726db39855c7231bf6ec3b7e3dfbbe76b324c
1 /* $Id: tei.c,v 2.20.2.3 2004/01/13 14:31:26 keil Exp $
3 * Author Karsten Keil
4 * based on the teles driver from Jan den Ouden
5 * Copyright by Karsten Keil <keil@isdn4linux.de>
6 *
7 * This software may be used and distributed according to the terms
8 * of the GNU General Public License, incorporated herein by reference.
10 * For changes and modifications please read
11 * Documentation/isdn/HiSax.cert
13 * Thanks to Jan den Ouden
14 * Fritz Elfert
18 #include "hisax.h"
19 #include "isdnl2.h"
20 #include <linux/init.h>
21 #include <linux/random.h>
23 const char *tei_revision = "$Revision: 2.20.2.3 $";
25 #define ID_REQUEST 1
26 #define ID_ASSIGNED 2
27 #define ID_DENIED 3
28 #define ID_CHK_REQ 4
29 #define ID_CHK_RES 5
30 #define ID_REMOVE 6
31 #define ID_VERIFY 7
33 #define TEI_ENTITY_ID 0xf
35 static struct Fsm teifsm;
37 void tei_handler(struct PStack *st, u_char pr, struct sk_buff *skb);
39 enum {
40 ST_TEI_NOP,
41 ST_TEI_IDREQ,
42 ST_TEI_IDVERIFY,
45 #define TEI_STATE_COUNT (ST_TEI_IDVERIFY+1)
47 static char *strTeiState[] =
49 "ST_TEI_NOP",
50 "ST_TEI_IDREQ",
51 "ST_TEI_IDVERIFY",
54 enum {
55 EV_IDREQ,
56 EV_ASSIGN,
57 EV_DENIED,
58 EV_CHKREQ,
59 EV_REMOVE,
60 EV_VERIFY,
61 EV_T202,
64 #define TEI_EVENT_COUNT (EV_T202+1)
66 static char *strTeiEvent[] =
68 "EV_IDREQ",
69 "EV_ASSIGN",
70 "EV_DENIED",
71 "EV_CHKREQ",
72 "EV_REMOVE",
73 "EV_VERIFY",
74 "EV_T202",
77 unsigned int
78 random_ri(void)
80 unsigned int x;
82 get_random_bytes(&x, sizeof(x));
83 return (x & 0xffff);
86 static struct PStack *
87 findtei(struct PStack *st, int tei)
89 struct PStack *ptr = *(st->l1.stlistp);
91 if (tei == 127)
92 return (NULL);
94 while (ptr)
95 if (ptr->l2.tei == tei)
96 return (ptr);
97 else
98 ptr = ptr->next;
99 return (NULL);
102 static void
103 put_tei_msg(struct PStack *st, u_char m_id, unsigned int ri, u_char tei)
105 struct sk_buff *skb;
106 u_char *bp;
108 if (!(skb = alloc_skb(8, GFP_ATOMIC))) {
109 printk(KERN_WARNING "HiSax: No skb for TEI manager\n");
110 return;
112 bp = skb_put(skb, 3);
113 bp[0] = (TEI_SAPI << 2);
114 bp[1] = (GROUP_TEI << 1) | 0x1;
115 bp[2] = UI;
116 bp = skb_put(skb, 5);
117 bp[0] = TEI_ENTITY_ID;
118 bp[1] = ri >> 8;
119 bp[2] = ri & 0xff;
120 bp[3] = m_id;
121 bp[4] = (tei << 1) | 1;
122 st->l2.l2l1(st, PH_DATA | REQUEST, skb);
125 static void
126 tei_id_request(struct FsmInst *fi, int event, void *arg)
128 struct PStack *st = fi->userdata;
130 if (st->l2.tei != -1) {
131 st->ma.tei_m.printdebug(&st->ma.tei_m,
132 "assign request for allready asigned tei %d",
133 st->l2.tei);
134 return;
136 st->ma.ri = random_ri();
137 if (st->ma.debug)
138 st->ma.tei_m.printdebug(&st->ma.tei_m,
139 "assign request ri %d", st->ma.ri);
140 put_tei_msg(st, ID_REQUEST, st->ma.ri, 127);
141 FsmChangeState(&st->ma.tei_m, ST_TEI_IDREQ);
142 FsmAddTimer(&st->ma.t202, st->ma.T202, EV_T202, NULL, 1);
143 st->ma.N202 = 3;
146 static void
147 tei_id_assign(struct FsmInst *fi, int event, void *arg)
149 struct PStack *ost, *st = fi->userdata;
150 struct sk_buff *skb = arg;
151 struct IsdnCardState *cs;
152 int ri, tei;
154 ri = ((unsigned int) skb->data[1] << 8) + skb->data[2];
155 tei = skb->data[4] >> 1;
156 if (st->ma.debug)
157 st->ma.tei_m.printdebug(&st->ma.tei_m,
158 "identity assign ri %d tei %d", ri, tei);
159 if ((ost = findtei(st, tei))) { /* same tei is in use */
160 if (ri != ost->ma.ri) {
161 st->ma.tei_m.printdebug(&st->ma.tei_m,
162 "possible duplicate assignment tei %d", tei);
163 ost->l2.l2tei(ost, MDL_ERROR | RESPONSE, NULL);
165 } else if (ri == st->ma.ri) {
166 FsmDelTimer(&st->ma.t202, 1);
167 FsmChangeState(&st->ma.tei_m, ST_TEI_NOP);
168 st->l3.l3l2(st, MDL_ASSIGN | REQUEST, (void *) (long) tei);
169 cs = (struct IsdnCardState *) st->l1.hardware;
170 cs->cardmsg(cs, MDL_ASSIGN | REQUEST, NULL);
174 static void
175 tei_id_test_dup(struct FsmInst *fi, int event, void *arg)
177 struct PStack *ost, *st = fi->userdata;
178 struct sk_buff *skb = arg;
179 int tei, ri;
181 ri = ((unsigned int) skb->data[1] << 8) + skb->data[2];
182 tei = skb->data[4] >> 1;
183 if (st->ma.debug)
184 st->ma.tei_m.printdebug(&st->ma.tei_m,
185 "foreign identity assign ri %d tei %d", ri, tei);
186 if ((ost = findtei(st, tei))) { /* same tei is in use */
187 if (ri != ost->ma.ri) { /* and it wasn't our request */
188 st->ma.tei_m.printdebug(&st->ma.tei_m,
189 "possible duplicate assignment tei %d", tei);
190 FsmEvent(&ost->ma.tei_m, EV_VERIFY, NULL);
195 static void
196 tei_id_denied(struct FsmInst *fi, int event, void *arg)
198 struct PStack *st = fi->userdata;
199 struct sk_buff *skb = arg;
200 int ri, tei;
202 ri = ((unsigned int) skb->data[1] << 8) + skb->data[2];
203 tei = skb->data[4] >> 1;
204 if (st->ma.debug)
205 st->ma.tei_m.printdebug(&st->ma.tei_m,
206 "identity denied ri %d tei %d", ri, tei);
209 static void
210 tei_id_chk_req(struct FsmInst *fi, int event, void *arg)
212 struct PStack *st = fi->userdata;
213 struct sk_buff *skb = arg;
214 int tei;
216 tei = skb->data[4] >> 1;
217 if (st->ma.debug)
218 st->ma.tei_m.printdebug(&st->ma.tei_m,
219 "identity check req tei %d", tei);
220 if ((st->l2.tei != -1) && ((tei == GROUP_TEI) || (tei == st->l2.tei))) {
221 FsmDelTimer(&st->ma.t202, 4);
222 FsmChangeState(&st->ma.tei_m, ST_TEI_NOP);
223 put_tei_msg(st, ID_CHK_RES, random_ri(), st->l2.tei);
227 static void
228 tei_id_remove(struct FsmInst *fi, int event, void *arg)
230 struct PStack *st = fi->userdata;
231 struct sk_buff *skb = arg;
232 struct IsdnCardState *cs;
233 int tei;
235 tei = skb->data[4] >> 1;
236 if (st->ma.debug)
237 st->ma.tei_m.printdebug(&st->ma.tei_m,
238 "identity remove tei %d", tei);
239 if ((st->l2.tei != -1) && ((tei == GROUP_TEI) || (tei == st->l2.tei))) {
240 FsmDelTimer(&st->ma.t202, 5);
241 FsmChangeState(&st->ma.tei_m, ST_TEI_NOP);
242 st->l3.l3l2(st, MDL_REMOVE | REQUEST, NULL);
243 cs = (struct IsdnCardState *) st->l1.hardware;
244 cs->cardmsg(cs, MDL_REMOVE | REQUEST, NULL);
248 static void
249 tei_id_verify(struct FsmInst *fi, int event, void *arg)
251 struct PStack *st = fi->userdata;
253 if (st->ma.debug)
254 st->ma.tei_m.printdebug(&st->ma.tei_m,
255 "id verify request for tei %d", st->l2.tei);
256 put_tei_msg(st, ID_VERIFY, 0, st->l2.tei);
257 FsmChangeState(&st->ma.tei_m, ST_TEI_IDVERIFY);
258 FsmAddTimer(&st->ma.t202, st->ma.T202, EV_T202, NULL, 2);
259 st->ma.N202 = 2;
262 static void
263 tei_id_req_tout(struct FsmInst *fi, int event, void *arg)
265 struct PStack *st = fi->userdata;
266 struct IsdnCardState *cs;
268 if (--st->ma.N202) {
269 st->ma.ri = random_ri();
270 if (st->ma.debug)
271 st->ma.tei_m.printdebug(&st->ma.tei_m,
272 "assign req(%d) ri %d", 4 - st->ma.N202,
273 st->ma.ri);
274 put_tei_msg(st, ID_REQUEST, st->ma.ri, 127);
275 FsmAddTimer(&st->ma.t202, st->ma.T202, EV_T202, NULL, 3);
276 } else {
277 st->ma.tei_m.printdebug(&st->ma.tei_m, "assign req failed");
278 st->l3.l3l2(st, MDL_ERROR | RESPONSE, NULL);
279 cs = (struct IsdnCardState *) st->l1.hardware;
280 cs->cardmsg(cs, MDL_REMOVE | REQUEST, NULL);
281 FsmChangeState(fi, ST_TEI_NOP);
285 static void
286 tei_id_ver_tout(struct FsmInst *fi, int event, void *arg)
288 struct PStack *st = fi->userdata;
289 struct IsdnCardState *cs;
291 if (--st->ma.N202) {
292 if (st->ma.debug)
293 st->ma.tei_m.printdebug(&st->ma.tei_m,
294 "id verify req(%d) for tei %d",
295 3 - st->ma.N202, st->l2.tei);
296 put_tei_msg(st, ID_VERIFY, 0, st->l2.tei);
297 FsmAddTimer(&st->ma.t202, st->ma.T202, EV_T202, NULL, 4);
298 } else {
299 st->ma.tei_m.printdebug(&st->ma.tei_m,
300 "verify req for tei %d failed", st->l2.tei);
301 st->l3.l3l2(st, MDL_REMOVE | REQUEST, NULL);
302 cs = (struct IsdnCardState *) st->l1.hardware;
303 cs->cardmsg(cs, MDL_REMOVE | REQUEST, NULL);
304 FsmChangeState(fi, ST_TEI_NOP);
308 static void
309 tei_l1l2(struct PStack *st, int pr, void *arg)
311 struct sk_buff *skb = arg;
312 int mt;
314 if (test_bit(FLG_FIXED_TEI, &st->l2.flag)) {
315 dev_kfree_skb(skb);
316 return;
319 if (pr == (PH_DATA | INDICATION)) {
320 if (skb->len < 3) {
321 st->ma.tei_m.printdebug(&st->ma.tei_m,
322 "short mgr frame %ld/3", skb->len);
323 } else if ((skb->data[0] != ((TEI_SAPI << 2) | 2)) ||
324 (skb->data[1] != ((GROUP_TEI << 1) | 1))) {
325 st->ma.tei_m.printdebug(&st->ma.tei_m,
326 "wrong mgr sapi/tei %x/%x",
327 skb->data[0], skb->data[1]);
328 } else if ((skb->data[2] & 0xef) != UI) {
329 st->ma.tei_m.printdebug(&st->ma.tei_m,
330 "mgr frame is not ui %x", skb->data[2]);
331 } else {
332 skb_pull(skb, 3);
333 if (skb->len < 5) {
334 st->ma.tei_m.printdebug(&st->ma.tei_m,
335 "short mgr frame %ld/5", skb->len);
336 } else if (skb->data[0] != TEI_ENTITY_ID) {
337 /* wrong management entity identifier, ignore */
338 st->ma.tei_m.printdebug(&st->ma.tei_m,
339 "tei handler wrong entity id %x",
340 skb->data[0]);
341 } else {
342 mt = skb->data[3];
343 if (mt == ID_ASSIGNED)
344 FsmEvent(&st->ma.tei_m, EV_ASSIGN, skb);
345 else if (mt == ID_DENIED)
346 FsmEvent(&st->ma.tei_m, EV_DENIED, skb);
347 else if (mt == ID_CHK_REQ)
348 FsmEvent(&st->ma.tei_m, EV_CHKREQ, skb);
349 else if (mt == ID_REMOVE)
350 FsmEvent(&st->ma.tei_m, EV_REMOVE, skb);
351 else {
352 st->ma.tei_m.printdebug(&st->ma.tei_m,
353 "tei handler wrong mt %x\n", mt);
357 } else {
358 st->ma.tei_m.printdebug(&st->ma.tei_m,
359 "tei handler wrong pr %x\n", pr);
361 dev_kfree_skb(skb);
364 static void
365 tei_l2tei(struct PStack *st, int pr, void *arg)
367 struct IsdnCardState *cs;
369 if (test_bit(FLG_FIXED_TEI, &st->l2.flag)) {
370 if (pr == (MDL_ASSIGN | INDICATION)) {
371 if (st->ma.debug)
372 st->ma.tei_m.printdebug(&st->ma.tei_m,
373 "fixed assign tei %d", st->l2.tei);
374 st->l3.l3l2(st, MDL_ASSIGN | REQUEST, (void *) (long) st->l2.tei);
375 cs = (struct IsdnCardState *) st->l1.hardware;
376 cs->cardmsg(cs, MDL_ASSIGN | REQUEST, NULL);
378 return;
380 switch (pr) {
381 case (MDL_ASSIGN | INDICATION):
382 FsmEvent(&st->ma.tei_m, EV_IDREQ, arg);
383 break;
384 case (MDL_ERROR | REQUEST):
385 FsmEvent(&st->ma.tei_m, EV_VERIFY, arg);
386 break;
387 default:
388 break;
392 static void
393 tei_debug(struct FsmInst *fi, char *fmt, ...)
395 va_list args;
396 struct PStack *st = fi->userdata;
398 va_start(args, fmt);
399 VHiSax_putstatus(st->l1.hardware, "tei ", fmt, args);
400 va_end(args);
403 void
404 setstack_tei(struct PStack *st)
406 st->l2.l2tei = tei_l2tei;
407 st->ma.T202 = 2000; /* T202 2000 milliseconds */
408 st->l1.l1tei = tei_l1l2;
409 st->ma.debug = 1;
410 st->ma.tei_m.fsm = &teifsm;
411 st->ma.tei_m.state = ST_TEI_NOP;
412 st->ma.tei_m.debug = 1;
413 st->ma.tei_m.userdata = st;
414 st->ma.tei_m.userint = 0;
415 st->ma.tei_m.printdebug = tei_debug;
416 FsmInitTimer(&st->ma.tei_m, &st->ma.t202);
419 void
420 init_tei(struct IsdnCardState *cs, int protocol)
424 void
425 release_tei(struct IsdnCardState *cs)
427 struct PStack *st = cs->stlist;
429 while (st) {
430 FsmDelTimer(&st->ma.t202, 1);
431 st = st->next;
435 static struct FsmNode TeiFnList[] __initdata =
437 {ST_TEI_NOP, EV_IDREQ, tei_id_request},
438 {ST_TEI_NOP, EV_ASSIGN, tei_id_test_dup},
439 {ST_TEI_NOP, EV_VERIFY, tei_id_verify},
440 {ST_TEI_NOP, EV_REMOVE, tei_id_remove},
441 {ST_TEI_NOP, EV_CHKREQ, tei_id_chk_req},
442 {ST_TEI_IDREQ, EV_T202, tei_id_req_tout},
443 {ST_TEI_IDREQ, EV_ASSIGN, tei_id_assign},
444 {ST_TEI_IDREQ, EV_DENIED, tei_id_denied},
445 {ST_TEI_IDVERIFY, EV_T202, tei_id_ver_tout},
446 {ST_TEI_IDVERIFY, EV_REMOVE, tei_id_remove},
447 {ST_TEI_IDVERIFY, EV_CHKREQ, tei_id_chk_req},
450 #define TEI_FN_COUNT (sizeof(TeiFnList)/sizeof(struct FsmNode))
452 int __init
453 TeiNew(void)
455 teifsm.state_count = TEI_STATE_COUNT;
456 teifsm.event_count = TEI_EVENT_COUNT;
457 teifsm.strEvent = strTeiEvent;
458 teifsm.strState = strTeiState;
459 return FsmNew(&teifsm, TeiFnList, TEI_FN_COUNT);
462 void
463 TeiFree(void)
465 FsmFree(&teifsm);