File: /usr/src/linux/drivers/isdn/hisax/isdnl3.c

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