GNU Linux-libre 4.19.245-gnu1
[releases.git] / drivers / isdn / hisax / l3_1tr6.c
1 /* $Id: l3_1tr6.c,v 2.15.2.3 2004/01/13 14:31:25 keil Exp $
2  *
3  * German 1TR6 D-channel protocol
4  *
5  * Author       Karsten Keil
6  * Copyright    by Karsten Keil      <keil@isdn4linux.de>
7  *
8  * This software may be used and distributed according to the terms
9  * of the GNU General Public License, incorporated herein by reference.
10  *
11  * For changes and modifications please read
12  * Documentation/isdn/HiSax.cert
13  *
14  */
15
16 #include "hisax.h"
17 #include "l3_1tr6.h"
18 #include "isdnl3.h"
19 #include <linux/ctype.h>
20
21 extern char *HiSax_getrev(const char *revision);
22 static const char *l3_1tr6_revision = "$Revision: 2.15.2.3 $";
23
24 #define MsgHead(ptr, cref, mty, dis)            \
25         *ptr++ = dis;                           \
26         *ptr++ = 0x1;                           \
27         *ptr++ = cref ^ 0x80;                   \
28         *ptr++ = mty
29
30 static void
31 l3_1TR6_message(struct l3_process *pc, u_char mt, u_char pd)
32 {
33         struct sk_buff *skb;
34         u_char *p;
35
36         if (!(skb = l3_alloc_skb(4)))
37                 return;
38         p = skb_put(skb, 4);
39         MsgHead(p, pc->callref, mt, pd);
40         l3_msg(pc->st, DL_DATA | REQUEST, skb);
41 }
42
43 static void
44 l3_1tr6_release_req(struct l3_process *pc, u_char pr, void *arg)
45 {
46         StopAllL3Timer(pc);
47         newl3state(pc, 19);
48         l3_1TR6_message(pc, MT_N1_REL, PROTO_DIS_N1);
49         L3AddTimer(&pc->timer, T308, CC_T308_1);
50 }
51
52 static void
53 l3_1tr6_invalid(struct l3_process *pc, u_char pr, void *arg)
54 {
55         struct sk_buff *skb = arg;
56
57         dev_kfree_skb(skb);
58         l3_1tr6_release_req(pc, 0, NULL);
59 }
60
61 static void
62 l3_1tr6_error(struct l3_process *pc, u_char *msg, struct sk_buff *skb)
63 {
64         dev_kfree_skb(skb);
65         if (pc->st->l3.debug & L3_DEB_WARN)
66                 l3_debug(pc->st, "%s", msg);
67         l3_1tr6_release_req(pc, 0, NULL);
68 }
69
70 static void
71 l3_1tr6_setup_req(struct l3_process *pc, u_char pr, void *arg)
72 {
73         struct sk_buff *skb;
74         u_char tmp[128];
75         u_char *p = tmp;
76         u_char *teln;
77         u_char *eaz;
78         u_char channel = 0;
79         int l;
80
81         MsgHead(p, pc->callref, MT_N1_SETUP, PROTO_DIS_N1);
82         teln = pc->para.setup.phone;
83         pc->para.spv = 0;
84         if (!isdigit(*teln)) {
85                 switch (0x5f & *teln) {
86                 case 'S':
87                         pc->para.spv = 1;
88                         break;
89                 case 'C':
90                         channel = 0x08;
91                         /* fall through */
92                 case 'P':
93                         channel |= 0x80;
94                         teln++;
95                         if (*teln == '1')
96                                 channel |= 0x01;
97                         else
98                                 channel |= 0x02;
99                         break;
100                 default:
101                         if (pc->st->l3.debug & L3_DEB_WARN)
102                                 l3_debug(pc->st, "Wrong MSN Code");
103                         break;
104                 }
105                 teln++;
106         }
107         if (channel) {
108                 *p++ = 0x18;    /* channel indicator */
109                 *p++ = 1;
110                 *p++ = channel;
111         }
112         if (pc->para.spv) {     /* SPV ? */
113                 /* NSF SPV */
114                 *p++ = WE0_netSpecFac;
115                 *p++ = 4;       /* Laenge */
116                 *p++ = 0;
117                 *p++ = FAC_SPV; /* SPV */
118                 *p++ = pc->para.setup.si1;      /* 0 for all Services */
119                 *p++ = pc->para.setup.si2;      /* 0 for all Services */
120                 *p++ = WE0_netSpecFac;
121                 *p++ = 4;       /* Laenge */
122                 *p++ = 0;
123                 *p++ = FAC_Activate;    /* aktiviere SPV (default) */
124                 *p++ = pc->para.setup.si1;      /* 0 for all Services */
125                 *p++ = pc->para.setup.si2;      /* 0 for all Services */
126         }
127         eaz = pc->para.setup.eazmsn;
128         if (*eaz) {
129                 *p++ = WE0_origAddr;
130                 *p++ = strlen(eaz) + 1;
131                 /* Classify as AnyPref. */
132                 *p++ = 0x81;    /* Ext = '1'B, Type = '000'B, Plan = '0001'B. */
133                 while (*eaz)
134                         *p++ = *eaz++ & 0x7f;
135         }
136         *p++ = WE0_destAddr;
137         *p++ = strlen(teln) + 1;
138         /* Classify as AnyPref. */
139         *p++ = 0x81;            /* Ext = '1'B, Type = '000'B, Plan = '0001'B. */
140         while (*teln)
141                 *p++ = *teln++ & 0x7f;
142
143         *p++ = WE_Shift_F6;
144         /* Codesatz 6 fuer Service */
145         *p++ = WE6_serviceInd;
146         *p++ = 2;               /* len=2 info,info2 */
147         *p++ = pc->para.setup.si1;
148         *p++ = pc->para.setup.si2;
149
150         l = p - tmp;
151         if (!(skb = l3_alloc_skb(l)))
152                 return;
153         skb_put_data(skb, tmp, l);
154         L3DelTimer(&pc->timer);
155         L3AddTimer(&pc->timer, T303, CC_T303);
156         newl3state(pc, 1);
157         l3_msg(pc->st, DL_DATA | REQUEST, skb);
158 }
159
160 static void
161 l3_1tr6_setup(struct l3_process *pc, u_char pr, void *arg)
162 {
163         u_char *p;
164         int bcfound = 0;
165         struct sk_buff *skb = arg;
166
167         /* Channel Identification */
168         p = findie(skb->data, skb->len, WE0_chanID, 0);
169         if (p) {
170                 if (p[1] != 1) {
171                         l3_1tr6_error(pc, "setup wrong chanID len", skb);
172                         return;
173                 }
174                 if ((p[2] & 0xf4) != 0x80) {
175                         l3_1tr6_error(pc, "setup wrong WE0_chanID", skb);
176                         return;
177                 }
178                 if ((pc->para.bchannel = p[2] & 0x3))
179                         bcfound++;
180         } else {
181                 l3_1tr6_error(pc, "missing setup chanID", skb);
182                 return;
183         }
184
185         p = skb->data;
186         if ((p = findie(p, skb->len, WE6_serviceInd, 6))) {
187                 pc->para.setup.si1 = p[2];
188                 pc->para.setup.si2 = p[3];
189         } else {
190                 l3_1tr6_error(pc, "missing setup SI", skb);
191                 return;
192         }
193
194         p = skb->data;
195         if ((p = findie(p, skb->len, WE0_destAddr, 0)))
196                 iecpy(pc->para.setup.eazmsn, p, 1);
197         else
198                 pc->para.setup.eazmsn[0] = 0;
199
200         p = skb->data;
201         if ((p = findie(p, skb->len, WE0_origAddr, 0))) {
202                 iecpy(pc->para.setup.phone, p, 1);
203         } else
204                 pc->para.setup.phone[0] = 0;
205
206         p = skb->data;
207         pc->para.spv = 0;
208         if ((p = findie(p, skb->len, WE0_netSpecFac, 0))) {
209                 if ((FAC_SPV == p[3]) || (FAC_Activate == p[3]))
210                         pc->para.spv = 1;
211         }
212         dev_kfree_skb(skb);
213
214         /* Signal all services, linklevel takes care of Service-Indicator */
215         if (bcfound) {
216                 if ((pc->para.setup.si1 != 7) && (pc->st->l3.debug & L3_DEB_WARN)) {
217                         l3_debug(pc->st, "non-digital call: %s -> %s",
218                                 pc->para.setup.phone,
219                                 pc->para.setup.eazmsn);
220                 }
221                 newl3state(pc, 6);
222                 pc->st->l3.l3l4(pc->st, CC_SETUP | INDICATION, pc);
223         } else
224                 release_l3_process(pc);
225 }
226
227 static void
228 l3_1tr6_setup_ack(struct l3_process *pc, u_char pr, void *arg)
229 {
230         u_char *p;
231         struct sk_buff *skb = arg;
232
233         L3DelTimer(&pc->timer);
234         p = skb->data;
235         newl3state(pc, 2);
236         if ((p = findie(p, skb->len, WE0_chanID, 0))) {
237                 if (p[1] != 1) {
238                         l3_1tr6_error(pc, "setup_ack wrong chanID len", skb);
239                         return;
240                 }
241                 if ((p[2] & 0xf4) != 0x80) {
242                         l3_1tr6_error(pc, "setup_ack wrong WE0_chanID", skb);
243                         return;
244                 }
245                 pc->para.bchannel = p[2] & 0x3;
246         } else {
247                 l3_1tr6_error(pc, "missing setup_ack WE0_chanID", skb);
248                 return;
249         }
250         dev_kfree_skb(skb);
251         L3AddTimer(&pc->timer, T304, CC_T304);
252         pc->st->l3.l3l4(pc->st, CC_MORE_INFO | INDICATION, pc);
253 }
254
255 static void
256 l3_1tr6_call_sent(struct l3_process *pc, u_char pr, void *arg)
257 {
258         u_char *p;
259         struct sk_buff *skb = arg;
260
261         L3DelTimer(&pc->timer);
262         p = skb->data;
263         if ((p = findie(p, skb->len, WE0_chanID, 0))) {
264                 if (p[1] != 1) {
265                         l3_1tr6_error(pc, "call sent wrong chanID len", skb);
266                         return;
267                 }
268                 if ((p[2] & 0xf4) != 0x80) {
269                         l3_1tr6_error(pc, "call sent wrong WE0_chanID", skb);
270                         return;
271                 }
272                 if ((pc->state == 2) && (pc->para.bchannel != (p[2] & 0x3))) {
273                         l3_1tr6_error(pc, "call sent wrong chanID value", skb);
274                         return;
275                 }
276                 pc->para.bchannel = p[2] & 0x3;
277         } else {
278                 l3_1tr6_error(pc, "missing call sent WE0_chanID", skb);
279                 return;
280         }
281         dev_kfree_skb(skb);
282         L3AddTimer(&pc->timer, T310, CC_T310);
283         newl3state(pc, 3);
284         pc->st->l3.l3l4(pc->st, CC_PROCEEDING | INDICATION, pc);
285 }
286
287 static void
288 l3_1tr6_alert(struct l3_process *pc, u_char pr, void *arg)
289 {
290         struct sk_buff *skb = arg;
291
292         dev_kfree_skb(skb);
293         L3DelTimer(&pc->timer); /* T304 */
294         newl3state(pc, 4);
295         pc->st->l3.l3l4(pc->st, CC_ALERTING | INDICATION, pc);
296 }
297
298 static void
299 l3_1tr6_info(struct l3_process *pc, u_char pr, void *arg)
300 {
301         u_char *p;
302         int i, tmpcharge = 0;
303         char a_charge[8];
304         struct sk_buff *skb = arg;
305
306         p = skb->data;
307         if ((p = findie(p, skb->len, WE6_chargingInfo, 6))) {
308                 iecpy(a_charge, p, 1);
309                 for (i = 0; i < strlen(a_charge); i++) {
310                         tmpcharge *= 10;
311                         tmpcharge += a_charge[i] & 0xf;
312                 }
313                 if (tmpcharge > pc->para.chargeinfo) {
314                         pc->para.chargeinfo = tmpcharge;
315                         pc->st->l3.l3l4(pc->st, CC_CHARGE | INDICATION, pc);
316                 }
317                 if (pc->st->l3.debug & L3_DEB_CHARGE) {
318                         l3_debug(pc->st, "charging info %d",
319                                  pc->para.chargeinfo);
320                 }
321         } else if (pc->st->l3.debug & L3_DEB_CHARGE)
322                 l3_debug(pc->st, "charging info not found");
323         dev_kfree_skb(skb);
324
325 }
326
327 static void
328 l3_1tr6_info_s2(struct l3_process *pc, u_char pr, void *arg)
329 {
330         struct sk_buff *skb = arg;
331
332         dev_kfree_skb(skb);
333 }
334
335 static void
336 l3_1tr6_connect(struct l3_process *pc, u_char pr, void *arg)
337 {
338         struct sk_buff *skb = arg;
339
340         L3DelTimer(&pc->timer); /* T310 */
341         if (!findie(skb->data, skb->len, WE6_date, 6)) {
342                 l3_1tr6_error(pc, "missing connect date", skb);
343                 return;
344         }
345         newl3state(pc, 10);
346         dev_kfree_skb(skb);
347         pc->para.chargeinfo = 0;
348         pc->st->l3.l3l4(pc->st, CC_SETUP | CONFIRM, pc);
349 }
350
351 static void
352 l3_1tr6_rel(struct l3_process *pc, u_char pr, void *arg)
353 {
354         struct sk_buff *skb = arg;
355         u_char *p;
356
357         p = skb->data;
358         if ((p = findie(p, skb->len, WE0_cause, 0))) {
359                 if (p[1] > 0) {
360                         pc->para.cause = p[2];
361                         if (p[1] > 1)
362                                 pc->para.loc = p[3];
363                         else
364                                 pc->para.loc = 0;
365                 } else {
366                         pc->para.cause = 0;
367                         pc->para.loc = 0;
368                 }
369         } else {
370                 pc->para.cause = NO_CAUSE;
371                 l3_1tr6_error(pc, "missing REL cause", skb);
372                 return;
373         }
374         dev_kfree_skb(skb);
375         StopAllL3Timer(pc);
376         newl3state(pc, 0);
377         l3_1TR6_message(pc, MT_N1_REL_ACK, PROTO_DIS_N1);
378         pc->st->l3.l3l4(pc->st, CC_RELEASE | INDICATION, pc);
379         release_l3_process(pc);
380 }
381
382 static void
383 l3_1tr6_rel_ack(struct l3_process *pc, u_char pr, void *arg)
384 {
385         struct sk_buff *skb = arg;
386
387         dev_kfree_skb(skb);
388         StopAllL3Timer(pc);
389         newl3state(pc, 0);
390         pc->para.cause = NO_CAUSE;
391         pc->st->l3.l3l4(pc->st, CC_RELEASE | CONFIRM, pc);
392         release_l3_process(pc);
393 }
394
395 static void
396 l3_1tr6_disc(struct l3_process *pc, u_char pr, void *arg)
397 {
398         struct sk_buff *skb = arg;
399         u_char *p;
400         int i, tmpcharge = 0;
401         char a_charge[8];
402
403         StopAllL3Timer(pc);
404         p = skb->data;
405         if ((p = findie(p, skb->len, WE6_chargingInfo, 6))) {
406                 iecpy(a_charge, p, 1);
407                 for (i = 0; i < strlen(a_charge); i++) {
408                         tmpcharge *= 10;
409                         tmpcharge += a_charge[i] & 0xf;
410                 }
411                 if (tmpcharge > pc->para.chargeinfo) {
412                         pc->para.chargeinfo = tmpcharge;
413                         pc->st->l3.l3l4(pc->st, CC_CHARGE | INDICATION, pc);
414                 }
415                 if (pc->st->l3.debug & L3_DEB_CHARGE) {
416                         l3_debug(pc->st, "charging info %d",
417                                  pc->para.chargeinfo);
418                 }
419         } else if (pc->st->l3.debug & L3_DEB_CHARGE)
420                 l3_debug(pc->st, "charging info not found");
421
422
423         p = skb->data;
424         if ((p = findie(p, skb->len, WE0_cause, 0))) {
425                 if (p[1] > 0) {
426                         pc->para.cause = p[2];
427                         if (p[1] > 1)
428                                 pc->para.loc = p[3];
429                         else
430                                 pc->para.loc = 0;
431                 } else {
432                         pc->para.cause = 0;
433                         pc->para.loc = 0;
434                 }
435         } else {
436                 if (pc->st->l3.debug & L3_DEB_WARN)
437                         l3_debug(pc->st, "cause not found");
438                 pc->para.cause = NO_CAUSE;
439         }
440         if (!findie(skb->data, skb->len, WE6_date, 6)) {
441                 l3_1tr6_error(pc, "missing connack date", skb);
442                 return;
443         }
444         dev_kfree_skb(skb);
445         newl3state(pc, 12);
446         pc->st->l3.l3l4(pc->st, CC_DISCONNECT | INDICATION, pc);
447 }
448
449
450 static void
451 l3_1tr6_connect_ack(struct l3_process *pc, u_char pr, void *arg)
452 {
453         struct sk_buff *skb = arg;
454
455         if (!findie(skb->data, skb->len, WE6_date, 6)) {
456                 l3_1tr6_error(pc, "missing connack date", skb);
457                 return;
458         }
459         dev_kfree_skb(skb);
460         newl3state(pc, 10);
461         pc->para.chargeinfo = 0;
462         L3DelTimer(&pc->timer);
463         pc->st->l3.l3l4(pc->st, CC_SETUP_COMPL | INDICATION, pc);
464 }
465
466 static void
467 l3_1tr6_alert_req(struct l3_process *pc, u_char pr, void *arg)
468 {
469         newl3state(pc, 7);
470         l3_1TR6_message(pc, MT_N1_ALERT, PROTO_DIS_N1);
471 }
472
473 static void
474 l3_1tr6_setup_rsp(struct l3_process *pc, u_char pr, void *arg)
475 {
476         struct sk_buff *skb;
477         u_char tmp[24];
478         u_char *p = tmp;
479         int l;
480
481         MsgHead(p, pc->callref, MT_N1_CONN, PROTO_DIS_N1);
482         if (pc->para.spv) {     /* SPV ? */
483                 /* NSF SPV */
484                 *p++ = WE0_netSpecFac;
485                 *p++ = 4;       /* Laenge */
486                 *p++ = 0;
487                 *p++ = FAC_SPV; /* SPV */
488                 *p++ = pc->para.setup.si1;
489                 *p++ = pc->para.setup.si2;
490                 *p++ = WE0_netSpecFac;
491                 *p++ = 4;       /* Laenge */
492                 *p++ = 0;
493                 *p++ = FAC_Activate;    /* aktiviere SPV */
494                 *p++ = pc->para.setup.si1;
495                 *p++ = pc->para.setup.si2;
496         }
497         newl3state(pc, 8);
498         l = p - tmp;
499         if (!(skb = l3_alloc_skb(l)))
500                 return;
501         skb_put_data(skb, tmp, l);
502         l3_msg(pc->st, DL_DATA | REQUEST, skb);
503         L3DelTimer(&pc->timer);
504         L3AddTimer(&pc->timer, T313, CC_T313);
505 }
506
507 static void
508 l3_1tr6_reset(struct l3_process *pc, u_char pr, void *arg)
509 {
510         release_l3_process(pc);
511 }
512
513 static void
514 l3_1tr6_disconnect_req(struct l3_process *pc, u_char pr, void *arg)
515 {
516         struct sk_buff *skb;
517         u_char tmp[16];
518         u_char *p = tmp;
519         int l;
520         u_char cause = 0x10;
521         u_char clen = 1;
522
523         if (pc->para.cause > 0)
524                 cause = pc->para.cause;
525         /* Map DSS1 causes */
526         switch (cause & 0x7f) {
527         case 0x10:
528                 clen = 0;
529                 break;
530         case 0x11:
531                 cause = CAUSE_UserBusy;
532                 break;
533         case 0x15:
534                 cause = CAUSE_CallRejected;
535                 break;
536         }
537         StopAllL3Timer(pc);
538         MsgHead(p, pc->callref, MT_N1_DISC, PROTO_DIS_N1);
539         *p++ = WE0_cause;
540         *p++ = clen;            /* Laenge */
541         if (clen)
542                 *p++ = cause | 0x80;
543         newl3state(pc, 11);
544         l = p - tmp;
545         if (!(skb = l3_alloc_skb(l)))
546                 return;
547         skb_put_data(skb, tmp, l);
548         l3_msg(pc->st, DL_DATA | REQUEST, skb);
549         L3AddTimer(&pc->timer, T305, CC_T305);
550 }
551
552 static void
553 l3_1tr6_t303(struct l3_process *pc, u_char pr, void *arg)
554 {
555         if (pc->N303 > 0) {
556                 pc->N303--;
557                 L3DelTimer(&pc->timer);
558                 l3_1tr6_setup_req(pc, pr, arg);
559         } else {
560                 L3DelTimer(&pc->timer);
561                 pc->para.cause = 0;
562                 l3_1tr6_disconnect_req(pc, 0, NULL);
563         }
564 }
565
566 static void
567 l3_1tr6_t304(struct l3_process *pc, u_char pr, void *arg)
568 {
569         L3DelTimer(&pc->timer);
570         pc->para.cause = 0xE6;
571         l3_1tr6_disconnect_req(pc, pr, NULL);
572         pc->st->l3.l3l4(pc->st, CC_SETUP_ERR, pc);
573 }
574
575 static void
576 l3_1tr6_t305(struct l3_process *pc, u_char pr, void *arg)
577 {
578         struct sk_buff *skb;
579         u_char tmp[16];
580         u_char *p = tmp;
581         int l;
582         u_char cause = 0x90;
583         u_char clen = 1;
584
585         L3DelTimer(&pc->timer);
586         if (pc->para.cause != NO_CAUSE)
587                 cause = pc->para.cause;
588         /* Map DSS1 causes */
589         switch (cause & 0x7f) {
590         case 0x10:
591                 clen = 0;
592                 break;
593         case 0x15:
594                 cause = CAUSE_CallRejected;
595                 break;
596         }
597         MsgHead(p, pc->callref, MT_N1_REL, PROTO_DIS_N1);
598         *p++ = WE0_cause;
599         *p++ = clen;            /* Laenge */
600         if (clen)
601                 *p++ = cause;
602         newl3state(pc, 19);
603         l = p - tmp;
604         if (!(skb = l3_alloc_skb(l)))
605                 return;
606         skb_put_data(skb, tmp, l);
607         l3_msg(pc->st, DL_DATA | REQUEST, skb);
608         L3AddTimer(&pc->timer, T308, CC_T308_1);
609 }
610
611 static void
612 l3_1tr6_t310(struct l3_process *pc, u_char pr, void *arg)
613 {
614         L3DelTimer(&pc->timer);
615         pc->para.cause = 0xE6;
616         l3_1tr6_disconnect_req(pc, pr, NULL);
617         pc->st->l3.l3l4(pc->st, CC_SETUP_ERR, pc);
618 }
619
620 static void
621 l3_1tr6_t313(struct l3_process *pc, u_char pr, void *arg)
622 {
623         L3DelTimer(&pc->timer);
624         pc->para.cause = 0xE6;
625         l3_1tr6_disconnect_req(pc, pr, NULL);
626         pc->st->l3.l3l4(pc->st, CC_CONNECT_ERR, pc);
627 }
628
629 static void
630 l3_1tr6_t308_1(struct l3_process *pc, u_char pr, void *arg)
631 {
632         L3DelTimer(&pc->timer);
633         l3_1TR6_message(pc, MT_N1_REL, PROTO_DIS_N1);
634         L3AddTimer(&pc->timer, T308, CC_T308_2);
635         newl3state(pc, 19);
636 }
637
638 static void
639 l3_1tr6_t308_2(struct l3_process *pc, u_char pr, void *arg)
640 {
641         L3DelTimer(&pc->timer);
642         pc->st->l3.l3l4(pc->st, CC_RELEASE_ERR, pc);
643         release_l3_process(pc);
644 }
645
646 static void
647 l3_1tr6_dl_reset(struct l3_process *pc, u_char pr, void *arg)
648 {
649         pc->para.cause = CAUSE_LocalProcErr;
650         l3_1tr6_disconnect_req(pc, pr, NULL);
651         pc->st->l3.l3l4(pc->st, CC_SETUP_ERR, pc);
652 }
653
654 static void
655 l3_1tr6_dl_release(struct l3_process *pc, u_char pr, void *arg)
656 {
657         newl3state(pc, 0);
658         pc->para.cause = 0x1b;          /* Destination out of order */
659         pc->para.loc = 0;
660         pc->st->l3.l3l4(pc->st, CC_RELEASE | INDICATION, pc);
661         release_l3_process(pc);
662 }
663
664 /* *INDENT-OFF* */
665 static struct stateentry downstl[] =
666 {
667         {SBIT(0),
668          CC_SETUP | REQUEST, l3_1tr6_setup_req},
669         {SBIT(1) | SBIT(2) | SBIT(3) | SBIT(4) | SBIT(6) | SBIT(7) | SBIT(8) |
670          SBIT(10),
671          CC_DISCONNECT | REQUEST, l3_1tr6_disconnect_req},
672         {SBIT(12),
673          CC_RELEASE | REQUEST, l3_1tr6_release_req},
674         {SBIT(6),
675          CC_IGNORE | REQUEST, l3_1tr6_reset},
676         {SBIT(6),
677          CC_REJECT | REQUEST, l3_1tr6_disconnect_req},
678         {SBIT(6),
679          CC_ALERTING | REQUEST, l3_1tr6_alert_req},
680         {SBIT(6) | SBIT(7),
681          CC_SETUP | RESPONSE, l3_1tr6_setup_rsp},
682         {SBIT(1),
683          CC_T303, l3_1tr6_t303},
684         {SBIT(2),
685          CC_T304, l3_1tr6_t304},
686         {SBIT(3),
687          CC_T310, l3_1tr6_t310},
688         {SBIT(8),
689          CC_T313, l3_1tr6_t313},
690         {SBIT(11),
691          CC_T305, l3_1tr6_t305},
692         {SBIT(19),
693          CC_T308_1, l3_1tr6_t308_1},
694         {SBIT(19),
695          CC_T308_2, l3_1tr6_t308_2},
696 };
697
698 static struct stateentry datastln1[] =
699 {
700         {SBIT(0),
701          MT_N1_INVALID, l3_1tr6_invalid},
702         {SBIT(0),
703          MT_N1_SETUP, l3_1tr6_setup},
704         {SBIT(1),
705          MT_N1_SETUP_ACK, l3_1tr6_setup_ack},
706         {SBIT(1) | SBIT(2),
707          MT_N1_CALL_SENT, l3_1tr6_call_sent},
708         {SBIT(1) | SBIT(2) | SBIT(3) | SBIT(4) | SBIT(7) | SBIT(8) | SBIT(10),
709          MT_N1_DISC, l3_1tr6_disc},
710         {SBIT(2) | SBIT(3) | SBIT(4),
711          MT_N1_ALERT, l3_1tr6_alert},
712         {SBIT(2) | SBIT(3) | SBIT(4),
713          MT_N1_CONN, l3_1tr6_connect},
714         {SBIT(2),
715          MT_N1_INFO, l3_1tr6_info_s2},
716         {SBIT(8),
717          MT_N1_CONN_ACK, l3_1tr6_connect_ack},
718         {SBIT(10),
719          MT_N1_INFO, l3_1tr6_info},
720         {SBIT(0) | SBIT(1) | SBIT(2) | SBIT(3) | SBIT(4) | SBIT(7) | SBIT(8) |
721          SBIT(10) | SBIT(11) | SBIT(12) | SBIT(15) | SBIT(17),
722          MT_N1_REL, l3_1tr6_rel},
723         {SBIT(19),
724          MT_N1_REL, l3_1tr6_rel_ack},
725         {SBIT(0) | SBIT(1) | SBIT(2) | SBIT(3) | SBIT(4) | SBIT(7) | SBIT(8) |
726          SBIT(10) | SBIT(11) | SBIT(12) | SBIT(15) | SBIT(17),
727          MT_N1_REL_ACK, l3_1tr6_invalid},
728         {SBIT(19),
729          MT_N1_REL_ACK, l3_1tr6_rel_ack}
730 };
731
732 static struct stateentry manstatelist[] =
733 {
734         {SBIT(2),
735          DL_ESTABLISH | INDICATION, l3_1tr6_dl_reset},
736         {ALL_STATES,
737          DL_RELEASE | INDICATION, l3_1tr6_dl_release},
738 };
739
740 /* *INDENT-ON* */
741
742 static void
743 up1tr6(struct PStack *st, int pr, void *arg)
744 {
745         int i, mt, cr;
746         struct l3_process *proc;
747         struct sk_buff *skb = arg;
748
749         switch (pr) {
750         case (DL_DATA | INDICATION):
751         case (DL_UNIT_DATA | INDICATION):
752                 break;
753         case (DL_ESTABLISH | CONFIRM):
754         case (DL_ESTABLISH | INDICATION):
755         case (DL_RELEASE | INDICATION):
756         case (DL_RELEASE | CONFIRM):
757                 l3_msg(st, pr, arg);
758                 return;
759                 break;
760         }
761         if (skb->len < 4) {
762                 if (st->l3.debug & L3_DEB_PROTERR) {
763                         l3_debug(st, "up1tr6 len only %d", skb->len);
764                 }
765                 dev_kfree_skb(skb);
766                 return;
767         }
768         if ((skb->data[0] & 0xfe) != PROTO_DIS_N0) {
769                 if (st->l3.debug & L3_DEB_PROTERR) {
770                         l3_debug(st, "up1tr6%sunexpected discriminator %x message len %d",
771                                 (pr == (DL_DATA | INDICATION)) ? " " : "(broadcast) ",
772                                 skb->data[0], skb->len);
773                 }
774                 dev_kfree_skb(skb);
775                 return;
776         }
777         if (skb->data[1] != 1) {
778                 if (st->l3.debug & L3_DEB_PROTERR) {
779                         l3_debug(st, "up1tr6 CR len not 1");
780                 }
781                 dev_kfree_skb(skb);
782                 return;
783         }
784         cr = skb->data[2];
785         mt = skb->data[3];
786         if (skb->data[0] == PROTO_DIS_N0) {
787                 dev_kfree_skb(skb);
788                 if (st->l3.debug & L3_DEB_STATE) {
789                         l3_debug(st, "up1tr6%s N0 mt %x unhandled",
790                                 (pr == (DL_DATA | INDICATION)) ? " " : "(broadcast) ", mt);
791                 }
792         } else if (skb->data[0] == PROTO_DIS_N1) {
793                 if (!(proc = getl3proc(st, cr))) {
794                         if (mt == MT_N1_SETUP) {
795                                 if (cr < 128) {
796                                         if (!(proc = new_l3_process(st, cr))) {
797                                                 if (st->l3.debug & L3_DEB_PROTERR) {
798                                                         l3_debug(st, "up1tr6 no roc mem");
799                                                 }
800                                                 dev_kfree_skb(skb);
801                                                 return;
802                                         }
803                                 } else {
804                                         dev_kfree_skb(skb);
805                                         return;
806                                 }
807                         } else if ((mt == MT_N1_REL) || (mt == MT_N1_REL_ACK) ||
808                                    (mt == MT_N1_CANC_ACK) || (mt == MT_N1_CANC_REJ) ||
809                                    (mt == MT_N1_REG_ACK) || (mt == MT_N1_REG_REJ) ||
810                                    (mt == MT_N1_SUSP_ACK) || (mt == MT_N1_RES_REJ) ||
811                                    (mt == MT_N1_INFO)) {
812                                 dev_kfree_skb(skb);
813                                 return;
814                         } else {
815                                 if (!(proc = new_l3_process(st, cr))) {
816                                         if (st->l3.debug & L3_DEB_PROTERR) {
817                                                 l3_debug(st, "up1tr6 no roc mem");
818                                         }
819                                         dev_kfree_skb(skb);
820                                         return;
821                                 }
822                                 mt = MT_N1_INVALID;
823                         }
824                 }
825                 for (i = 0; i < ARRAY_SIZE(datastln1); i++)
826                         if ((mt == datastln1[i].primitive) &&
827                             ((1 << proc->state) & datastln1[i].state))
828                                 break;
829                 if (i == ARRAY_SIZE(datastln1)) {
830                         dev_kfree_skb(skb);
831                         if (st->l3.debug & L3_DEB_STATE) {
832                                 l3_debug(st, "up1tr6%sstate %d mt %x unhandled",
833                                         (pr == (DL_DATA | INDICATION)) ? " " : "(broadcast) ",
834                                         proc->state, mt);
835                         }
836                         return;
837                 } else {
838                         if (st->l3.debug & L3_DEB_STATE) {
839                                 l3_debug(st, "up1tr6%sstate %d mt %x",
840                                         (pr == (DL_DATA | INDICATION)) ? " " : "(broadcast) ",
841                                         proc->state, mt);
842                         }
843                         datastln1[i].rout(proc, pr, skb);
844                 }
845         }
846 }
847
848 static void
849 down1tr6(struct PStack *st, int pr, void *arg)
850 {
851         int i, cr;
852         struct l3_process *proc;
853         struct Channel *chan;
854
855         if ((DL_ESTABLISH | REQUEST) == pr) {
856                 l3_msg(st, pr, NULL);
857                 return;
858         } else if ((CC_SETUP | REQUEST) == pr) {
859                 chan = arg;
860                 cr = newcallref();
861                 cr |= 0x80;
862                 if (!(proc = new_l3_process(st, cr))) {
863                         return;
864                 } else {
865                         proc->chan = chan;
866                         chan->proc = proc;
867                         memcpy(&proc->para.setup, &chan->setup, sizeof(setup_parm));
868                         proc->callref = cr;
869                 }
870         } else {
871                 proc = arg;
872         }
873
874         for (i = 0; i < ARRAY_SIZE(downstl); i++)
875                 if ((pr == downstl[i].primitive) &&
876                     ((1 << proc->state) & downstl[i].state))
877                         break;
878         if (i == ARRAY_SIZE(downstl)) {
879                 if (st->l3.debug & L3_DEB_STATE) {
880                         l3_debug(st, "down1tr6 state %d prim %d unhandled",
881                                 proc->state, pr);
882                 }
883         } else {
884                 if (st->l3.debug & L3_DEB_STATE) {
885                         l3_debug(st, "down1tr6 state %d prim %d",
886                                 proc->state, pr);
887                 }
888                 downstl[i].rout(proc, pr, arg);
889         }
890 }
891
892 static void
893 man1tr6(struct PStack *st, int pr, void *arg)
894 {
895         int i;
896         struct l3_process *proc = arg;
897
898         if (!proc) {
899                 printk(KERN_ERR "HiSax man1tr6 without proc pr=%04x\n", pr);
900                 return;
901         }
902         for (i = 0; i < ARRAY_SIZE(manstatelist); i++)
903                 if ((pr == manstatelist[i].primitive) &&
904                     ((1 << proc->state) & manstatelist[i].state))
905                         break;
906         if (i == ARRAY_SIZE(manstatelist)) {
907                 if (st->l3.debug & L3_DEB_STATE) {
908                         l3_debug(st, "cr %d man1tr6 state %d prim %d unhandled",
909                                  proc->callref & 0x7f, proc->state, pr);
910                 }
911         } else {
912                 if (st->l3.debug & L3_DEB_STATE) {
913                         l3_debug(st, "cr %d man1tr6 state %d prim %d",
914                                  proc->callref & 0x7f, proc->state, pr);
915                 }
916                 manstatelist[i].rout(proc, pr, arg);
917         }
918 }
919
920 void
921 setstack_1tr6(struct PStack *st)
922 {
923         char tmp[64];
924
925         st->lli.l4l3 = down1tr6;
926         st->l2.l2l3 = up1tr6;
927         st->l3.l3ml3 = man1tr6;
928         st->l3.N303 = 0;
929
930         strcpy(tmp, l3_1tr6_revision);
931         printk(KERN_INFO "HiSax: 1TR6 Rev. %s\n", HiSax_getrev(tmp));
932 }