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

Subversion Repositories or1k

[/] [or1k/] [trunk/] [linux/] [linux-2.4/] [drivers/] [isdn/] [avmb1/] [capidrv.c] - Blame information for rev 1765

Details | Compare with Previous | View Log

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

powered by: WebSVN 2.1.0

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