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