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

Subversion Repositories or1k

[/] [or1k/] [trunk/] [rc203soc/] [sw/] [uClinux/] [drivers/] [isdn/] [hisax/] [l3_1tr6.c] - Blame information for rev 1777

Go to most recent revision | Details | Compare with Previous | View Log

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

powered by: WebSVN 2.1.0

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