* added 0.99 linux version
[mascara-docs.git] / i386 / linux / linux-2.3.21 / drivers / isdn / hisax / tei.c
blobf21284bece2c2a9a99a0f69af2e2467d38bc2ca2
1 /* $Id: tei.c,v 2.13 1999/07/21 14:46:28 keil Exp $
3 * Author Karsten Keil (keil@isdn4linux.de)
4 * based on the teles driver from Jan den Ouden
6 * This file is (c) under GNU PUBLIC LICENSE
7 * For changes and modifications please read
8 * ../../../Documentation/isdn/HiSax.cert
10 * Thanks to Jan den Ouden
11 * Fritz Elfert
13 * $Log: tei.c,v $
14 * Revision 2.13 1999/07/21 14:46:28 keil
15 * changes from EICON certification
17 * Revision 2.12 1999/07/01 08:12:11 keil
18 * Common HiSax version for 2.0, 2.1, 2.2 and 2.3 kernel
20 * Revision 2.11 1998/11/15 23:55:24 keil
21 * changes from 2.0
23 * Revision 2.10 1998/05/25 14:08:10 keil
24 * HiSax 3.0
25 * fixed X.75 and leased line to work again
26 * Point2Point and fixed TEI are runtime options now:
27 * hisaxctrl <id> 7 1 set PTP
28 * hisaxctrl <id> 8 <TEIVALUE *2 >
29 * set fixed TEI to TEIVALUE (0-63)
31 * Revision 2.9 1998/05/25 12:58:23 keil
32 * HiSax golden code from certification, Don't use !!!
33 * No leased lines, no X75, but many changes.
35 * Revision 2.8 1998/03/07 22:57:07 tsbogend
36 * made HiSax working on Linux/Alpha
38 * Revision 2.7 1998/02/12 23:08:11 keil
39 * change for 2.1.86 (removing FREE_READ/FREE_WRITE from [dev]_kfree_skb()
41 * Revision 2.6 1998/02/02 13:41:42 keil
42 * fix MDL_ASSIGN for PtP
44 * Revision 2.5 1997/11/06 17:09:12 keil
45 * New 2.1 init code
47 * Revision 2.4 1997/10/29 19:04:46 keil
48 * changes for 2.1
50 * Revision 2.3 1997/10/01 09:21:43 fritz
51 * Removed old compatibility stuff for 2.0.X kernels.
52 * From now on, this code is for 2.1.X ONLY!
53 * Old stuff is still in the separate branch.
55 * Revision 2.2 1997/07/31 19:24:39 keil
56 * fixed a warning
58 * Revision 2.1 1997/07/31 11:50:16 keil
59 * ONE TEI and FIXED TEI handling
61 * Revision 2.0 1997/07/27 21:13:30 keil
62 * New TEI managment
64 * Revision 1.9 1997/06/26 11:18:02 keil
65 * New managment
67 * Revision 1.8 1997/04/07 22:59:08 keil
68 * GFP_KERNEL --> GFP_ATOMIC
70 * Revision 1.7 1997/04/06 22:54:03 keil
71 * Using SKB's
73 * Old log removed/ KKe
76 #define __NO_VERSION__
77 #include "hisax.h"
78 #include "isdnl2.h"
79 #include <linux/random.h>
81 const char *tei_revision = "$Revision: 2.13 $";
83 #define ID_REQUEST 1
84 #define ID_ASSIGNED 2
85 #define ID_DENIED 3
86 #define ID_CHK_REQ 4
87 #define ID_CHK_RES 5
88 #define ID_REMOVE 6
89 #define ID_VERIFY 7
91 #define TEI_ENTITY_ID 0xf
93 static
94 struct Fsm teifsm =
95 {NULL, 0, 0, NULL, NULL};
97 void tei_handler(struct PStack *st, u_char pr, struct sk_buff *skb);
99 enum {
100 ST_TEI_NOP,
101 ST_TEI_IDREQ,
102 ST_TEI_IDVERIFY,
105 #define TEI_STATE_COUNT (ST_TEI_IDVERIFY+1)
107 static char *strTeiState[] =
109 "ST_TEI_NOP",
110 "ST_TEI_IDREQ",
111 "ST_TEI_IDVERIFY",
114 enum {
115 EV_IDREQ,
116 EV_ASSIGN,
117 EV_DENIED,
118 EV_CHKREQ,
119 EV_REMOVE,
120 EV_VERIFY,
121 EV_T202,
124 #define TEI_EVENT_COUNT (EV_T202+1)
126 static char *strTeiEvent[] =
128 "EV_IDREQ",
129 "EV_ASSIGN",
130 "EV_DENIED",
131 "EV_CHKREQ",
132 "EV_REMOVE",
133 "EV_VERIFY",
134 "EV_T202",
137 unsigned int
138 random_ri(void)
140 unsigned int x;
142 get_random_bytes(&x, sizeof(x));
143 return (x & 0xffff);
146 static struct PStack *
147 findtei(struct PStack *st, int tei)
149 struct PStack *ptr = *(st->l1.stlistp);
151 if (tei == 127)
152 return (NULL);
154 while (ptr)
155 if (ptr->l2.tei == tei)
156 return (ptr);
157 else
158 ptr = ptr->next;
159 return (NULL);
162 static void
163 put_tei_msg(struct PStack *st, u_char m_id, unsigned int ri, u_char tei)
165 struct sk_buff *skb;
166 u_char *bp;
168 if (!(skb = alloc_skb(8, GFP_ATOMIC))) {
169 printk(KERN_WARNING "HiSax: No skb for TEI manager\n");
170 return;
172 SET_SKB_FREE(skb);
173 bp = skb_put(skb, 3);
174 bp[0] = (TEI_SAPI << 2);
175 bp[1] = (GROUP_TEI << 1) | 0x1;
176 bp[2] = UI;
177 bp = skb_put(skb, 5);
178 bp[0] = TEI_ENTITY_ID;
179 bp[1] = ri >> 8;
180 bp[2] = ri & 0xff;
181 bp[3] = m_id;
182 bp[4] = (tei << 1) | 1;
183 st->l2.l2l1(st, PH_DATA | REQUEST, skb);
186 static void
187 tei_id_request(struct FsmInst *fi, int event, void *arg)
189 struct PStack *st = fi->userdata;
191 if (st->l2.tei != -1) {
192 st->ma.tei_m.printdebug(&st->ma.tei_m,
193 "assign request for allready asigned tei %d",
194 st->l2.tei);
195 return;
197 st->ma.ri = random_ri();
198 if (st->ma.debug)
199 st->ma.tei_m.printdebug(&st->ma.tei_m,
200 "assign request ri %d", st->ma.ri);
201 put_tei_msg(st, ID_REQUEST, st->ma.ri, 127);
202 FsmChangeState(&st->ma.tei_m, ST_TEI_IDREQ);
203 FsmAddTimer(&st->ma.t202, st->ma.T202, EV_T202, NULL, 1);
204 st->ma.N202 = 3;
207 static void
208 tei_id_assign(struct FsmInst *fi, int event, void *arg)
210 struct PStack *ost, *st = fi->userdata;
211 struct sk_buff *skb = arg;
212 struct IsdnCardState *cs;
213 int ri, tei;
215 ri = ((unsigned int) skb->data[1] << 8) + skb->data[2];
216 tei = skb->data[4] >> 1;
217 if (st->ma.debug)
218 st->ma.tei_m.printdebug(&st->ma.tei_m,
219 "identity assign ri %d tei %d", ri, tei);
220 if ((ost = findtei(st, tei))) { /* same tei is in use */
221 if (ri != ost->ma.ri) {
222 st->ma.tei_m.printdebug(&st->ma.tei_m,
223 "possible duplicate assignment tei %d", tei);
224 ost->l2.l2tei(ost, MDL_ERROR | RESPONSE, NULL);
226 } else if (ri == st->ma.ri) {
227 FsmDelTimer(&st->ma.t202, 1);
228 FsmChangeState(&st->ma.tei_m, ST_TEI_NOP);
229 st->l3.l3l2(st, MDL_ASSIGN | REQUEST, (void *) (long) tei);
230 cs = (struct IsdnCardState *) st->l1.hardware;
231 cs->cardmsg(cs, MDL_ASSIGN | REQUEST, NULL);
235 static void
236 tei_id_test_dup(struct FsmInst *fi, int event, void *arg)
238 struct PStack *ost, *st = fi->userdata;
239 struct sk_buff *skb = arg;
240 int tei, ri;
242 ri = ((unsigned int) skb->data[1] << 8) + skb->data[2];
243 tei = skb->data[4] >> 1;
244 if (st->ma.debug)
245 st->ma.tei_m.printdebug(&st->ma.tei_m,
246 "foreign identity assign ri %d tei %d", ri, tei);
247 if ((ost = findtei(st, tei))) { /* same tei is in use */
248 st->ma.tei_m.printdebug(&st->ma.tei_m,
249 "possible duplicate assignment tei %d", tei);
250 FsmEvent(&ost->ma.tei_m, EV_VERIFY, NULL);
254 static void
255 tei_id_denied(struct FsmInst *fi, int event, void *arg)
257 struct PStack *st = fi->userdata;
258 struct sk_buff *skb = arg;
259 int ri, tei;
261 ri = ((unsigned int) skb->data[1] << 8) + skb->data[2];
262 tei = skb->data[4] >> 1;
263 if (st->ma.debug)
264 st->ma.tei_m.printdebug(&st->ma.tei_m,
265 "identity denied ri %d tei %d", ri, tei);
268 static void
269 tei_id_chk_req(struct FsmInst *fi, int event, void *arg)
271 struct PStack *st = fi->userdata;
272 struct sk_buff *skb = arg;
273 int tei;
275 tei = skb->data[4] >> 1;
276 if (st->ma.debug)
277 st->ma.tei_m.printdebug(&st->ma.tei_m,
278 "identity check req tei %d", tei);
279 if ((st->l2.tei != -1) && ((tei == GROUP_TEI) || (tei == st->l2.tei))) {
280 FsmDelTimer(&st->ma.t202, 4);
281 FsmChangeState(&st->ma.tei_m, ST_TEI_NOP);
282 put_tei_msg(st, ID_CHK_RES, random_ri(), st->l2.tei);
286 static void
287 tei_id_remove(struct FsmInst *fi, int event, void *arg)
289 struct PStack *st = fi->userdata;
290 struct sk_buff *skb = arg;
291 struct IsdnCardState *cs;
292 int tei;
294 tei = skb->data[4] >> 1;
295 if (st->ma.debug)
296 st->ma.tei_m.printdebug(&st->ma.tei_m,
297 "identity remove tei %d", tei);
298 if ((st->l2.tei != -1) && ((tei == GROUP_TEI) || (tei == st->l2.tei))) {
299 FsmDelTimer(&st->ma.t202, 5);
300 FsmChangeState(&st->ma.tei_m, ST_TEI_NOP);
301 st->l3.l3l2(st, MDL_REMOVE | REQUEST, 0);
302 cs = (struct IsdnCardState *) st->l1.hardware;
303 cs->cardmsg(cs, MDL_REMOVE | REQUEST, NULL);
307 static void
308 tei_id_verify(struct FsmInst *fi, int event, void *arg)
310 struct PStack *st = fi->userdata;
312 if (st->ma.debug)
313 st->ma.tei_m.printdebug(&st->ma.tei_m,
314 "id verify request for tei %d", st->l2.tei);
315 put_tei_msg(st, ID_VERIFY, 0, st->l2.tei);
316 FsmChangeState(&st->ma.tei_m, ST_TEI_IDVERIFY);
317 FsmAddTimer(&st->ma.t202, st->ma.T202, EV_T202, NULL, 2);
318 st->ma.N202 = 2;
321 static void
322 tei_id_req_tout(struct FsmInst *fi, int event, void *arg)
324 struct PStack *st = fi->userdata;
325 struct IsdnCardState *cs;
327 if (--st->ma.N202) {
328 st->ma.ri = random_ri();
329 if (st->ma.debug)
330 st->ma.tei_m.printdebug(&st->ma.tei_m,
331 "assign req(%d) ri %d", 4 - st->ma.N202,
332 st->ma.ri);
333 put_tei_msg(st, ID_REQUEST, st->ma.ri, 127);
334 FsmAddTimer(&st->ma.t202, st->ma.T202, EV_T202, NULL, 3);
335 } else {
336 st->ma.tei_m.printdebug(&st->ma.tei_m, "assign req failed");
337 st->l3.l3l2(st, MDL_ERROR | RESPONSE, 0);
338 cs = (struct IsdnCardState *) st->l1.hardware;
339 cs->cardmsg(cs, MDL_REMOVE | REQUEST, NULL);
340 FsmChangeState(fi, ST_TEI_NOP);
344 static void
345 tei_id_ver_tout(struct FsmInst *fi, int event, void *arg)
347 struct PStack *st = fi->userdata;
348 struct IsdnCardState *cs;
350 if (--st->ma.N202) {
351 if (st->ma.debug)
352 st->ma.tei_m.printdebug(&st->ma.tei_m,
353 "id verify req(%d) for tei %d",
354 3 - st->ma.N202, st->l2.tei);
355 put_tei_msg(st, ID_VERIFY, 0, st->l2.tei);
356 FsmAddTimer(&st->ma.t202, st->ma.T202, EV_T202, NULL, 4);
357 } else {
358 st->ma.tei_m.printdebug(&st->ma.tei_m,
359 "verify req for tei %d failed", st->l2.tei);
360 st->l3.l3l2(st, MDL_REMOVE | REQUEST, 0);
361 cs = (struct IsdnCardState *) st->l1.hardware;
362 cs->cardmsg(cs, MDL_REMOVE | REQUEST, NULL);
363 FsmChangeState(fi, ST_TEI_NOP);
367 static void
368 tei_l1l2(struct PStack *st, int pr, void *arg)
370 struct sk_buff *skb = arg;
371 int mt;
373 if (test_bit(FLG_FIXED_TEI, &st->l2.flag)) {
374 idev_kfree_skb(skb, FREE_READ);
375 return;
378 if (pr == (PH_DATA | INDICATION)) {
379 if (skb->len < 3) {
380 st->ma.tei_m.printdebug(&st->ma.tei_m,
381 "short mgr frame %ld/3", skb->len);
382 } else if ((skb->data[0] != ((TEI_SAPI << 2) | 2)) ||
383 (skb->data[1] != ((GROUP_TEI << 1) | 1))) {
384 st->ma.tei_m.printdebug(&st->ma.tei_m,
385 "wrong mgr sapi/tei %x/%x",
386 skb->data[0], skb->data[1]);
387 } else if ((skb->data[2] & 0xef) != UI) {
388 st->ma.tei_m.printdebug(&st->ma.tei_m,
389 "mgr frame is not ui %x", skb->data[2]);
390 } else {
391 skb_pull(skb, 3);
392 if (skb->len < 5) {
393 st->ma.tei_m.printdebug(&st->ma.tei_m,
394 "short mgr frame %ld/5", skb->len);
395 } else if (skb->data[0] != TEI_ENTITY_ID) {
396 /* wrong management entity identifier, ignore */
397 st->ma.tei_m.printdebug(&st->ma.tei_m,
398 "tei handler wrong entity id %x",
399 skb->data[0]);
400 } else {
401 mt = skb->data[3];
402 if (mt == ID_ASSIGNED)
403 FsmEvent(&st->ma.tei_m, EV_ASSIGN, skb);
404 else if (mt == ID_DENIED)
405 FsmEvent(&st->ma.tei_m, EV_DENIED, skb);
406 else if (mt == ID_CHK_REQ)
407 FsmEvent(&st->ma.tei_m, EV_CHKREQ, skb);
408 else if (mt == ID_REMOVE)
409 FsmEvent(&st->ma.tei_m, EV_REMOVE, skb);
410 else {
411 st->ma.tei_m.printdebug(&st->ma.tei_m,
412 "tei handler wrong mt %x\n", mt);
416 } else {
417 st->ma.tei_m.printdebug(&st->ma.tei_m,
418 "tei handler wrong pr %x\n", pr);
420 idev_kfree_skb(skb, FREE_READ);
423 static void
424 tei_l2tei(struct PStack *st, int pr, void *arg)
426 struct IsdnCardState *cs;
428 if (test_bit(FLG_FIXED_TEI, &st->l2.flag)) {
429 if (pr == (MDL_ASSIGN | INDICATION)) {
430 if (st->ma.debug)
431 st->ma.tei_m.printdebug(&st->ma.tei_m,
432 "fixed assign tei %d", st->l2.tei);
433 st->l3.l3l2(st, MDL_ASSIGN | REQUEST, (void *) (long) st->l2.tei);
434 cs = (struct IsdnCardState *) st->l1.hardware;
435 cs->cardmsg(cs, MDL_ASSIGN | REQUEST, NULL);
437 return;
439 switch (pr) {
440 case (MDL_ASSIGN | INDICATION):
441 FsmEvent(&st->ma.tei_m, EV_IDREQ, arg);
442 break;
443 case (MDL_ERROR | REQUEST):
444 FsmEvent(&st->ma.tei_m, EV_VERIFY, arg);
445 break;
446 default:
447 break;
451 static void
452 tei_debug(struct FsmInst *fi, char *fmt, ...)
454 va_list args;
455 struct PStack *st = fi->userdata;
457 va_start(args, fmt);
458 VHiSax_putstatus(st->l1.hardware, "tei ", fmt, args);
459 va_end(args);
462 void
463 setstack_tei(struct PStack *st)
465 st->l2.l2tei = tei_l2tei;
466 st->ma.T202 = 2000; /* T202 2000 milliseconds */
467 st->l1.l1tei = tei_l1l2;
468 st->ma.debug = 1;
469 st->ma.tei_m.fsm = &teifsm;
470 st->ma.tei_m.state = ST_TEI_NOP;
471 st->ma.tei_m.debug = 1;
472 st->ma.tei_m.userdata = st;
473 st->ma.tei_m.userint = 0;
474 st->ma.tei_m.printdebug = tei_debug;
475 FsmInitTimer(&st->ma.tei_m, &st->ma.t202);
478 void
479 init_tei(struct IsdnCardState *cs, int protocol)
483 void
484 release_tei(struct IsdnCardState *cs)
486 struct PStack *st = cs->stlist;
488 while (st) {
489 FsmDelTimer(&st->ma.t202, 1);
490 st = st->next;
494 static struct FsmNode TeiFnList[] HISAX_INITDATA =
496 {ST_TEI_NOP, EV_IDREQ, tei_id_request},
497 {ST_TEI_NOP, EV_ASSIGN, tei_id_test_dup},
498 {ST_TEI_NOP, EV_VERIFY, tei_id_verify},
499 {ST_TEI_NOP, EV_REMOVE, tei_id_remove},
500 {ST_TEI_NOP, EV_CHKREQ, tei_id_chk_req},
501 {ST_TEI_IDREQ, EV_T202, tei_id_req_tout},
502 {ST_TEI_IDREQ, EV_ASSIGN, tei_id_assign},
503 {ST_TEI_IDREQ, EV_DENIED, tei_id_denied},
504 {ST_TEI_IDVERIFY, EV_T202, tei_id_ver_tout},
505 {ST_TEI_IDVERIFY, EV_REMOVE, tei_id_remove},
506 {ST_TEI_IDVERIFY, EV_CHKREQ, tei_id_chk_req},
509 #define TEI_FN_COUNT (sizeof(TeiFnList)/sizeof(struct FsmNode))
511 HISAX_INITFUNC(void
512 TeiNew(void))
514 teifsm.state_count = TEI_STATE_COUNT;
515 teifsm.event_count = TEI_EVENT_COUNT;
516 teifsm.strEvent = strTeiEvent;
517 teifsm.strState = strTeiState;
518 FsmNew(&teifsm, TeiFnList, TEI_FN_COUNT);
521 void
522 TeiFree(void)
524 FsmFree(&teifsm);