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

Subversion Repositories or1k

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

Details | Compare with Previous | View Log

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

powered by: WebSVN 2.1.0

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