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