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

Subversion Repositories or1k

[/] [or1k/] [trunk/] [rc203soc/] [sw/] [uClinux/] [drivers/] [isdn/] [avmb1/] [capidrv.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
/*
2
 * $Id: capidrv.c,v 1.1 2005-12-20 10:16:58 jcastillo Exp $
3
 *
4
 * ISDN4Linux Driver, using capi20 interface (kernelcapi)
5
 *
6
 * Copyright 1997 by Carsten Paeth (calle@calle.in-berlin.de)
7
 *
8
 * $Log: not supported by cvs2svn $
9
 * Revision 1.1.1.1  2001/09/10 07:44:18  simons
10
 * Initial import
11
 *
12
 * Revision 1.1.1.1  2001/07/02 17:58:32  simons
13
 * Initial revision
14
 *
15
 * Revision 1.3.2.12  1998/09/11 15:37:11  calle
16
 * Started with support for CAPI channel allocation/bundling.
17
 *
18
 * Revision 1.3.2.11  1998/04/02 10:27:59  calle
19
 * version check for D2 trace was wrong :-(
20
 *
21
 * Revision 1.3.2.10  1998/03/20 14:38:24  calle
22
 * capidrv: prepared state machines for suspend/resume/hold
23
 * capidrv: fix bug in state machine if B1/T1 is out of nccis
24
 * b1capi: changed some errno returns.
25
 * b1capi: detect if you try to add same T1 to different io address.
26
 * b1capi: change number of nccis depending on number of channels.
27
 * b1lli: cosmetics
28
 *
29
 * Revision 1.3.2.9  1998/03/20 09:01:12  calle
30
 * Changes capi_register handling to get full support for 30 bchannels.
31
 *
32
 * Revision 1.3.2.8  1998/03/18 17:51:28  calle
33
 * added controller number to error messages
34
 *
35
 * Revision 1.3.2.7  1998/02/27 15:40:47  calle
36
 * T1 running with slow link. bugfix in capi_release.
37
 *
38
 * Revision 1.3.2.6  1998/02/02 19:51:13  calle
39
 * Fixed vbox (audio) acceptb.
40
 *
41
 * Revision 1.3.2.5  1997/10/29 09:35:29  calle
42
 * correct byteorder problem with new isdnlog interface.
43
 *
44
 * Revision 1.3.2.4  1997/10/26 15:04:24  calle
45
 * prepared isdnlog interface for d2-trace in newer firmware.
46
 *
47
 * Revision 1.3.2.3  1997/10/24 06:37:00  calle
48
 * changed LISTEN cipmask, now we can distinguish voice, fax und data calls.
49
 *
50
 * Revision 1.3.2.2  1997/10/08 05:42:25  calle
51
 * Added isdnlog support. patch to isdnlog needed.
52
 *
53
 * Revision 1.3.2.1  1997/07/13 12:16:48  calle
54
 * bug fix for more than one controller in connect_req.
55
 *
56
 * Revision 1.3  1997/05/18 09:24:15  calle
57
 * added verbose disconnect reason reporting to avmb1.
58
 * some fixes in capi20 interface.
59
 * changed info messages for B1-PCI
60
 *
61
 * Revision 1.2  1997/03/05 21:19:59  fritz
62
 * Removed include of config.h (mkdep stated this is unneded).
63
 *
64
 * Revision 1.1  1997/03/04 21:50:31  calle
65
 * Frirst version in isdn4linux
66
 *
67
 * Revision 2.2  1997/02/12 09:31:39  calle
68
 * new version
69
 *
70
 * Revision 1.1  1997/01/31 10:32:20  calle
71
 * Initial revision
72
 *
73
 */
74
 
75
#include <linux/module.h>
76
#include <linux/errno.h>
77
#include <linux/kernel.h>
78
#include <linux/major.h>
79
#include <linux/sched.h>
80
#include <linux/malloc.h>
81
#include <linux/fcntl.h>
82
#include <linux/fs.h>
83
#include <linux/signal.h>
84
#include <linux/mm.h>
85
#include <linux/timer.h>
86
#include <linux/wait.h>
87
#include <linux/skbuff.h>
88
#include <linux/isdn.h>
89
#include <linux/isdnif.h>
90
#include <linux/capi.h>
91
#include <linux/kernelcapi.h>
92
#include <linux/ctype.h>
93
 
94
#include "compat.h"
95
#include "capiutil.h"
96
#include "capicmd.h"
97
#include "capidrv.h"
98
 
99
static char *revision = "$Revision: 1.1 $";
100
int debugmode = 0;
101
 
102
#ifdef HAS_NEW_SYMTAB
103
MODULE_AUTHOR("Carsten Paeth <calle@calle.in-berlin.de>");
104
MODULE_PARM(debugmode, "i");
105
#endif
106
 
107
/* -------- type definitions ----------------------------------------- */
108
 
109
 
110
struct capidrv_contr {
111
 
112
        struct capidrv_contr *next;
113
 
114
        __u32 contrnr;
115
        char name[20];
116
 
117
        /*
118
         * for isdn4linux
119
         */
120
        isdn_if interface;
121
        int myid;
122
 
123
        /*
124
         * LISTEN state
125
         */
126
        int state;
127
        __u32 cipmask;
128
        __u32 cipmask2;
129
 
130
        /*
131
         * ID of capi message sent
132
         */
133
        __u16 msgid;
134
 
135
        /*
136
         * B-Channels
137
         */
138
        int nbchan;
139
        struct capidrv_bchan {
140
                struct capidrv_contr *contr;
141
                __u8 msn[ISDN_MSNLEN];
142
                int l2;
143
                int l3;
144
                __u8 num[ISDN_MSNLEN];
145
                __u8 mynum[ISDN_MSNLEN];
146
                int si1;
147
                int si2;
148
                int incoming;
149
                int disconnecting;
150
                struct capidrv_plci {
151
                        struct capidrv_plci *next;
152
                        __u32 plci;
153
                        __u32 ncci;     /* ncci for CONNECT_ACTIVE_IND */
154
                        __u16 msgid;    /* to identfy CONNECT_CONF */
155
                        int chan;
156
                        int state;
157
                        int leasedline;
158
                        struct capidrv_ncci {
159
                                struct capidrv_ncci *next;
160
                                struct capidrv_plci *plcip;
161
                                __u32 ncci;
162
                                __u16 msgid;    /* to identfy CONNECT_B3_CONF */
163
                                int chan;
164
                                int state;
165
                                int oldstate;
166
                                /* */
167
                                __u16 datahandle;
168
                        } *ncci_list;
169
                } *plcip;
170
                struct capidrv_ncci *nccip;
171
        } *bchans;
172
 
173
        struct capidrv_plci *plci_list;
174
 
175
        /* for q931 data */
176
        __u8  q931_buf[4096];
177
        __u8 *q931_read;
178
        __u8 *q931_write;
179
        __u8 *q931_end;
180
};
181
 
182
 
183
struct capidrv_data {
184
        __u16 appid;
185
        int ncontr;
186
        struct capidrv_contr *contr_list;
187
};
188
 
189
typedef struct capidrv_plci capidrv_plci;
190
typedef struct capidrv_ncci capidrv_ncci;
191
typedef struct capidrv_contr capidrv_contr;
192
typedef struct capidrv_data capidrv_data;
193
typedef struct capidrv_bchan capidrv_bchan;
194
 
195
/* -------- data definitions ----------------------------------------- */
196
 
197
static capidrv_data global;
198
static struct capi_interface *capifuncs;
199
 
200
static void handle_dtrace_data(capidrv_contr *card,
201
        int send, int level2, __u8 *data, __u16 len);
202
 
203
/* -------- convert functions ---------------------------------------- */
204
 
205
static inline __u32 b1prot(int l2, int l3)
206
{
207
        switch (l2) {
208
        case ISDN_PROTO_L2_X75I:
209
        case ISDN_PROTO_L2_X75UI:
210
        case ISDN_PROTO_L2_X75BUI:
211
                return 0;
212
        case ISDN_PROTO_L2_HDLC:
213
        default:
214
                return 0;
215
        case ISDN_PROTO_L2_TRANS:
216
                return 1;
217
        }
218
}
219
 
220
static inline __u32 b2prot(int l2, int l3)
221
{
222
        switch (l2) {
223
        case ISDN_PROTO_L2_X75I:
224
        case ISDN_PROTO_L2_X75UI:
225
        case ISDN_PROTO_L2_X75BUI:
226
        default:
227
                return 0;
228
        case ISDN_PROTO_L2_HDLC:
229
        case ISDN_PROTO_L2_TRANS:
230
                return 1;
231
        }
232
}
233
 
234
static inline __u32 b3prot(int l2, int l3)
235
{
236
        switch (l2) {
237
        case ISDN_PROTO_L2_X75I:
238
        case ISDN_PROTO_L2_X75UI:
239
        case ISDN_PROTO_L2_X75BUI:
240
        case ISDN_PROTO_L2_HDLC:
241
        case ISDN_PROTO_L2_TRANS:
242
        default:
243
                return 0;
244
        }
245
}
246
 
247
static inline __u16 si2cip(__u8 si1, __u8 si2)
248
{
249
        static const __u8 cip[17][5] =
250
        {
251
        /*  0  1  2  3  4  */
252
                {0, 0, 0, 0, 0},     /*0 */
253
                {16, 16, 4, 26, 16},    /*1 */
254
                {17, 17, 17, 4, 4},     /*2 */
255
                {2, 2, 2, 2, 2},        /*3 */
256
                {18, 18, 18, 18, 18},   /*4 */
257
                {2, 2, 2, 2, 2},        /*5 */
258
                {0, 0, 0, 0, 0},     /*6 */
259
                {2, 2, 2, 2, 2},        /*7 */
260
                {2, 2, 2, 2, 2},        /*8 */
261
                {21, 21, 21, 21, 21},   /*9 */
262
                {19, 19, 19, 19, 19},   /*10 */
263
                {0, 0, 0, 0, 0},     /*11 */
264
                {0, 0, 0, 0, 0},     /*12 */
265
                {0, 0, 0, 0, 0},     /*13 */
266
                {0, 0, 0, 0, 0},     /*14 */
267
                {22, 22, 22, 22, 22},   /*15 */
268
                {27, 27, 27, 28, 27}    /*16 */
269
        };
270
        if (si1 > 16)
271
                si1 = 0;
272
        if (si2 > 4)
273
                si2 = 0;
274
 
275
        return (__u16) cip[si1][si2];
276
}
277
 
278
static inline __u8 cip2si1(__u16 cipval)
279
{
280
        static const __u8 si[32] =
281
        {7, 1, 7, 7, 1, 1, 7, 7,        /*0-7 */
282
         7, 1, 0, 0, 0, 0, 0, 0,      /*8-15 */
283
         1, 2, 4, 10, 9, 9, 15, 7,      /*16-23 */
284
         7, 7, 1, 16, 16, 0, 0, 0};        /*24-31 */
285
 
286
        if (cipval > 31)
287
                cipval = 0;      /* .... */
288
        return si[cipval];
289
}
290
 
291
static inline __u8 cip2si2(__u16 cipval)
292
{
293
        static const __u8 si[32] =
294
        {0, 0, 0, 0, 2, 3, 0, 0,      /*0-7 */
295
         0, 3, 0, 0, 0, 0, 0, 0,       /*8-15 */
296
         1, 2, 0, 0, 9, 0, 0, 0,     /*16-23 */
297
         0, 0, 3, 2, 3, 0, 0, 0};    /*24-31 */
298
 
299
        if (cipval > 31)
300
                cipval = 0;      /* .... */
301
        return si[cipval];
302
}
303
 
304
 
305
/* -------- controller managment ------------------------------------- */
306
 
307
static inline capidrv_contr *findcontrbydriverid(int driverid)
308
{
309
        capidrv_contr *p = global.contr_list;
310
 
311
        while (p) {
312
                if (p->myid == driverid)
313
                        return p;
314
                p = p->next;
315
        }
316
        return (capidrv_contr *) 0;
317
}
318
 
319
static capidrv_contr *findcontrbynumber(__u32 contr)
320
{
321
        capidrv_contr *p = global.contr_list;
322
 
323
        while (p) {
324
                if (p->contrnr == contr)
325
                        return p;
326
                p = p->next;
327
        }
328
        return (capidrv_contr *) 0;
329
}
330
 
331
 
332
/* -------- plci management ------------------------------------------ */
333
 
334
static capidrv_plci *new_plci(capidrv_contr * card, int chan)
335
{
336
        capidrv_plci *plcip;
337
 
338
        plcip = (capidrv_plci *) kmalloc(sizeof(capidrv_plci), GFP_ATOMIC);
339
 
340
        if (plcip == 0)
341
                return 0;
342
 
343
        memset(plcip, 0, sizeof(capidrv_plci));
344
        plcip->state = ST_PLCI_NONE;
345
        plcip->plci = 0;
346
        plcip->msgid = 0;
347
        plcip->chan = chan;
348
        plcip->next = card->plci_list;
349
        card->plci_list = plcip;
350
        card->bchans[chan].plcip = plcip;
351
 
352
        return plcip;
353
}
354
 
355
static capidrv_plci *find_plci_by_plci(capidrv_contr * card, __u32 plci)
356
{
357
        capidrv_plci *p;
358
        for (p = card->plci_list; p; p = p->next)
359
                if (p->plci == plci)
360
                        return p;
361
        return 0;
362
}
363
 
364
static capidrv_plci *find_plci_by_msgid(capidrv_contr * card, __u16 msgid)
365
{
366
        capidrv_plci *p;
367
        for (p = card->plci_list; p; p = p->next)
368
                if (p->msgid == msgid)
369
                        return p;
370
        return 0;
371
}
372
 
373
static capidrv_plci *find_plci_by_ncci(capidrv_contr * card, __u32 ncci)
374
{
375
        capidrv_plci *p;
376
        for (p = card->plci_list; p; p = p->next)
377
                if (p->plci == (ncci & 0xffff))
378
                        return p;
379
        return 0;
380
}
381
 
382
static void free_plci(capidrv_contr * card, capidrv_plci * plcip)
383
{
384
        capidrv_plci **pp;
385
 
386
        for (pp = &card->plci_list; *pp; pp = &(*pp)->next) {
387
                if (*pp == plcip) {
388
                        *pp = (*pp)->next;
389
                        card->bchans[plcip->chan].plcip = 0;
390
                        card->bchans[plcip->chan].disconnecting = 0;
391
                        card->bchans[plcip->chan].incoming = 0;
392
                        kfree(plcip);
393
                        return;
394
                }
395
        }
396
        printk(KERN_ERR "capidrv-%d: free_plci %p (0x%x) not found, Huh?\n",
397
               card->contrnr, plcip, plcip->plci);
398
}
399
 
400
/* -------- ncci management ------------------------------------------ */
401
 
402
static inline capidrv_ncci *new_ncci(capidrv_contr * card,
403
                                     capidrv_plci * plcip,
404
                                     __u32 ncci)
405
{
406
        capidrv_ncci *nccip;
407
 
408
        nccip = (capidrv_ncci *) kmalloc(sizeof(capidrv_ncci), GFP_ATOMIC);
409
 
410
        if (nccip == 0)
411
                return 0;
412
 
413
        memset(nccip, 0, sizeof(capidrv_ncci));
414
        nccip->ncci = ncci;
415
        nccip->state = ST_NCCI_NONE;
416
        nccip->plcip = plcip;
417
        nccip->chan = plcip->chan;
418
        nccip->datahandle = 0;
419
 
420
        nccip->next = plcip->ncci_list;
421
        plcip->ncci_list = nccip;
422
 
423
        card->bchans[plcip->chan].nccip = nccip;
424
 
425
        return nccip;
426
}
427
 
428
static inline capidrv_ncci *find_ncci(capidrv_contr * card, __u32 ncci)
429
{
430
        capidrv_plci *plcip;
431
        capidrv_ncci *p;
432
 
433
        if ((plcip = find_plci_by_ncci(card, ncci)) == 0)
434
                return 0;
435
 
436
        for (p = plcip->ncci_list; p; p = p->next)
437
                if (p->ncci == ncci)
438
                        return p;
439
        return 0;
440
}
441
 
442
static inline capidrv_ncci *find_ncci_by_msgid(capidrv_contr * card,
443
                                               __u32 ncci, __u16 msgid)
444
{
445
        capidrv_plci *plcip;
446
        capidrv_ncci *p;
447
 
448
        if ((plcip = find_plci_by_ncci(card, ncci)) == 0)
449
                return 0;
450
 
451
        for (p = plcip->ncci_list; p; p = p->next)
452
                if (p->msgid == msgid)
453
                        return p;
454
        return 0;
455
}
456
 
457
static void free_ncci(capidrv_contr * card, struct capidrv_ncci *nccip)
458
{
459
        struct capidrv_ncci **pp;
460
 
461
        for (pp = &(nccip->plcip->ncci_list); *pp; pp = &(*pp)->next) {
462
                if (*pp == nccip) {
463
                        *pp = (*pp)->next;
464
                        break;
465
                }
466
        }
467
        card->bchans[nccip->chan].nccip = 0;
468
        kfree(nccip);
469
}
470
 
471
/* -------- convert and send capi message ---------------------------- */
472
 
473
static void send_message(capidrv_contr * card, _cmsg * cmsg)
474
{
475
        struct sk_buff *skb;
476
        size_t len;
477
        capi_cmsg2message(cmsg, cmsg->buf);
478
        len = CAPIMSG_LEN(cmsg->buf);
479
        skb = dev_alloc_skb(len);
480
        SET_SKB_FREE(skb);
481
        memcpy(skb_put(skb, len), cmsg->buf, len);
482
        (*capifuncs->capi_put_message) (global.appid, skb);
483
}
484
 
485
/* -------- state machine -------------------------------------------- */
486
 
487
struct listenstatechange {
488
        int actstate;
489
        int nextstate;
490
        int event;
491
};
492
 
493
static struct listenstatechange listentable[] =
494
{
495
  {ST_LISTEN_NONE, ST_LISTEN_WAIT_CONF, EV_LISTEN_REQ},
496
  {ST_LISTEN_ACTIVE, ST_LISTEN_ACTIVE_WAIT_CONF, EV_LISTEN_REQ},
497
  {ST_LISTEN_WAIT_CONF, ST_LISTEN_NONE, EV_LISTEN_CONF_ERROR},
498
  {ST_LISTEN_ACTIVE_WAIT_CONF, ST_LISTEN_ACTIVE, EV_LISTEN_CONF_ERROR},
499
  {ST_LISTEN_WAIT_CONF, ST_LISTEN_NONE, EV_LISTEN_CONF_EMPTY},
500
  {ST_LISTEN_ACTIVE_WAIT_CONF, ST_LISTEN_NONE, EV_LISTEN_CONF_EMPTY},
501
  {ST_LISTEN_WAIT_CONF, ST_LISTEN_ACTIVE, EV_LISTEN_CONF_OK},
502
  {ST_LISTEN_ACTIVE_WAIT_CONF, ST_LISTEN_ACTIVE, EV_LISTEN_CONF_OK},
503
  {},
504
};
505
 
506
static void listen_change_state(capidrv_contr * card, int event)
507
{
508
        struct listenstatechange *p = listentable;
509
        while (p->event) {
510
                if (card->state == p->actstate && p->event == event) {
511
                        if (debugmode)
512
                                printk(KERN_DEBUG "capidrv-%d: listen_change_state %d -> %d\n",
513
                                       card->contrnr, card->state, p->nextstate);
514
                        card->state = p->nextstate;
515
                        return;
516
                }
517
                p++;
518
        }
519
        printk(KERN_ERR "capidrv-%d: listen_change_state state=%d event=%d ????\n",
520
               card->contrnr, card->state, event);
521
 
522
}
523
 
524
/* ------------------------------------------------------------------ */
525
 
526
static void p0(capidrv_contr * card, capidrv_plci * plci)
527
{
528
        isdn_ctrl cmd;
529
 
530
        card->bchans[plci->chan].contr = 0;
531
        cmd.command = ISDN_STAT_DHUP;
532
        cmd.driver = card->myid;
533
        cmd.arg = plci->chan;
534
        card->interface.statcallb(&cmd);
535
        free_plci(card, plci);
536
}
537
 
538
/* ------------------------------------------------------------------ */
539
 
540
struct plcistatechange {
541
        int actstate;
542
        int nextstate;
543
        int event;
544
        void (*changefunc) (capidrv_contr * card, capidrv_plci * plci);
545
};
546
 
547
static struct plcistatechange plcitable[] =
548
{
549
  /* P-0 */
550
  {ST_PLCI_NONE, ST_PLCI_OUTGOING, EV_PLCI_CONNECT_REQ, 0},
551
  {ST_PLCI_NONE, ST_PLCI_ALLOCATED, EV_PLCI_FACILITY_IND_UP, 0},
552
  {ST_PLCI_NONE, ST_PLCI_INCOMING, EV_PLCI_CONNECT_IND, 0},
553
  {ST_PLCI_NONE, ST_PLCI_RESUMEING, EV_PLCI_RESUME_REQ, 0},
554
  /* P-0.1 */
555
  {ST_PLCI_OUTGOING, ST_PLCI_NONE, EV_PLCI_CONNECT_CONF_ERROR, p0},
556
  {ST_PLCI_OUTGOING, ST_PLCI_ALLOCATED, EV_PLCI_CONNECT_CONF_OK, 0},
557
  {ST_PLCI_OUTGOING, ST_PLCI_DISCONNECTING, EV_PLCI_DISCONNECT_REQ, 0},
558
  {ST_PLCI_OUTGOING, ST_PLCI_DISCONNECTING, EV_PLCI_FACILITY_IND_DOWN, 0},
559
  /* P-1 */
560
  {ST_PLCI_ALLOCATED, ST_PLCI_ACTIVE, EV_PLCI_CONNECT_ACTIVE_IND, 0},
561
  {ST_PLCI_ALLOCATED, ST_PLCI_DISCONNECTING, EV_PLCI_DISCONNECT_REQ, 0},
562
  {ST_PLCI_ALLOCATED, ST_PLCI_DISCONNECTING, EV_PLCI_FACILITY_IND_DOWN, 0},
563
  {ST_PLCI_ALLOCATED, ST_PLCI_DISCONNECTED, EV_PLCI_DISCONNECT_IND, 0},
564
  /* P-ACT */
565
  {ST_PLCI_ACTIVE, ST_PLCI_DISCONNECTING, EV_PLCI_DISCONNECT_REQ, 0},
566
  {ST_PLCI_ACTIVE, ST_PLCI_DISCONNECTING, EV_PLCI_FACILITY_IND_DOWN, 0},
567
  {ST_PLCI_ACTIVE, ST_PLCI_DISCONNECTED, EV_PLCI_DISCONNECT_IND, 0},
568
  {ST_PLCI_ACTIVE, ST_PLCI_HELD, EV_PLCI_HOLD_IND, 0},
569
  {ST_PLCI_ACTIVE, ST_PLCI_DISCONNECTING, EV_PLCI_SUSPEND_IND, 0},
570
  /* P-2 */
571
  {ST_PLCI_INCOMING, ST_PLCI_DISCONNECTING, EV_PLCI_CONNECT_REJECT, 0},
572
  {ST_PLCI_INCOMING, ST_PLCI_FACILITY_IND, EV_PLCI_FACILITY_IND_UP, 0},
573
  {ST_PLCI_INCOMING, ST_PLCI_ACCEPTING, EV_PLCI_CONNECT_RESP, 0},
574
  {ST_PLCI_INCOMING, ST_PLCI_DISCONNECTING, EV_PLCI_DISCONNECT_REQ, 0},
575
  {ST_PLCI_INCOMING, ST_PLCI_DISCONNECTING, EV_PLCI_FACILITY_IND_DOWN, 0},
576
  {ST_PLCI_INCOMING, ST_PLCI_DISCONNECTED, EV_PLCI_DISCONNECT_IND, 0},
577
  {ST_PLCI_INCOMING, ST_PLCI_DISCONNECTING, EV_PLCI_CD_IND, 0},
578
  /* P-3 */
579
  {ST_PLCI_FACILITY_IND, ST_PLCI_DISCONNECTING, EV_PLCI_CONNECT_REJECT, 0},
580
  {ST_PLCI_FACILITY_IND, ST_PLCI_ACCEPTING, EV_PLCI_CONNECT_ACTIVE_IND, 0},
581
  {ST_PLCI_FACILITY_IND, ST_PLCI_DISCONNECTING, EV_PLCI_DISCONNECT_REQ, 0},
582
  {ST_PLCI_FACILITY_IND, ST_PLCI_DISCONNECTING, EV_PLCI_FACILITY_IND_DOWN, 0},
583
  {ST_PLCI_FACILITY_IND, ST_PLCI_DISCONNECTED, EV_PLCI_DISCONNECT_IND, 0},
584
  /* P-4 */
585
  {ST_PLCI_ACCEPTING, ST_PLCI_ACTIVE, EV_PLCI_CONNECT_ACTIVE_IND, 0},
586
  {ST_PLCI_ACCEPTING, ST_PLCI_DISCONNECTING, EV_PLCI_DISCONNECT_REQ, 0},
587
  {ST_PLCI_ACCEPTING, ST_PLCI_DISCONNECTING, EV_PLCI_FACILITY_IND_DOWN, 0},
588
  {ST_PLCI_ACCEPTING, ST_PLCI_DISCONNECTED, EV_PLCI_DISCONNECT_IND, 0},
589
  /* P-5 */
590
  {ST_PLCI_DISCONNECTING, ST_PLCI_DISCONNECTED, EV_PLCI_DISCONNECT_IND, 0},
591
  /* P-6 */
592
  {ST_PLCI_DISCONNECTED, ST_PLCI_NONE, EV_PLCI_DISCONNECT_RESP, p0},
593
  /* P-0.Res */
594
  {ST_PLCI_RESUMEING, ST_PLCI_NONE, EV_PLCI_RESUME_CONF_ERROR, p0},
595
  {ST_PLCI_RESUMEING, ST_PLCI_RESUME, EV_PLCI_RESUME_CONF_OK, 0},
596
  /* P-RES */
597
  {ST_PLCI_RESUME, ST_PLCI_ACTIVE, EV_PLCI_RESUME_IND, 0},
598
  /* P-HELD */
599
  {ST_PLCI_HELD, ST_PLCI_ACTIVE, EV_PLCI_RETRIEVE_IND, 0},
600
  {},
601
};
602
 
603
static void plci_change_state(capidrv_contr * card, capidrv_plci * plci, int event)
604
{
605
        struct plcistatechange *p = plcitable;
606
        while (p->event) {
607
                if (plci->state == p->actstate && p->event == event) {
608
                        if (debugmode)
609
                                printk(KERN_DEBUG "capidrv-%d: plci_change_state:0x%x %d -> %d\n",
610
                                  card->contrnr, plci->plci, plci->state, p->nextstate);
611
                        plci->state = p->nextstate;
612
                        if (p->changefunc)
613
                                p->changefunc(card, plci);
614
                        return;
615
                }
616
                p++;
617
        }
618
        printk(KERN_ERR "capidrv-%d: plci_change_state:0x%x state=%d event=%d ????\n",
619
               card->contrnr, plci->plci, plci->state, event);
620
}
621
 
622
/* ------------------------------------------------------------------ */
623
 
624
static _cmsg cmsg;
625
 
626
static void n0(capidrv_contr * card, capidrv_ncci * ncci)
627
{
628
        isdn_ctrl cmd;
629
 
630
        capi_fill_DISCONNECT_REQ(&cmsg,
631
                                 global.appid,
632
                                 card->msgid++,
633
                                 ncci->plcip->plci,
634
                                 0,      /* BChannelinformation */
635
                                 0,      /* Keypadfacility */
636
                                 0,      /* Useruserdata */   /* $$$$ */
637
 
638
        );
639
        send_message(card, &cmsg);
640
        plci_change_state(card, ncci->plcip, EV_PLCI_DISCONNECT_REQ);
641
 
642
        cmd.command = ISDN_STAT_BHUP;
643
        cmd.driver = card->myid;
644
        cmd.arg = ncci->chan;
645
        card->interface.statcallb(&cmd);
646
        free_ncci(card, ncci);
647
}
648
 
649
/* ------------------------------------------------------------------ */
650
 
651
struct nccistatechange {
652
        int actstate;
653
        int nextstate;
654
        int event;
655
        void (*changefunc) (capidrv_contr * card, capidrv_ncci * ncci);
656
};
657
 
658
static struct nccistatechange nccitable[] =
659
{
660
  /* N-0 */
661
  {ST_NCCI_NONE, ST_NCCI_OUTGOING, EV_NCCI_CONNECT_B3_REQ, 0},
662
  {ST_NCCI_NONE, ST_NCCI_INCOMING, EV_NCCI_CONNECT_B3_IND, 0},
663
  /* N-0.1 */
664
  {ST_NCCI_OUTGOING, ST_NCCI_ALLOCATED, EV_NCCI_CONNECT_B3_CONF_OK, 0},
665
  {ST_NCCI_OUTGOING, ST_NCCI_NONE, EV_NCCI_CONNECT_B3_CONF_ERROR, n0},
666
  /* N-1 */
667
  {ST_NCCI_INCOMING, ST_NCCI_DISCONNECTING, EV_NCCI_CONNECT_B3_REJECT, 0},
668
  {ST_NCCI_INCOMING, ST_NCCI_ALLOCATED, EV_NCCI_CONNECT_B3_RESP, 0},
669
  {ST_NCCI_INCOMING, ST_NCCI_DISCONNECTED, EV_NCCI_DISCONNECT_B3_IND, 0},
670
  {ST_NCCI_INCOMING, ST_NCCI_DISCONNECTING, EV_NCCI_DISCONNECT_B3_REQ, 0},
671
  /* N-2 */
672
  {ST_NCCI_ALLOCATED, ST_NCCI_ACTIVE, EV_NCCI_CONNECT_B3_ACTIVE_IND, 0},
673
  {ST_NCCI_ALLOCATED, ST_NCCI_DISCONNECTED, EV_NCCI_DISCONNECT_B3_IND, 0},
674
  {ST_NCCI_ALLOCATED, ST_NCCI_DISCONNECTING, EV_NCCI_DISCONNECT_B3_REQ, 0},
675
  /* N-ACT */
676
  {ST_NCCI_ACTIVE, ST_NCCI_ACTIVE, EV_NCCI_RESET_B3_IND, 0},
677
  {ST_NCCI_ACTIVE, ST_NCCI_RESETING, EV_NCCI_RESET_B3_REQ, 0},
678
  {ST_NCCI_ACTIVE, ST_NCCI_DISCONNECTED, EV_NCCI_DISCONNECT_B3_IND, 0},
679
  {ST_NCCI_ACTIVE, ST_NCCI_DISCONNECTING, EV_NCCI_DISCONNECT_B3_REQ, 0},
680
  /* N-3 */
681
  {ST_NCCI_RESETING, ST_NCCI_ACTIVE, EV_NCCI_RESET_B3_IND, 0},
682
  {ST_NCCI_RESETING, ST_NCCI_DISCONNECTED, EV_NCCI_DISCONNECT_B3_IND, 0},
683
  {ST_NCCI_RESETING, ST_NCCI_DISCONNECTING, EV_NCCI_DISCONNECT_B3_REQ, 0},
684
  /* N-4 */
685
  {ST_NCCI_DISCONNECTING, ST_NCCI_DISCONNECTED, EV_NCCI_DISCONNECT_B3_IND, 0},
686
  {ST_NCCI_DISCONNECTING, ST_NCCI_PREVIOUS, EV_NCCI_DISCONNECT_B3_CONF_ERROR,0},
687
  /* N-5 */
688
  {ST_NCCI_DISCONNECTED, ST_NCCI_NONE, EV_NCCI_DISCONNECT_B3_RESP, n0},
689
  {},
690
};
691
 
692
static void ncci_change_state(capidrv_contr * card, capidrv_ncci * ncci, int event)
693
{
694
        struct nccistatechange *p = nccitable;
695
        while (p->event) {
696
                if (ncci->state == p->actstate && p->event == event) {
697
                        if (debugmode)
698
                                printk(KERN_DEBUG "capidrv-%d: ncci_change_state:0x%x %d -> %d\n",
699
                                  card->contrnr, ncci->ncci, ncci->state, p->nextstate);
700
                        if (p->nextstate == ST_NCCI_PREVIOUS) {
701
                                ncci->state = ncci->oldstate;
702
                                ncci->oldstate = p->actstate;
703
                        } else {
704
                                ncci->oldstate = p->actstate;
705
                                ncci->state = p->nextstate;
706
                        }
707
                        if (p->changefunc)
708
                                p->changefunc(card, ncci);
709
                        return;
710
                }
711
                p++;
712
        }
713
        printk(KERN_ERR "capidrv-%d: ncci_change_state:0x%x state=%d event=%d ????\n",
714
               card->contrnr, ncci->ncci, ncci->state, event);
715
}
716
 
717
/* ------------------------------------------------------------------- */
718
 
719
static inline int new_bchan(capidrv_contr * card)
720
{
721
        int i;
722
        for (i = 0; i < card->nbchan; i++) {
723
                if (card->bchans[i].plcip == 0) {
724
                        card->bchans[i].disconnecting = 0;
725
                        return i;
726
                }
727
        }
728
        return -1;
729
}
730
 
731
/* ------------------------------------------------------------------- */
732
 
733
static void handle_controller(_cmsg * cmsg)
734
{
735
        capidrv_contr *card = findcontrbynumber(cmsg->adr.adrController & 0x7f);
736
 
737
        if (!card) {
738
                printk(KERN_ERR "capidrv: %s from unknown controller 0x%x\n",
739
                       capi_cmd2str(cmsg->Command, cmsg->Subcommand),
740
                       cmsg->adr.adrController & 0x7f);
741
                return;
742
        }
743
        switch (CAPICMD(cmsg->Command, cmsg->Subcommand)) {
744
 
745
        case CAPI_LISTEN_CONF:  /* Controller */
746
                if (debugmode)
747
                        printk(KERN_DEBUG "capidrv-%d: listenconf Info=0x%4x (%s) cipmask=0x%x\n",
748
                               card->contrnr, cmsg->Info, capi_info2str(cmsg->Info), card->cipmask);
749
                if (cmsg->Info) {
750
                        listen_change_state(card, EV_LISTEN_CONF_ERROR);
751
                } else if (card->cipmask == 0) {
752
                        listen_change_state(card, EV_LISTEN_CONF_EMPTY);
753
                } else {
754
                        listen_change_state(card, EV_LISTEN_CONF_OK);
755
                }
756
                break;
757
 
758
        case CAPI_MANUFACTURER_IND:     /* Controller */
759
                if (   cmsg->ManuID == 0x214D5641
760
                    && cmsg->Class == 0
761
                    && cmsg->Function == 1) {
762
                   __u8  *data = cmsg->ManuData+3;
763
                   __u16  len = cmsg->ManuData[0];
764
                   __u16 layer;
765
                   int direction;
766
                   if (len == 255) {
767
                      len = (cmsg->ManuData[1] | (cmsg->ManuData[2] << 8));
768
                      data += 2;
769
                   }
770
                   len -= 2;
771
                   layer = ((*(data-1)) << 8) | *(data-2);
772
                   if (layer & 0x300)
773
                        direction = (layer & 0x200) ? 0 : 1;
774
                   else direction = (layer & 0x800) ? 0 : 1;
775
                   if (layer & 0x0C00) {
776
                        if ((layer & 0xff) == 0x80) {
777
                           handle_dtrace_data(card, direction, 1, data, len);
778
                           break;
779
                        }
780
                   } else if ((layer & 0xff) < 0x80) {
781
                      handle_dtrace_data(card, direction, 0, data, len);
782
                      break;
783
                   }
784
                   printk(KERN_INFO "capidrv-%d: %s from controller 0x%x layer 0x%x, ignored\n",
785
                        card->contrnr,
786
                        capi_cmd2str(cmsg->Command, cmsg->Subcommand),
787
                        cmsg->adr.adrController, layer);
788
                   break;
789
                }
790
                goto ignored;
791
        case CAPI_MANUFACTURER_CONF:    /* Controller */
792
                if (cmsg->ManuID == 0x214D5641) {
793
                   char *s = 0;
794
                   switch (cmsg->Class) {
795
                      case 0: break;
796
                      case 1: s = "unknown class"; break;
797
                      case 2: s = "unknown function"; break;
798
                      default: s = "unkown error"; break;
799
                   }
800
                   if (s)
801
                   printk(KERN_INFO "capidrv-%d: %s from controller 0x%x function %d: %s\n",
802
                        card->contrnr,
803
                        capi_cmd2str(cmsg->Command, cmsg->Subcommand),
804
                        cmsg->adr.adrController,
805
                        cmsg->Function, s);
806
                   break;
807
                }
808
                goto ignored;
809
        case CAPI_FACILITY_IND: /* Controller/plci/ncci */
810
                goto ignored;
811
        case CAPI_FACILITY_CONF:        /* Controller/plci/ncci */
812
                goto ignored;
813
        case CAPI_INFO_IND:     /* Controller/plci */
814
                goto ignored;
815
        case CAPI_INFO_CONF:    /* Controller/plci */
816
                goto ignored;
817
 
818
        default:
819
                printk(KERN_ERR "capidrv-%d: got %s from controller 0x%x ???",
820
                       card->contrnr,
821
                       capi_cmd2str(cmsg->Command, cmsg->Subcommand),
822
                       cmsg->adr.adrController);
823
        }
824
        return;
825
 
826
      ignored:
827
        printk(KERN_INFO "capidrv-%d: %s from controller 0x%x ignored\n",
828
               card->contrnr,
829
               capi_cmd2str(cmsg->Command, cmsg->Subcommand),
830
               cmsg->adr.adrController);
831
}
832
 
833
static void handle_incoming_call(capidrv_contr * card, _cmsg * cmsg)
834
{
835
        capidrv_plci *plcip;
836
        capidrv_bchan *bchan;
837
        isdn_ctrl cmd;
838
        int chan;
839
 
840
        if ((chan = new_bchan(card)) == -1) {
841
                printk(KERN_ERR "capidrv-%d: incoming call on not existing bchan ?\n", card->contrnr);
842
                return;
843
        }
844
        bchan = &card->bchans[chan];
845
        if ((plcip = new_plci(card, chan)) == 0) {
846
                printk(KERN_ERR "capidrv-%d: incoming call: no memory, sorry.\n", card->contrnr);
847
                return;
848
        }
849
        bchan->incoming = 1;
850
        plcip->plci = cmsg->adr.adrPLCI;
851
        plci_change_state(card, plcip, EV_PLCI_CONNECT_IND);
852
 
853
        cmd.command = ISDN_STAT_ICALL;
854
        cmd.driver = card->myid;
855
        cmd.arg = chan;
856
        memset(&cmd.parm.setup, 0, sizeof(cmd.parm.setup));
857
        strncpy(cmd.parm.setup.phone,
858
                cmsg->CallingPartyNumber + 3,
859
                cmsg->CallingPartyNumber[0] - 2);
860
        strncpy(cmd.parm.setup.eazmsn,
861
                cmsg->CalledPartyNumber + 2,
862
                cmsg->CalledPartyNumber[0] - 1);
863
        cmd.parm.setup.si1 = cip2si1(cmsg->CIPValue);
864
        cmd.parm.setup.si2 = cip2si2(cmsg->CIPValue);
865
        cmd.parm.setup.plan = cmsg->CallingPartyNumber[1];
866
        cmd.parm.setup.screen = cmsg->CallingPartyNumber[2];
867
 
868
        printk(KERN_INFO "capidrv-%d: incoming call %s,%d,%d,%s\n",
869
                        card->contrnr,
870
                        cmd.parm.setup.phone,
871
                        cmd.parm.setup.si1,
872
                        cmd.parm.setup.si2,
873
                        cmd.parm.setup.eazmsn);
874
 
875
        switch (card->interface.statcallb(&cmd)) {
876
        case 0:
877
                /* No device matching this call.
878
                 * and isdn_common.c has send a HANGUP command
879
                 * which is ignored in state ST_PLCI_INCOMING,
880
                 * so we send RESP to ignore the call
881
                 */
882
                capi_cmsg_answer(cmsg);
883
                cmsg->Reject = 1;       /* ignore */
884
                send_message(card, cmsg);
885
                plci_change_state(card, plcip, EV_PLCI_CONNECT_REJECT);
886
                printk(KERN_INFO "capidrv-%d: incoming call %s,%d,%d,%s ignored\n",
887
                        card->contrnr,
888
                        cmd.parm.setup.phone,
889
                        cmd.parm.setup.si1,
890
                        cmd.parm.setup.si2,
891
                        cmd.parm.setup.eazmsn);
892
                break;
893
        case 1:
894
                /* At least one device matching this call (RING on ttyI)
895
                 * HL-driver may send ALERTING on the D-channel in this
896
                 * case.
897
                 * really means: RING on ttyI or a net interface
898
                 * accepted this call already.
899
                 *
900
                 * If the call was accepted, state has already changed,
901
                 * and CONNECT_RESP already sent.
902
                 */
903
                if (plcip->state == ST_PLCI_INCOMING) {
904
                        printk(KERN_INFO "capidrv-%d: incoming call %s,%d,%d,%s tty alerting\n",
905
                                card->contrnr,
906
                                cmd.parm.setup.phone,
907
                                cmd.parm.setup.si1,
908
                                cmd.parm.setup.si2,
909
                                cmd.parm.setup.eazmsn);
910
                        capi_fill_ALERT_REQ(cmsg,
911
                                            global.appid,
912
                                            card->msgid++,
913
                                            plcip->plci,        /* adr */
914
                                            0,   /* BChannelinformation */
915
                                            0,   /* Keypadfacility */
916
                                            0,   /* Useruserdata */
917
 
918
                        );
919
                        plcip->msgid = cmsg->Messagenumber;
920
                        send_message(card, cmsg);
921
                } else {
922
                        printk(KERN_INFO "capidrv-%d: incoming call %s,%d,%d,%s on netdev\n",
923
                                card->contrnr,
924
                                cmd.parm.setup.phone,
925
                                cmd.parm.setup.si1,
926
                                cmd.parm.setup.si2,
927
                                cmd.parm.setup.eazmsn);
928
                }
929
                break;
930
 
931
        case 2:         /* Call will be rejected. */
932
                capi_cmsg_answer(cmsg);
933
                cmsg->Reject = 2;       /* reject call, normal call clearing */
934
                send_message(card, cmsg);
935
                plci_change_state(card, plcip, EV_PLCI_CONNECT_REJECT);
936
                break;
937
 
938
        default:
939
                /* An error happened. (Invalid parameters for example.) */
940
                capi_cmsg_answer(cmsg);
941
                cmsg->Reject = 8;       /* reject call,
942
                                           destination out of order */
943
                send_message(card, cmsg);
944
                plci_change_state(card, plcip, EV_PLCI_CONNECT_REJECT);
945
                break;
946
        }
947
        return;
948
}
949
 
950
static void handle_plci(_cmsg * cmsg)
951
{
952
        capidrv_contr *card = findcontrbynumber(cmsg->adr.adrController & 0x7f);
953
        capidrv_plci *plcip;
954
        isdn_ctrl cmd;
955
 
956
        if (!card) {
957
                printk(KERN_ERR "capidrv: %s from unknown controller 0x%x\n",
958
                       capi_cmd2str(cmsg->Command, cmsg->Subcommand),
959
                       cmsg->adr.adrController & 0x7f);
960
                return;
961
        }
962
        switch (CAPICMD(cmsg->Command, cmsg->Subcommand)) {
963
 
964
        case CAPI_DISCONNECT_IND:       /* plci */
965
                if (cmsg->Reason) {
966
                        printk(KERN_INFO "capidrv-%d: %s reason 0x%x (%s) for plci 0x%x\n",
967
                           card->contrnr,
968
                           capi_cmd2str(cmsg->Command, cmsg->Subcommand),
969
                               cmsg->Reason, capi_info2str(cmsg->Reason), cmsg->adr.adrPLCI);
970
                }
971
                if (!(plcip = find_plci_by_plci(card, cmsg->adr.adrPLCI))) {
972
                        capi_cmsg_answer(cmsg);
973
                        send_message(card, cmsg);
974
                        goto notfound;
975
                }
976
                card->bchans[plcip->chan].disconnecting = 1;
977
                plci_change_state(card, plcip, EV_PLCI_DISCONNECT_IND);
978
                capi_cmsg_answer(cmsg);
979
                send_message(card, cmsg);
980
                plci_change_state(card, plcip, EV_PLCI_DISCONNECT_RESP);
981
                break;
982
 
983
        case CAPI_DISCONNECT_CONF:      /* plci */
984
                if (cmsg->Info) {
985
                        printk(KERN_INFO "capidrv-%d: %s info 0x%x (%s) for plci 0x%x\n",
986
                           card->contrnr,
987
                           capi_cmd2str(cmsg->Command, cmsg->Subcommand),
988
                               cmsg->Info, capi_info2str(cmsg->Info),
989
                               cmsg->adr.adrPLCI);
990
                }
991
                if (!(plcip = find_plci_by_plci(card, cmsg->adr.adrPLCI)))
992
                        goto notfound;
993
 
994
                card->bchans[plcip->chan].disconnecting = 1;
995
                break;
996
 
997
        case CAPI_ALERT_CONF:   /* plci */
998
                if (cmsg->Info) {
999
                        printk(KERN_INFO "capidrv-%d: %s info 0x%x (%s) for plci 0x%x\n",
1000
                           card->contrnr,
1001
                           capi_cmd2str(cmsg->Command, cmsg->Subcommand),
1002
                               cmsg->Info, capi_info2str(cmsg->Info),
1003
                               cmsg->adr.adrPLCI);
1004
                }
1005
                break;
1006
 
1007
        case CAPI_CONNECT_IND:  /* plci */
1008
                handle_incoming_call(card, cmsg);
1009
                break;
1010
 
1011
        case CAPI_CONNECT_CONF: /* plci */
1012
                if (cmsg->Info) {
1013
                        printk(KERN_INFO "capidrv-%d: %s info 0x%x (%s) for plci 0x%x\n",
1014
                           card->contrnr,
1015
                           capi_cmd2str(cmsg->Command, cmsg->Subcommand),
1016
                               cmsg->Info, capi_info2str(cmsg->Info),
1017
                               cmsg->adr.adrPLCI);
1018
                }
1019
                if (!(plcip = find_plci_by_msgid(card, cmsg->Messagenumber)))
1020
                        goto notfound;
1021
 
1022
                plcip->plci = cmsg->adr.adrPLCI;
1023
                if (cmsg->Info) {
1024
                        plci_change_state(card, plcip, EV_PLCI_CONNECT_CONF_ERROR);
1025
                } else {
1026
                        plci_change_state(card, plcip, EV_PLCI_CONNECT_CONF_OK);
1027
                }
1028
                break;
1029
 
1030
        case CAPI_CONNECT_ACTIVE_IND:   /* plci */
1031
 
1032
                if (!(plcip = find_plci_by_plci(card, cmsg->adr.adrPLCI)))
1033
                        goto notfound;
1034
 
1035
                if (card->bchans[plcip->chan].incoming) {
1036
                        capi_cmsg_answer(cmsg);
1037
                        send_message(card, cmsg);
1038
                        plci_change_state(card, plcip, EV_PLCI_CONNECT_ACTIVE_IND);
1039
                } else {
1040
                        capidrv_ncci *nccip;
1041
                        capi_cmsg_answer(cmsg);
1042
                        send_message(card, cmsg);
1043
 
1044
                        nccip = new_ncci(card, plcip, cmsg->adr.adrPLCI);
1045
 
1046
                        if (!nccip) {
1047
                                printk(KERN_ERR "capidrv-%d: no mem for ncci, sorry\n", card->contrnr);
1048
                                break;  /* $$$$ */
1049
                        }
1050
                        capi_fill_CONNECT_B3_REQ(cmsg,
1051
                                                 global.appid,
1052
                                                 card->msgid++,
1053
                                                 plcip->plci,   /* adr */
1054
 
1055
                        );
1056
                        nccip->msgid = cmsg->Messagenumber;
1057
                        send_message(card, cmsg);
1058
                        cmd.command = ISDN_STAT_DCONN;
1059
                        cmd.driver = card->myid;
1060
                        cmd.arg = plcip->chan;
1061
                        card->interface.statcallb(&cmd);
1062
                        plci_change_state(card, plcip, EV_PLCI_CONNECT_ACTIVE_IND);
1063
                        ncci_change_state(card, nccip, EV_NCCI_CONNECT_B3_REQ);
1064
                }
1065
                break;
1066
 
1067
        case CAPI_INFO_IND:     /* Controller/plci */
1068
 
1069
                if (!(plcip = find_plci_by_plci(card, cmsg->adr.adrPLCI)))
1070
                        goto notfound;
1071
 
1072
                if (cmsg->InfoNumber == 0x4000) {
1073
                        if (cmsg->InfoElement[0] == 4) {
1074
                                cmd.command = ISDN_STAT_CINF;
1075
                                cmd.driver = card->myid;
1076
                                cmd.arg = plcip->chan;
1077
                                sprintf(cmd.parm.num, "%lu",
1078
                                        (unsigned long)
1079
                                        ((__u32) cmsg->InfoElement[1]
1080
                                  | ((__u32) (cmsg->InfoElement[2]) << 8)
1081
                                 | ((__u32) (cmsg->InfoElement[3]) << 16)
1082
                                         | ((__u32) (cmsg->InfoElement[4]) << 24)));
1083
                                card->interface.statcallb(&cmd);
1084
                                break;
1085
                        }
1086
                }
1087
                printk(KERN_ERR "capidrv-%d: %s\n",
1088
                                card->contrnr, capi_cmsg2str(cmsg));
1089
                break;
1090
 
1091
        case CAPI_CONNECT_ACTIVE_CONF:          /* plci */
1092
                goto ignored;
1093
        case CAPI_SELECT_B_PROTOCOL_CONF:       /* plci */
1094
                goto ignored;
1095
        case CAPI_FACILITY_IND: /* Controller/plci/ncci */
1096
                goto ignored;
1097
        case CAPI_FACILITY_CONF:        /* Controller/plci/ncci */
1098
                goto ignored;
1099
 
1100
        case CAPI_INFO_CONF:    /* Controller/plci */
1101
                goto ignored;
1102
 
1103
        default:
1104
                printk(KERN_ERR "capidrv-%d: got %s for plci 0x%x ???",
1105
                       card->contrnr,
1106
                       capi_cmd2str(cmsg->Command, cmsg->Subcommand),
1107
                       cmsg->adr.adrPLCI);
1108
        }
1109
        return;
1110
      ignored:
1111
        printk(KERN_INFO "capidrv-%d: %s for plci 0x%x ignored\n",
1112
               card->contrnr,
1113
               capi_cmd2str(cmsg->Command, cmsg->Subcommand),
1114
               cmsg->adr.adrPLCI);
1115
        return;
1116
      notfound:
1117
        printk(KERN_ERR "capidrv-%d: %s: plci 0x%x not found\n",
1118
               card->contrnr,
1119
               capi_cmd2str(cmsg->Command, cmsg->Subcommand),
1120
               cmsg->adr.adrPLCI);
1121
        return;
1122
}
1123
 
1124
static void handle_ncci(_cmsg * cmsg)
1125
{
1126
        capidrv_contr *card = findcontrbynumber(cmsg->adr.adrController & 0x7f);
1127
        capidrv_plci *plcip;
1128
        capidrv_ncci *nccip;
1129
        isdn_ctrl cmd;
1130
 
1131
        if (!card) {
1132
                printk(KERN_ERR "capidrv: %s from unknown controller 0x%x\n",
1133
                       capi_cmd2str(cmsg->Command, cmsg->Subcommand),
1134
                       cmsg->adr.adrController & 0x7f);
1135
                return;
1136
        }
1137
        switch (CAPICMD(cmsg->Command, cmsg->Subcommand)) {
1138
 
1139
        case CAPI_CONNECT_B3_ACTIVE_IND:        /* ncci */
1140
                if (!(nccip = find_ncci(card, cmsg->adr.adrNCCI)))
1141
                        goto notfound;
1142
 
1143
                capi_cmsg_answer(cmsg);
1144
                send_message(card, cmsg);
1145
                ncci_change_state(card, nccip, EV_NCCI_CONNECT_B3_ACTIVE_IND);
1146
 
1147
                cmd.command = ISDN_STAT_BCONN;
1148
                cmd.driver = card->myid;
1149
                cmd.arg = nccip->chan;
1150
                card->interface.statcallb(&cmd);
1151
 
1152
                printk(KERN_INFO "capidrv-%d: chan %d up with ncci 0x%x\n",
1153
                       card->contrnr, nccip->chan, nccip->ncci);
1154
                break;
1155
 
1156
        case CAPI_CONNECT_B3_ACTIVE_CONF:       /* ncci */
1157
                goto ignored;
1158
 
1159
        case CAPI_CONNECT_B3_IND:       /* ncci */
1160
 
1161
                plcip = find_plci_by_ncci(card, cmsg->adr.adrNCCI);
1162
                if (plcip) {
1163
                        nccip = new_ncci(card, plcip, cmsg->adr.adrNCCI);
1164
                        if (nccip) {
1165
                                ncci_change_state(card, nccip, EV_NCCI_CONNECT_B3_IND);
1166
                                capi_fill_CONNECT_B3_RESP(cmsg,
1167
                                                          global.appid,
1168
                                                          card->msgid++,
1169
                                                          nccip->ncci,  /* adr */
1170
                                                          0,     /* Reject */
1171
 
1172
                                );
1173
                                send_message(card, cmsg);
1174
                                ncci_change_state(card, nccip, EV_NCCI_CONNECT_B3_RESP);
1175
                                break;
1176
                        }
1177
                        printk(KERN_ERR "capidrv-%d: no mem for ncci, sorry\n",                                                 card->contrnr);
1178
                } else {
1179
                        printk(KERN_ERR "capidrv-%d: %s: plci for ncci 0x%x not found\n",
1180
                           card->contrnr,
1181
                           capi_cmd2str(cmsg->Command, cmsg->Subcommand),
1182
                               cmsg->adr.adrNCCI);
1183
                }
1184
                capi_fill_CONNECT_B3_RESP(cmsg,
1185
                                          global.appid,
1186
                                          card->msgid++,
1187
                                          cmsg->adr.adrNCCI,
1188
                                          2,    /* Reject */
1189
 
1190
                );
1191
                send_message(card, cmsg);
1192
                break;
1193
 
1194
        case CAPI_CONNECT_B3_CONF:      /* ncci */
1195
 
1196
                if (!(nccip = find_ncci_by_msgid(card,
1197
                                                 cmsg->adr.adrNCCI,
1198
                                                 cmsg->Messagenumber)))
1199
                        goto notfound;
1200
 
1201
                nccip->ncci = cmsg->adr.adrNCCI;
1202
                if (cmsg->Info) {
1203
                        printk(KERN_INFO "capidrv-%d: %s info 0x%x (%s) for ncci 0x%x\n",
1204
                           card->contrnr,
1205
                           capi_cmd2str(cmsg->Command, cmsg->Subcommand),
1206
                               cmsg->Info, capi_info2str(cmsg->Info),
1207
                               cmsg->adr.adrNCCI);
1208
                }
1209
 
1210
                if (cmsg->Info)
1211
                        ncci_change_state(card, nccip, EV_NCCI_CONNECT_B3_CONF_ERROR);
1212
                else
1213
                        ncci_change_state(card, nccip, EV_NCCI_CONNECT_B3_CONF_OK);
1214
                break;
1215
 
1216
        case CAPI_CONNECT_B3_T90_ACTIVE_IND:    /* ncci */
1217
                capi_cmsg_answer(cmsg);
1218
                send_message(card, cmsg);
1219
                break;
1220
 
1221
        case CAPI_DATA_B3_IND:  /* ncci */
1222
                /* handled in handle_data() */
1223
                goto ignored;
1224
 
1225
        case CAPI_DATA_B3_CONF: /* ncci */
1226
                if (!(nccip = find_ncci(card, cmsg->adr.adrNCCI)))
1227
                        goto notfound;
1228
 
1229
                cmd.command = ISDN_STAT_BSENT;
1230
                cmd.driver = card->myid;
1231
                cmd.arg = nccip->chan;
1232
                card->interface.statcallb(&cmd);
1233
 
1234
                break;
1235
 
1236
        case CAPI_DISCONNECT_B3_IND:    /* ncci */
1237
                if (!(nccip = find_ncci(card, cmsg->adr.adrNCCI)))
1238
                        goto notfound;
1239
 
1240
                card->bchans[nccip->chan].disconnecting = 1;
1241
                ncci_change_state(card, nccip, EV_NCCI_DISCONNECT_B3_IND);
1242
                capi_cmsg_answer(cmsg);
1243
                send_message(card, cmsg);
1244
                ncci_change_state(card, nccip, EV_NCCI_DISCONNECT_B3_RESP);
1245
                break;
1246
 
1247
        case CAPI_DISCONNECT_B3_CONF:   /* ncci */
1248
                if (!(nccip = find_ncci(card, cmsg->adr.adrNCCI)))
1249
                        goto notfound;
1250
                if (cmsg->Info) {
1251
                        printk(KERN_INFO "capidrv-%d: %s info 0x%x (%s) for ncci 0x%x\n",
1252
                           card->contrnr,
1253
                           capi_cmd2str(cmsg->Command, cmsg->Subcommand),
1254
                               cmsg->Info, capi_info2str(cmsg->Info),
1255
                               cmsg->adr.adrNCCI);
1256
                        ncci_change_state(card, nccip, EV_NCCI_DISCONNECT_B3_CONF_ERROR);
1257
                }
1258
                break;
1259
 
1260
        case CAPI_RESET_B3_IND: /* ncci */
1261
                if (!(nccip = find_ncci(card, cmsg->adr.adrNCCI)))
1262
                        goto notfound;
1263
                ncci_change_state(card, nccip, EV_NCCI_RESET_B3_IND);
1264
                capi_cmsg_answer(cmsg);
1265
                send_message(card, cmsg);
1266
                break;
1267
 
1268
        case CAPI_RESET_B3_CONF:        /* ncci */
1269
                goto ignored;   /* $$$$ */
1270
 
1271
        case CAPI_FACILITY_IND: /* Controller/plci/ncci */
1272
                goto ignored;
1273
        case CAPI_FACILITY_CONF:        /* Controller/plci/ncci */
1274
                goto ignored;
1275
 
1276
        default:
1277
                printk(KERN_ERR "capidrv-%d: got %s for ncci 0x%x ???",
1278
                       card->contrnr,
1279
                       capi_cmd2str(cmsg->Command, cmsg->Subcommand),
1280
                       cmsg->adr.adrNCCI);
1281
        }
1282
        return;
1283
      ignored:
1284
        printk(KERN_INFO "capidrv-%d: %s for ncci 0x%x ignored\n",
1285
               card->contrnr,
1286
               capi_cmd2str(cmsg->Command, cmsg->Subcommand),
1287
               cmsg->adr.adrNCCI);
1288
        return;
1289
      notfound:
1290
        printk(KERN_ERR "capidrv-%d: %s: ncci 0x%x not found\n",
1291
               card->contrnr,
1292
               capi_cmd2str(cmsg->Command, cmsg->Subcommand),
1293
               cmsg->adr.adrNCCI);
1294
}
1295
 
1296
 
1297
static void handle_data(_cmsg * cmsg, struct sk_buff *skb)
1298
{
1299
        capidrv_contr *card = findcontrbynumber(cmsg->adr.adrController & 0x7f);
1300
        capidrv_ncci *nccip;
1301
 
1302
        if (!card) {
1303
                printk(KERN_ERR "capidrv: %s from unknown controller 0x%x\n",
1304
                       capi_cmd2str(cmsg->Command, cmsg->Subcommand),
1305
                       cmsg->adr.adrController & 0x7f);
1306
                return;
1307
        }
1308
        if (!(nccip = find_ncci(card, cmsg->adr.adrNCCI))) {
1309
                printk(KERN_ERR "capidrv-%d: %s: ncci 0x%x not found\n",
1310
                       card->contrnr,
1311
                       capi_cmd2str(cmsg->Command, cmsg->Subcommand),
1312
                       cmsg->adr.adrNCCI);
1313
                kfree_skb(skb, FREE_READ);
1314
                return;
1315
        }
1316
        (void) skb_pull(skb, CAPIMSG_LEN(skb->data));
1317
        card->interface.rcvcallb_skb(card->myid, nccip->chan, skb);
1318
        capi_cmsg_answer(cmsg);
1319
        send_message(card, cmsg);
1320
}
1321
 
1322
static _cmsg s_cmsg;
1323
 
1324
static void capidrv_signal(__u16 applid, __u32 dummy)
1325
{
1326
        struct sk_buff *skb = 0;
1327
 
1328
        while ((*capifuncs->capi_get_message) (global.appid, &skb) == CAPI_NOERROR) {
1329
                capi_message2cmsg(&s_cmsg, skb->data);
1330
                if (debugmode > 1)
1331
                        printk(KERN_DEBUG "capidrv_signal: applid=%d %s\n",
1332
                                        applid, capi_cmsg2str(&s_cmsg));
1333
 
1334
                if (s_cmsg.Command == CAPI_DATA_B3
1335
                    && s_cmsg.Subcommand == CAPI_IND) {
1336
                        handle_data(&s_cmsg, skb);
1337
                        continue;
1338
                }
1339
                kfree_skb(skb, FREE_READ);
1340
                if ((s_cmsg.adr.adrController & 0xffffff00) == 0)
1341
                        handle_controller(&s_cmsg);
1342
                else if ((s_cmsg.adr.adrPLCI & 0xffff0000) == 0)
1343
                        handle_plci(&s_cmsg);
1344
                else
1345
                        handle_ncci(&s_cmsg);
1346
        }
1347
}
1348
 
1349
/* ------------------------------------------------------------------- */
1350
 
1351
#define PUTBYTE_TO_STATUS(card, byte) \
1352
        do { \
1353
                *(card)->q931_write++ = (byte); \
1354
                if ((card)->q931_write > (card)->q931_end) \
1355
                        (card)->q931_write = (card)->q931_buf; \
1356
        } while (0)
1357
 
1358
static void handle_dtrace_data(capidrv_contr *card,
1359
                             int send, int level2, __u8 *data, __u16 len)
1360
{
1361
    long flags;
1362
    __u8 *p, *end;
1363
    isdn_ctrl cmd;
1364
 
1365
    if (!len) {
1366
       printk(KERN_DEBUG "capidrv-%d: avmb1_q931_data: len == %d\n",
1367
                                card->contrnr, len);
1368
       return;
1369
    }
1370
 
1371
    save_flags(flags);
1372
    cli();
1373
 
1374
    if (level2) {
1375
        PUTBYTE_TO_STATUS(card, 'D');
1376
        PUTBYTE_TO_STATUS(card, '2');
1377
        PUTBYTE_TO_STATUS(card, send ? '>' : '<');
1378
        PUTBYTE_TO_STATUS(card, ':');
1379
    } else {
1380
        PUTBYTE_TO_STATUS(card, 'D');
1381
        PUTBYTE_TO_STATUS(card, '3');
1382
        PUTBYTE_TO_STATUS(card, send ? '>' : '<');
1383
        PUTBYTE_TO_STATUS(card, ':');
1384
    }
1385
 
1386
    for (p = data, end = data+len; p < end; p++) {
1387
       __u8 w;
1388
       PUTBYTE_TO_STATUS(card, ' ');
1389
       w = (*p >> 4) & 0xf;
1390
       PUTBYTE_TO_STATUS(card, (w < 10) ? '0'+w : 'A'-10+w);
1391
       w = *p & 0xf;
1392
       PUTBYTE_TO_STATUS(card, (w < 10) ? '0'+w : 'A'-10+w);
1393
    }
1394
    PUTBYTE_TO_STATUS(card, '\n');
1395
 
1396
    restore_flags(flags);
1397
 
1398
    cmd.command = ISDN_STAT_STAVAIL;
1399
    cmd.driver = card->myid;
1400
    cmd.arg = len*3+5;
1401
    card->interface.statcallb(&cmd);
1402
}
1403
 
1404
/* ------------------------------------------------------------------- */
1405
 
1406
static _cmsg cmdcmsg;
1407
 
1408
static int capidrv_ioctl(isdn_ctrl * c, capidrv_contr * card)
1409
{
1410
        switch (c->arg) {
1411
        default:
1412
                printk(KERN_DEBUG "capidrv-%d: capidrv_ioctl(%ld) called ??\n",
1413
                                card->contrnr, c->arg);
1414
                return -EINVAL;
1415
        }
1416
        return -EINVAL;
1417
}
1418
 
1419
/*
1420
 * Handle leased lines (CAPI-Bundling)
1421
 */
1422
 
1423
struct internal_bchannelinfo {
1424
   unsigned short channelalloc;
1425
   unsigned short operation;
1426
   unsigned char  cmask[31];
1427
};
1428
 
1429
static int decodeFVteln(char *teln, unsigned long *bmaskp, int *activep)
1430
{
1431
        unsigned long bmask = 0;
1432
        int active = !0;
1433
        char *s;
1434
        int i;
1435
 
1436
        if (strncmp(teln, "FV:", 3) != 0)
1437
                return 1;
1438
        s = teln + 3;
1439
        while (*s && *s == ' ') s++;
1440
        if (!*s) return -2;
1441
        if (*s == 'p' || *s == 'P') {
1442
                active = 0;
1443
                s++;
1444
        }
1445
        if (*s == 'a' || *s == 'A') {
1446
                active = !0;
1447
                s++;
1448
        }
1449
        while (*s) {
1450
                int digit1 = 0;
1451
                int digit2 = 0;
1452
                if (!isdigit(*s)) return -3;
1453
                while (isdigit(*s)) { digit1 = digit1*10 + (*s - '0'); s++; }
1454
                if (digit1 <= 0 && digit1 > 30) return -4;
1455
                if (*s == 0 || *s == ',' || *s == ' ') {
1456
                        bmask |= (1 << digit1);
1457
                        digit1 = 0;
1458
                        if (*s) s++;
1459
                        continue;
1460
                }
1461
                if (*s != '-') return -5;
1462
                s++;
1463
                if (!isdigit(*s)) return -3;
1464
                while (isdigit(*s)) { digit2 = digit2*10 + (*s - '0'); s++; }
1465
                if (digit2 <= 0 && digit2 > 30) return -4;
1466
                if (*s == 0 || *s == ',' || *s == ' ') {
1467
                        if (digit1 > digit2)
1468
                                for (i = digit2; i <= digit1 ; i++)
1469
                                        bmask |= (1 << i);
1470
                        else
1471
                                for (i = digit1; i <= digit2 ; i++)
1472
                                        bmask |= (1 << i);
1473
                        digit1 = digit2 = 0;
1474
                        if (*s) s++;
1475
                        continue;
1476
                }
1477
                return -6;
1478
        }
1479
        if (activep) *activep = active;
1480
        if (bmaskp) *bmaskp = bmask;
1481
        return 0;
1482
}
1483
 
1484
static int FVteln2capi20(char *teln, __u8 AdditionalInfo[1+2+2+31])
1485
{
1486
        unsigned long bmask;
1487
        int active;
1488
        int rc, i;
1489
 
1490
        rc = decodeFVteln(teln, &bmask, &active);
1491
        if (rc) return rc;
1492
        /* Length */
1493
        AdditionalInfo[0] = 2+2+31;
1494
        /* Channel: 3 => use channel allocation */
1495
        AdditionalInfo[1] = 3; AdditionalInfo[2] = 0;
1496
        /* Operation: 0 => DTE mode, 1 => DCE mode */
1497
        if (active) {
1498
                AdditionalInfo[3] = 0; AdditionalInfo[4] = 0;
1499
        } else {
1500
                AdditionalInfo[3] = 1; AdditionalInfo[4] = 0;
1501
        }
1502
        /* Channel mask array */
1503
        AdditionalInfo[5] = 0; /* no D-Channel */
1504
        for (i=1; i <= 30; i++)
1505
                AdditionalInfo[5+i] = (bmask & (1 << i)) ? 0xff : 0;
1506
        return 0;
1507
}
1508
 
1509
static int capidrv_command(isdn_ctrl * c, capidrv_contr * card)
1510
{
1511
        isdn_ctrl cmd;
1512
        struct capidrv_bchan *bchan;
1513
        struct capidrv_plci *plcip;
1514
        __u8 AdditionalInfo[1+2+2+31];
1515
        int rc, isleasedline = 0;
1516
 
1517
        if (c->command == ISDN_CMD_IOCTL)
1518
                return capidrv_ioctl(c, card);
1519
 
1520
        switch (c->command) {
1521
        case ISDN_CMD_DIAL:{
1522
                        __u8 calling[ISDN_MSNLEN + 3];
1523
                        __u8 called[ISDN_MSNLEN + 2];
1524
 
1525
                        if (debugmode)
1526
                                printk(KERN_DEBUG "capidrv-%d: ISDN_CMD_DIAL(ch=%ld,\"%s,%d,%d,%s\")\n",
1527
                                        card->contrnr,
1528
                                        c->arg,
1529
                                        c->parm.setup.phone,
1530
                                        c->parm.setup.si1,
1531
                                        c->parm.setup.si2,
1532
                                        c->parm.setup.eazmsn);
1533
 
1534
                        bchan = &card->bchans[c->arg % card->nbchan];
1535
 
1536
                        if (bchan->plcip) {
1537
                                printk(KERN_ERR "capidrv-%d: dail ch=%ld,\"%s,%d,%d,%s\" in use (plci=0x%x)\n",
1538
                                        card->contrnr,
1539
                                        c->arg,
1540
                                        c->parm.setup.phone,
1541
                                        c->parm.setup.si1,
1542
                                        c->parm.setup.si2,
1543
                                        c->parm.setup.eazmsn,
1544
                                        bchan->plcip->plci);
1545
                                return 0;
1546
                        }
1547
                        bchan->si1 = c->parm.setup.si1;
1548
                        bchan->si2 = c->parm.setup.si2;
1549
 
1550
                        strncpy(bchan->num, c->parm.setup.phone, sizeof(bchan->num));
1551
                        strncpy(bchan->mynum, c->parm.setup.eazmsn, sizeof(bchan->mynum));
1552
 
1553
                        rc = FVteln2capi20(bchan->num, AdditionalInfo);
1554
                        isleasedline = (rc == 0);
1555
                        if (rc < 0)
1556
                                printk(KERN_ERR "capidrv-%d: WARNING: illegal leased linedefinition \"%s\"\n", card->contrnr, bchan->num);
1557
 
1558
                        if (isleasedline) {
1559
                                calling[0] = 0;
1560
                                called[0] = 0;
1561
                                if (debugmode)
1562
                                        printk(KERN_DEBUG "capidrv-%d: connecting leased line\n", card->contrnr);
1563
                        } else {
1564
                                calling[0] = strlen(bchan->mynum) + 2;
1565
                                calling[1] = 0;
1566
                                calling[2] = 0x80;
1567
                                strncpy(calling + 3, bchan->mynum, ISDN_MSNLEN);
1568
                                called[0] = strlen(bchan->num) + 1;
1569
                                called[1] = 0x80;
1570
                                strncpy(called + 2, bchan->num, ISDN_MSNLEN);
1571
                        }
1572
 
1573
 
1574
                        capi_fill_CONNECT_REQ(&cmdcmsg,
1575
                                              global.appid,
1576
                                              card->msgid++,
1577
                                              card->contrnr,    /* adr */
1578
                                          si2cip(bchan->si1, bchan->si2),       /* cipvalue */
1579
                                              called,   /* CalledPartyNumber */
1580
                                              calling,  /* CallingPartyNumber */
1581
                                              0, /* CalledPartySubaddress */
1582
                                              0, /* CallingPartySubaddress */
1583
                                            b1prot(bchan->l2, bchan->l3),       /* B1protocol */
1584
                                            b2prot(bchan->l2, bchan->l3),       /* B2protocol */
1585
                                            b3prot(bchan->l2, bchan->l3),       /* B3protocol */
1586
                                              0, /* B1configuration */
1587
                                              0, /* B2configuration */
1588
                                              0, /* B3configuration */
1589
                                              0, /* BC */
1590
                                              0, /* LLC */
1591
                                              0, /* HLC */
1592
                                              /* BChannelinformation */
1593
                                              isleasedline ? AdditionalInfo : 0,
1594
                                              0, /* Keypadfacility */
1595
                                              0, /* Useruserdata */
1596
 
1597
                            );
1598
                        if ((plcip = new_plci(card, (c->arg % card->nbchan))) == 0) {
1599
                                cmd.command = ISDN_STAT_DHUP;
1600
                                cmd.driver = card->myid;
1601
                                cmd.arg = (c->arg % card->nbchan);
1602
                                card->interface.statcallb(&cmd);
1603
                                return -1;
1604
                        }
1605
                        plcip->msgid = cmdcmsg.Messagenumber;
1606
                        plcip->leasedline = isleasedline;
1607
                        plci_change_state(card, plcip, EV_PLCI_CONNECT_REQ);
1608
                        send_message(card, &cmdcmsg);
1609
                        return 0;
1610
                }
1611
 
1612
        case ISDN_CMD_ACCEPTD:
1613
 
1614
                bchan = &card->bchans[c->arg % card->nbchan];
1615
                if (debugmode)
1616
                        printk(KERN_DEBUG "capidrv-%d: ISDN_CMD_ACCEPTD(ch=%ld) l2=%d l3=%d\n",
1617
                               card->contrnr,
1618
                               c->arg, bchan->l2, bchan->l3);
1619
 
1620
                capi_fill_CONNECT_RESP(&cmdcmsg,
1621
                                       global.appid,
1622
                                       card->msgid++,
1623
                                       bchan->plcip->plci,      /* adr */
1624
                                       0,        /* Reject */
1625
                                       b1prot(bchan->l2, bchan->l3),    /* B1protocol */
1626
                                       b2prot(bchan->l2, bchan->l3),    /* B2protocol */
1627
                                       b3prot(bchan->l2, bchan->l3),    /* B3protocol */
1628
                                       0,        /* B1configuration */
1629
                                       0,        /* B2configuration */
1630
                                       0,        /* B3configuration */
1631
                                       0,        /* ConnectedNumber */
1632
                                       0,        /* ConnectedSubaddress */
1633
                                       0,        /* LLC */
1634
                                       0,        /* BChannelinformation */
1635
                                       0,        /* Keypadfacility */
1636
                                       0,        /* Useruserdata */
1637
 
1638
                );
1639
                capi_cmsg2message(&cmdcmsg, cmdcmsg.buf);
1640
                plci_change_state(card, bchan->plcip, EV_PLCI_CONNECT_RESP);
1641
                send_message(card, &cmdcmsg);
1642
                return 0;
1643
 
1644
        case ISDN_CMD_ACCEPTB:
1645
                if (debugmode)
1646
                        printk(KERN_DEBUG "capidrv-%d: ISDN_CMD_ACCEPTB(ch=%ld)\n",
1647
                               card->contrnr,
1648
                               c->arg);
1649
                return -ENOSYS;
1650
 
1651
        case ISDN_CMD_HANGUP:
1652
                if (debugmode)
1653
                        printk(KERN_DEBUG "capidrv-%d: ISDN_CMD_HANGUP(ch=%ld)\n",
1654
                               card->contrnr,
1655
                               c->arg);
1656
                bchan = &card->bchans[c->arg % card->nbchan];
1657
 
1658
                if (bchan->disconnecting) {
1659
                        if (debugmode)
1660
                                printk(KERN_DEBUG "capidrv-%d: chan %ld already disconnecting ...\n",
1661
                                       card->contrnr,
1662
                                       c->arg);
1663
                        return 0;
1664
                }
1665
                if (bchan->nccip) {
1666
                        bchan->disconnecting = 1;
1667
                        capi_fill_DISCONNECT_B3_REQ(&cmdcmsg,
1668
                                                    global.appid,
1669
                                                    card->msgid++,
1670
                                                    bchan->nccip->ncci,
1671
 
1672
                        );
1673
                        ncci_change_state(card, bchan->nccip, EV_NCCI_DISCONNECT_B3_REQ);
1674
                        send_message(card, &cmdcmsg);
1675
                } else if (bchan->plcip) {
1676
                        bchan->disconnecting = 1;
1677
                        if (bchan->plcip->state == ST_PLCI_INCOMING) {
1678
                                /* just ignore, we a called from isdn_status_callback(),
1679
                                 * which will return 0 or 2, this is handled by the
1680
                                 * CONNECT_IND handler
1681
                                 */
1682
                        } else {
1683
                                capi_fill_DISCONNECT_REQ(&cmdcmsg,
1684
                                                         global.appid,
1685
                                                         card->msgid++,
1686
                                                      bchan->plcip->plci,
1687
                                                         0,      /* BChannelinformation */
1688
                                                         0,      /* Keypadfacility */
1689
                                                         0,      /* Useruserdata */
1690
 
1691
                                );
1692
                                plci_change_state(card, bchan->plcip, EV_PLCI_DISCONNECT_REQ);
1693
                                send_message(card, &cmdcmsg);
1694
                        }
1695
                }
1696
/* ready */
1697
 
1698
        case ISDN_CMD_SETL2:
1699
                if (debugmode)
1700
                        printk(KERN_DEBUG "capidrv-%d: set L2 on chan %ld to %ld\n",
1701
                               card->contrnr,
1702
                               (c->arg & 0xff), (c->arg >> 8));
1703
                bchan = &card->bchans[(c->arg & 0xff) % card->nbchan];
1704
                bchan->l2 = (c->arg >> 8);
1705
                return 0;
1706
 
1707
        case ISDN_CMD_SETL3:
1708
                if (debugmode)
1709
                        printk(KERN_DEBUG "capidrv-%d: set L3 on chan %ld to %ld\n",
1710
                               card->contrnr,
1711
                               (c->arg & 0xff), (c->arg >> 8));
1712
                bchan = &card->bchans[(c->arg & 0xff) % card->nbchan];
1713
                bchan->l3 = (c->arg >> 8);
1714
                return 0;
1715
 
1716
        case ISDN_CMD_SETEAZ:
1717
                if (debugmode)
1718
                        printk(KERN_DEBUG "capidrv-%d: set EAZ \"%s\" on chan %ld\n",
1719
                               card->contrnr,
1720
                               c->parm.num, c->arg);
1721
                bchan = &card->bchans[c->arg % card->nbchan];
1722
                strncpy(bchan->msn, c->parm.num, ISDN_MSNLEN);
1723
                return 0;
1724
 
1725
        case ISDN_CMD_CLREAZ:
1726
                if (debugmode)
1727
                        printk(KERN_DEBUG "capidrv-%d: clearing EAZ on chan %ld\n",
1728
                                        card->contrnr, c->arg);
1729
                bchan = &card->bchans[c->arg % card->nbchan];
1730
                bchan->msn[0] = 0;
1731
                return 0;
1732
 
1733
        case ISDN_CMD_LOCK:
1734
                if (debugmode > 1)
1735
                        printk(KERN_DEBUG "capidrv-%d: ISDN_CMD_LOCK (%ld)\n", card->contrnr, c->arg);
1736
                MOD_INC_USE_COUNT;
1737
                break;
1738
 
1739
        case ISDN_CMD_UNLOCK:
1740
                if (debugmode > 1)
1741
                        printk(KERN_DEBUG "capidrv-%d: ISDN_CMD_UNLOCK (%ld)\n",
1742
                                        card->contrnr, c->arg);
1743
                MOD_DEC_USE_COUNT;
1744
                break;
1745
 
1746
/* never called */
1747
        case ISDN_CMD_GETL2:
1748
                if (debugmode)
1749
                        printk(KERN_DEBUG "capidrv-%d: ISDN_CMD_GETL2\n",
1750
                                        card->contrnr);
1751
                return -ENODEV;
1752
        case ISDN_CMD_GETL3:
1753
                if (debugmode)
1754
                        printk(KERN_DEBUG "capidrv-%d: ISDN_CMD_GETL3\n",
1755
                                        card->contrnr);
1756
                return -ENODEV;
1757
        case ISDN_CMD_GETEAZ:
1758
                if (debugmode)
1759
                        printk(KERN_DEBUG "capidrv-%d: ISDN_CMD_GETEAZ\n",
1760
                                        card->contrnr);
1761
                return -ENODEV;
1762
        case ISDN_CMD_SETSIL:
1763
                if (debugmode)
1764
                        printk(KERN_DEBUG "capidrv-%d: ISDN_CMD_SETSIL\n",
1765
                                        card->contrnr);
1766
                return -ENODEV;
1767
        case ISDN_CMD_GETSIL:
1768
                if (debugmode)
1769
                        printk(KERN_DEBUG "capidrv-%d: ISDN_CMD_GETSIL\n",
1770
                                        card->contrnr);
1771
                return -ENODEV;
1772
        default:
1773
                printk(KERN_ERR "capidrv-%d: ISDN_CMD_%d, Huh?\n",
1774
                                        card->contrnr, c->command);
1775
                return -EINVAL;
1776
        }
1777
        return 0;
1778
}
1779
 
1780
static int if_command(isdn_ctrl * c)
1781
{
1782
        capidrv_contr *card = findcontrbydriverid(c->driver);
1783
 
1784
        if (card)
1785
                return capidrv_command(c, card);
1786
 
1787
        printk(KERN_ERR
1788
             "capidrv-%d: if_command %d called with invalid driverId %d!\n",
1789
               card->contrnr, c->command, c->driver);
1790
        return -ENODEV;
1791
}
1792
 
1793
static _cmsg sendcmsg;
1794
 
1795
static int if_sendbuf(int id, int channel, struct sk_buff *skb)
1796
{
1797
        capidrv_contr *card = findcontrbydriverid(id);
1798
        capidrv_bchan *bchan;
1799
        capidrv_ncci *nccip;
1800
        int len = skb->len;
1801
        size_t msglen;
1802
        __u16 errcode;
1803
 
1804
        if (!card) {
1805
                printk(KERN_ERR "capidrv-%d: if_sendbuf called with invalid driverId %d!\n",
1806
                       card->contrnr, id);
1807
                return 0;
1808
        }
1809
        bchan = &card->bchans[channel % card->nbchan];
1810
        nccip = bchan->nccip;
1811
        if (!nccip || nccip->state != ST_NCCI_ACTIVE) {
1812
                printk(KERN_ERR "capidrv-%d: if_sendbuf: %s:%d: chan not up!\n",
1813
                       card->contrnr, card->name, channel);
1814
                return 0;
1815
        }
1816
        capi_fill_DATA_B3_REQ(&sendcmsg, global.appid, card->msgid++,
1817
                              nccip->ncci,      /* adr */
1818
                              (__u32) skb->data,        /* Data */
1819
                              skb->len,         /* DataLength */
1820
                              nccip->datahandle++,      /* DataHandle */
1821
 
1822
            );
1823
        capi_cmsg2message(&sendcmsg, sendcmsg.buf);
1824
        msglen = CAPIMSG_LEN(sendcmsg.buf);
1825
        if (skb_headroom(skb) < msglen) {
1826
                struct sk_buff *nskb = dev_alloc_skb(msglen + skb->len);
1827
                if (!nskb) {
1828
                        printk(KERN_ERR "capidrv-%d: if_sendbuf: no memory\n",
1829
                                        card->contrnr);
1830
                        return 0;
1831
                }
1832
#if 0
1833
                printk(KERN_DEBUG "capidrv-%d: only %d bytes headroom\n",
1834
                       card->contrnr, skb_headroom(skb));
1835
#endif
1836
                SET_SKB_FREE(nskb);
1837
                memcpy(skb_put(nskb, msglen), sendcmsg.buf, msglen);
1838
                memcpy(skb_put(nskb, skb->len), skb->data, skb->len);
1839
                errcode = (*capifuncs->capi_put_message) (global.appid, nskb);
1840
                switch (errcode) {
1841
                case CAPI_NOERROR:
1842
                        dev_kfree_skb(skb, FREE_WRITE);
1843
                        return len;
1844
                case CAPI_SENDQUEUEFULL:
1845
                        dev_kfree_skb(nskb, FREE_WRITE);
1846
                        return 0;
1847
                default:
1848
                        return -1;
1849
                }
1850
        } else {
1851
                memcpy(skb_push(skb, msglen), sendcmsg.buf, msglen);
1852
                errcode = (*capifuncs->capi_put_message) (global.appid, skb);
1853
                switch (errcode) {
1854
                case CAPI_NOERROR:
1855
                        return len;
1856
                case CAPI_SENDQUEUEFULL:
1857
                        return 0;
1858
                default:
1859
                        return -1;
1860
                }
1861
        }
1862
}
1863
 
1864
static int if_readstat(__u8 *buf, int len, int user, int id, int channel)
1865
{
1866
        capidrv_contr *card = findcontrbydriverid(id);
1867
        int count;
1868
        __u8 *p;
1869
 
1870
        if (!card) {
1871
                printk(KERN_ERR "capidrv-%d: if_readstat called with invalid driverId %d!\n",
1872
                       card->contrnr, id);
1873
                return -ENODEV;
1874
        }
1875
 
1876
        for (p=buf, count=0; count < len; p++, count++) {
1877
                if (user)
1878
                        put_user(*card->q931_read++, p);
1879
                else
1880
                        *p = *card->q931_read++;
1881
                if (card->q931_read > card->q931_end)
1882
                        card->q931_read = card->q931_buf;
1883
        }
1884
        return count;
1885
 
1886
}
1887
 
1888
static void enable_dchannel_trace(capidrv_contr *card)
1889
{
1890
        __u8 manufacturer[CAPI_MANUFACTURER_LEN];
1891
        capi_version version;
1892
        __u16 contr = card->contrnr;
1893
        __u16 errcode;
1894
        __u16 avmversion[3];
1895
 
1896
        errcode = (*capifuncs->capi_get_manufacturer)(contr, manufacturer);
1897
        if (errcode != CAPI_NOERROR) {
1898
           printk(KERN_ERR "%s: can't get manufacturer (0x%x)\n",
1899
                        card->name, errcode);
1900
           return;
1901
        }
1902
        if (strstr(manufacturer, "AVM") == 0) {
1903
           printk(KERN_ERR "%s: not from AVM, no d-channel trace possible\n",
1904
                        card->name);
1905
           return;
1906
        }
1907
        errcode = (*capifuncs->capi_get_version)(contr, &version);
1908
        if (errcode != CAPI_NOERROR) {
1909
           printk(KERN_ERR "%s: can't get version (0x%x)\n",
1910
                        card->name, errcode);
1911
           return;
1912
        }
1913
        avmversion[0] = (version.majormanuversion >> 4) & 0x0f;
1914
        avmversion[1] = (version.majormanuversion << 4) & 0xf0;
1915
        avmversion[1] |= (version.minormanuversion >> 4) & 0x0f;
1916
        avmversion[2] |= version.minormanuversion & 0x0f;
1917
 
1918
        if (avmversion[0] > 3 || (avmversion[0] == 3 && avmversion[1] > 5)) {
1919
                printk(KERN_INFO "%s: D2 trace enabled\n", card->name);
1920
                capi_fill_MANUFACTURER_REQ(&cmdcmsg, global.appid,
1921
                                           card->msgid++,
1922
                                           contr,
1923
                                           0x214D5641,  /* ManuID */
1924
                                           0,           /* Class */
1925
                                           1,           /* Function */
1926
                                           (_cstruct)"\004\200\014\000\000");
1927
        } else {
1928
                printk(KERN_INFO "%s: D3 trace enabled\n", card->name);
1929
                capi_fill_MANUFACTURER_REQ(&cmdcmsg, global.appid,
1930
                                           card->msgid++,
1931
                                           contr,
1932
                                           0x214D5641,  /* ManuID */
1933
                                           0,           /* Class */
1934
                                           1,           /* Function */
1935
                                           (_cstruct)"\004\002\003\000\000");
1936
        }
1937
        send_message(card, &cmdcmsg);
1938
}
1939
 
1940
static int capidrv_addcontr(__u16 contr, struct capi_profile *profp)
1941
{
1942
        capidrv_contr *card;
1943
        isdn_ctrl cmd;
1944
        char id[20];
1945
        int i;
1946
 
1947
        sprintf(id, "capidrv-%d", contr);
1948
        if (!(card = (capidrv_contr *) kmalloc(sizeof(capidrv_contr), GFP_ATOMIC))) {
1949
                printk(KERN_WARNING
1950
                 "capidrv: (%s) Could not allocate contr-struct.\n", id);
1951
                return -1;
1952
        }
1953
        memset(card, 0, sizeof(capidrv_contr));
1954
        strcpy(card->name, id);
1955
        card->contrnr = contr;
1956
        card->nbchan = profp->nbchannel;
1957
        card->bchans = (capidrv_bchan *) kmalloc(sizeof(capidrv_bchan) * card->nbchan, GFP_ATOMIC);
1958
        if (!card->bchans) {
1959
                printk(KERN_WARNING
1960
                "capidrv: (%s) Could not allocate bchan-structs.\n", id);
1961
                kfree(card);
1962
                return -1;
1963
        }
1964
        card->interface.channels = profp->nbchannel;
1965
        card->interface.maxbufsize = 2048;
1966
        card->interface.command = if_command;
1967
        card->interface.writebuf_skb = if_sendbuf;
1968
        card->interface.writecmd = 0;
1969
        card->interface.readstat = if_readstat;
1970
        card->interface.features = ISDN_FEATURE_L2_X75I |
1971
            ISDN_FEATURE_L2_X75UI |
1972
            ISDN_FEATURE_L2_X75BUI |
1973
            ISDN_FEATURE_L2_HDLC |
1974
            ISDN_FEATURE_L2_TRANS |
1975
            ISDN_FEATURE_L3_TRANS |
1976
            ISDN_FEATURE_P_UNKNOWN;
1977
        card->interface.hl_hdrlen = 22; /* len of DATA_B3_REQ */
1978
        strncpy(card->interface.id, id, sizeof(card->interface.id) - 1);
1979
        card->next = global.contr_list;
1980
        global.contr_list = card;
1981
        global.ncontr++;
1982
        card->q931_read = card->q931_buf;
1983
        card->q931_write = card->q931_buf;
1984
        card->q931_end = card->q931_buf + sizeof(card->q931_buf) - 1;
1985
 
1986
        if (!register_isdn(&card->interface)) {
1987
                global.contr_list = global.contr_list->next;
1988
                printk(KERN_ERR "capidrv: Unable to register contr %s\n", id);
1989
                kfree(card->bchans);
1990
                kfree(card);
1991
                return -1;
1992
        }
1993
        card->myid = card->interface.channels;
1994
 
1995
        memset(card->bchans, 0, sizeof(capidrv_bchan) * card->nbchan);
1996
        for (i = 0; i < card->nbchan; i++) {
1997
                card->bchans[i].contr = card;
1998
        }
1999
 
2000
        cmd.driver = card->myid;
2001
        cmd.command = ISDN_STAT_RUN;
2002
        card->interface.statcallb(&cmd);
2003
 
2004
        card->cipmask = 0x1FFF03FF;     /* any */
2005
        card->cipmask2 = 0;
2006
 
2007
        capi_fill_LISTEN_REQ(&cmdcmsg, global.appid,
2008
                             card->msgid++,
2009
                             contr,     /* controller */
2010
                             1 << 6,    /* Infomask */
2011
                             card->cipmask,
2012
                             card->cipmask2,
2013
                             0, 0);
2014
        send_message(card, &cmdcmsg);
2015
        listen_change_state(card, EV_LISTEN_REQ);
2016
 
2017
        printk(KERN_INFO "%s: now up (%d B channels)\n",
2018
                card->name, card->nbchan);
2019
 
2020
        if (card->nbchan == 2)  /* no T1 */
2021
                enable_dchannel_trace(card);
2022
 
2023
        return 0;
2024
}
2025
 
2026
static int capidrv_delcontr(__u16 contr)
2027
{
2028
        capidrv_contr **pp, *card;
2029
        isdn_ctrl cmd;
2030
        int i;
2031
 
2032
        for (pp = &global.contr_list; *pp; pp = &(*pp)->next) {
2033
                if ((*pp)->contrnr == contr)
2034
                        break;
2035
        }
2036
        if (!*pp) {
2037
                printk(KERN_ERR "capidrv: delcontr: no contr %u\n", contr);
2038
                return -1;
2039
        }
2040
        card = *pp;
2041
        *pp = (*pp)->next;
2042
        global.ncontr--;
2043
 
2044
        for (i = 0; i < card->nbchan; i++) {
2045
                if (card->bchans[i].nccip)
2046
                        free_ncci(card, card->bchans[i].nccip);
2047
                if (card->bchans[i].plcip)
2048
                        free_plci(card, card->bchans[i].plcip);
2049
                if (card->plci_list)
2050
                        printk(KERN_ERR "capidrv: bug in free_plci()\n");
2051
        }
2052
        kfree(card->bchans);
2053
 
2054
        cmd.command = ISDN_STAT_UNLOAD;
2055
        cmd.driver = card->myid;
2056
        card->interface.statcallb(&cmd);
2057
 
2058
        printk(KERN_INFO "%s: now down.\n", card->name);
2059
 
2060
        kfree(card);
2061
 
2062
        return 0;
2063
}
2064
 
2065
 
2066
static void lower_callback(unsigned int cmd, __u16 contr, void *data)
2067
{
2068
        switch (cmd) {
2069
        case KCI_CONTRUP:
2070
                (void) capidrv_addcontr(contr, (capi_profile *) data);
2071
                break;
2072
        case KCI_CONTRDOWN:
2073
                (void) capidrv_delcontr(contr);
2074
                break;
2075
        }
2076
}
2077
 
2078
static struct capi_interface_user cuser = {
2079
        "capidrv",
2080
        lower_callback
2081
};
2082
 
2083
#ifdef MODULE
2084
#define capidrv_init init_module
2085
#endif
2086
 
2087
int capidrv_init(void)
2088
{
2089
        struct capi_register_params rparam;
2090
        capi_profile profile;
2091
        char rev[10];
2092
        char *p;
2093
        __u32 ncontr, contr;
2094
        __u16 errcode;
2095
 
2096
        capifuncs = attach_capi_interface(&cuser);
2097
 
2098
        if (!capifuncs)
2099
                return -EIO;
2100
 
2101
#ifndef HAS_NEW_SYMTAB
2102
        /* No symbols to export, hide all symbols */
2103
        register_symtab(NULL);
2104
#endif
2105
 
2106
        if ((p = strchr(revision, ':'))) {
2107
                strcpy(rev, p + 1);
2108
                p = strchr(rev, '$');
2109
                *p = 0;
2110
        } else
2111
                strcpy(rev, " ??? ");
2112
 
2113
        rparam.level3cnt = -2;  /* number of bchannels twice */
2114
        rparam.datablkcnt = 16;
2115
        rparam.datablklen = 2048;
2116
        errcode = (*capifuncs->capi_register) (&rparam, &global.appid);
2117
        if (errcode) {
2118
                detach_capi_interface(&cuser);
2119
                return -EIO;
2120
        }
2121
 
2122
        errcode = (*capifuncs->capi_get_profile) (0, &profile);
2123
        if (errcode != CAPI_NOERROR) {
2124
                (void) (*capifuncs->capi_release) (global.appid);
2125
                detach_capi_interface(&cuser);
2126
                return -EIO;
2127
        }
2128
 
2129
        (void) (*capifuncs->capi_set_signal) (global.appid, capidrv_signal, 0);
2130
 
2131
        ncontr = profile.ncontroller;
2132
        for (contr = 1; contr <= ncontr; contr++) {
2133
                errcode = (*capifuncs->capi_get_profile) (contr, &profile);
2134
                if (errcode != CAPI_NOERROR)
2135
                        continue;
2136
                (void) capidrv_addcontr(contr, &profile);
2137
        }
2138
 
2139
        return 0;
2140
}
2141
 
2142
#ifdef MODULE
2143
void cleanup_module(void)
2144
{
2145
        capidrv_contr *card, *next;
2146
        char rev[10];
2147
        char *p;
2148
 
2149
        if ((p = strchr(revision, ':'))) {
2150
                strcpy(rev, p + 1);
2151
                p = strchr(rev, '$');
2152
                *p = 0;
2153
        } else {
2154
                strcpy(rev, " ??? ");
2155
        }
2156
 
2157
        for (card = global.contr_list; card; card = next) {
2158
                next = card->next;
2159
                capidrv_delcontr(card->contrnr);
2160
        }
2161
 
2162
        (void) (*capifuncs->capi_release) (global.appid);
2163
        detach_capi_interface(&cuser);
2164
 
2165
        printk(KERN_NOTICE "capidrv: Rev%s: unloaded\n", rev);
2166
}
2167
 
2168
#endif

powered by: WebSVN 2.1.0

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