import of upstream 2.4.34.4 from kernel.org
[linux-2.4.git] / drivers / isdn / hisax / isdnl3.c
1 /* $Id: isdnl3.c,v 1.1.4.1 2001/11/20 14:19:36 kai Exp $
2  *
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.
9  *
10  * For changes and modifications please read
11  * ../../../Documentation/isdn/HiSax.cert
12  *
13  * Thanks to    Jan den Ouden
14  *              Fritz Elfert
15  *
16  */
17
18 #define __NO_VERSION__
19 #include <linux/init.h>
20 #include "hisax.h"
21 #include "isdnl3.h"
22 #include <linux/config.h>
23
24 const char *l3_revision = "$Revision: 1.1.4.1 $";
25
26 static struct Fsm l3fsm;
27
28 enum {
29         ST_L3_LC_REL,
30         ST_L3_LC_ESTAB_WAIT,
31         ST_L3_LC_REL_DELAY, 
32         ST_L3_LC_REL_WAIT,
33         ST_L3_LC_ESTAB,
34 };
35
36 #define L3_STATE_COUNT (ST_L3_LC_ESTAB+1)
37
38 static char *strL3State[] =
39 {
40         "ST_L3_LC_REL",
41         "ST_L3_LC_ESTAB_WAIT",
42         "ST_L3_LC_REL_DELAY",
43         "ST_L3_LC_REL_WAIT",
44         "ST_L3_LC_ESTAB",
45 };
46
47 enum {
48         EV_ESTABLISH_REQ,
49         EV_ESTABLISH_IND,
50         EV_ESTABLISH_CNF,
51         EV_RELEASE_REQ,
52         EV_RELEASE_CNF,
53         EV_RELEASE_IND,
54         EV_TIMEOUT,
55 };
56
57 #define L3_EVENT_COUNT (EV_TIMEOUT+1)
58
59 static char *strL3Event[] =
60 {
61         "EV_ESTABLISH_REQ",
62         "EV_ESTABLISH_IND",
63         "EV_ESTABLISH_CNF",
64         "EV_RELEASE_REQ",
65         "EV_RELEASE_CNF",
66         "EV_RELEASE_IND",
67         "EV_TIMEOUT",
68 };
69
70 static void
71 l3m_debug(struct FsmInst *fi, char *fmt, ...)
72 {
73         va_list args;
74         struct PStack *st = fi->userdata;
75
76         va_start(args, fmt);
77         VHiSax_putstatus(st->l1.hardware, st->l3.debug_id, fmt, args);
78         va_end(args);
79 }
80
81 u_char *
82 findie(u_char * p, int size, u_char ie, int wanted_set)
83 {
84         int l, codeset, maincodeset;
85         u_char *pend = p + size;
86
87         /* skip protocol discriminator, callref and message type */
88         p++;
89         l = (*p++) & 0xf;
90         p += l;
91         p++;
92         codeset = 0;
93         maincodeset = 0;
94         /* while there are bytes left... */
95         while (p < pend) {
96                 if ((*p & 0xf0) == 0x90) {
97                         codeset = *p & 0x07;
98                         if (!(*p & 0x08))
99                                 maincodeset = codeset;
100                 }
101                 if (*p & 0x80)
102                         p++;
103                 else {
104                         if (codeset == wanted_set) {
105                                 if (*p == ie)
106                                   { /* improved length check (Werner Cornelius) */
107                                     if ((pend - p) < 2) 
108                                       return(NULL); 
109                                     if (*(p+1) > (pend - (p+2))) 
110                                       return(NULL); 
111                                     return (p);
112                                   }           
113                                   
114                                 if (*p > ie)
115                                         return (NULL);
116                         }
117                         p++;
118                         l = *p++;
119                         p += l;
120                         codeset = maincodeset;
121                 }
122         }
123         return (NULL);
124 }
125
126 int
127 getcallref(u_char * p)
128 {
129         int l, cr = 0;
130
131         p++;                    /* prot discr */
132         if (*p & 0xfe)          /* wrong callref BRI only 1 octet*/
133                 return(-2);
134         l = 0xf & *p++;         /* callref length */
135         if (!l)                 /* dummy CallRef */
136                 return(-1);
137         cr = *p++;
138         return (cr);
139 }
140
141 static int OrigCallRef = 0;
142
143 int
144 newcallref(void)
145 {
146         if (OrigCallRef == 127)
147                 OrigCallRef = 1;
148         else
149                 OrigCallRef++;
150         return (OrigCallRef);
151 }
152
153 void
154 newl3state(struct l3_process *pc, int state)
155 {
156         if (pc->debug & L3_DEB_STATE)
157                 l3_debug(pc->st, "newstate cr %d %d --> %d", 
158                          pc->callref & 0x7F,
159                          pc->state, state);
160         pc->state = state;
161 }
162
163 static void
164 L3ExpireTimer(struct L3Timer *t)
165 {
166         t->pc->st->lli.l4l3(t->pc->st, t->event, t->pc);
167 }
168
169 void
170 L3InitTimer(struct l3_process *pc, struct L3Timer *t)
171 {
172         t->pc = pc;
173         t->tl.function = (void *) L3ExpireTimer;
174         t->tl.data = (long) t;
175         init_timer(&t->tl);
176 }
177
178 void
179 L3DelTimer(struct L3Timer *t)
180 {
181         del_timer(&t->tl);
182 }
183
184 int
185 L3AddTimer(struct L3Timer *t,
186            int millisec, int event)
187 {
188         if (timer_pending(&t->tl)) {
189                 printk(KERN_WARNING "L3AddTimer: timer already active!\n");
190                 return -1;
191         }
192         init_timer(&t->tl);
193         t->event = event;
194         t->tl.expires = jiffies + (millisec * HZ) / 1000;
195         add_timer(&t->tl);
196         return 0;
197 }
198
199 void
200 StopAllL3Timer(struct l3_process *pc)
201 {
202         L3DelTimer(&pc->timer);
203 }
204
205 struct sk_buff *
206 l3_alloc_skb(int len)
207 {
208         struct sk_buff *skb;
209
210         if (!(skb = alloc_skb(len + MAX_HEADER_LEN, GFP_ATOMIC))) {
211                 printk(KERN_WARNING "HiSax: No skb for D-channel\n");
212                 return (NULL);
213         }
214         skb_reserve(skb, MAX_HEADER_LEN);
215         return (skb);
216 }
217
218 static void
219 no_l3_proto(struct PStack *st, int pr, void *arg)
220 {
221         struct sk_buff *skb = arg;
222
223         HiSax_putstatus(st->l1.hardware, "L3", "no D protocol");
224         if (skb) {
225                 dev_kfree_skb(skb);
226         }
227 }
228
229 static int
230 no_l3_proto_spec(struct PStack *st, isdn_ctrl *ic)
231 {
232         printk(KERN_WARNING "HiSax: no specific protocol handler for proto %lu\n",ic->arg & 0xFF);
233         return(-1);
234 }
235
236 #ifdef  CONFIG_HISAX_EURO
237 extern void setstack_dss1(struct PStack *st);
238 #endif
239
240 #ifdef  CONFIG_HISAX_NI1
241 extern void setstack_ni1(struct PStack *st);
242 #endif
243
244 #ifdef  CONFIG_HISAX_1TR6
245 extern void setstack_1tr6(struct PStack *st);
246 #endif
247
248 struct l3_process
249 *getl3proc(struct PStack *st, int cr)
250 {
251         struct l3_process *p = st->l3.proc;
252
253         while (p)
254                 if (p->callref == cr)
255                         return (p);
256                 else
257                         p = p->next;
258         return (NULL);
259 }
260
261 struct l3_process
262 *new_l3_process(struct PStack *st, int cr)
263 {
264         struct l3_process *p, *np;
265
266         if (!(p = kmalloc(sizeof(struct l3_process), GFP_ATOMIC))) {
267                 printk(KERN_ERR "HiSax can't get memory for cr %d\n", cr);
268                 return (NULL);
269         }
270         if (!st->l3.proc)
271                 st->l3.proc = p;
272         else {
273                 np = st->l3.proc;
274                 while (np->next)
275                         np = np->next;
276                 np->next = p;
277         }
278         p->next = NULL;
279         p->debug = st->l3.debug;
280         p->callref = cr;
281         p->state = 0;
282         p->chan = NULL;
283         p->st = st;
284         p->N303 = st->l3.N303;
285         L3InitTimer(p, &p->timer);
286         return (p);
287 };
288
289 void
290 release_l3_process(struct l3_process *p)
291 {
292         struct l3_process *np, *pp = NULL;
293
294         if (!p)
295                 return;
296         np = p->st->l3.proc;
297         while (np) {
298                 if (np == p) {
299                         StopAllL3Timer(p);
300                         if (pp)
301                                 pp->next = np->next;
302                         else if (!(p->st->l3.proc = np->next) &&
303                                 !test_bit(FLG_PTP, &p->st->l2.flag)) {
304                                 if (p->debug)
305                                         l3_debug(p->st, "release_l3_process: last process");
306                                 if (!skb_queue_len(&p->st->l3.squeue)) {
307                                         if (p->debug)
308                                                 l3_debug(p->st, "release_l3_process: release link");
309                                         if (p->st->protocol != ISDN_PTYPE_NI1)
310                                                 FsmEvent(&p->st->l3.l3m, EV_RELEASE_REQ, NULL);
311                                         else
312                                                 FsmEvent(&p->st->l3.l3m, EV_RELEASE_IND, NULL);
313                                 } else {
314                                         if (p->debug)
315                                                 l3_debug(p->st, "release_l3_process: not release link");
316                                 }
317                         } 
318                         kfree(p);
319                         return;
320                 }
321                 pp = np;
322                 np = np->next;
323         }
324         printk(KERN_ERR "HiSax internal L3 error CR(%d) not in list\n", p->callref);
325         l3_debug(p->st, "HiSax internal L3 error CR(%d) not in list", p->callref);
326 };
327
328 static void
329 l3ml3p(struct PStack *st, int pr)
330 {
331         struct l3_process *p = st->l3.proc;
332         struct l3_process *np;
333
334         while (p) {
335                 /* p might be kfreed under us, so we need to save where we want to go on */
336                 np = p->next;
337                 st->l3.l3ml3(st, pr, p);
338                 p = np;
339         }
340 }
341
342 void
343 setstack_l3dc(struct PStack *st, struct Channel *chanp)
344 {
345         char tmp[64];
346
347         st->l3.proc   = NULL;
348         st->l3.global = NULL;
349         skb_queue_head_init(&st->l3.squeue);
350         st->l3.l3m.fsm = &l3fsm;
351         st->l3.l3m.state = ST_L3_LC_REL;
352         st->l3.l3m.debug = 1;
353         st->l3.l3m.userdata = st;
354         st->l3.l3m.userint = 0;
355         st->l3.l3m.printdebug = l3m_debug;
356         FsmInitTimer(&st->l3.l3m, &st->l3.l3m_timer);
357         strcpy(st->l3.debug_id, "L3DC ");
358         st->lli.l4l3_proto = no_l3_proto_spec;
359
360 #ifdef  CONFIG_HISAX_EURO
361         if (st->protocol == ISDN_PTYPE_EURO) {
362                 setstack_dss1(st);
363         } else
364 #endif
365 #ifdef  CONFIG_HISAX_NI1
366         if (st->protocol == ISDN_PTYPE_NI1) {
367                 setstack_ni1(st);
368         } else
369 #endif
370 #ifdef  CONFIG_HISAX_1TR6
371         if (st->protocol == ISDN_PTYPE_1TR6) {
372                 setstack_1tr6(st);
373         } else
374 #endif
375         if (st->protocol == ISDN_PTYPE_LEASED) {
376                 st->lli.l4l3 = no_l3_proto;
377                 st->l2.l2l3 = no_l3_proto;
378                 st->l3.l3ml3 = no_l3_proto;
379                 printk(KERN_INFO "HiSax: Leased line mode\n");
380         } else {
381                 st->lli.l4l3 = no_l3_proto;
382                 st->l2.l2l3 = no_l3_proto;
383                 st->l3.l3ml3 = no_l3_proto;
384                 sprintf(tmp, "protocol %s not supported",
385                         (st->protocol == ISDN_PTYPE_1TR6) ? "1tr6" :
386                         (st->protocol == ISDN_PTYPE_EURO) ? "euro" :
387                         (st->protocol == ISDN_PTYPE_NI1) ? "ni1" :
388                         "unknown");
389                 printk(KERN_WARNING "HiSax: %s\n", tmp);
390                 st->protocol = -1;
391         }
392 }
393
394 void
395 isdnl3_trans(struct PStack *st, int pr, void *arg) {
396         st->l3.l3l2(st, pr, arg);
397 }
398
399 void
400 releasestack_isdnl3(struct PStack *st)
401 {
402         while (st->l3.proc)
403                 release_l3_process(st->l3.proc);
404         if (st->l3.global) {
405                 StopAllL3Timer(st->l3.global);
406                 kfree(st->l3.global);
407                 st->l3.global = NULL;
408         }
409         FsmDelTimer(&st->l3.l3m_timer, 54);
410         skb_queue_purge(&st->l3.squeue);
411 }
412
413 void
414 setstack_l3bc(struct PStack *st, struct Channel *chanp)
415 {
416
417         st->l3.proc   = NULL;
418         st->l3.global = NULL;
419         skb_queue_head_init(&st->l3.squeue);
420         st->l3.l3m.fsm = &l3fsm;
421         st->l3.l3m.state = ST_L3_LC_REL;
422         st->l3.l3m.debug = 1;
423         st->l3.l3m.userdata = st;
424         st->l3.l3m.userint = 0;
425         st->l3.l3m.printdebug = l3m_debug;
426         strcpy(st->l3.debug_id, "L3BC ");
427         st->lli.l4l3 = isdnl3_trans;
428 }
429
430 #define DREL_TIMER_VALUE 40000
431
432 static void
433 lc_activate(struct FsmInst *fi, int event, void *arg)
434 {
435         struct PStack *st = fi->userdata;
436
437         FsmChangeState(fi, ST_L3_LC_ESTAB_WAIT);
438         st->l3.l3l2(st, DL_ESTABLISH | REQUEST, NULL);
439 }
440
441 static void
442 lc_connect(struct FsmInst *fi, int event, void *arg)
443 {
444         struct PStack *st = fi->userdata;
445         struct sk_buff *skb = arg;
446         int dequeued = 0;
447
448         FsmChangeState(fi, ST_L3_LC_ESTAB);
449         while ((skb = skb_dequeue(&st->l3.squeue))) {
450                 st->l3.l3l2(st, DL_DATA | REQUEST, skb);
451                 dequeued++;
452         }
453         if ((!st->l3.proc) &&  dequeued) {
454                 if (st->l3.debug)
455                         l3_debug(st, "lc_connect: release link");
456                 FsmEvent(&st->l3.l3m, EV_RELEASE_REQ, NULL);
457         } else
458                 l3ml3p(st, DL_ESTABLISH | INDICATION);
459 }
460
461 static void
462 lc_connected(struct FsmInst *fi, int event, void *arg)
463 {
464         struct PStack *st = fi->userdata;
465         struct sk_buff *skb = arg;
466         int dequeued = 0;
467
468         FsmDelTimer(&st->l3.l3m_timer, 51);
469         FsmChangeState(fi, ST_L3_LC_ESTAB);
470         while ((skb = skb_dequeue(&st->l3.squeue))) {
471                 st->l3.l3l2(st, DL_DATA | REQUEST, skb);
472                 dequeued++;
473         }
474         if ((!st->l3.proc) &&  dequeued) {
475                 if (st->l3.debug)
476                         l3_debug(st, "lc_connected: release link");
477                 FsmEvent(&st->l3.l3m, EV_RELEASE_REQ, NULL);
478         } else
479                 l3ml3p(st, DL_ESTABLISH | CONFIRM);
480 }
481
482 static void
483 lc_start_delay(struct FsmInst *fi, int event, void *arg)
484 {
485        struct PStack *st = fi->userdata;
486
487        FsmChangeState(fi, ST_L3_LC_REL_DELAY);
488        FsmAddTimer(&st->l3.l3m_timer, DREL_TIMER_VALUE, EV_TIMEOUT, NULL, 50);
489 }
490
491 static void
492 lc_start_delay_check(struct FsmInst *fi, int event, void *arg)
493 /* 20/09/00 - GE timer not user for NI-1 as layer 2 should stay up */
494 {
495        struct PStack *st = fi->userdata;
496
497        FsmChangeState(fi, ST_L3_LC_REL_DELAY);
498        /* 19/09/00 - GE timer not user for NI-1 */
499        if (st->protocol != ISDN_PTYPE_NI1) 
500                 FsmAddTimer(&st->l3.l3m_timer, DREL_TIMER_VALUE, EV_TIMEOUT, NULL, 50);
501 }
502
503 static void
504 lc_release_req(struct FsmInst *fi, int event, void *arg)
505 {
506         struct PStack *st = fi->userdata;
507
508         if (test_bit(FLG_L2BLOCK, &st->l2.flag)) {
509                 if (st->l3.debug)
510                         l3_debug(st, "lc_release_req: l2 blocked");
511                 /* restart release timer */
512                 FsmAddTimer(&st->l3.l3m_timer, DREL_TIMER_VALUE, EV_TIMEOUT, NULL, 51);
513         } else {
514                 FsmChangeState(fi, ST_L3_LC_REL_WAIT);
515                 st->l3.l3l2(st, DL_RELEASE | REQUEST, NULL);
516         }
517 }
518
519 static void
520 lc_release_ind(struct FsmInst *fi, int event, void *arg)
521 {
522         struct PStack *st = fi->userdata;
523
524         FsmDelTimer(&st->l3.l3m_timer, 52);
525         FsmChangeState(fi, ST_L3_LC_REL);
526         skb_queue_purge(&st->l3.squeue);
527         l3ml3p(st, DL_RELEASE | INDICATION);
528 }
529
530 static void
531 lc_release_cnf(struct FsmInst *fi, int event, void *arg)
532 {
533         struct PStack *st = fi->userdata;
534
535         FsmChangeState(fi, ST_L3_LC_REL);
536         skb_queue_purge(&st->l3.squeue);
537         l3ml3p(st, DL_RELEASE | CONFIRM);
538 }
539
540
541 /* *INDENT-OFF* */
542 static struct FsmNode L3FnList[] __initdata =
543 {
544         {ST_L3_LC_REL,          EV_ESTABLISH_REQ,       lc_activate},
545         {ST_L3_LC_REL,          EV_ESTABLISH_IND,       lc_connect},
546         {ST_L3_LC_REL,          EV_ESTABLISH_CNF,       lc_connect},
547         {ST_L3_LC_ESTAB_WAIT,   EV_ESTABLISH_CNF,       lc_connected},
548         {ST_L3_LC_ESTAB_WAIT,   EV_RELEASE_REQ,         lc_start_delay},
549         {ST_L3_LC_ESTAB_WAIT,   EV_RELEASE_IND,         lc_release_ind},
550         {ST_L3_LC_ESTAB,        EV_RELEASE_IND,         lc_release_ind},
551         {ST_L3_LC_ESTAB,        EV_RELEASE_REQ,         lc_start_delay_check},
552         {ST_L3_LC_REL_DELAY,    EV_RELEASE_IND,         lc_release_ind},
553         {ST_L3_LC_REL_DELAY,    EV_ESTABLISH_REQ,       lc_connected},
554         {ST_L3_LC_REL_DELAY,    EV_TIMEOUT,             lc_release_req},
555         {ST_L3_LC_REL_WAIT,     EV_RELEASE_CNF,         lc_release_cnf},
556         {ST_L3_LC_REL_WAIT,     EV_ESTABLISH_REQ,       lc_activate},
557 };
558 /* *INDENT-ON* */
559
560 #define L3_FN_COUNT (sizeof(L3FnList)/sizeof(struct FsmNode))
561
562 void
563 l3_msg(struct PStack *st, int pr, void *arg)
564 {
565         switch (pr) {
566                 case (DL_DATA | REQUEST):
567                         if (st->l3.l3m.state == ST_L3_LC_ESTAB) {
568                                 st->l3.l3l2(st, pr, arg);
569                         } else {
570                                 struct sk_buff *skb = arg;
571
572                                 skb_queue_tail(&st->l3.squeue, skb);
573                                 FsmEvent(&st->l3.l3m, EV_ESTABLISH_REQ, NULL); 
574                         }
575                         break;
576                 case (DL_ESTABLISH | REQUEST):
577                         FsmEvent(&st->l3.l3m, EV_ESTABLISH_REQ, NULL);
578                         break;
579                 case (DL_ESTABLISH | CONFIRM):
580                         FsmEvent(&st->l3.l3m, EV_ESTABLISH_CNF, NULL);
581                         break;
582                 case (DL_ESTABLISH | INDICATION):
583                         FsmEvent(&st->l3.l3m, EV_ESTABLISH_IND, NULL);
584                         break;
585                 case (DL_RELEASE | INDICATION):
586                         FsmEvent(&st->l3.l3m, EV_RELEASE_IND, NULL);
587                         break;
588                 case (DL_RELEASE | CONFIRM):
589                         FsmEvent(&st->l3.l3m, EV_RELEASE_CNF, NULL);
590                         break;
591                 case (DL_RELEASE | REQUEST):
592                         FsmEvent(&st->l3.l3m, EV_RELEASE_REQ, NULL);
593                         break;
594         }
595 }
596
597 int __init
598 Isdnl3New(void)
599 {
600         l3fsm.state_count = L3_STATE_COUNT;
601         l3fsm.event_count = L3_EVENT_COUNT;
602         l3fsm.strEvent = strL3Event;
603         l3fsm.strState = strL3State;
604         return FsmNew(&l3fsm, L3FnList, L3_FN_COUNT);
605 }
606
607 void
608 Isdnl3Free(void)
609 {
610         FsmFree(&l3fsm);
611 }