OpenCores
URL https://opencores.org/ocsvn/or1k_old/or1k_old/trunk

Subversion Repositories or1k_old

[/] [or1k_old/] [trunk/] [uclinux/] [uClinux-2.0.x/] [drivers/] [isdn/] [hisax/] [l3dss1.c] - Blame information for rev 1782

Details | Compare with Previous | View Log

Line No. Rev Author Line
1 199 simons
/* $Id: l3dss1.c,v 1.1.1.1 2001-09-10 07:44:18 simons Exp $
2
 
3
 * EURO/DSS1 D-channel protocol
4
 *
5
 * Author       Karsten Keil (keil@temic-ech.spacenet.de)
6
 *              based on the teles driver from Jan den Ouden
7
 *
8
 *              This file is (c) under GNU PUBLIC LICENSE
9
 *              For changes and modifications please read
10
 *              ../../../Documentation/isdn/HiSax.cert
11
 *
12
 * Thanks to    Jan den Ouden
13
 *              Fritz Elfert
14
 *
15
 * $Log: not supported by cvs2svn $
16
 * Revision 1.1.1.1  2001/07/02 17:58:32  simons
17
 * Initial revision
18
 *
19
 * Revision 1.16.2.8  1998/11/03 00:07:14  keil
20
 * certification related changes
21
 * fixed logging for smaller stack use
22
 *
23
 * Revision 1.16.2.7  1998/10/25 18:16:25  fritz
24
 * Replaced some read-only variables by defines.
25
 *
26
 * Revision 1.16.2.6  1998/10/23 15:00:56  fritz
27
 * Eliminated a compiler warning.
28
 *
29
 * Revision 1.16.2.5  1998/09/27 13:06:48  keil
30
 * Apply most changes from 2.1.X (HiSax 3.1)
31
 *
32
 * Revision 1.16.2.4  1998/05/27 18:06:08  keil
33
 * HiSax 3.0
34
 *
35
 * Revision 1.16.2.3  1998/02/03 23:16:06  keil
36
 * german AOC
37
 *
38
 * Revision 1.16.2.2  1997/11/15 18:54:15  keil
39
 * cosmetics
40
 *
41
 * Revision 1.16.2.1  1997/10/17 22:14:16  keil
42
 * update to last hisax version
43
 *
44
 * Revision 2.2  1997/08/07 17:44:36  keil
45
 * Fix RESTART
46
 *
47
 * Revision 2.1  1997/08/03 14:36:33  keil
48
 * Implement RESTART procedure
49
 *
50
 * Revision 2.0  1997/07/27 21:15:43  keil
51
 * New Callref based layer3
52
 *
53
 * Revision 1.17  1997/06/26 11:11:46  keil
54
 * SET_SKBFREE now on creation of a SKB
55
 *
56
 * Revision 1.15  1997/04/17 11:50:48  keil
57
 * pa->loc was undefined, if it was not send by the exchange
58
 *
59
 * Old log removed /KKe
60
 *
61
 */
62
 
63
#define __NO_VERSION__
64
#include "hisax.h"
65
#include "isdnl3.h"
66
#include "l3dss1.h"
67
#include <linux/ctype.h>
68
 
69
extern char *HiSax_getrev(const char *revision);
70
const char *dss1_revision = "$Revision: 1.1.1.1 $";
71
 
72
#define EXT_BEARER_CAPS 1
73
 
74
#define MsgHead(ptr, cref, mty) \
75
        *ptr++ = 0x8; \
76
        *ptr++ = 0x1; \
77
        *ptr++ = cref^0x80; \
78
        *ptr++ = mty
79
 
80
 
81
#if HISAX_DE_AOC
82
static void
83
l3dss1_parse_facility(struct l3_process *pc, u_char * p)
84
{
85
        int qd_len = 0;
86
 
87
        p++;
88
        qd_len = *p++;
89
        if (qd_len == 0) {
90
                l3_debug(pc->st, "qd_len == 0");
91
                return;
92
        }
93
        if ((*p & 0x1F) != 0x11) {      /* Service discriminator, supplementary service */
94
                l3_debug(pc->st, "supplementary service != 0x11");
95
                return;
96
        }
97
        while (qd_len > 0 && !(*p & 0x80)) {     /* extension ? */
98
                p++;
99
                qd_len--;
100
        }
101
        if (qd_len < 2) {
102
                l3_debug(pc->st, "qd_len < 2");
103
                return;
104
        }
105
        p++;
106
        qd_len--;
107
        if ((*p & 0xE0) != 0xA0) {      /* class and form */
108
                l3_debug(pc->st, "class and form != 0xA0");
109
                return;
110
        }
111
        switch (*p & 0x1F) {    /* component tag */
112
                case 1: /* invoke */
113
                        {
114
                                unsigned char nlen = 0, ilen;
115
                                int ident;
116
 
117
                                p++;
118
                                qd_len--;
119
                                if (qd_len < 1) {
120
                                        l3_debug(pc->st, "qd_len < 1");
121
                                        break;
122
                                }
123
                                if (*p & 0x80) {        /* length format */
124
                                        l3_debug(pc->st, "*p & 0x80 length format");
125
                                        break;
126
                                }
127
                                nlen = *p++;
128
                                qd_len--;
129
                                if (qd_len < nlen) {
130
                                        l3_debug(pc->st, "qd_len < nlen");
131
                                        return;
132
                                }
133
                                qd_len -= nlen;
134
 
135
                                if (nlen < 2) {
136
                                        l3_debug(pc->st, "nlen < 2");
137
                                        return;
138
                                }
139
                                if (*p != 0x02) {       /* invoke identifier tag */
140
                                        l3_debug(pc->st, "invoke identifier tag !=0x02");
141
                                        return;
142
                                }
143
                                p++;
144
                                nlen--;
145
                                if (*p & 0x80) {        /* length format */
146
                                        l3_debug(pc->st, "*p & 0x80 length format 2");
147
                                        break;
148
                                }
149
                                ilen = *p++;
150
                                nlen--;
151
                                if (ilen > nlen || ilen == 0) {
152
                                        l3_debug(pc->st, "ilen > nlen || ilen == 0");
153
                                        return;
154
                                }
155
                                nlen -= ilen;
156
                                ident = 0;
157
                                while (ilen > 0) {
158
                                        ident = (ident << 8) | (*p++ & 0xFF);   /* invoke identifier */
159
                                        ilen--;
160
                                }
161
 
162
                                if (nlen < 2) {
163
                                        l3_debug(pc->st, "nlen < 2 22");
164
                                        return;
165
                                }
166
                                if (*p != 0x02) {       /* operation value */
167
                                        l3_debug(pc->st, "operation value !=0x02");
168
                                        return;
169
                                }
170
                                p++;
171
                                nlen--;
172
                                ilen = *p++;
173
                                nlen--;
174
                                if (ilen > nlen || ilen == 0) {
175
                                        l3_debug(pc->st, "ilen > nlen || ilen == 0 22");
176
                                        return;
177
                                }
178
                                nlen -= ilen;
179
                                ident = 0;
180
                                while (ilen > 0) {
181
                                        ident = (ident << 8) | (*p++ & 0xFF);
182
                                        ilen--;
183
                                }
184
 
185
#define FOO1(s,a,b) \
186
            while(nlen > 1) {           \
187
                    int ilen = p[1];    \
188
                    if(nlen < ilen+2) { \
189
                            l3_debug(pc->st, "FOO1  nlen < ilen+2"); \
190
                            return;             \
191
                    }                   \
192
                    nlen -= ilen+2;             \
193
                    if((*p & 0xFF) == (a)) {    \
194
                            int nlen = ilen;    \
195
                            p += 2;             \
196
                            b;          \
197
                    } else {            \
198
                            p += ilen+2;        \
199
                    }                   \
200
            }
201
 
202
                                switch (ident) {
203
                                        default:
204
                                                break;
205
                                        case 0x22:      /* during */
206
                                                FOO1("1A", 0x30, FOO1("1C", 0xA1, FOO1("1D", 0x30, FOO1("1E", 0x02, ( {
207
                                                               ident = 0;
208
                                                        nlen = (nlen)?nlen:0; /* Make gcc happy */
209
                                                        while (ilen > 0) {
210
                                                                                                                     ident = (ident << 8) | *p++;
211
                                                                  ilen--;
212
                                                                        }
213
                                                                                                                     if (ident > pc->para.chargeinfo) {
214
                                                                                                                     pc->para.chargeinfo = ident;
215
                                                                                                                     pc->st->l3.l3l4(pc->st, CC_CHARGE | INDICATION, pc);
216
                                                                        }
217
                                                                                                                     if (pc->st->l3.debug & L3_DEB_CHARGE) {
218
                                                                                                                     if (*(p + 2) == 0) {
219
                                                                                                                     l3_debug(pc->st, "charging info during %d", pc->para.chargeinfo);
220
                                                                        }
221
                                                                   else {
222
                                                                                                                     l3_debug(pc->st, "charging info final %d", pc->para.chargeinfo);
223
                                                                        }
224
                                                                        }
225
                                                                        }
226
                                                                    )))))
227
                                                        break;
228
                                        case 0x24:      /* final */
229
                                                FOO1("2A", 0x30, FOO1("2B", 0x30, FOO1("2C", 0xA1, FOO1("2D", 0x30, FOO1("2E", 0x02, ( {
230
                                                               ident = 0;
231
                                                        nlen = (nlen)?nlen:0; /* Make gcc happy */
232
                                                        while (ilen > 0) {
233
                                                                                                                                      ident = (ident << 8) | *p++;
234
                                                                  ilen--;
235
                                                                        }
236
                                                                                                                                      if (ident > pc->para.chargeinfo) {
237
                                                                                                                                      pc->para.chargeinfo = ident;
238
                                                                                                                                      pc->st->l3.l3l4(pc->st, CC_CHARGE | INDICATION, pc);
239
                                                                        }
240
                                                                                                                                      if (pc->st->l3.debug & L3_DEB_CHARGE) {
241
                                                                                                                                      l3_debug(pc->st, "charging info final %d", pc->para.chargeinfo);
242
                                                                        }
243
                                                                        }
244
                                                                   ))))))
245
                                                        break;
246
                                }
247
#undef FOO1
248
 
249
                        }
250
                        break;
251
                case 2: /* return result */
252
                        l3_debug(pc->st, "return result break");
253
                        break;
254
                case 3: /* return error */
255
                        l3_debug(pc->st, "return error break");
256
                        break;
257
                default:
258
                        l3_debug(pc->st, "default break");
259
                        break;
260
        }
261
}
262
#endif
263
 
264
static int
265
l3dss1_check_messagetype_validity(int mt)
266
{
267
/* verify if a message type exists */
268
        switch (mt) {
269
                case MT_ALERTING:
270
                case MT_CALL_PROCEEDING:
271
                case MT_CONNECT:
272
                case MT_CONNECT_ACKNOWLEDGE:
273
                case MT_PROGRESS:
274
                case MT_SETUP:
275
                case MT_SETUP_ACKNOWLEDGE:
276
                case MT_RESUME:
277
                case MT_RESUME_ACKNOWLEDGE:
278
                case MT_RESUME_REJECT:
279
                case MT_SUSPEND:
280
                case MT_SUSPEND_ACKNOWLEDGE:
281
                case MT_SUSPEND_REJECT:
282
                case MT_USER_INFORMATION:
283
                case MT_DISCONNECT:
284
                case MT_RELEASE:
285
                case MT_RELEASE_COMPLETE:
286
                case MT_RESTART:
287
                case MT_RESTART_ACKNOWLEDGE:
288
                case MT_SEGMENT:
289
                case MT_CONGESTION_CONTROL:
290
                case MT_INFORMATION:
291
                case MT_FACILITY:
292
                case MT_NOTIFY:
293
                case MT_STATUS:
294
                case MT_STATUS_ENQUIRY:
295
                        return(1);
296
                default:
297
                        return(0);
298
        }
299
        return(0);
300
}
301
 
302
static void
303
l3dss1_message(struct l3_process *pc, u_char mt)
304
{
305
        struct sk_buff *skb;
306
        u_char *p;
307
 
308
        if (!(skb = l3_alloc_skb(4)))
309
                return;
310
        p = skb_put(skb, 4);
311
        MsgHead(p, pc->callref, mt);
312
        l3_msg(pc->st, DL_DATA | REQUEST, skb);
313
}
314
 
315
static void
316
l3dss1_release_req(struct l3_process *pc, u_char pr, void *arg)
317
{
318
        StopAllL3Timer(pc);
319
        newl3state(pc, 19);
320
        l3dss1_message(pc, MT_RELEASE);
321
        L3AddTimer(&pc->timer, T308, CC_T308_1);
322
}
323
 
324
static void
325
l3dss1_release_cmpl(struct l3_process *pc, u_char pr, void *arg)
326
{
327
        u_char *p;
328
        struct sk_buff *skb = arg;
329
        int cause = -1;
330
 
331
        p = skb->data;
332
        pc->para.loc = 0;
333
        if ((p = findie(p, skb->len, IE_CAUSE, 0))) {
334
                p++;
335
                if (*p++ == 2)
336
                        pc->para.loc = *p++;
337
                cause = *p & 0x7f;
338
        }
339
        dev_kfree_skb(skb, FREE_READ);
340
        StopAllL3Timer(pc);
341
        pc->para.cause = cause;
342
        newl3state(pc, 0);
343
        pc->st->l3.l3l4(pc->st, CC_RELEASE | CONFIRM, pc);
344
        release_l3_process(pc);
345
}
346
 
347
#if EXT_BEARER_CAPS
348
 
349
u_char *
350
EncodeASyncParams(u_char * p, u_char si2)
351
{                               // 7c 06 88  90 21 42 00 bb
352
 
353
        p[0] = p[1] = 0;
354
        p[2] = 0x80;
355
        if (si2 & 32)           // 7 data bits
356
 
357
                p[2] += 16;
358
        else                    // 8 data bits
359
 
360
                p[2] += 24;
361
 
362
        if (si2 & 16)           // 2 stop bits
363
 
364
                p[2] += 96;
365
        else                    // 1 stop bit
366
 
367
                p[2] = 32;
368
 
369
        if (si2 & 8)            // even parity
370
 
371
                p[2] += 2;
372
        else                    // no parity
373
 
374
                p[2] += 3;
375
 
376
        switch (si2 & 0x07) {
377
                case 0:
378
                        p[0] = 66;       // 1200 bit/s
379
 
380
                        break;
381
                case 1:
382
                        p[0] = 88;       // 1200/75 bit/s
383
 
384
                        break;
385
                case 2:
386
                        p[0] = 87;       // 75/1200 bit/s
387
 
388
                        break;
389
                case 3:
390
                        p[0] = 67;       // 2400 bit/s
391
 
392
                        break;
393
                case 4:
394
                        p[0] = 69;       // 4800 bit/s
395
 
396
                        break;
397
                case 5:
398
                        p[0] = 72;       // 9600 bit/s
399
 
400
                        break;
401
                case 6:
402
                        p[0] = 73;       // 14400 bit/s
403
 
404
                        break;
405
                case 7:
406
                        p[0] = 75;       // 19200 bit/s
407
 
408
                        break;
409
        }
410
        return p + 3;
411
}
412
 
413
u_char
414
EncodeSyncParams(u_char si2, u_char ai)
415
{
416
 
417
        switch (si2) {
418
                case 0:
419
                        return ai + 2;  // 1200 bit/s
420
 
421
                case 1:
422
                        return ai + 24;         // 1200/75 bit/s
423
 
424
                case 2:
425
                        return ai + 23;         // 75/1200 bit/s
426
 
427
                case 3:
428
                        return ai + 3;  // 2400 bit/s
429
 
430
                case 4:
431
                        return ai + 5;  // 4800 bit/s
432
 
433
                case 5:
434
                        return ai + 8;  // 9600 bit/s
435
 
436
                case 6:
437
                        return ai + 9;  // 14400 bit/s
438
 
439
                case 7:
440
                        return ai + 11;         // 19200 bit/s
441
 
442
                case 8:
443
                        return ai + 14;         // 48000 bit/s
444
 
445
                case 9:
446
                        return ai + 15;         // 56000 bit/s
447
 
448
                case 15:
449
                        return ai + 40;         // negotiate bit/s
450
 
451
                default:
452
                        break;
453
        }
454
        return ai;
455
}
456
 
457
 
458
static u_char
459
DecodeASyncParams(u_char si2, u_char * p)
460
{
461
        u_char info;
462
 
463
        switch (p[5]) {
464
                case 66:        // 1200 bit/s
465
 
466
                        break;  // si2 don't change
467
 
468
                case 88:        // 1200/75 bit/s
469
 
470
                        si2 += 1;
471
                        break;
472
                case 87:        // 75/1200 bit/s
473
 
474
                        si2 += 2;
475
                        break;
476
                case 67:        // 2400 bit/s
477
 
478
                        si2 += 3;
479
                        break;
480
                case 69:        // 4800 bit/s
481
 
482
                        si2 += 4;
483
                        break;
484
                case 72:        // 9600 bit/s
485
 
486
                        si2 += 5;
487
                        break;
488
                case 73:        // 14400 bit/s
489
 
490
                        si2 += 6;
491
                        break;
492
                case 75:        // 19200 bit/s
493
 
494
                        si2 += 7;
495
                        break;
496
        }
497
 
498
        info = p[7] & 0x7f;
499
        if ((info & 16) && (!(info & 8)))       // 7 data bits
500
 
501
                si2 += 32;      // else 8 data bits
502
 
503
        if ((info & 96) == 96)  // 2 stop bits
504
 
505
                si2 += 16;      // else 1 stop bit
506
 
507
        if ((info & 2) && (!(info & 1)))        // even parity
508
 
509
                si2 += 8;       // else no parity
510
 
511
        return si2;
512
}
513
 
514
 
515
static u_char
516
DecodeSyncParams(u_char si2, u_char info)
517
{
518
        info &= 0x7f;
519
        switch (info) {
520
                case 40:        // bit/s negotiation failed  ai := 165 not 175!
521
 
522
                        return si2 + 15;
523
                case 15:        // 56000 bit/s failed, ai := 0 not 169 !
524
 
525
                        return si2 + 9;
526
                case 14:        // 48000 bit/s
527
 
528
                        return si2 + 8;
529
                case 11:        // 19200 bit/s
530
 
531
                        return si2 + 7;
532
                case 9: // 14400 bit/s
533
 
534
                        return si2 + 6;
535
                case 8: // 9600  bit/s
536
 
537
                        return si2 + 5;
538
                case 5: // 4800  bit/s
539
 
540
                        return si2 + 4;
541
                case 3: // 2400  bit/s
542
 
543
                        return si2 + 3;
544
                case 23:        // 75/1200 bit/s
545
 
546
                        return si2 + 2;
547
                case 24:        // 1200/75 bit/s
548
 
549
                        return si2 + 1;
550
                default:        // 1200 bit/s
551
 
552
                        return si2;
553
        }
554
}
555
 
556
static u_char
557
DecodeSI2(struct sk_buff *skb)
558
{
559
        u_char *p;              //, *pend=skb->data + skb->len;
560
 
561
        if ((p = findie(skb->data, skb->len, 0x7c, 0))) {
562
                switch (p[4] & 0x0f) {
563
                        case 0x01:
564
                                if (p[1] == 0x04)       // sync. Bitratenadaption
565
 
566
                                        return DecodeSyncParams(160, p[5]);     // V.110/X.30
567
 
568
                                else if (p[1] == 0x06)  // async. Bitratenadaption
569
 
570
                                        return DecodeASyncParams(192, p);       // V.110/X.30
571
 
572
                                break;
573
                        case 0x08:      // if (p[5] == 0x02) // sync. Bitratenadaption
574
 
575
                                return DecodeSyncParams(176, p[5]);     // V.120
576
 
577
                                break;
578
                }
579
        }
580
        return 0;
581
}
582
 
583
#endif
584
 
585
 
586
static void
587
l3dss1_setup_req(struct l3_process *pc, u_char pr,
588
                 void *arg)
589
{
590
        struct sk_buff *skb;
591
        u_char tmp[128];
592
        u_char *p = tmp;
593
        u_char channel = 0;
594
        u_char screen = 0x80;
595
        u_char *teln;
596
        u_char *msn;
597
        u_char *sub;
598
        u_char *sp;
599
        int l;
600
 
601
        MsgHead(p, pc->callref, MT_SETUP);
602
 
603
        /*
604
         * Set Bearer Capability, Map info from 1TR6-convention to EDSS1
605
         */
606
#if HISAX_EURO_SENDCOMPLETE
607
        *p++ = 0xa1;            /* complete indicator */
608
#endif
609
        switch (pc->para.setup.si1) {
610
                case 1: /* Telephony                               */
611
                        *p++ = 0x4;     /* BC-IE-code                              */
612
                        *p++ = 0x3;     /* Length                                  */
613
                        *p++ = 0x90;    /* Coding Std. CCITT, 3.1 kHz audio     */
614
                        *p++ = 0x90;    /* Circuit-Mode 64kbps                     */
615
                        *p++ = 0xa3;    /* A-Law Audio                             */
616
                        break;
617
                case 5: /* Datatransmission 64k, BTX               */
618
                case 7: /* Datatransmission 64k                    */
619
                default:
620
                        *p++ = 0x4;     /* BC-IE-code                              */
621
                        *p++ = 0x2;     /* Length                                  */
622
                        *p++ = 0x88;    /* Coding Std. CCITT, unrestr. dig. Inform. */
623
                        *p++ = 0x90;    /* Circuit-Mode 64kbps                      */
624
                        break;
625
        }
626
        /*
627
         * What about info2? Mapping to High-Layer-Compatibility?
628
         */
629
        teln = pc->para.setup.phone;
630
        if (*teln) {
631
                /* parse number for special things */
632
                if (!isdigit(*teln)) {
633
                        switch (0x5f & *teln) {
634
                                case 'C':
635
                                        channel = 0x08;
636
                                case 'P':
637
                                        channel |= 0x80;
638
                                        teln++;
639
                                        if (*teln == '1')
640
                                                channel |= 0x01;
641
                                        else
642
                                                channel |= 0x02;
643
                                        break;
644
                                case 'R':
645
                                        screen = 0xA0;
646
                                        break;
647
                                case 'D':
648
                                        screen = 0x80;
649
                                        break;
650
                                default:
651
                                        if (pc->debug & L3_DEB_WARN)
652
                                                l3_debug(pc->st, "Wrong MSN Code");
653
                                        break;
654
                        }
655
                        teln++;
656
                }
657
        }
658
        if (channel) {
659
                *p++ = IE_CHANNEL_ID;
660
                *p++ = 1;
661
                *p++ = channel;
662
        }
663
        msn = pc->para.setup.eazmsn;
664
        sub = NULL;
665
        sp = msn;
666
        while (*sp) {
667
                if ('.' == *sp) {
668
                        sub = sp;
669
                        *sp = 0;
670
                } else
671
                        sp++;
672
        }
673
        if (*msn) {
674
                *p++ = 0x6c;
675
                *p++ = strlen(msn) + (screen ? 2 : 1);
676
                /* Classify as AnyPref. */
677
                if (screen) {
678
                        *p++ = 0x01;    /* Ext = '0'B, Type = '000'B, Plan = '0001'B. */
679
                        *p++ = screen;
680
                } else
681
                        *p++ = 0x81;    /* Ext = '1'B, Type = '000'B, Plan = '0001'B. */
682
                while (*msn)
683
                        *p++ = *msn++ & 0x7f;
684
        }
685
        if (sub) {
686
                *sub++ = '.';
687
                *p++ = 0x6d;    /* Calling party subaddress */
688
                *p++ = strlen(sub) + 2;
689
                *p++ = 0x80;    /* NSAP coded */
690
                *p++ = 0x50;    /* local IDI format */
691
                while (*sub)
692
                        *p++ = *sub++ & 0x7f;
693
        }
694
        sub = NULL;
695
        sp = teln;
696
        while (*sp) {
697
                if ('.' == *sp) {
698
                        sub = sp;
699
                        *sp = 0;
700
                } else
701
                        sp++;
702
        }
703
        *p++ = 0x70;
704
        *p++ = strlen(teln) + 1;
705
        /* Classify as AnyPref. */
706
        *p++ = 0x81;            /* Ext = '1'B, Type = '000'B, Plan = '0001'B. */
707
        while (*teln)
708
                *p++ = *teln++ & 0x7f;
709
 
710
        if (sub) {
711
                *sub++ = '.';
712
                *p++ = 0x71;    /* Called party subaddress */
713
                *p++ = strlen(sub) + 2;
714
                *p++ = 0x80;    /* NSAP coded */
715
                *p++ = 0x50;    /* local IDI format */
716
                while (*sub)
717
                        *p++ = *sub++ & 0x7f;
718
        }
719
#if EXT_BEARER_CAPS
720
        if ((pc->para.setup.si2 >= 160) && (pc->para.setup.si2 <= 175)) {       // sync. Bitratenadaption, V.110/X.30
721
 
722
                *p++ = 0x7c;
723
                *p++ = 0x04;
724
                *p++ = 0x88;
725
                *p++ = 0x90;
726
                *p++ = 0x21;
727
                *p++ = EncodeSyncParams(pc->para.setup.si2 - 160, 0x80);
728
        } else if ((pc->para.setup.si2 >= 176) && (pc->para.setup.si2 <= 191)) {        // sync. Bitratenadaption, V.120
729
 
730
                *p++ = 0x7c;
731
                *p++ = 0x05;
732
                *p++ = 0x88;
733
                *p++ = 0x90;
734
                *p++ = 0x28;
735
                *p++ = EncodeSyncParams(pc->para.setup.si2 - 176, 0);
736
                *p++ = 0x82;
737
        } else if (pc->para.setup.si2 >= 192) {         // async. Bitratenadaption, V.110/X.30
738
 
739
                *p++ = 0x7c;
740
                *p++ = 0x06;
741
                *p++ = 0x88;
742
                *p++ = 0x90;
743
                *p++ = 0x21;
744
                p = EncodeASyncParams(p, pc->para.setup.si2 - 192);
745
#if HISAX_SEND_STD_LLC_IE
746
        } else {
747
                *p++ = 0x7c;
748
                *p++ = 0x02;
749
                *p++ = 0x88;
750
                *p++ = 0x90;
751
#endif
752
        }
753
#endif
754
        l = p - tmp;
755
        if (!(skb = l3_alloc_skb(l)))
756
                return;
757
        memcpy(skb_put(skb, l), tmp, l);
758
        L3DelTimer(&pc->timer);
759
        L3AddTimer(&pc->timer, T303, CC_T303);
760
        newl3state(pc, 1);
761
        l3_msg(pc->st, DL_DATA | REQUEST, skb);
762
}
763
 
764
static void
765
l3dss1_call_proc(struct l3_process *pc, u_char pr, void *arg)
766
{
767
        u_char *p;
768
        struct sk_buff *skb = arg;
769
 
770
        L3DelTimer(&pc->timer);
771
        p = skb->data;
772
        if ((p = findie(p, skb->len, IE_CHANNEL_ID, 0))) {
773
                pc->para.bchannel = p[2] & 0x3;
774
                if ((!pc->para.bchannel) && (pc->debug & L3_DEB_WARN))
775
                        l3_debug(pc->st, "setup answer without bchannel");
776
        } else if (pc->debug & L3_DEB_WARN)
777
                l3_debug(pc->st, "setup answer without bchannel");
778
        dev_kfree_skb(skb, FREE_READ);
779
        newl3state(pc, 3);
780
        L3AddTimer(&pc->timer, T310, CC_T310);
781
        pc->st->l3.l3l4(pc->st, CC_PROCEEDING | INDICATION, pc);
782
}
783
 
784
static void
785
l3dss1_setup_ack(struct l3_process *pc, u_char pr, void *arg)
786
{
787
        u_char *p;
788
        struct sk_buff *skb = arg;
789
 
790
        L3DelTimer(&pc->timer);
791
        p = skb->data;
792
        if ((p = findie(p, skb->len, IE_CHANNEL_ID, 0))) {
793
                pc->para.bchannel = p[2] & 0x3;
794
                if ((!pc->para.bchannel) && (pc->debug & L3_DEB_WARN))
795
                        l3_debug(pc->st, "setup answer without bchannel");
796
        } else if (pc->debug & L3_DEB_WARN)
797
                l3_debug(pc->st, "setup answer without bchannel");
798
        dev_kfree_skb(skb, FREE_READ);
799
        newl3state(pc, 2);
800
        L3AddTimer(&pc->timer, T304, CC_T304);
801
        pc->st->l3.l3l4(pc->st, CC_MORE_INFO | INDICATION, pc);
802
}
803
 
804
static void
805
l3dss1_disconnect(struct l3_process *pc, u_char pr, void *arg)
806
{
807
        u_char *p;
808
        struct sk_buff *skb = arg;
809
        int cause = -1;
810
 
811
        StopAllL3Timer(pc);
812
        p = skb->data;
813
        pc->para.loc = 0;
814
        if ((p = findie(p, skb->len, IE_CAUSE, 0))) {
815
                p++;
816
                if (*p++ == 2)
817
                        pc->para.loc = *p++;
818
                cause = *p & 0x7f;
819
        }
820
        dev_kfree_skb(skb, FREE_READ);
821
        newl3state(pc, 12);
822
        pc->para.cause = cause;
823
        pc->st->l3.l3l4(pc->st, CC_DISCONNECT | INDICATION, pc);
824
}
825
 
826
static void
827
l3dss1_connect(struct l3_process *pc, u_char pr, void *arg)
828
{
829
        struct sk_buff *skb = arg;
830
 
831
        dev_kfree_skb(skb, FREE_READ);
832
        L3DelTimer(&pc->timer); /* T310 */
833
        newl3state(pc, 10);
834
        pc->para.chargeinfo = 0;
835
        pc->st->l3.l3l4(pc->st, CC_SETUP | CONFIRM, pc);
836
}
837
 
838
static void
839
l3dss1_alerting(struct l3_process *pc, u_char pr, void *arg)
840
{
841
        struct sk_buff *skb = arg;
842
 
843
        dev_kfree_skb(skb, FREE_READ);
844
        L3DelTimer(&pc->timer); /* T304 */
845
        newl3state(pc, 4);
846
        pc->st->l3.l3l4(pc->st, CC_ALERTING | INDICATION, pc);
847
}
848
 
849
static void
850
l3dss1_msg_without_setup(struct l3_process *pc, u_char pr, void *arg)
851
{
852
        /* This routine is called if here was no SETUP made (checks in dss1up and in
853
         * l3dss1_setup) and a RELEASE_COMPLETE have to be sent with an error code
854
         * MT_STATUS_ENQUIRE in the NULL state is handled too
855
         */
856
        u_char tmp[16];
857
        u_char *p = tmp;
858
        int l;
859
        struct sk_buff *skb;
860
 
861
        switch (pc->para.cause) {
862
                case 81:        /* 0x51 invalid callreference */
863
                case 88:        /* 0x58 incomp destination */
864
                case 96:        /* 0x60 mandory IE missing */
865
                case 101:       /* 0x65 incompatible Callstate */
866
                        MsgHead(p, pc->callref, MT_RELEASE_COMPLETE);
867
                        *p++ = IE_CAUSE;
868
                        *p++ = 0x2;
869
                        *p++ = 0x80;
870
                        *p++ = pc->para.cause | 0x80;
871
                        break;
872
                default:
873
                        printk(KERN_ERR "HiSax internal error l3dss1_msg_without_setup\n");
874
                        return;
875
        }
876
        l = p - tmp;
877
        if (!(skb = l3_alloc_skb(l)))
878
                return;
879
        memcpy(skb_put(skb, l), tmp, l);
880
        l3_msg(pc->st, DL_DATA | REQUEST, skb);
881
        release_l3_process(pc);
882
}
883
 
884
static void
885
l3dss1_setup(struct l3_process *pc, u_char pr, void *arg)
886
{
887
        u_char *p, *ptmp[8];
888
        int i;
889
        int bcfound = 0;
890
        char tmp[80];
891
        struct sk_buff *skb = arg;
892
 
893
        /* ETS 300-104 1.3.4 and 1.3.5
894
         * we need to detect unknown inform. element from 0 to 7
895
         */
896
        p = skb->data;
897
        for (i = 0; i < 8; i++)
898
                ptmp[i] = skb->data;
899
        if (findie(ptmp[1], skb->len, 0x01, 0)
900
            || findie(ptmp[2], skb->len, 0x02, 0)
901
            || findie(ptmp[3], skb->len, 0x03, 0)
902
            || findie(ptmp[5], skb->len, 0x05, 0)
903
            || findie(ptmp[6], skb->len, 0x06, 0)
904
            || findie(ptmp[7], skb->len, 0x07, 0)) {
905
                /* if ie is < 8 and not 0 nor 4, send RELEASE_COMPLETE
906
                 * cause 0x60
907
                 */
908
                pc->para.cause = 0x60;
909
                dev_kfree_skb(skb, FREE_READ);
910
                l3dss1_msg_without_setup(pc, pr, NULL);
911
                return;
912
        }
913
        /*
914
         * Channel Identification
915
         */
916
        p = skb->data;
917
        if ((p = findie(p, skb->len, IE_CHANNEL_ID, 0))) {
918
                pc->para.bchannel = p[2] & 0x3;
919
                if (pc->para.bchannel)
920
                        bcfound++;
921
                else if (pc->debug & L3_DEB_WARN)
922
                        l3_debug(pc->st, "setup without bchannel");
923
        } else {
924
                if (pc->debug & L3_DEB_WARN)
925
                        l3_debug(pc->st, "setup without bchannel");
926
                pc->para.cause = 0x60;
927
                dev_kfree_skb(skb, FREE_READ);
928
                l3dss1_msg_without_setup(pc, pr, NULL);
929
                return;
930
        }
931
        /*
932
           * Bearer Capabilities
933
         */
934
        p = skb->data;
935
        if ((p = findie(p, skb->len, 0x04, 0))) {
936
                pc->para.setup.si2 = 0;
937
                switch (p[2] & 0x1f) {
938
                        case 0x00:
939
                                /* Speech */
940
                        case 0x10:
941
                                /* 3.1 Khz audio */
942
                                pc->para.setup.si1 = 1;
943
                                break;
944
                        case 0x08:
945
                                /* Unrestricted digital information */
946
                                pc->para.setup.si1 = 7;
947
/* JIM, 05.11.97 I wanna set service indicator 2 */
948
#if EXT_BEARER_CAPS
949
                                pc->para.setup.si2 = DecodeSI2(skb);
950
                                printk(KERN_DEBUG "HiSax: SI=%d, AI=%d\n",
951
                                 pc->para.setup.si1, pc->para.setup.si2);
952
#endif
953
                                break;
954
                        case 0x09:
955
                                /* Restricted digital information */
956
                                pc->para.setup.si1 = 2;
957
                                break;
958
                        case 0x11:
959
                                /* Unrestr. digital information  with tones/announcements */
960
                                pc->para.setup.si1 = 3;
961
                                break;
962
                        case 0x18:
963
                                /* Video */
964
                                pc->para.setup.si1 = 4;
965
                                break;
966
                        default:
967
                                pc->para.setup.si1 = 0;
968
                }
969
        } else {
970
                if (pc->debug & L3_DEB_WARN)
971
                        l3_debug(pc->st, "setup without bearer capabilities");
972
                /* ETS 300-104 1.3.3 */
973
                pc->para.cause = 0x60;
974
                dev_kfree_skb(skb, FREE_READ);
975
                l3dss1_msg_without_setup(pc, pr, NULL);
976
                return;
977
        }
978
 
979
        p = skb->data;
980
        if ((p = findie(p, skb->len, 0x70, 0)))
981
                iecpy(pc->para.setup.eazmsn, p, 1);
982
        else
983
                pc->para.setup.eazmsn[0] = 0;
984
 
985
        p = skb->data;
986
        if ((p = findie(p, skb->len, 0x71, 0))) {
987
                /* Called party subaddress */
988
                if ((p[1] >= 2) && (p[2] == 0x80) && (p[3] == 0x50)) {
989
                        tmp[0] = '.';
990
                        iecpy(&tmp[1], p, 2);
991
                        strcat(pc->para.setup.eazmsn, tmp);
992
                } else if (pc->debug & L3_DEB_WARN)
993
                        l3_debug(pc->st, "wrong called subaddress");
994
        }
995
        p = skb->data;
996
        if ((p = findie(p, skb->len, 0x6c, 0))) {
997
                pc->para.setup.plan = p[2];
998
                if (p[2] & 0x80) {
999
                        iecpy(pc->para.setup.phone, p, 1);
1000
                        pc->para.setup.screen = 0;
1001
                } else {
1002
                        iecpy(pc->para.setup.phone, p, 2);
1003
                        pc->para.setup.screen = p[3];
1004
                }
1005
        } else {
1006
                pc->para.setup.phone[0] = 0;
1007
                pc->para.setup.plan = 0;
1008
                pc->para.setup.screen = 0;
1009
        }
1010
        p = skb->data;
1011
        if ((p = findie(p, skb->len, 0x6d, 0))) {
1012
                /* Calling party subaddress */
1013
                if ((p[1] >= 2) && (p[2] == 0x80) && (p[3] == 0x50)) {
1014
                        tmp[0] = '.';
1015
                        iecpy(&tmp[1], p, 2);
1016
                        strcat(pc->para.setup.phone, tmp);
1017
                } else if (pc->debug & L3_DEB_WARN)
1018
                        l3_debug(pc->st, "wrong calling subaddress");
1019
        }
1020
        dev_kfree_skb(skb, FREE_READ);
1021
 
1022
        if (bcfound) {
1023
                if ((pc->para.setup.si1 != 7) && (pc->debug & L3_DEB_WARN)) {
1024
                        l3_debug(pc->st, "non-digital call: %s -> %s",
1025
                            pc->para.setup.phone, pc->para.setup.eazmsn);
1026
                }
1027
                if ((pc->para.setup.si1 != 7) &&
1028
                    test_bit(FLG_PTP, &pc->st->l2.flag)) {
1029
                        pc->para.cause = 0x58;
1030
                        l3dss1_msg_without_setup(pc, pr, NULL);
1031
                        return;
1032
                }
1033
                newl3state(pc, 6);
1034
                pc->st->l3.l3l4(pc->st, CC_SETUP | INDICATION, pc);
1035
        } else
1036
                release_l3_process(pc);
1037
}
1038
 
1039
static void
1040
l3dss1_reset(struct l3_process *pc, u_char pr, void *arg)
1041
{
1042
        release_l3_process(pc);
1043
}
1044
 
1045
static void
1046
l3dss1_setup_rsp(struct l3_process *pc, u_char pr,
1047
                 void *arg)
1048
{
1049
        newl3state(pc, 8);
1050
        l3dss1_message(pc, MT_CONNECT);
1051
        L3DelTimer(&pc->timer);
1052
        L3AddTimer(&pc->timer, T313, CC_T313);
1053
}
1054
 
1055
static void
1056
l3dss1_connect_ack(struct l3_process *pc, u_char pr, void *arg)
1057
{
1058
        struct sk_buff *skb = arg;
1059
 
1060
        dev_kfree_skb(skb, FREE_READ);
1061
        newl3state(pc, 10);
1062
        L3DelTimer(&pc->timer);
1063
        pc->st->l3.l3l4(pc->st, CC_SETUP_COMPL | INDICATION, pc);
1064
}
1065
 
1066
static void
1067
l3dss1_disconnect_req(struct l3_process *pc, u_char pr, void *arg)
1068
{
1069
        struct sk_buff *skb;
1070
        u_char tmp[16];
1071
        u_char *p = tmp;
1072
        int l;
1073
        u_char cause = 0x10;
1074
 
1075
        if (pc->para.cause > 0)
1076
                cause = pc->para.cause;
1077
 
1078
        StopAllL3Timer(pc);
1079
 
1080
        MsgHead(p, pc->callref, MT_DISCONNECT);
1081
 
1082
        *p++ = IE_CAUSE;
1083
        *p++ = 0x2;
1084
        *p++ = 0x80;
1085
        *p++ = cause | 0x80;
1086
 
1087
        l = p - tmp;
1088
        if (!(skb = l3_alloc_skb(l)))
1089
                return;
1090
        memcpy(skb_put(skb, l), tmp, l);
1091
        newl3state(pc, 11);
1092
        l3_msg(pc->st, DL_DATA | REQUEST, skb);
1093
        L3AddTimer(&pc->timer, T305, CC_T305);
1094
}
1095
 
1096
static void
1097
l3dss1_reject_req(struct l3_process *pc, u_char pr, void *arg)
1098
{
1099
        struct sk_buff *skb;
1100
        u_char tmp[16];
1101
        u_char *p = tmp;
1102
        int l;
1103
        u_char cause = 0x95;
1104
 
1105
        if (pc->para.cause > 0)
1106
                cause = pc->para.cause;
1107
 
1108
        MsgHead(p, pc->callref, MT_RELEASE_COMPLETE);
1109
 
1110
        *p++ = IE_CAUSE;
1111
        *p++ = 0x2;
1112
        *p++ = 0x80;
1113
        *p++ = cause;
1114
 
1115
        l = p - tmp;
1116
        if (!(skb = l3_alloc_skb(l)))
1117
                return;
1118
        memcpy(skb_put(skb, l), tmp, l);
1119
        l3_msg(pc->st, DL_DATA | REQUEST, skb);
1120
        pc->st->l3.l3l4(pc->st, CC_RELEASE | INDICATION, pc);
1121
        newl3state(pc, 0);
1122
        release_l3_process(pc);
1123
}
1124
 
1125
static void
1126
l3dss1_release(struct l3_process *pc, u_char pr, void *arg)
1127
{
1128
        u_char *p;
1129
        struct sk_buff *skb = arg;
1130
        int cause = -1;
1131
 
1132
        p = skb->data;
1133
        if ((p = findie(p, skb->len, IE_CAUSE, 0))) {
1134
                p++;
1135
                if (*p++ == 2)
1136
                        pc->para.loc = *p++;
1137
                cause = *p & 0x7f;
1138
        }
1139
        p = skb->data;
1140
        if ((p = findie(p, skb->len, IE_FACILITY, 0))) {
1141
#if HISAX_DE_AOC
1142
                l3dss1_parse_facility(pc, p);
1143
#else
1144
                p = NULL;
1145
#endif
1146
        }
1147
        dev_kfree_skb(skb, FREE_READ);
1148
        StopAllL3Timer(pc);
1149
        pc->para.cause = cause;
1150
        l3dss1_message(pc, MT_RELEASE_COMPLETE);
1151
        pc->st->l3.l3l4(pc->st, CC_RELEASE | INDICATION, pc);
1152
        newl3state(pc, 0);
1153
        release_l3_process(pc);
1154
}
1155
 
1156
static void
1157
l3dss1_alert_req(struct l3_process *pc, u_char pr,
1158
                 void *arg)
1159
{
1160
        newl3state(pc, 7);
1161
        l3dss1_message(pc, MT_ALERTING);
1162
}
1163
 
1164
static void
1165
l3dss1_status_enq(struct l3_process *pc, u_char pr, void *arg)
1166
{
1167
        u_char tmp[16];
1168
        u_char *p = tmp;
1169
        int l;
1170
        struct sk_buff *skb = arg;
1171
 
1172
        dev_kfree_skb(skb, FREE_READ);
1173
 
1174
        MsgHead(p, pc->callref, MT_STATUS);
1175
 
1176
        *p++ = IE_CAUSE;
1177
        *p++ = 0x2;
1178
        *p++ = 0x80;
1179
        *p++ = 0x9E;            /* answer status enquire */
1180
 
1181
        *p++ = 0x14;            /* CallState */
1182
        *p++ = 0x1;
1183
        *p++ = pc->state & 0x3f;
1184
 
1185
        l = p - tmp;
1186
        if (!(skb = l3_alloc_skb(l)))
1187
                return;
1188
        memcpy(skb_put(skb, l), tmp, l);
1189
        l3_msg(pc->st, DL_DATA | REQUEST, skb);
1190
}
1191
 
1192
static void
1193
l3dss1_status_req(struct l3_process *pc, u_char pr, void *arg)
1194
{
1195
        /* ETS 300-104 7.4.1, 8.4.1, 10.3.1, 11.4.1, 12.4.1, 13.4.1, 14.4.1...
1196
           if setup has been made and a non expected message type is received, we must send MT_STATUS cause 0x62  */
1197
        u_char tmp[16];
1198
        u_char *p = tmp;
1199
        int l;
1200
        struct sk_buff *skb = arg;
1201
 
1202
        dev_kfree_skb(skb, FREE_READ);
1203
 
1204
        MsgHead(p, pc->callref, MT_STATUS);
1205
 
1206
        *p++ = IE_CAUSE;
1207
        *p++ = 0x2;
1208
        *p++ = 0x80;
1209
        *p++ = 0x62 | 0x80;     /* status sending */
1210
 
1211
        *p++ = 0x14;            /* CallState */
1212
        *p++ = 0x1;
1213
        *p++ = pc->state & 0x3f;
1214
 
1215
        l = p - tmp;
1216
        if (!(skb = l3_alloc_skb(l)))
1217
                return;
1218
        memcpy(skb_put(skb, l), tmp, l);
1219
        l3_msg(pc->st, DL_DATA | REQUEST, skb);
1220
}
1221
 
1222
static void
1223
l3dss1_release_ind(struct l3_process *pc, u_char pr, void *arg)
1224
{
1225
        u_char *p;
1226
        struct sk_buff *skb = arg;
1227
        int callState = 0;
1228
        p = skb->data;
1229
 
1230
        if ((p = findie(p, skb->len, IE_CALL_STATE, 0))) {
1231
                p++;
1232
                if (1 == *p++)
1233
                        callState = *p;
1234
        }
1235
        if (callState == 0) {
1236
                /* ETS 300-104 7.6.1, 8.6.1, 10.6.1... and 16.1
1237
                 * set down layer 3 without sending any message
1238
                 */
1239
                pc->st->l3.l3l4(pc->st, CC_RELEASE | INDICATION, pc);
1240
                newl3state(pc, 0);
1241
                release_l3_process(pc);
1242
        } else {
1243
                pc->st->l3.l3l4(pc->st, CC_IGNORE | INDICATION, pc);
1244
        }
1245
}
1246
 
1247
static void
1248
l3dss1_t303(struct l3_process *pc, u_char pr, void *arg)
1249
{
1250
        if (pc->N303 > 0) {
1251
                pc->N303--;
1252
                L3DelTimer(&pc->timer);
1253
                l3dss1_setup_req(pc, pr, arg);
1254
        } else {
1255
                L3DelTimer(&pc->timer);
1256
                pc->st->l3.l3l4(pc->st, CC_NOSETUP_RSP, pc);
1257
                release_l3_process(pc);
1258
        }
1259
}
1260
 
1261
static void
1262
l3dss1_t304(struct l3_process *pc, u_char pr, void *arg)
1263
{
1264
        L3DelTimer(&pc->timer);
1265
        pc->para.cause = 0xE6;
1266
        l3dss1_disconnect_req(pc, pr, NULL);
1267
        pc->st->l3.l3l4(pc->st, CC_SETUP_ERR, pc);
1268
 
1269
}
1270
 
1271
static void
1272
l3dss1_t305(struct l3_process *pc, u_char pr, void *arg)
1273
{
1274
        u_char tmp[16];
1275
        u_char *p = tmp;
1276
        int l;
1277
        struct sk_buff *skb;
1278
        u_char cause = 0x90;
1279
 
1280
        L3DelTimer(&pc->timer);
1281
        if (pc->para.cause > 0)
1282
                cause = pc->para.cause | 0x80;
1283
 
1284
        MsgHead(p, pc->callref, MT_RELEASE);
1285
 
1286
        *p++ = IE_CAUSE;
1287
        *p++ = 0x2;
1288
        *p++ = 0x80;
1289
        *p++ = cause;
1290
 
1291
        l = p - tmp;
1292
        if (!(skb = l3_alloc_skb(l)))
1293
                return;
1294
        memcpy(skb_put(skb, l), tmp, l);
1295
        newl3state(pc, 19);
1296
        l3_msg(pc->st, DL_DATA | REQUEST, skb);
1297
        L3AddTimer(&pc->timer, T308, CC_T308_1);
1298
}
1299
 
1300
static void
1301
l3dss1_t310(struct l3_process *pc, u_char pr, void *arg)
1302
{
1303
        L3DelTimer(&pc->timer);
1304
        pc->para.cause = 0xE6;
1305
        l3dss1_disconnect_req(pc, pr, NULL);
1306
        pc->st->l3.l3l4(pc->st, CC_SETUP_ERR, pc);
1307
}
1308
 
1309
static void
1310
l3dss1_t313(struct l3_process *pc, u_char pr, void *arg)
1311
{
1312
        L3DelTimer(&pc->timer);
1313
        pc->para.cause = 0xE6;
1314
        l3dss1_disconnect_req(pc, pr, NULL);
1315
        pc->st->l3.l3l4(pc->st, CC_CONNECT_ERR, pc);
1316
}
1317
 
1318
static void
1319
l3dss1_t308_1(struct l3_process *pc, u_char pr, void *arg)
1320
{
1321
        newl3state(pc, 19);
1322
        L3DelTimer(&pc->timer);
1323
        l3dss1_message(pc, MT_RELEASE);
1324
        L3AddTimer(&pc->timer, T308, CC_T308_2);
1325
}
1326
 
1327
static void
1328
l3dss1_t308_2(struct l3_process *pc, u_char pr, void *arg)
1329
{
1330
        L3DelTimer(&pc->timer);
1331
        pc->st->l3.l3l4(pc->st, CC_RELEASE_ERR, pc);
1332
        release_l3_process(pc);
1333
}
1334
 
1335
static void
1336
l3dss1_t318(struct l3_process *pc, u_char pr, void *arg)
1337
{
1338
        L3DelTimer(&pc->timer);
1339
        pc->para.cause = 0x66;  /* Timer expiry */
1340
        pc->para.loc = 0;        /* local */
1341
        pc->st->l3.l3l4(pc->st, CC_RESUME_ERR, pc);
1342
        newl3state(pc, 19);
1343
        l3dss1_message(pc, MT_RELEASE);
1344
        L3AddTimer(&pc->timer, T308, CC_T308_1);
1345
}
1346
 
1347
static void
1348
l3dss1_t319(struct l3_process *pc, u_char pr, void *arg)
1349
{
1350
        L3DelTimer(&pc->timer);
1351
        pc->para.cause = 0x66;  /* Timer expiry */
1352
        pc->para.loc = 0;        /* local */
1353
        pc->st->l3.l3l4(pc->st, CC_SUSPEND_ERR, pc);
1354
        newl3state(pc, 10);
1355
}
1356
 
1357
static void
1358
l3dss1_restart(struct l3_process *pc, u_char pr, void *arg)
1359
{
1360
        L3DelTimer(&pc->timer);
1361
        pc->st->l3.l3l4(pc->st, CC_DLRL | INDICATION, pc);
1362
        release_l3_process(pc);
1363
}
1364
 
1365
static void
1366
l3dss1_status(struct l3_process *pc, u_char pr, void *arg)
1367
{
1368
        u_char *p;
1369
        char tmp[64], *t;
1370
        int l;
1371
        struct sk_buff *skb = arg;
1372
        int cause, callState;
1373
 
1374
        cause = callState = -1;
1375
        p = skb->data;
1376
        t = tmp;
1377
        if ((p = findie(p, skb->len, IE_CAUSE, 0))) {
1378
                p++;
1379
                l = *p++;
1380
                t += sprintf(t, "Status CR %x Cause:", pc->callref);
1381
                while (l--) {
1382
                        cause = *p;
1383
                        t += sprintf(t, " %2x", *p++);
1384
                }
1385
        } else
1386
                sprintf(t, "Status CR %x no Cause", pc->callref);
1387
        l3_debug(pc->st, tmp);
1388
        p = skb->data;
1389
        t = tmp;
1390
        t += sprintf(t, "Status state %x ", pc->state);
1391
        if ((p = findie(p, skb->len, IE_CALL_STATE, 0))) {
1392
                p++;
1393
                if (1 == *p++) {
1394
                        callState = *p;
1395
                        t += sprintf(t, "peer state %x", *p);
1396
                } else
1397
                        t += sprintf(t, "peer state len error");
1398
        } else
1399
                sprintf(t, "no peer state");
1400
        l3_debug(pc->st, tmp);
1401
        if (((cause & 0x7f) == 0x6f) && (callState == 0)) {
1402
                /* ETS 300-104 7.6.1, 8.6.1, 10.6.1...
1403
                 * if received MT_STATUS with cause == 0x6f and call
1404
                 * state == 0, then we must set down layer 3
1405
                 */
1406
                l3dss1_release_ind(pc, pr, arg);
1407
        } else
1408
                dev_kfree_skb(skb, FREE_READ);
1409
}
1410
 
1411
static void
1412
l3dss1_facility(struct l3_process *pc, u_char pr, void *arg)
1413
{
1414
        u_char *p;
1415
        struct sk_buff *skb = arg;
1416
 
1417
        p = skb->data;
1418
        if ((p = findie(p, skb->len, IE_FACILITY, 0))) {
1419
#if HISAX_DE_AOC
1420
                l3dss1_parse_facility(pc, p);
1421
#else
1422
                p = NULL;
1423
#endif
1424
        }
1425
}
1426
 
1427
static void
1428
l3dss1_suspend_req(struct l3_process *pc, u_char pr, void *arg)
1429
{
1430
        struct sk_buff *skb;
1431
        u_char tmp[32];
1432
        u_char *p = tmp;
1433
        u_char i, l;
1434
        u_char *msg = pc->chan->setup.phone;
1435
 
1436
        MsgHead(p, pc->callref, MT_SUSPEND);
1437
 
1438
        *p++ = IE_CALLID;
1439
        l = *msg++;
1440
        if (l && (l <= 10)) {   /* Max length 10 octets */
1441
                *p++ = l;
1442
                for (i = 0; i < l; i++)
1443
                        *p++ = *msg++;
1444
        } else {
1445
                l3_debug(pc->st, "SUS wrong CALLID len %d", l);
1446
                return;
1447
        }
1448
        l = p - tmp;
1449
        if (!(skb = l3_alloc_skb(l)))
1450
                return;
1451
        memcpy(skb_put(skb, l), tmp, l);
1452
        l3_msg(pc->st, DL_DATA | REQUEST, skb);
1453
        newl3state(pc, 15);
1454
        L3AddTimer(&pc->timer, T319, CC_T319);
1455
}
1456
 
1457
static void
1458
l3dss1_suspend_ack(struct l3_process *pc, u_char pr, void *arg)
1459
{
1460
        struct sk_buff *skb = arg;
1461
 
1462
        L3DelTimer(&pc->timer);
1463
        newl3state(pc, 0);
1464
        dev_kfree_skb(skb, FREE_READ);
1465
        pc->para.cause = -1;
1466
        pc->st->l3.l3l4(pc->st, CC_SUSPEND | CONFIRM, pc);
1467
        release_l3_process(pc);
1468
}
1469
 
1470
static void
1471
l3dss1_suspend_rej(struct l3_process *pc, u_char pr, void *arg)
1472
{
1473
        u_char *p;
1474
        struct sk_buff *skb = arg;
1475
        int cause = -1;
1476
 
1477
        L3DelTimer(&pc->timer);
1478
        p = skb->data;
1479
        if ((p = findie(p, skb->len, IE_CAUSE, 0))) {
1480
                p++;
1481
                if (*p++ == 2)
1482
                        pc->para.loc = *p++;
1483
                cause = *p & 0x7f;
1484
        }
1485
        dev_kfree_skb(skb, FREE_READ);
1486
        pc->para.cause = cause;
1487
        pc->st->l3.l3l4(pc->st, CC_SUSPEND_ERR, pc);
1488
        newl3state(pc, 10);
1489
}
1490
 
1491
static void
1492
l3dss1_resume_req(struct l3_process *pc, u_char pr, void *arg)
1493
{
1494
        struct sk_buff *skb;
1495
        u_char tmp[32];
1496
        u_char *p = tmp;
1497
        u_char i, l;
1498
        u_char *msg = pc->para.setup.phone;
1499
 
1500
        MsgHead(p, pc->callref, MT_RESUME);
1501
 
1502
        *p++ = IE_CALLID;
1503
        l = *msg++;
1504
        if (l && (l <= 10)) {   /* Max length 10 octets */
1505
                *p++ = l;
1506
                for (i = 0; i < l; i++)
1507
                        *p++ = *msg++;
1508
        } else {
1509
                l3_debug(pc->st, "RES wrong CALLID len %d", l);
1510
                return;
1511
        }
1512
        l = p - tmp;
1513
        if (!(skb = l3_alloc_skb(l)))
1514
                return;
1515
        memcpy(skb_put(skb, l), tmp, l);
1516
        l3_msg(pc->st, DL_DATA | REQUEST, skb);
1517
        newl3state(pc, 17);
1518
        L3AddTimer(&pc->timer, T319, CC_T319);
1519
}
1520
 
1521
static void
1522
l3dss1_resume_ack(struct l3_process *pc, u_char pr, void *arg)
1523
{
1524
        u_char *p;
1525
        struct sk_buff *skb = arg;
1526
 
1527
        L3DelTimer(&pc->timer);
1528
        p = skb->data;
1529
        if ((p = findie(p, skb->len, IE_CHANNEL_ID, 0))) {
1530
                pc->para.bchannel = p[2] & 0x3;
1531
                if ((!pc->para.bchannel) && (pc->debug & L3_DEB_WARN))
1532
                        l3_debug(pc->st, "resume ack without bchannel");
1533
        } else if (pc->debug & L3_DEB_WARN)
1534
                l3_debug(pc->st, "resume ack without bchannel");
1535
        dev_kfree_skb(skb, FREE_READ);
1536
        pc->st->l3.l3l4(pc->st, CC_RESUME | CONFIRM, pc);
1537
        newl3state(pc, 10);
1538
}
1539
 
1540
static void
1541
l3dss1_resume_rej(struct l3_process *pc, u_char pr, void *arg)
1542
{
1543
        u_char *p;
1544
        struct sk_buff *skb = arg;
1545
        int cause = -1;
1546
 
1547
        L3DelTimer(&pc->timer);
1548
        p = skb->data;
1549
        if ((p = findie(p, skb->len, IE_CAUSE, 0))) {
1550
                p++;
1551
                if (*p++ == 2)
1552
                        pc->para.loc = *p++;
1553
                cause = *p & 0x7f;
1554
        }
1555
        dev_kfree_skb(skb, FREE_READ);
1556
        pc->para.cause = cause;
1557
        newl3state(pc, 0);
1558
        pc->st->l3.l3l4(pc->st, CC_RESUME_ERR, pc);
1559
        release_l3_process(pc);
1560
}
1561
 
1562
static void
1563
l3dss1_global_restart(struct l3_process *pc, u_char pr, void *arg)
1564
{
1565
        u_char tmp[32];
1566
        u_char *p;
1567
        u_char ri, ch = 0, chan = 0;
1568
        int l;
1569
        struct sk_buff *skb = arg;
1570
        struct l3_process *up;
1571
 
1572
        newl3state(pc, 2);
1573
        L3DelTimer(&pc->timer);
1574
        p = skb->data;
1575
        if ((p = findie(p, skb->len, IE_RESTART_IND, 0))) {
1576
                ri = p[2];
1577
                l3_debug(pc->st, "Restart %x", ri);
1578
        } else {
1579
                l3_debug(pc->st, "Restart without restart IE");
1580
                ri = 0x86;
1581
        }
1582
        p = skb->data;
1583
        if ((p = findie(p, skb->len, IE_CHANNEL_ID, 0))) {
1584
                chan = p[2] & 3;
1585
                ch = p[2];
1586
                if (pc->st->l3.debug)
1587
                        l3_debug(pc->st, "Restart for channel %d", chan);
1588
        }
1589
        dev_kfree_skb(skb, FREE_READ);
1590
        newl3state(pc, 2);
1591
        up = pc->st->l3.proc;
1592
        while (up) {
1593
                if ((ri & 7) == 7)
1594
                        up->st->lli.l4l3(up->st, CC_RESTART | REQUEST, up);
1595
                else if (up->para.bchannel == chan)
1596
                        up->st->lli.l4l3(up->st, CC_RESTART | REQUEST, up);
1597
                up = up->next;
1598
        }
1599
        p = tmp;
1600
        MsgHead(p, pc->callref, MT_RESTART_ACKNOWLEDGE);
1601
        if (chan) {
1602
                *p++ = IE_CHANNEL_ID;
1603
                *p++ = 1;
1604
                *p++ = ch | 0x80;
1605
        }
1606
        *p++ = 0x79;            /* RESTART Ind */
1607
        *p++ = 1;
1608
        *p++ = ri;
1609
        l = p - tmp;
1610
        if (!(skb = l3_alloc_skb(l)))
1611
                return;
1612
        memcpy(skb_put(skb, l), tmp, l);
1613
        newl3state(pc, 0);
1614
        l3_msg(pc->st, DL_DATA | REQUEST, skb);
1615
}
1616
/* *INDENT-OFF* */
1617
static struct stateentry downstatelist[] =
1618
{
1619
        {SBIT(0),
1620
         CC_SETUP | REQUEST, l3dss1_setup_req},
1621
        {SBIT(0),
1622
         CC_RESUME | REQUEST, l3dss1_resume_req},
1623
        {SBIT(1) | SBIT(2) | SBIT(3) | SBIT(4) | SBIT(6) | SBIT(7) | SBIT(8) | SBIT(10),
1624
         CC_DISCONNECT | REQUEST, l3dss1_disconnect_req},
1625
        {SBIT(12),
1626
         CC_RELEASE | REQUEST, l3dss1_release_req},
1627
        {ALL_STATES,
1628
         CC_DLRL | REQUEST, l3dss1_reset},
1629
        {ALL_STATES,
1630
         CC_RESTART | REQUEST, l3dss1_restart},
1631
        {SBIT(6),
1632
         CC_IGNORE | REQUEST, l3dss1_reset},
1633
        {SBIT(6),
1634
         CC_REJECT | REQUEST, l3dss1_reject_req},
1635
        {SBIT(6),
1636
         CC_ALERTING | REQUEST, l3dss1_alert_req},
1637
        {SBIT(6) | SBIT(7),
1638
         CC_SETUP | RESPONSE, l3dss1_setup_rsp},
1639
        {SBIT(10),
1640
         CC_SUSPEND | REQUEST, l3dss1_suspend_req},
1641
        {SBIT(1),
1642
         CC_T303, l3dss1_t303},
1643
        {SBIT(2),
1644
         CC_T304, l3dss1_t304},
1645
        {SBIT(3),
1646
         CC_T310, l3dss1_t310},
1647
        {SBIT(8),
1648
         CC_T313, l3dss1_t313},
1649
        {SBIT(11),
1650
         CC_T305, l3dss1_t305},
1651
        {SBIT(15),
1652
         CC_T319, l3dss1_t319},
1653
        {SBIT(17),
1654
         CC_T318, l3dss1_t318},
1655
        {SBIT(19),
1656
         CC_T308_1, l3dss1_t308_1},
1657
        {SBIT(19),
1658
         CC_T308_2, l3dss1_t308_2},
1659
};
1660
 
1661
#define DOWNSLLEN \
1662
        (sizeof(downstatelist) / sizeof(struct stateentry))
1663
 
1664
static struct stateentry datastatelist[] =
1665
{
1666
        {ALL_STATES,
1667
         MT_STATUS_ENQUIRY, l3dss1_status_enq},
1668
        {ALL_STATES,
1669
         MT_FACILITY, l3dss1_facility},
1670
        {SBIT(19),
1671
         MT_STATUS, l3dss1_release_ind},
1672
        {ALL_STATES,
1673
         MT_STATUS, l3dss1_status},
1674
        {SBIT(0) | SBIT(6),
1675
         MT_SETUP, l3dss1_setup},
1676
        {SBIT(1) | SBIT(2),
1677
         MT_CALL_PROCEEDING, l3dss1_call_proc},
1678
        {SBIT(3) | SBIT(4) | SBIT(8) | SBIT(10) | SBIT(11) | SBIT(19),
1679
         MT_CALL_PROCEEDING, l3dss1_status_req},
1680
        {SBIT(1),
1681
         MT_SETUP_ACKNOWLEDGE, l3dss1_setup_ack},
1682
        {SBIT(2) | SBIT(3) | SBIT(4) | SBIT(8) | SBIT(10) | SBIT(11) | SBIT(19),
1683
         MT_SETUP_ACKNOWLEDGE, l3dss1_status_req},
1684
        {SBIT(1) | SBIT(2) | SBIT(3),
1685
         MT_ALERTING, l3dss1_alerting},
1686
        {SBIT(4) | SBIT(8) | SBIT(10) | SBIT(11) | SBIT(19),
1687
         MT_ALERTING, l3dss1_status_req},
1688
        {SBIT(0) | SBIT(1) | SBIT(2) | SBIT(3) | SBIT(4) | SBIT(7) | SBIT(8) | SBIT(10) |
1689
         SBIT(11) | SBIT(12) | SBIT(15) | SBIT(17) | SBIT(19),
1690
         MT_RELEASE_COMPLETE, l3dss1_release_cmpl},
1691
        {SBIT(1) | SBIT(2) | SBIT(3) | SBIT(4) | SBIT(7) | SBIT(8) | SBIT(10) |
1692
         SBIT(11) | SBIT(12) | SBIT(15) /* | SBIT(17) | SBIT(19)*/,
1693
         MT_RELEASE, l3dss1_release},
1694
        {SBIT(19),  MT_RELEASE, l3dss1_release_ind},
1695
        {SBIT(1) | SBIT(2) | SBIT(3) | SBIT(4) | SBIT(7) | SBIT(8) | SBIT(10) | SBIT(15),
1696
         MT_DISCONNECT, l3dss1_disconnect},
1697
        {SBIT(11),
1698
         MT_DISCONNECT, l3dss1_release_req},
1699
        {SBIT(1) | SBIT(2) | SBIT(3) | SBIT(4),
1700
         MT_CONNECT, l3dss1_connect},
1701
        {SBIT(8) | SBIT(10) | SBIT(11) | SBIT(19),
1702
         MT_CONNECT, l3dss1_status_req},
1703
        {SBIT(1) | SBIT(2) | SBIT(3) | SBIT(4) | SBIT(11) | SBIT(19),
1704
         MT_CONNECT_ACKNOWLEDGE, l3dss1_status_req},
1705
        {SBIT(8),
1706
         MT_CONNECT_ACKNOWLEDGE, l3dss1_connect_ack},
1707
        {SBIT(15),
1708
         MT_SUSPEND_ACKNOWLEDGE, l3dss1_suspend_ack},
1709
        {SBIT(15),
1710
         MT_SUSPEND_REJECT, l3dss1_suspend_rej},
1711
        {SBIT(17),
1712
         MT_RESUME_ACKNOWLEDGE, l3dss1_resume_ack},
1713
        {SBIT(17),
1714
         MT_RESUME_REJECT, l3dss1_resume_rej},
1715
        {SBIT(1) | SBIT(2) | SBIT(3) | SBIT(4) | SBIT(8) | SBIT(10) | SBIT(11) | SBIT(15) | SBIT(17) | SBIT(19),
1716
         MT_INVALID, l3dss1_status_req},
1717
};
1718
 
1719
#define DATASLLEN \
1720
        (sizeof(datastatelist) / sizeof(struct stateentry))
1721
 
1722
static struct stateentry globalmes_list[] =
1723
{
1724
        {ALL_STATES,
1725
         MT_STATUS, l3dss1_status},
1726
        {SBIT(0),
1727
         MT_RESTART, l3dss1_global_restart},
1728
/*      {SBIT(1),
1729
         MT_RESTART_ACKNOWLEDGE, l3dss1_restart_ack},
1730
*/
1731
};
1732
#define GLOBALM_LEN \
1733
        (sizeof(globalmes_list) / sizeof(struct stateentry))
1734
/* *INDENT-ON* */
1735
 
1736
 
1737
static void
1738
global_handler(struct PStack *st, int mt, struct sk_buff *skb)
1739
{
1740
        int i;
1741
        struct l3_process *proc = st->l3.global;
1742
 
1743
        for (i = 0; i < GLOBALM_LEN; i++)
1744
                if ((mt == globalmes_list[i].primitive) &&
1745
                    ((1 << proc->state) & globalmes_list[i].state))
1746
                        break;
1747
        if (i == GLOBALM_LEN) {
1748
                dev_kfree_skb(skb, FREE_READ);
1749
                if (st->l3.debug & L3_DEB_STATE) {
1750
                        l3_debug(st, "dss1 global state %d mt %x unhandled",
1751
                                proc->state, mt);
1752
                }
1753
                return;
1754
        } else {
1755
                if (st->l3.debug & L3_DEB_STATE) {
1756
                        l3_debug(st, "dss1 global %d mt %x",
1757
                                proc->state, mt);
1758
                }
1759
                globalmes_list[i].rout(proc, mt, skb);
1760
        }
1761
}
1762
 
1763
static void
1764
dss1up(struct PStack *st, int pr, void *arg)
1765
{
1766
        int i, mt, cr, cause, callState;
1767
        char *ptr;
1768
        struct sk_buff *skb = arg;
1769
        struct l3_process *proc;
1770
 
1771
        switch (pr) {
1772
                case (DL_DATA | INDICATION):
1773
                case (DL_UNIT_DATA | INDICATION):
1774
                        break;
1775
                case (DL_ESTABLISH | CONFIRM):
1776
                case (DL_ESTABLISH | INDICATION):
1777
                case (DL_RELEASE | INDICATION):
1778
                case (DL_RELEASE | CONFIRM):
1779
                        l3_msg(st, pr, arg);
1780
                        return;
1781
                        break;
1782
        }
1783
        if (skb->data[0] != PROTO_DIS_EURO) {
1784
                if (st->l3.debug & L3_DEB_PROTERR) {
1785
                        l3_debug(st, "dss1up%sunexpected discriminator %x message len %d",
1786
                                 (pr == (DL_DATA | INDICATION)) ? " " : "(broadcast) ",
1787
                                 skb->data[0], skb->len);
1788
                }
1789
                dev_kfree_skb(skb, FREE_READ);
1790
                return;
1791
        }
1792
        cr = getcallref(skb->data);
1793
        mt = skb->data[skb->data[1] + 2];
1794
        if (!cr) {              /* Global CallRef */
1795
                global_handler(st, mt, skb);
1796
                return;
1797
        } else if (cr == -1) {  /* Dummy Callref */
1798
                dev_kfree_skb(skb, FREE_READ);
1799
                return;
1800
        } else if (!(proc = getl3proc(st, cr))) {
1801
                /* No transaction process exist, that means no call with
1802
                 * this callreference is active
1803
                 */
1804
                if (mt == MT_SETUP) {
1805
                        /* Setup creates a new transaction process */
1806
                        if (!(proc = new_l3_process(st, cr))) {
1807
                                /* May be to answer with RELEASE_COMPLETE and
1808
                                 * CAUSE 0x2f "Resource unavailable", but this
1809
                                 * need a new_l3_process too ... arghh
1810
                                 */
1811
                                dev_kfree_skb(skb, FREE_READ);
1812
                                return;
1813
                        }
1814
                } else if (mt == MT_STATUS) {
1815
                        cause = 0;
1816
                        if ((ptr = findie(skb->data, skb->len, IE_CAUSE, 0)) != NULL) {
1817
                                ptr++;
1818
                                if (*ptr++ == 2)
1819
                                        ptr++;
1820
                                cause = *ptr & 0x7f;
1821
                        }
1822
                        callState = 0;
1823
                        if ((ptr = findie(skb->data, skb->len, IE_CALL_STATE, 0)) != NULL) {
1824
                                ptr++;
1825
                                if (*ptr++ == 2)
1826
                                        ptr++;
1827
                                callState = *ptr;
1828
                        }
1829
                        if (callState == 0) {
1830
                                /* ETS 300-104 part 2.4.1
1831
                                 * if setup has not been made and a message type
1832
                                 * MT_STATUS is received with call state == 0,
1833
                                 * we must send nothing
1834
                                 */
1835
                                dev_kfree_skb(skb, FREE_READ);
1836
                                return;
1837
                        } else {
1838
                                /* ETS 300-104 part 2.4.2
1839
                                 * if setup has not been made and a message type
1840
                                 * MT_STATUS is received with call state != 0,
1841
                                 * we must send MT_RELEASE_COMPLETE cause 101
1842
                                 */
1843
                                dev_kfree_skb(skb, FREE_READ);
1844
                                if ((proc = new_l3_process(st, cr))) {
1845
                                        proc->para.cause = 0x65;        /* 101 */
1846
                                        l3dss1_msg_without_setup(proc, 0, NULL);
1847
                                }
1848
                                return;
1849
                        }
1850
                } else if (mt == MT_RELEASE_COMPLETE) {
1851
                        dev_kfree_skb(skb, FREE_READ);
1852
                        return;
1853
                } else {
1854
                        /* ETS 300-104 part 2
1855
                         * if setup has not been made and a message type
1856
                         * (except MT_SETUP and RELEASE_COMPLETE) is received,
1857
                         * we must send MT_RELEASE_COMPLETE cause 81 */
1858
                        dev_kfree_skb(skb, FREE_READ);
1859
                        if ((proc = new_l3_process(st, cr))) {
1860
                                proc->para.cause = 0x51;        /* 81 */
1861
                                l3dss1_msg_without_setup(proc, 0, NULL);
1862
                        }
1863
                        return;
1864
                }
1865
        } else if (!l3dss1_check_messagetype_validity(mt)) {
1866
                /* ETS 300-104 7.4.2, 8.4.2, 10.3.2, 11.4.2, 12.4.2, 13.4.2,
1867
                 * 14.4.2...
1868
                 * if setup has been made and invalid message type is received,
1869
                 * we must send MT_STATUS cause 0x62
1870
                 */
1871
                mt = MT_INVALID;        /* sorry, not clean, but do the right thing ;-) */
1872
        }
1873
        for (i = 0; i < DATASLLEN; i++)
1874
                if ((mt == datastatelist[i].primitive) &&
1875
                    ((1 << proc->state) & datastatelist[i].state))
1876
                        break;
1877
        if (i == DATASLLEN) {
1878
                dev_kfree_skb(skb, FREE_READ);
1879
                if (st->l3.debug & L3_DEB_STATE) {
1880
                        l3_debug(st, "dss1up%sstate %d mt %x unhandled",
1881
                                (pr == (DL_DATA | INDICATION)) ? " " : "(broadcast) ",
1882
                                proc->state, mt);
1883
                }
1884
                return;
1885
        } else {
1886
                if (st->l3.debug & L3_DEB_STATE) {
1887
                        l3_debug(st, "dss1up%sstate %d mt %x",
1888
                                (pr == (DL_DATA | INDICATION)) ? " " : "(broadcast) ",
1889
                                proc->state, mt);
1890
                }
1891
                datastatelist[i].rout(proc, pr, skb);
1892
        }
1893
}
1894
 
1895
static void
1896
dss1down(struct PStack *st, int pr, void *arg)
1897
{
1898
        int i, cr;
1899
        struct l3_process *proc;
1900
        struct Channel *chan;
1901
 
1902
        if (((DL_ESTABLISH | REQUEST) == pr) || ((DL_RELEASE | REQUEST) == pr)) {
1903
                l3_msg(st, pr, NULL);
1904
                return;
1905
        } else if (((CC_SETUP | REQUEST) == pr) || ((CC_RESUME | REQUEST) == pr)) {
1906
                chan = arg;
1907
                cr = newcallref();
1908
                cr |= 0x80;
1909
                if ((proc = new_l3_process(st, cr))) {
1910
                        proc->chan = chan;
1911
                        chan->proc = proc;
1912
                        proc->para.setup = chan->setup;
1913
                        proc->callref = cr;
1914
                }
1915
        } else {
1916
                proc = arg;
1917
        }
1918
        if (!proc) {
1919
                printk(KERN_ERR "HiSax dss1down without proc pr=%04x\n", pr);
1920
                return;
1921
        }
1922
        for (i = 0; i < DOWNSLLEN; i++)
1923
                if ((pr == downstatelist[i].primitive) &&
1924
                    ((1 << proc->state) & downstatelist[i].state))
1925
                        break;
1926
        if (i == DOWNSLLEN) {
1927
                if (st->l3.debug & L3_DEB_STATE) {
1928
                        l3_debug(st, "dss1down state %d prim %d unhandled",
1929
                                proc->state, pr);
1930
                }
1931
        } else {
1932
                if (st->l3.debug & L3_DEB_STATE) {
1933
                        l3_debug(st, "dss1down state %d prim %d",
1934
                                proc->state, pr);
1935
                }
1936
                downstatelist[i].rout(proc, pr, arg);
1937
        }
1938
}
1939
 
1940
void
1941
setstack_dss1(struct PStack *st)
1942
{
1943
        char tmp[64];
1944
 
1945
        st->lli.l4l3 = dss1down;
1946
        st->l2.l2l3 = dss1up;
1947
        st->l3.N303 = 1;
1948
        if (!(st->l3.global = kmalloc(sizeof(struct l3_process), GFP_ATOMIC))) {
1949
                printk(KERN_ERR "HiSax can't get memory for dss1 global CR\n");
1950
        } else {
1951
                st->l3.global->state = 0;
1952
                st->l3.global->callref = 0;
1953
                st->l3.global->next = NULL;
1954
                st->l3.global->debug = L3_DEB_WARN;
1955
                st->l3.global->st = st;
1956
                st->l3.global->N303 = 1;
1957
                L3InitTimer(st->l3.global, &st->l3.global->timer);
1958
        }
1959
        strcpy(tmp, dss1_revision);
1960
        printk(KERN_INFO "HiSax: DSS1 Rev. %s\n", HiSax_getrev(tmp));
1961
}

powered by: WebSVN 2.1.0

© copyright 1999-2024 OpenCores.org, equivalent to Oliscience, all rights reserved. OpenCores®, registered trademark.