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

Subversion Repositories or1k

[/] [or1k/] [tags/] [before_ORP/] [uclinux/] [uClinux-2.0.x/] [drivers/] [isdn/] [avmb1/] [capidrv.c] - Blame information for rev 1765

Details | Compare with Previous | View Log

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

powered by: WebSVN 2.1.0

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