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