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

Subversion Repositories or1k

[/] [or1k/] [trunk/] [uclinux/] [uClinux-2.0.x/] [drivers/] [isdn/] [hisax/] [isdnl3.c] - Blame information for rev 1765

Details | Compare with Previous | View Log

Line No. Rev Author Line
1 199 simons
/* $Id: isdnl3.c,v 1.1.1.1 2001-09-10 07:44:18 simons Exp $
2
 
3
 * Author       Karsten Keil (keil@isdn4linux.de)
4
 *              based on the teles driver from Jan den Ouden
5
 *
6
 *              This file is (c) under GNU PUBLIC LICENSE
7
 *              For changes and modifications please read
8
 *              ../../../Documentation/isdn/HiSax.cert
9
 *
10
 * Thanks to    Jan den Ouden
11
 *              Fritz Elfert
12
 *
13
 * $Log: not supported by cvs2svn $
14
 * Revision 1.1.1.1  2001/07/02 17:58:32  simons
15
 * Initial revision
16
 *
17
 * Revision 1.10.2.6  1998/11/03 00:07:06  keil
18
 * certification related changes
19
 * fixed logging for smaller stack use
20
 *
21
 * Revision 1.10.2.5  1998/09/27 13:06:39  keil
22
 * Apply most changes from 2.1.X (HiSax 3.1)
23
 *
24
 * Revision 1.10.2.4  1998/05/27 18:05:59  keil
25
 * HiSax 3.0
26
 *
27
 * Revision 1.10.2.3  1997/11/15 18:54:09  keil
28
 * cosmetics
29
 *
30
 * Revision 1.10.2.2  1997/10/17 22:14:05  keil
31
 * update to last hisax version
32
 *
33
 * Revision 2.1  1997/08/03 14:36:32  keil
34
 * Implement RESTART procedure
35
 *
36
 * Revision 2.0  1997/07/27 21:15:42  keil
37
 * New Callref based layer3
38
 *
39
 * Revision 1.11  1997/06/26 11:11:44  keil
40
 * SET_SKBFREE now on creation of a SKB
41
 *
42
 * Revision 1.10  1997/04/06 22:54:16  keil
43
 * Using SKB's
44
 *
45
 * Revision 1.9  1997/03/25 23:11:25  keil
46
 * US NI-1 protocol
47
 *
48
 * Revision 1.8  1997/03/21 18:53:44  keil
49
 * Report no protocol error to syslog too
50
 *
51
 * Remove old logs /KKe
52
 *
53
 */
54
#define __NO_VERSION__
55
#include "hisax.h"
56
#include "isdnl3.h"
57
#include <linux/config.h>
58
 
59
const char *l3_revision = "$Revision: 1.1.1.1 $";
60
 
61
static
62
struct Fsm l3fsm =
63
{NULL, 0, 0, NULL, NULL};
64
 
65
enum {
66
        ST_L3_LC_REL,
67
        ST_L3_LC_ESTAB_WAIT,
68
        ST_L3_LC_REL_WAIT,
69
        ST_L3_LC_ESTAB,
70
};
71
 
72
#define L3_STATE_COUNT (ST_L3_LC_ESTAB+1)
73
 
74
static char *strL3State[] =
75
{
76
        "ST_L3_LC_REL",
77
        "ST_L3_LC_ESTAB_WAIT",
78
        "ST_L3_LC_REL_WAIT",
79
        "ST_L3_LC_ESTAB",
80
};
81
 
82
enum {
83
        EV_ESTABLISH_REQ,
84
        EV_ESTABLISH_IND,
85
        EV_ESTABLISH_CNF,
86
        EV_RELEASE_REQ,
87
        EV_RELEASE_CNF,
88
        EV_RELEASE_IND,
89
};
90
 
91
#define L3_EVENT_COUNT (EV_RELEASE_IND+1)
92
 
93
static char *strL3Event[] =
94
{
95
        "EV_ESTABLISH_REQ",
96
        "EV_ESTABLISH_IND",
97
        "EV_ESTABLISH_CNF",
98
        "EV_RELEASE_REQ",
99
        "EV_RELEASE_CNF",
100
        "EV_RELEASE_IND",
101
};
102
 
103
static void
104
l3m_debug(struct FsmInst *fi, char *fmt, ...)
105
{
106
        va_list args;
107
        struct PStack *st = fi->userdata;
108
 
109
        va_start(args, fmt);
110
        VHiSax_putstatus(st->l1.hardware, st->l3.debug_id, fmt, args);
111
        va_end(args);
112
}
113
 
114
u_char *
115
findie(u_char * p, int size, u_char ie, int wanted_set)
116
{
117
        int l, codeset, maincodeset;
118
        u_char *pend = p + size;
119
 
120
        /* skip protocol discriminator, callref and message type */
121
        p++;
122
        l = (*p++) & 0xf;
123
        p += l;
124
        p++;
125
        codeset = 0;
126
        maincodeset = 0;
127
        /* while there are bytes left... */
128
        while (p < pend) {
129
                if ((*p & 0xf0) == 0x90) {
130
                        codeset = *p & 0x07;
131
                        if (!(*p & 0x08))
132
                                maincodeset = codeset;
133
                }
134
                if (*p & 0x80)
135
                        p++;
136
                else {
137
                        if (codeset == wanted_set) {
138
                                if (*p == ie)
139
                                        return (p);
140
                                if (*p > ie)
141
                                        return (NULL);
142
                        }
143
                        p++;
144
                        l = *p++;
145
                        p += l;
146
                        codeset = maincodeset;
147
                }
148
        }
149
        return (NULL);
150
}
151
 
152
int
153
getcallref(u_char * p)
154
{
155
        int l, m = 1, cr = 0;
156
        p++;                    /* prot discr */
157
        l = 0xf & *p++;         /* callref length */
158
        if (!l)                 /* dummy CallRef */
159
                return(-1);
160
        while (l--) {
161
                cr += m * (*p++);
162
                m *= 8;
163
        }
164
        return (cr);
165
}
166
 
167
static int OrigCallRef = 0;
168
 
169
int
170
newcallref(void)
171
{
172
        if (OrigCallRef == 127)
173
                OrigCallRef = 1;
174
        else
175
                OrigCallRef++;
176
        return (OrigCallRef);
177
}
178
 
179
void
180
newl3state(struct l3_process *pc, int state)
181
{
182
        if (pc->debug & L3_DEB_STATE)
183
                l3_debug(pc->st, "newstate cr %d %d --> %d", pc->callref,
184
                        pc->state, state);
185
        pc->state = state;
186
}
187
 
188
static void
189
L3ExpireTimer(struct L3Timer *t)
190
{
191
        t->pc->st->lli.l4l3(t->pc->st, t->event, t->pc);
192
}
193
 
194
void
195
L3InitTimer(struct l3_process *pc, struct L3Timer *t)
196
{
197
        t->pc = pc;
198
        t->tl.function = (void *) L3ExpireTimer;
199
        t->tl.data = (long) t;
200
        init_timer(&t->tl);
201
}
202
 
203
void
204
L3DelTimer(struct L3Timer *t)
205
{
206
        del_timer(&t->tl);
207
}
208
 
209
int
210
L3AddTimer(struct L3Timer *t,
211
           int millisec, int event)
212
{
213
        if (t->tl.next || t->tl.prev) {
214
                printk(KERN_WARNING "L3AddTimer: timer already active!\n");
215
                return -1;
216
        }
217
        init_timer(&t->tl);
218
        t->event = event;
219
        t->tl.expires = jiffies + (millisec * HZ) / 1000;
220
        add_timer(&t->tl);
221
        return 0;
222
}
223
 
224
void
225
StopAllL3Timer(struct l3_process *pc)
226
{
227
        L3DelTimer(&pc->timer);
228
}
229
 
230
struct sk_buff *
231
l3_alloc_skb(int len)
232
{
233
        struct sk_buff *skb;
234
 
235
        if (!(skb = alloc_skb(len + MAX_HEADER_LEN, GFP_ATOMIC))) {
236
                printk(KERN_WARNING "HiSax: No skb for D-channel\n");
237
                return (NULL);
238
        }
239
        SET_SKB_FREE(skb);
240
        skb_reserve(skb, MAX_HEADER_LEN);
241
        return (skb);
242
}
243
 
244
static void
245
no_l3_proto(struct PStack *st, int pr, void *arg)
246
{
247
        struct sk_buff *skb = arg;
248
 
249
        HiSax_putstatus(st->l1.hardware, "L3", "no D protocol");
250
        if (skb) {
251
                dev_kfree_skb(skb, FREE_READ);
252
        }
253
}
254
 
255
#ifdef  CONFIG_HISAX_EURO
256
extern void setstack_dss1(struct PStack *st);
257
#endif
258
 
259
#ifdef        CONFIG_HISAX_NI1
260
extern void setstack_ni1(struct PStack *st);
261
#endif
262
 
263
#ifdef  CONFIG_HISAX_1TR6
264
extern void setstack_1tr6(struct PStack *st);
265
#endif
266
 
267
struct l3_process
268
*getl3proc(struct PStack *st, int cr)
269
{
270
        struct l3_process *p = st->l3.proc;
271
 
272
        while (p)
273
                if (p->callref == cr)
274
                        return (p);
275
                else
276
                        p = p->next;
277
        return (NULL);
278
}
279
 
280
struct l3_process
281
*new_l3_process(struct PStack *st, int cr)
282
{
283
        struct l3_process *p, *np;
284
 
285
        if (!(p = kmalloc(sizeof(struct l3_process), GFP_ATOMIC))) {
286
                printk(KERN_ERR "HiSax can't get memory for cr %d\n", cr);
287
                return (NULL);
288
        }
289
        if (!st->l3.proc)
290
                st->l3.proc = p;
291
        else {
292
                np = st->l3.proc;
293
                while (np->next)
294
                        np = np->next;
295
                np->next = p;
296
        }
297
        p->next = NULL;
298
        p->debug = L3_DEB_WARN;
299
        p->callref = cr;
300
        p->state = 0;
301
        p->chan = NULL;
302
        p->st = st;
303
        p->N303 = st->l3.N303;
304
        L3InitTimer(p, &p->timer);
305
        return (p);
306
};
307
 
308
void
309
release_l3_process(struct l3_process *p)
310
{
311
        struct l3_process *np, *pp = NULL;
312
 
313
        if (!p)
314
                return;
315
        np = p->st->l3.proc;
316
        while (np) {
317
                if (np == p) {
318
                        StopAllL3Timer(p);
319
                        if (pp)
320
                                pp->next = np->next;
321
                        else
322
                                p->st->l3.proc = np->next;
323
                        kfree(p);
324
                        return;
325
                }
326
                pp = np;
327
                np = np->next;
328
        }
329
        printk(KERN_ERR "HiSax internal L3 error CR(%d) not in list\n", p->callref);
330
        l3_debug(p->st, "HiSax internal L3 error CR(%d) not in list", p->callref);
331
};
332
 
333
void
334
setstack_l3dc(struct PStack *st, struct Channel *chanp)
335
{
336
        char tmp[64];
337
 
338
        st->l3.proc   = NULL;
339
        st->l3.global = NULL;
340
        skb_queue_head_init(&st->l3.squeue);
341
        st->l3.l3m.fsm = &l3fsm;
342
        st->l3.l3m.state = ST_L3_LC_REL;
343
        st->l3.l3m.debug = 1;
344
        st->l3.l3m.userdata = st;
345
        st->l3.l3m.userint = 0;
346
        st->l3.l3m.printdebug = l3m_debug;
347
        strcpy(st->l3.debug_id, "L3DC ");
348
 
349
#ifdef  CONFIG_HISAX_EURO
350
        if (st->protocol == ISDN_PTYPE_EURO) {
351
                setstack_dss1(st);
352
        } else
353
#endif
354
#ifdef        CONFIG_HISAX_NI1
355
        if (st->protocol == ISDN_PTYPE_NI1) {
356
                setstack_ni1(st);
357
        } else
358
#endif
359
#ifdef  CONFIG_HISAX_1TR6
360
        if (st->protocol == ISDN_PTYPE_1TR6) {
361
                setstack_1tr6(st);
362
        } else
363
#endif
364
        if (st->protocol == ISDN_PTYPE_LEASED) {
365
                st->lli.l4l3 = no_l3_proto;
366
                st->l2.l2l3 = no_l3_proto;
367
                printk(KERN_INFO "HiSax: Leased line mode\n");
368
        } else {
369
                st->lli.l4l3 = no_l3_proto;
370
                st->l2.l2l3 = no_l3_proto;
371
                sprintf(tmp, "protocol %s not supported",
372
                        (st->protocol == ISDN_PTYPE_1TR6) ? "1tr6" :
373
                        (st->protocol == ISDN_PTYPE_EURO) ? "euro" :
374
                        (st->protocol == ISDN_PTYPE_NI1) ? "ni1" :
375
                        "unknown");
376
                printk(KERN_WARNING "HiSax: %s\n", tmp);
377
                st->protocol = -1;
378
        }
379
}
380
 
381
void
382
isdnl3_trans(struct PStack *st, int pr, void *arg) {
383
        st->l3.l3l2(st, pr, arg);
384
}
385
 
386
void
387
releasestack_isdnl3(struct PStack *st)
388
{
389
        while (st->l3.proc)
390
                release_l3_process(st->l3.proc);
391
        if (st->l3.global) {
392
                StopAllL3Timer(st->l3.global);
393
                kfree(st->l3.global);
394
                st->l3.global = NULL;
395
        }
396
        discard_queue(&st->l3.squeue);
397
}
398
 
399
void
400
setstack_l3bc(struct PStack *st, struct Channel *chanp)
401
{
402
 
403
        st->l3.proc   = NULL;
404
        st->l3.global = NULL;
405
        skb_queue_head_init(&st->l3.squeue);
406
        st->l3.l3m.fsm = &l3fsm;
407
        st->l3.l3m.state = ST_L3_LC_REL;
408
        st->l3.l3m.debug = 1;
409
        st->l3.l3m.userdata = st;
410
        st->l3.l3m.userint = 0;
411
        st->l3.l3m.printdebug = l3m_debug;
412
        strcpy(st->l3.debug_id, "L3BC ");
413
        st->lli.l4l3 = isdnl3_trans;
414
}
415
 
416
static void
417
lc_activate(struct FsmInst *fi, int event, void *arg)
418
{
419
        struct PStack *st = fi->userdata;
420
 
421
        FsmChangeState(fi, ST_L3_LC_ESTAB_WAIT);
422
        st->l3.l3l2(st, DL_ESTABLISH | REQUEST, NULL);
423
}
424
 
425
static void
426
lc_connect(struct FsmInst *fi, int event, void *arg)
427
{
428
        struct PStack *st = fi->userdata;
429
        struct sk_buff *skb = arg;
430
 
431
        FsmChangeState(fi, ST_L3_LC_ESTAB);
432
        while ((skb = skb_dequeue(&st->l3.squeue))) {
433
                st->l3.l3l2(st, DL_DATA | REQUEST, skb);
434
        }
435
        st->l3.l3l4(st, DL_ESTABLISH | INDICATION, NULL);
436
}
437
 
438
static void
439
lc_release_req(struct FsmInst *fi, int event, void *arg)
440
{
441
        struct PStack *st = fi->userdata;
442
 
443
        if (fi->state == ST_L3_LC_ESTAB_WAIT)
444
                FsmChangeState(fi, ST_L3_LC_REL);
445
        else
446
                FsmChangeState(fi, ST_L3_LC_REL_WAIT);
447
        st->l3.l3l2(st, DL_RELEASE | REQUEST, NULL);
448
}
449
 
450
static void
451
lc_release_ind(struct FsmInst *fi, int event, void *arg)
452
{
453
        struct PStack *st = fi->userdata;
454
 
455
        FsmChangeState(fi, ST_L3_LC_REL);
456
        discard_queue(&st->l3.squeue);
457
        st->l3.l3l4(st, DL_RELEASE | INDICATION, NULL);
458
}
459
 
460
/* *INDENT-OFF* */
461
static struct FsmNode L3FnList[] HISAX_INITDATA =
462
{
463
        {ST_L3_LC_REL,          EV_ESTABLISH_REQ,       lc_activate},
464
        {ST_L3_LC_REL,          EV_ESTABLISH_IND,       lc_connect},
465
        {ST_L3_LC_REL,          EV_ESTABLISH_CNF,       lc_connect},
466
        {ST_L3_LC_ESTAB_WAIT,   EV_ESTABLISH_CNF,       lc_connect},
467
        {ST_L3_LC_ESTAB_WAIT,   EV_RELEASE_REQ,         lc_release_req},
468
        {ST_L3_LC_ESTAB_WAIT,   EV_RELEASE_IND,         lc_release_ind},
469
        {ST_L3_LC_ESTAB,        EV_RELEASE_IND,         lc_release_ind},
470
        {ST_L3_LC_ESTAB,        EV_RELEASE_REQ,         lc_release_req},
471
        {ST_L3_LC_REL_WAIT,     EV_RELEASE_CNF,         lc_release_ind},
472
        {ST_L3_LC_REL_WAIT,     EV_ESTABLISH_REQ,       lc_activate},
473
};
474
/* *INDENT-ON* */
475
 
476
#define L3_FN_COUNT (sizeof(L3FnList)/sizeof(struct FsmNode))
477
 
478
void
479
l3_msg(struct PStack *st, int pr, void *arg)
480
{
481
 
482
        switch (pr) {
483
                case (DL_DATA | REQUEST):
484
                        if (st->l3.l3m.state == ST_L3_LC_ESTAB) {
485
                                st->l3.l3l2(st, pr, arg);
486
                        } else {
487
                                struct sk_buff *skb = arg;
488
 
489
                                skb_queue_head(&st->l3.squeue, skb);
490
                                FsmEvent(&st->l3.l3m, EV_ESTABLISH_REQ, NULL);
491
                        }
492
                        break;
493
                case (DL_ESTABLISH | REQUEST):
494
                        FsmEvent(&st->l3.l3m, EV_ESTABLISH_REQ, NULL);
495
                        break;
496
                case (DL_ESTABLISH | CONFIRM):
497
                        FsmEvent(&st->l3.l3m, EV_ESTABLISH_CNF, NULL);
498
                        break;
499
                case (DL_ESTABLISH | INDICATION):
500
                        FsmEvent(&st->l3.l3m, EV_ESTABLISH_IND, NULL);
501
                        break;
502
                case (DL_RELEASE | INDICATION):
503
                        FsmEvent(&st->l3.l3m, EV_RELEASE_IND, NULL);
504
                        break;
505
                case (DL_RELEASE | CONFIRM):
506
                        FsmEvent(&st->l3.l3m, EV_RELEASE_CNF, NULL);
507
                        break;
508
                case (DL_RELEASE | REQUEST):
509
                        FsmEvent(&st->l3.l3m, EV_RELEASE_REQ, NULL);
510
                        break;
511
        }
512
}
513
 
514
HISAX_INITFUNC(void
515
Isdnl3New(void))
516
{
517
        l3fsm.state_count = L3_STATE_COUNT;
518
        l3fsm.event_count = L3_EVENT_COUNT;
519
        l3fsm.strEvent = strL3Event;
520
        l3fsm.strState = strL3State;
521
        FsmNew(&l3fsm, L3FnList, L3_FN_COUNT);
522
}
523
 
524
void
525
Isdnl3Free(void)
526
{
527
        FsmFree(&l3fsm);
528
}

powered by: WebSVN 2.1.0

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