2 * $Id: capidrv.c,v 1.26 1999/08/06 07:41:16 calle Exp $
4 * ISDN4Linux Driver, using capi20 interface (kernelcapi)
6 * Copyright 1997 by Carsten Paeth (calle@calle.in-berlin.de)
9 * Revision 1.26 1999/08/06 07:41:16 calle
10 * Added the "vbox patch". if (si1 == 1) si2 = 0;
12 * Revision 1.25 1999/08/04 10:10:11 calle
13 * Bugfix: corrected /proc functions, added structure for new AVM cards.
15 * Revision 1.24 1999/07/20 06:48:02 calle
16 * Bugfix: firmware version check for D2 trace was too restrictiv.
18 * Revision 1.23 1999/07/09 15:05:44 keil
19 * compat.h is now isdn_compat.h
21 * Revision 1.22 1999/07/06 07:24:14 calle
22 * Bugfix: call to kfree_skb in capidrv_signal was too early,
23 * thanks to Lars Heete <hel@admin.de>.
25 * Revision 1.21 1999/07/01 15:26:34 calle
26 * complete new version (I love it):
27 * + new hardware independed "capi_driver" interface that will make it easy to:
28 * - support other controllers with CAPI-2.0 (i.e. USB Controller)
29 * - write a CAPI-2.0 for the passive cards
30 * - support serial link CAPI-2.0 boxes.
31 * + wrote "capi_driver" for all supported cards.
32 * + "capi_driver" (supported cards) now have to be configured with
33 * make menuconfig, in the past all supported cards where included
35 * + new and better informations in /proc/capi/
36 * + new ioctl to switch trace of capi messages per controller
37 * using "avmcapictrl trace [contr] on|off|...."
38 * + complete testcircle with all supported cards and also the
39 * PCMCIA cards (now patch for pcmcia-cs-3.0.13 needed) done.
41 * Revision 1.20 1999/07/01 08:22:59 keil
42 * compatibility macros now in <linux/isdn_compat.h>
44 * Revision 1.19 1999/06/29 16:16:54 calle
45 * Let ISDN_CMD_UNLOAD work with open isdn devices without crash again.
46 * Also right unlocking (ISDN_CMD_UNLOCK) is done now.
47 * isdnlog should check returncode of read(2) calls.
49 * Revision 1.18 1999/06/21 15:24:15 calle
50 * extend information in /proc.
52 * Revision 1.17 1999/06/10 16:53:55 calle
53 * Removing of module b1pci will now remove card from lower level.
55 * Revision 1.16 1999/05/31 11:50:33 calle
56 * Bugfix: In if_sendbuf, skb_push'ed DATA_B3 header was not skb_pull'ed
57 * on failure, result in data block with DATA_B3 header transmitted
59 * Revision 1.15 1999/05/25 21:26:16 calle
60 * Include CAPI-Channelallocation (leased lines) from the 2.0 tree.
62 * Revision 1.14 1999/05/22 07:55:06 calle
63 * Added *V110* to AVM B1 driver.
65 * Revision 1.13 1998/06/26 15:12:55 fritz
66 * Added handling of STAT_ICALL with incomplete CPN.
67 * Added AT&L for ttyI emulator.
68 * Added more locking stuff in tty_write.
70 * Revision 1.12 1998/03/29 16:06:03 calle
71 * changes from 2.0 tree merged.
73 * Revision 1.3.2.10 1998/03/20 14:38:24 calle
74 * capidrv: prepared state machines for suspend/resume/hold
75 * capidrv: fix bug in state machine if B1/T1 is out of nccis
76 * b1capi: changed some errno returns.
77 * b1capi: detect if you try to add same T1 to different io address.
78 * b1capi: change number of nccis depending on number of channels.
81 * Revision 1.3.2.9 1998/03/20 09:01:12 calle
82 * Changes capi_register handling to get full support for 30 bchannels.
84 * Revision 1.3.2.8 1998/03/18 17:51:28 calle
85 * added controller number to error messages
87 * Revision 1.3.2.7 1998/02/27 15:40:47 calle
88 * T1 running with slow link. bugfix in capi_release.
90 * Revision 1.11 1998/02/13 07:09:15 calle
91 * change for 2.1.86 (removing FREE_READ/FREE_WRITE from [dev]_kfree_skb()
93 * Revision 1.10 1998/02/02 19:52:23 calle
94 * Fixed vbox (audio) acceptb.
96 * Revision 1.9 1998/01/31 11:14:45 calle
97 * merged changes to 2.0 tree, prepare 2.1.82 to work.
99 * Revision 1.8 1997/11/04 06:12:09 calle
100 * capi.c: new read/write in file_ops since 2.1.60
101 * capidrv.c: prepared isdnlog interface for d2-trace in newer firmware.
102 * capiutil.c: needs config.h (CONFIG_ISDN_DRV_AVMB1_VERBOSE_REASON)
103 * compat.h: added #define LinuxVersionCode
105 * Revision 1.7 1997/10/11 10:36:34 calle
106 * Added isdnlog support. patch to isdnlog needed.
108 * Revision 1.6 1997/10/11 10:25:55 calle
109 * New interface for lowlevel drivers. BSENT with nr. of bytes sent,
110 * allow sending without ACK.
112 * Revision 1.5 1997/10/01 09:21:16 fritz
113 * Removed old compatibility stuff for 2.0.X kernels.
114 * From now on, this code is for 2.1.X ONLY!
115 * Old stuff is still in the separate branch.
117 * Revision 1.4 1997/07/13 12:22:43 calle
118 * bug fix for more than one controller in connect_req.
119 * debugoutput now with contrnr.
121 * Revision 1.3 1997/05/18 09:24:15 calle
122 * added verbose disconnect reason reporting to avmb1.
123 * some fixes in capi20 interface.
124 * changed info messages for B1-PCI
126 * Revision 1.2 1997/03/05 21:19:59 fritz
127 * Removed include of config.h (mkdep stated this is unneded).
129 * Revision 1.1 1997/03/04 21:50:31 calle
130 * Frirst version in isdn4linux
132 * Revision 2.2 1997/02/12 09:31:39 calle
135 * Revision 1.1 1997/01/31 10:32:20 calle
140 #include <linux/module.h>
141 #include <linux/errno.h>
142 #include <linux/kernel.h>
143 #include <linux/major.h>
144 #include <linux/sched.h>
145 #include <linux/malloc.h>
146 #include <linux/fcntl.h>
147 #include <linux/fs.h>
148 #include <linux/signal.h>
149 #include <linux/mm.h>
150 #include <linux/timer.h>
151 #include <linux/wait.h>
152 #include <linux/skbuff.h>
153 #include <linux/isdn.h>
154 #include <linux/isdnif.h>
155 #include <linux/proc_fs.h>
156 #include <linux/capi.h>
157 #include <linux/kernelcapi.h>
158 #include <linux/ctype.h>
159 #include <asm/segment.h>
161 #include <linux/isdn_compat.h>
162 #include "capiutil.h"
166 static char *revision
= "$Revision: 1.26 $";
169 MODULE_AUTHOR("Carsten Paeth <calle@calle.in-berlin.de>");
170 MODULE_PARM(debugmode
, "i");
172 /* -------- type definitions ----------------------------------------- */
175 struct capidrv_contr
{
177 struct capidrv_contr
*next
;
196 * ID of capi message sent
204 struct capidrv_bchan
{
205 struct capidrv_contr
*contr
;
206 __u8 msn
[ISDN_MSNLEN
];
209 __u8 num
[ISDN_MSNLEN
];
210 __u8 mynum
[ISDN_MSNLEN
];
215 struct capidrv_plci
{
216 struct capidrv_plci
*next
;
218 __u32 ncci
; /* ncci for CONNECT_ACTIVE_IND */
219 __u16 msgid
; /* to identfy CONNECT_CONF */
223 struct capidrv_ncci
{
224 struct capidrv_ncci
*next
;
225 struct capidrv_plci
*plcip
;
227 __u16 msgid
; /* to identfy CONNECT_B3_CONF */
233 struct ncci_datahandle_queue
{
234 struct ncci_datahandle_queue
*next
;
240 struct capidrv_ncci
*nccip
;
243 struct capidrv_plci
*plci_list
;
253 struct capidrv_data
{
256 struct capidrv_contr
*contr_list
;
259 unsigned long nrecvctlpkt
;
260 unsigned long nrecvdatapkt
;
261 unsigned long nsentctlpkt
;
262 unsigned long nsentdatapkt
;
265 typedef struct capidrv_plci capidrv_plci
;
266 typedef struct capidrv_ncci capidrv_ncci
;
267 typedef struct capidrv_contr capidrv_contr
;
268 typedef struct capidrv_data capidrv_data
;
269 typedef struct capidrv_bchan capidrv_bchan
;
271 /* -------- data definitions ----------------------------------------- */
273 static capidrv_data global
;
274 static struct capi_interface
*capifuncs
;
276 static void handle_dtrace_data(capidrv_contr
*card
,
277 int send
, int level2
, __u8
*data
, __u16 len
);
279 /* -------- convert functions ---------------------------------------- */
281 static inline __u32
b1prot(int l2
, int l3
)
284 case ISDN_PROTO_L2_X75I
:
285 case ISDN_PROTO_L2_X75UI
:
286 case ISDN_PROTO_L2_X75BUI
:
288 case ISDN_PROTO_L2_HDLC
:
291 case ISDN_PROTO_L2_TRANS
:
293 case ISDN_PROTO_L2_V11096
:
294 case ISDN_PROTO_L2_V11019
:
295 case ISDN_PROTO_L2_V11038
:
297 case ISDN_PROTO_L2_FAX
:
302 static inline __u32
b2prot(int l2
, int l3
)
305 case ISDN_PROTO_L2_X75I
:
306 case ISDN_PROTO_L2_X75UI
:
307 case ISDN_PROTO_L2_X75BUI
:
310 case ISDN_PROTO_L2_HDLC
:
311 case ISDN_PROTO_L2_TRANS
:
312 case ISDN_PROTO_L2_V11096
:
313 case ISDN_PROTO_L2_V11019
:
314 case ISDN_PROTO_L2_V11038
:
316 case ISDN_PROTO_L2_FAX
:
321 static inline __u32
b3prot(int l2
, int l3
)
324 case ISDN_PROTO_L2_X75I
:
325 case ISDN_PROTO_L2_X75UI
:
326 case ISDN_PROTO_L2_X75BUI
:
327 case ISDN_PROTO_L2_HDLC
:
328 case ISDN_PROTO_L2_TRANS
:
329 case ISDN_PROTO_L2_V11096
:
330 case ISDN_PROTO_L2_V11019
:
331 case ISDN_PROTO_L2_V11038
:
334 case ISDN_PROTO_L2_FAX
:
339 static _cstruct
b1config_sync_v110(__u16 rate
)
341 /* CAPI-Spec "B1 Configuration" */
342 static unsigned char buf
[9];
343 buf
[0] = 8; /* len */
344 /* maximum bitrate */
345 buf
[1] = rate
& 0xff; buf
[2] = (rate
>> 8) & 0xff;
346 buf
[3] = buf
[4] = 0; /* reserved, bits per character */
347 buf
[5] = buf
[6] = 0; /* reserved, parity */
348 buf
[7] = buf
[9] = 0; /* reserved, stop bits */
352 static _cstruct
b1config(int l2
, int l3
)
355 case ISDN_PROTO_L2_X75I
:
356 case ISDN_PROTO_L2_X75UI
:
357 case ISDN_PROTO_L2_X75BUI
:
358 case ISDN_PROTO_L2_HDLC
:
359 case ISDN_PROTO_L2_TRANS
:
362 case ISDN_PROTO_L2_V11096
:
363 return b1config_sync_v110(9600);
364 case ISDN_PROTO_L2_V11019
:
365 return b1config_sync_v110(19200);
366 case ISDN_PROTO_L2_V11038
:
367 return b1config_sync_v110(38400);
371 static inline __u16
si2cip(__u8 si1
, __u8 si2
)
373 static const __u8 cip
[17][5] =
376 {0, 0, 0, 0, 0}, /*0 */
377 {16, 16, 4, 26, 16}, /*1 */
378 {17, 17, 17, 4, 4}, /*2 */
379 {2, 2, 2, 2, 2}, /*3 */
380 {18, 18, 18, 18, 18}, /*4 */
381 {2, 2, 2, 2, 2}, /*5 */
382 {0, 0, 0, 0, 0}, /*6 */
383 {2, 2, 2, 2, 2}, /*7 */
384 {2, 2, 2, 2, 2}, /*8 */
385 {21, 21, 21, 21, 21}, /*9 */
386 {19, 19, 19, 19, 19}, /*10 */
387 {0, 0, 0, 0, 0}, /*11 */
388 {0, 0, 0, 0, 0}, /*12 */
389 {0, 0, 0, 0, 0}, /*13 */
390 {0, 0, 0, 0, 0}, /*14 */
391 {22, 22, 22, 22, 22}, /*15 */
392 {27, 27, 27, 28, 27} /*16 */
399 return (__u16
) cip
[si1
][si2
];
402 static inline __u8
cip2si1(__u16 cipval
)
404 static const __u8 si
[32] =
405 {7, 1, 7, 7, 1, 1, 7, 7, /*0-7 */
406 7, 1, 0, 0, 0, 0, 0, 0, /*8-15 */
407 1, 2, 4, 10, 9, 9, 15, 7, /*16-23 */
408 7, 7, 1, 16, 16, 0, 0, 0}; /*24-31 */
411 cipval
= 0; /* .... */
415 static inline __u8
cip2si2(__u16 cipval
)
417 static const __u8 si
[32] =
418 {0, 0, 0, 0, 2, 3, 0, 0, /*0-7 */
419 0, 3, 0, 0, 0, 0, 0, 0, /*8-15 */
420 1, 2, 0, 0, 9, 0, 0, 0, /*16-23 */
421 0, 0, 3, 2, 3, 0, 0, 0}; /*24-31 */
424 cipval
= 0; /* .... */
429 /* -------- controller managment ------------------------------------- */
431 static inline capidrv_contr
*findcontrbydriverid(int driverid
)
433 capidrv_contr
*p
= global
.contr_list
;
436 if (p
->myid
== driverid
)
440 return (capidrv_contr
*) 0;
443 static capidrv_contr
*findcontrbynumber(__u32 contr
)
445 capidrv_contr
*p
= global
.contr_list
;
448 if (p
->contrnr
== contr
)
452 return (capidrv_contr
*) 0;
456 /* -------- plci management ------------------------------------------ */
458 static capidrv_plci
*new_plci(capidrv_contr
* card
, int chan
)
462 plcip
= (capidrv_plci
*) kmalloc(sizeof(capidrv_plci
), GFP_ATOMIC
);
467 memset(plcip
, 0, sizeof(capidrv_plci
));
468 plcip
->state
= ST_PLCI_NONE
;
472 plcip
->next
= card
->plci_list
;
473 card
->plci_list
= plcip
;
474 card
->bchans
[chan
].plcip
= plcip
;
479 static capidrv_plci
*find_plci_by_plci(capidrv_contr
* card
, __u32 plci
)
482 for (p
= card
->plci_list
; p
; p
= p
->next
)
488 static capidrv_plci
*find_plci_by_msgid(capidrv_contr
* card
, __u16 msgid
)
491 for (p
= card
->plci_list
; p
; p
= p
->next
)
492 if (p
->msgid
== msgid
)
497 static capidrv_plci
*find_plci_by_ncci(capidrv_contr
* card
, __u32 ncci
)
500 for (p
= card
->plci_list
; p
; p
= p
->next
)
501 if (p
->plci
== (ncci
& 0xffff))
506 static void free_plci(capidrv_contr
* card
, capidrv_plci
* plcip
)
510 for (pp
= &card
->plci_list
; *pp
; pp
= &(*pp
)->next
) {
513 card
->bchans
[plcip
->chan
].plcip
= 0;
514 card
->bchans
[plcip
->chan
].disconnecting
= 0;
515 card
->bchans
[plcip
->chan
].incoming
= 0;
520 printk(KERN_ERR
"capidrv-%d: free_plci %p (0x%x) not found, Huh?\n",
521 card
->contrnr
, plcip
, plcip
->plci
);
524 /* -------- ncci management ------------------------------------------ */
526 static inline capidrv_ncci
*new_ncci(capidrv_contr
* card
,
527 capidrv_plci
* plcip
,
532 nccip
= (capidrv_ncci
*) kmalloc(sizeof(capidrv_ncci
), GFP_ATOMIC
);
537 memset(nccip
, 0, sizeof(capidrv_ncci
));
539 nccip
->state
= ST_NCCI_NONE
;
540 nccip
->plcip
= plcip
;
541 nccip
->chan
= plcip
->chan
;
542 nccip
->datahandle
= 0;
544 nccip
->next
= plcip
->ncci_list
;
545 plcip
->ncci_list
= nccip
;
547 card
->bchans
[plcip
->chan
].nccip
= nccip
;
552 static inline capidrv_ncci
*find_ncci(capidrv_contr
* card
, __u32 ncci
)
557 if ((plcip
= find_plci_by_ncci(card
, ncci
)) == 0)
560 for (p
= plcip
->ncci_list
; p
; p
= p
->next
)
566 static inline capidrv_ncci
*find_ncci_by_msgid(capidrv_contr
* card
,
567 __u32 ncci
, __u16 msgid
)
572 if ((plcip
= find_plci_by_ncci(card
, ncci
)) == 0)
575 for (p
= plcip
->ncci_list
; p
; p
= p
->next
)
576 if (p
->msgid
== msgid
)
581 static void free_ncci(capidrv_contr
* card
, struct capidrv_ncci
*nccip
)
583 struct capidrv_ncci
**pp
;
585 for (pp
= &(nccip
->plcip
->ncci_list
); *pp
; pp
= &(*pp
)->next
) {
591 card
->bchans
[nccip
->chan
].nccip
= 0;
595 static int capidrv_add_ack(struct capidrv_ncci
*nccip
,
596 __u16 datahandle
, int len
)
598 struct ncci_datahandle_queue
*n
, **pp
;
600 n
= (struct ncci_datahandle_queue
*)
601 kmalloc(sizeof(struct ncci_datahandle_queue
), GFP_ATOMIC
);
603 printk(KERN_ERR
"capidrv: kmalloc ncci_datahandle failed\n");
607 n
->datahandle
= datahandle
;
609 for (pp
= &nccip
->ackqueue
; *pp
; pp
= &(*pp
)->next
) ;
614 static int capidrv_del_ack(struct capidrv_ncci
*nccip
, __u16 datahandle
)
616 struct ncci_datahandle_queue
**pp
, *p
;
619 for (pp
= &nccip
->ackqueue
; *pp
; pp
= &(*pp
)->next
) {
620 if ((*pp
)->datahandle
== datahandle
) {
631 /* -------- convert and send capi message ---------------------------- */
633 static void send_message(capidrv_contr
* card
, _cmsg
* cmsg
)
637 capi_cmsg2message(cmsg
, cmsg
->buf
);
638 len
= CAPIMSG_LEN(cmsg
->buf
);
639 skb
= alloc_skb(len
, GFP_ATOMIC
);
640 memcpy(skb_put(skb
, len
), cmsg
->buf
, len
);
641 (*capifuncs
->capi_put_message
) (global
.appid
, skb
);
642 global
.nsentctlpkt
++;
645 /* -------- state machine -------------------------------------------- */
647 struct listenstatechange
{
653 static struct listenstatechange listentable
[] =
655 {ST_LISTEN_NONE
, ST_LISTEN_WAIT_CONF
, EV_LISTEN_REQ
},
656 {ST_LISTEN_ACTIVE
, ST_LISTEN_ACTIVE_WAIT_CONF
, EV_LISTEN_REQ
},
657 {ST_LISTEN_WAIT_CONF
, ST_LISTEN_NONE
, EV_LISTEN_CONF_ERROR
},
658 {ST_LISTEN_ACTIVE_WAIT_CONF
, ST_LISTEN_ACTIVE
, EV_LISTEN_CONF_ERROR
},
659 {ST_LISTEN_WAIT_CONF
, ST_LISTEN_NONE
, EV_LISTEN_CONF_EMPTY
},
660 {ST_LISTEN_ACTIVE_WAIT_CONF
, ST_LISTEN_NONE
, EV_LISTEN_CONF_EMPTY
},
661 {ST_LISTEN_WAIT_CONF
, ST_LISTEN_ACTIVE
, EV_LISTEN_CONF_OK
},
662 {ST_LISTEN_ACTIVE_WAIT_CONF
, ST_LISTEN_ACTIVE
, EV_LISTEN_CONF_OK
},
666 static void listen_change_state(capidrv_contr
* card
, int event
)
668 struct listenstatechange
*p
= listentable
;
670 if (card
->state
== p
->actstate
&& p
->event
== event
) {
672 printk(KERN_DEBUG
"capidrv-%d: listen_change_state %d -> %d\n",
673 card
->contrnr
, card
->state
, p
->nextstate
);
674 card
->state
= p
->nextstate
;
679 printk(KERN_ERR
"capidrv-%d: listen_change_state state=%d event=%d ????\n",
680 card
->contrnr
, card
->state
, event
);
684 /* ------------------------------------------------------------------ */
686 static void p0(capidrv_contr
* card
, capidrv_plci
* plci
)
690 card
->bchans
[plci
->chan
].contr
= 0;
691 cmd
.command
= ISDN_STAT_DHUP
;
692 cmd
.driver
= card
->myid
;
693 cmd
.arg
= plci
->chan
;
694 card
->interface
.statcallb(&cmd
);
695 free_plci(card
, plci
);
698 /* ------------------------------------------------------------------ */
700 struct plcistatechange
{
704 void (*changefunc
) (capidrv_contr
* card
, capidrv_plci
* plci
);
707 static struct plcistatechange plcitable
[] =
710 {ST_PLCI_NONE
, ST_PLCI_OUTGOING
, EV_PLCI_CONNECT_REQ
, 0},
711 {ST_PLCI_NONE
, ST_PLCI_ALLOCATED
, EV_PLCI_FACILITY_IND_UP
, 0},
712 {ST_PLCI_NONE
, ST_PLCI_INCOMING
, EV_PLCI_CONNECT_IND
, 0},
713 {ST_PLCI_NONE
, ST_PLCI_RESUMEING
, EV_PLCI_RESUME_REQ
, 0},
715 {ST_PLCI_OUTGOING
, ST_PLCI_NONE
, EV_PLCI_CONNECT_CONF_ERROR
, p0
},
716 {ST_PLCI_OUTGOING
, ST_PLCI_ALLOCATED
, EV_PLCI_CONNECT_CONF_OK
, 0},
717 {ST_PLCI_OUTGOING
, ST_PLCI_DISCONNECTING
, EV_PLCI_DISCONNECT_REQ
, 0},
718 {ST_PLCI_OUTGOING
, ST_PLCI_DISCONNECTING
, EV_PLCI_FACILITY_IND_DOWN
, 0},
720 {ST_PLCI_ALLOCATED
, ST_PLCI_ACTIVE
, EV_PLCI_CONNECT_ACTIVE_IND
, 0},
721 {ST_PLCI_ALLOCATED
, ST_PLCI_DISCONNECTING
, EV_PLCI_DISCONNECT_REQ
, 0},
722 {ST_PLCI_ALLOCATED
, ST_PLCI_DISCONNECTING
, EV_PLCI_FACILITY_IND_DOWN
, 0},
723 {ST_PLCI_ALLOCATED
, ST_PLCI_DISCONNECTED
, EV_PLCI_DISCONNECT_IND
, 0},
725 {ST_PLCI_ACTIVE
, ST_PLCI_DISCONNECTING
, EV_PLCI_DISCONNECT_REQ
, 0},
726 {ST_PLCI_ACTIVE
, ST_PLCI_DISCONNECTING
, EV_PLCI_FACILITY_IND_DOWN
, 0},
727 {ST_PLCI_ACTIVE
, ST_PLCI_DISCONNECTED
, EV_PLCI_DISCONNECT_IND
, 0},
728 {ST_PLCI_ACTIVE
, ST_PLCI_HELD
, EV_PLCI_HOLD_IND
, 0},
729 {ST_PLCI_ACTIVE
, ST_PLCI_DISCONNECTING
, EV_PLCI_SUSPEND_IND
, 0},
731 {ST_PLCI_INCOMING
, ST_PLCI_DISCONNECTING
, EV_PLCI_CONNECT_REJECT
, 0},
732 {ST_PLCI_INCOMING
, ST_PLCI_FACILITY_IND
, EV_PLCI_FACILITY_IND_UP
, 0},
733 {ST_PLCI_INCOMING
, ST_PLCI_ACCEPTING
, EV_PLCI_CONNECT_RESP
, 0},
734 {ST_PLCI_INCOMING
, ST_PLCI_DISCONNECTING
, EV_PLCI_DISCONNECT_REQ
, 0},
735 {ST_PLCI_INCOMING
, ST_PLCI_DISCONNECTING
, EV_PLCI_FACILITY_IND_DOWN
, 0},
736 {ST_PLCI_INCOMING
, ST_PLCI_DISCONNECTED
, EV_PLCI_DISCONNECT_IND
, 0},
737 {ST_PLCI_INCOMING
, ST_PLCI_DISCONNECTING
, EV_PLCI_CD_IND
, 0},
739 {ST_PLCI_FACILITY_IND
, ST_PLCI_DISCONNECTING
, EV_PLCI_CONNECT_REJECT
, 0},
740 {ST_PLCI_FACILITY_IND
, ST_PLCI_ACCEPTING
, EV_PLCI_CONNECT_ACTIVE_IND
, 0},
741 {ST_PLCI_FACILITY_IND
, ST_PLCI_DISCONNECTING
, EV_PLCI_DISCONNECT_REQ
, 0},
742 {ST_PLCI_FACILITY_IND
, ST_PLCI_DISCONNECTING
, EV_PLCI_FACILITY_IND_DOWN
, 0},
743 {ST_PLCI_FACILITY_IND
, ST_PLCI_DISCONNECTED
, EV_PLCI_DISCONNECT_IND
, 0},
745 {ST_PLCI_ACCEPTING
, ST_PLCI_ACTIVE
, EV_PLCI_CONNECT_ACTIVE_IND
, 0},
746 {ST_PLCI_ACCEPTING
, ST_PLCI_DISCONNECTING
, EV_PLCI_DISCONNECT_REQ
, 0},
747 {ST_PLCI_ACCEPTING
, ST_PLCI_DISCONNECTING
, EV_PLCI_FACILITY_IND_DOWN
, 0},
748 {ST_PLCI_ACCEPTING
, ST_PLCI_DISCONNECTED
, EV_PLCI_DISCONNECT_IND
, 0},
750 {ST_PLCI_DISCONNECTING
, ST_PLCI_DISCONNECTED
, EV_PLCI_DISCONNECT_IND
, 0},
752 {ST_PLCI_DISCONNECTED
, ST_PLCI_NONE
, EV_PLCI_DISCONNECT_RESP
, p0
},
754 {ST_PLCI_RESUMEING
, ST_PLCI_NONE
, EV_PLCI_RESUME_CONF_ERROR
, p0
},
755 {ST_PLCI_RESUMEING
, ST_PLCI_RESUME
, EV_PLCI_RESUME_CONF_OK
, 0},
757 {ST_PLCI_RESUME
, ST_PLCI_ACTIVE
, EV_PLCI_RESUME_IND
, 0},
759 {ST_PLCI_HELD
, ST_PLCI_ACTIVE
, EV_PLCI_RETRIEVE_IND
, 0},
763 static void plci_change_state(capidrv_contr
* card
, capidrv_plci
* plci
, int event
)
765 struct plcistatechange
*p
= plcitable
;
767 if (plci
->state
== p
->actstate
&& p
->event
== event
) {
769 printk(KERN_DEBUG
"capidrv-%d: plci_change_state:0x%x %d -> %d\n",
770 card
->contrnr
, plci
->plci
, plci
->state
, p
->nextstate
);
771 plci
->state
= p
->nextstate
;
773 p
->changefunc(card
, plci
);
778 printk(KERN_ERR
"capidrv-%d: plci_change_state:0x%x state=%d event=%d ????\n",
779 card
->contrnr
, plci
->plci
, plci
->state
, event
);
782 /* ------------------------------------------------------------------ */
786 static void n0(capidrv_contr
* card
, capidrv_ncci
* ncci
)
790 capi_fill_DISCONNECT_REQ(&cmsg
,
794 0, /* BChannelinformation */
795 0, /* Keypadfacility */
796 0, /* Useruserdata */ /* $$$$ */
797 0 /* Facilitydataarray */
799 send_message(card
, &cmsg
);
800 plci_change_state(card
, ncci
->plcip
, EV_PLCI_DISCONNECT_REQ
);
802 cmd
.command
= ISDN_STAT_BHUP
;
803 cmd
.driver
= card
->myid
;
804 cmd
.arg
= ncci
->chan
;
805 card
->interface
.statcallb(&cmd
);
806 free_ncci(card
, ncci
);
809 /* ------------------------------------------------------------------ */
811 struct nccistatechange
{
815 void (*changefunc
) (capidrv_contr
* card
, capidrv_ncci
* ncci
);
818 static struct nccistatechange nccitable
[] =
821 {ST_NCCI_NONE
, ST_NCCI_OUTGOING
, EV_NCCI_CONNECT_B3_REQ
, 0},
822 {ST_NCCI_NONE
, ST_NCCI_INCOMING
, EV_NCCI_CONNECT_B3_IND
, 0},
824 {ST_NCCI_OUTGOING
, ST_NCCI_ALLOCATED
, EV_NCCI_CONNECT_B3_CONF_OK
, 0},
825 {ST_NCCI_OUTGOING
, ST_NCCI_NONE
, EV_NCCI_CONNECT_B3_CONF_ERROR
, n0
},
827 {ST_NCCI_INCOMING
, ST_NCCI_DISCONNECTING
, EV_NCCI_CONNECT_B3_REJECT
, 0},
828 {ST_NCCI_INCOMING
, ST_NCCI_ALLOCATED
, EV_NCCI_CONNECT_B3_RESP
, 0},
829 {ST_NCCI_INCOMING
, ST_NCCI_DISCONNECTED
, EV_NCCI_DISCONNECT_B3_IND
, 0},
830 {ST_NCCI_INCOMING
, ST_NCCI_DISCONNECTING
, EV_NCCI_DISCONNECT_B3_REQ
, 0},
832 {ST_NCCI_ALLOCATED
, ST_NCCI_ACTIVE
, EV_NCCI_CONNECT_B3_ACTIVE_IND
, 0},
833 {ST_NCCI_ALLOCATED
, ST_NCCI_DISCONNECTED
, EV_NCCI_DISCONNECT_B3_IND
, 0},
834 {ST_NCCI_ALLOCATED
, ST_NCCI_DISCONNECTING
, EV_NCCI_DISCONNECT_B3_REQ
, 0},
836 {ST_NCCI_ACTIVE
, ST_NCCI_ACTIVE
, EV_NCCI_RESET_B3_IND
, 0},
837 {ST_NCCI_ACTIVE
, ST_NCCI_RESETING
, EV_NCCI_RESET_B3_REQ
, 0},
838 {ST_NCCI_ACTIVE
, ST_NCCI_DISCONNECTED
, EV_NCCI_DISCONNECT_B3_IND
, 0},
839 {ST_NCCI_ACTIVE
, ST_NCCI_DISCONNECTING
, EV_NCCI_DISCONNECT_B3_REQ
, 0},
841 {ST_NCCI_RESETING
, ST_NCCI_ACTIVE
, EV_NCCI_RESET_B3_IND
, 0},
842 {ST_NCCI_RESETING
, ST_NCCI_DISCONNECTED
, EV_NCCI_DISCONNECT_B3_IND
, 0},
843 {ST_NCCI_RESETING
, ST_NCCI_DISCONNECTING
, EV_NCCI_DISCONNECT_B3_REQ
, 0},
845 {ST_NCCI_DISCONNECTING
, ST_NCCI_DISCONNECTED
, EV_NCCI_DISCONNECT_B3_IND
, 0},
846 {ST_NCCI_DISCONNECTING
, ST_NCCI_PREVIOUS
, EV_NCCI_DISCONNECT_B3_CONF_ERROR
,0},
848 {ST_NCCI_DISCONNECTED
, ST_NCCI_NONE
, EV_NCCI_DISCONNECT_B3_RESP
, n0
},
852 static void ncci_change_state(capidrv_contr
* card
, capidrv_ncci
* ncci
, int event
)
854 struct nccistatechange
*p
= nccitable
;
856 if (ncci
->state
== p
->actstate
&& p
->event
== event
) {
858 printk(KERN_DEBUG
"capidrv-%d: ncci_change_state:0x%x %d -> %d\n",
859 card
->contrnr
, ncci
->ncci
, ncci
->state
, p
->nextstate
);
860 if (p
->nextstate
== ST_NCCI_PREVIOUS
) {
861 ncci
->state
= ncci
->oldstate
;
862 ncci
->oldstate
= p
->actstate
;
864 ncci
->oldstate
= p
->actstate
;
865 ncci
->state
= p
->nextstate
;
868 p
->changefunc(card
, ncci
);
873 printk(KERN_ERR
"capidrv-%d: ncci_change_state:0x%x state=%d event=%d ????\n",
874 card
->contrnr
, ncci
->ncci
, ncci
->state
, event
);
877 /* ------------------------------------------------------------------- */
879 static inline int new_bchan(capidrv_contr
* card
)
882 for (i
= 0; i
< card
->nbchan
; i
++) {
883 if (card
->bchans
[i
].plcip
== 0) {
884 card
->bchans
[i
].disconnecting
= 0;
891 /* ------------------------------------------------------------------- */
893 static void handle_controller(_cmsg
* cmsg
)
895 capidrv_contr
*card
= findcontrbynumber(cmsg
->adr
.adrController
& 0x7f);
898 printk(KERN_ERR
"capidrv: %s from unknown controller 0x%x\n",
899 capi_cmd2str(cmsg
->Command
, cmsg
->Subcommand
),
900 cmsg
->adr
.adrController
& 0x7f);
903 switch (CAPICMD(cmsg
->Command
, cmsg
->Subcommand
)) {
905 case CAPI_LISTEN_CONF
: /* Controller */
907 printk(KERN_DEBUG
"capidrv-%d: listenconf Info=0x%4x (%s) cipmask=0x%x\n",
908 card
->contrnr
, cmsg
->Info
, capi_info2str(cmsg
->Info
), card
->cipmask
);
910 listen_change_state(card
, EV_LISTEN_CONF_ERROR
);
911 } else if (card
->cipmask
== 0) {
912 listen_change_state(card
, EV_LISTEN_CONF_EMPTY
);
914 listen_change_state(card
, EV_LISTEN_CONF_OK
);
918 case CAPI_MANUFACTURER_IND
: /* Controller */
919 if ( cmsg
->ManuID
== 0x214D5641
921 && cmsg
->Function
== 1) {
922 __u8
*data
= cmsg
->ManuData
+3;
923 __u16 len
= cmsg
->ManuData
[0];
927 len
= (cmsg
->ManuData
[1] | (cmsg
->ManuData
[2] << 8));
931 layer
= ((*(data
-1)) << 8) | *(data
-2);
933 direction
= (layer
& 0x200) ? 0 : 1;
934 else direction
= (layer
& 0x800) ? 0 : 1;
935 if (layer
& 0x0C00) {
936 if ((layer
& 0xff) == 0x80) {
937 handle_dtrace_data(card
, direction
, 1, data
, len
);
940 } else if ((layer
& 0xff) < 0x80) {
941 handle_dtrace_data(card
, direction
, 0, data
, len
);
944 printk(KERN_INFO
"capidrv-%d: %s from controller 0x%x layer 0x%x, ignored\n",
946 capi_cmd2str(cmsg
->Command
, cmsg
->Subcommand
),
947 cmsg
->adr
.adrController
, layer
);
951 case CAPI_MANUFACTURER_CONF
: /* Controller */
952 if (cmsg
->ManuID
== 0x214D5641) {
954 switch (cmsg
->Class
) {
956 case 1: s
= "unknown class"; break;
957 case 2: s
= "unknown function"; break;
958 default: s
= "unkown error"; break;
961 printk(KERN_INFO
"capidrv-%d: %s from controller 0x%x function %d: %s\n",
963 capi_cmd2str(cmsg
->Command
, cmsg
->Subcommand
),
964 cmsg
->adr
.adrController
,
969 case CAPI_FACILITY_IND
: /* Controller/plci/ncci */
971 case CAPI_FACILITY_CONF
: /* Controller/plci/ncci */
973 case CAPI_INFO_IND
: /* Controller/plci */
975 case CAPI_INFO_CONF
: /* Controller/plci */
979 printk(KERN_ERR
"capidrv-%d: got %s from controller 0x%x ???",
981 capi_cmd2str(cmsg
->Command
, cmsg
->Subcommand
),
982 cmsg
->adr
.adrController
);
987 printk(KERN_INFO
"capidrv-%d: %s from controller 0x%x ignored\n",
989 capi_cmd2str(cmsg
->Command
, cmsg
->Subcommand
),
990 cmsg
->adr
.adrController
);
993 static void handle_incoming_call(capidrv_contr
* card
, _cmsg
* cmsg
)
996 capidrv_bchan
*bchan
;
1000 if ((chan
= new_bchan(card
)) == -1) {
1001 printk(KERN_ERR
"capidrv-%d: incoming call on not existing bchan ?\n", card
->contrnr
);
1004 bchan
= &card
->bchans
[chan
];
1005 if ((plcip
= new_plci(card
, chan
)) == 0) {
1006 printk(KERN_ERR
"capidrv-%d: incoming call: no memory, sorry.\n", card
->contrnr
);
1009 bchan
->incoming
= 1;
1010 plcip
->plci
= cmsg
->adr
.adrPLCI
;
1011 plci_change_state(card
, plcip
, EV_PLCI_CONNECT_IND
);
1013 cmd
.command
= ISDN_STAT_ICALL
;
1014 cmd
.driver
= card
->myid
;
1016 memset(&cmd
.parm
.setup
, 0, sizeof(cmd
.parm
.setup
));
1017 strncpy(cmd
.parm
.setup
.phone
,
1018 cmsg
->CallingPartyNumber
+ 3,
1019 cmsg
->CallingPartyNumber
[0] - 2);
1020 strncpy(cmd
.parm
.setup
.eazmsn
,
1021 cmsg
->CalledPartyNumber
+ 2,
1022 cmsg
->CalledPartyNumber
[0] - 1);
1023 cmd
.parm
.setup
.si1
= cip2si1(cmsg
->CIPValue
);
1024 cmd
.parm
.setup
.si2
= cip2si2(cmsg
->CIPValue
);
1025 cmd
.parm
.setup
.plan
= cmsg
->CallingPartyNumber
[1];
1026 cmd
.parm
.setup
.screen
= cmsg
->CallingPartyNumber
[2];
1028 printk(KERN_INFO
"capidrv-%d: incoming call %s,%d,%d,%s\n",
1030 cmd
.parm
.setup
.phone
,
1033 cmd
.parm
.setup
.eazmsn
);
1035 if (cmd
.parm
.setup
.si1
== 1 && cmd
.parm
.setup
.si2
!= 0) {
1036 printk(KERN_INFO
"capidrv-%d: patching si2=%d to 0 for VBOX\n",
1038 cmd
.parm
.setup
.si2
);
1039 cmd
.parm
.setup
.si2
= 0;
1042 switch (card
->interface
.statcallb(&cmd
)) {
1045 /* No device matching this call.
1046 * and isdn_common.c has send a HANGUP command
1047 * which is ignored in state ST_PLCI_INCOMING,
1048 * so we send RESP to ignore the call
1050 capi_cmsg_answer(cmsg
);
1051 cmsg
->Reject
= 1; /* ignore */
1052 send_message(card
, cmsg
);
1053 plci_change_state(card
, plcip
, EV_PLCI_CONNECT_REJECT
);
1054 printk(KERN_INFO
"capidrv-%d: incoming call %s,%d,%d,%s ignored\n",
1056 cmd
.parm
.setup
.phone
,
1059 cmd
.parm
.setup
.eazmsn
);
1062 /* At least one device matching this call (RING on ttyI)
1063 * HL-driver may send ALERTING on the D-channel in this
1065 * really means: RING on ttyI or a net interface
1066 * accepted this call already.
1068 * If the call was accepted, state has already changed,
1069 * and CONNECT_RESP already sent.
1071 if (plcip
->state
== ST_PLCI_INCOMING
) {
1072 printk(KERN_INFO
"capidrv-%d: incoming call %s,%d,%d,%s tty alerting\n",
1074 cmd
.parm
.setup
.phone
,
1077 cmd
.parm
.setup
.eazmsn
);
1078 capi_fill_ALERT_REQ(cmsg
,
1081 plcip
->plci
, /* adr */
1082 0, /* BChannelinformation */
1083 0, /* Keypadfacility */
1084 0, /* Useruserdata */
1085 0 /* Facilitydataarray */
1087 plcip
->msgid
= cmsg
->Messagenumber
;
1088 send_message(card
, cmsg
);
1090 printk(KERN_INFO
"capidrv-%d: incoming call %s,%d,%d,%s on netdev\n",
1092 cmd
.parm
.setup
.phone
,
1095 cmd
.parm
.setup
.eazmsn
);
1099 case 2: /* Call will be rejected. */
1100 capi_cmsg_answer(cmsg
);
1101 cmsg
->Reject
= 2; /* reject call, normal call clearing */
1102 send_message(card
, cmsg
);
1103 plci_change_state(card
, plcip
, EV_PLCI_CONNECT_REJECT
);
1107 /* An error happened. (Invalid parameters for example.) */
1108 capi_cmsg_answer(cmsg
);
1109 cmsg
->Reject
= 8; /* reject call,
1110 destination out of order */
1111 send_message(card
, cmsg
);
1112 plci_change_state(card
, plcip
, EV_PLCI_CONNECT_REJECT
);
1118 static void handle_plci(_cmsg
* cmsg
)
1120 capidrv_contr
*card
= findcontrbynumber(cmsg
->adr
.adrController
& 0x7f);
1121 capidrv_plci
*plcip
;
1125 printk(KERN_ERR
"capidrv: %s from unknown controller 0x%x\n",
1126 capi_cmd2str(cmsg
->Command
, cmsg
->Subcommand
),
1127 cmsg
->adr
.adrController
& 0x7f);
1130 switch (CAPICMD(cmsg
->Command
, cmsg
->Subcommand
)) {
1132 case CAPI_DISCONNECT_IND
: /* plci */
1134 printk(KERN_INFO
"capidrv-%d: %s reason 0x%x (%s) for plci 0x%x\n",
1136 capi_cmd2str(cmsg
->Command
, cmsg
->Subcommand
),
1137 cmsg
->Reason
, capi_info2str(cmsg
->Reason
), cmsg
->adr
.adrPLCI
);
1139 if (!(plcip
= find_plci_by_plci(card
, cmsg
->adr
.adrPLCI
))) {
1140 capi_cmsg_answer(cmsg
);
1141 send_message(card
, cmsg
);
1144 card
->bchans
[plcip
->chan
].disconnecting
= 1;
1145 plci_change_state(card
, plcip
, EV_PLCI_DISCONNECT_IND
);
1146 capi_cmsg_answer(cmsg
);
1147 send_message(card
, cmsg
);
1148 plci_change_state(card
, plcip
, EV_PLCI_DISCONNECT_RESP
);
1151 case CAPI_DISCONNECT_CONF
: /* plci */
1153 printk(KERN_INFO
"capidrv-%d: %s info 0x%x (%s) for plci 0x%x\n",
1155 capi_cmd2str(cmsg
->Command
, cmsg
->Subcommand
),
1156 cmsg
->Info
, capi_info2str(cmsg
->Info
),
1159 if (!(plcip
= find_plci_by_plci(card
, cmsg
->adr
.adrPLCI
)))
1162 card
->bchans
[plcip
->chan
].disconnecting
= 1;
1165 case CAPI_ALERT_CONF
: /* plci */
1167 printk(KERN_INFO
"capidrv-%d: %s info 0x%x (%s) for plci 0x%x\n",
1169 capi_cmd2str(cmsg
->Command
, cmsg
->Subcommand
),
1170 cmsg
->Info
, capi_info2str(cmsg
->Info
),
1175 case CAPI_CONNECT_IND
: /* plci */
1176 handle_incoming_call(card
, cmsg
);
1179 case CAPI_CONNECT_CONF
: /* plci */
1181 printk(KERN_INFO
"capidrv-%d: %s info 0x%x (%s) for plci 0x%x\n",
1183 capi_cmd2str(cmsg
->Command
, cmsg
->Subcommand
),
1184 cmsg
->Info
, capi_info2str(cmsg
->Info
),
1187 if (!(plcip
= find_plci_by_msgid(card
, cmsg
->Messagenumber
)))
1190 plcip
->plci
= cmsg
->adr
.adrPLCI
;
1192 plci_change_state(card
, plcip
, EV_PLCI_CONNECT_CONF_ERROR
);
1194 plci_change_state(card
, plcip
, EV_PLCI_CONNECT_CONF_OK
);
1198 case CAPI_CONNECT_ACTIVE_IND
: /* plci */
1200 if (!(plcip
= find_plci_by_plci(card
, cmsg
->adr
.adrPLCI
)))
1203 if (card
->bchans
[plcip
->chan
].incoming
) {
1204 capi_cmsg_answer(cmsg
);
1205 send_message(card
, cmsg
);
1206 plci_change_state(card
, plcip
, EV_PLCI_CONNECT_ACTIVE_IND
);
1208 capidrv_ncci
*nccip
;
1209 capi_cmsg_answer(cmsg
);
1210 send_message(card
, cmsg
);
1212 nccip
= new_ncci(card
, plcip
, cmsg
->adr
.adrPLCI
);
1215 printk(KERN_ERR
"capidrv-%d: no mem for ncci, sorry\n", card
->contrnr
);
1218 capi_fill_CONNECT_B3_REQ(cmsg
,
1221 plcip
->plci
, /* adr */
1224 nccip
->msgid
= cmsg
->Messagenumber
;
1225 send_message(card
, cmsg
);
1226 cmd
.command
= ISDN_STAT_DCONN
;
1227 cmd
.driver
= card
->myid
;
1228 cmd
.arg
= plcip
->chan
;
1229 card
->interface
.statcallb(&cmd
);
1230 plci_change_state(card
, plcip
, EV_PLCI_CONNECT_ACTIVE_IND
);
1231 ncci_change_state(card
, nccip
, EV_NCCI_CONNECT_B3_REQ
);
1235 case CAPI_INFO_IND
: /* Controller/plci */
1237 if (!(plcip
= find_plci_by_plci(card
, cmsg
->adr
.adrPLCI
)))
1240 if (cmsg
->InfoNumber
== 0x4000) {
1241 if (cmsg
->InfoElement
[0] == 4) {
1242 cmd
.command
= ISDN_STAT_CINF
;
1243 cmd
.driver
= card
->myid
;
1244 cmd
.arg
= plcip
->chan
;
1245 sprintf(cmd
.parm
.num
, "%lu",
1247 ((__u32
) cmsg
->InfoElement
[1]
1248 | ((__u32
) (cmsg
->InfoElement
[2]) << 8)
1249 | ((__u32
) (cmsg
->InfoElement
[3]) << 16)
1250 | ((__u32
) (cmsg
->InfoElement
[4]) << 24)));
1251 card
->interface
.statcallb(&cmd
);
1255 printk(KERN_ERR
"capidrv-%d: %s\n",
1256 card
->contrnr
, capi_cmsg2str(cmsg
));
1259 case CAPI_CONNECT_ACTIVE_CONF
: /* plci */
1261 case CAPI_SELECT_B_PROTOCOL_CONF
: /* plci */
1263 case CAPI_FACILITY_IND
: /* Controller/plci/ncci */
1265 case CAPI_FACILITY_CONF
: /* Controller/plci/ncci */
1268 case CAPI_INFO_CONF
: /* Controller/plci */
1272 printk(KERN_ERR
"capidrv-%d: got %s for plci 0x%x ???",
1274 capi_cmd2str(cmsg
->Command
, cmsg
->Subcommand
),
1279 printk(KERN_INFO
"capidrv-%d: %s for plci 0x%x ignored\n",
1281 capi_cmd2str(cmsg
->Command
, cmsg
->Subcommand
),
1285 printk(KERN_ERR
"capidrv-%d: %s: plci 0x%x not found\n",
1287 capi_cmd2str(cmsg
->Command
, cmsg
->Subcommand
),
1292 static void handle_ncci(_cmsg
* cmsg
)
1294 capidrv_contr
*card
= findcontrbynumber(cmsg
->adr
.adrController
& 0x7f);
1295 capidrv_plci
*plcip
;
1296 capidrv_ncci
*nccip
;
1301 printk(KERN_ERR
"capidrv: %s from unknown controller 0x%x\n",
1302 capi_cmd2str(cmsg
->Command
, cmsg
->Subcommand
),
1303 cmsg
->adr
.adrController
& 0x7f);
1306 switch (CAPICMD(cmsg
->Command
, cmsg
->Subcommand
)) {
1308 case CAPI_CONNECT_B3_ACTIVE_IND
: /* ncci */
1309 if (!(nccip
= find_ncci(card
, cmsg
->adr
.adrNCCI
)))
1312 capi_cmsg_answer(cmsg
);
1313 send_message(card
, cmsg
);
1314 ncci_change_state(card
, nccip
, EV_NCCI_CONNECT_B3_ACTIVE_IND
);
1316 cmd
.command
= ISDN_STAT_BCONN
;
1317 cmd
.driver
= card
->myid
;
1318 cmd
.arg
= nccip
->chan
;
1319 card
->interface
.statcallb(&cmd
);
1321 printk(KERN_INFO
"capidrv-%d: chan %d up with ncci 0x%x\n",
1322 card
->contrnr
, nccip
->chan
, nccip
->ncci
);
1325 case CAPI_CONNECT_B3_ACTIVE_CONF
: /* ncci */
1328 case CAPI_CONNECT_B3_IND
: /* ncci */
1330 plcip
= find_plci_by_ncci(card
, cmsg
->adr
.adrNCCI
);
1332 nccip
= new_ncci(card
, plcip
, cmsg
->adr
.adrNCCI
);
1334 ncci_change_state(card
, nccip
, EV_NCCI_CONNECT_B3_IND
);
1335 capi_fill_CONNECT_B3_RESP(cmsg
,
1338 nccip
->ncci
, /* adr */
1342 send_message(card
, cmsg
);
1343 ncci_change_state(card
, nccip
, EV_NCCI_CONNECT_B3_RESP
);
1346 printk(KERN_ERR
"capidrv-%d: no mem for ncci, sorry\n", card
->contrnr
);
1348 printk(KERN_ERR
"capidrv-%d: %s: plci for ncci 0x%x not found\n",
1350 capi_cmd2str(cmsg
->Command
, cmsg
->Subcommand
),
1353 capi_fill_CONNECT_B3_RESP(cmsg
,
1360 send_message(card
, cmsg
);
1363 case CAPI_CONNECT_B3_CONF
: /* ncci */
1365 if (!(nccip
= find_ncci_by_msgid(card
,
1367 cmsg
->Messagenumber
)))
1370 nccip
->ncci
= cmsg
->adr
.adrNCCI
;
1372 printk(KERN_INFO
"capidrv-%d: %s info 0x%x (%s) for ncci 0x%x\n",
1374 capi_cmd2str(cmsg
->Command
, cmsg
->Subcommand
),
1375 cmsg
->Info
, capi_info2str(cmsg
->Info
),
1380 ncci_change_state(card
, nccip
, EV_NCCI_CONNECT_B3_CONF_ERROR
);
1382 ncci_change_state(card
, nccip
, EV_NCCI_CONNECT_B3_CONF_OK
);
1385 case CAPI_CONNECT_B3_T90_ACTIVE_IND
: /* ncci */
1386 capi_cmsg_answer(cmsg
);
1387 send_message(card
, cmsg
);
1390 case CAPI_DATA_B3_IND
: /* ncci */
1391 /* handled in handle_data() */
1394 case CAPI_DATA_B3_CONF
: /* ncci */
1395 if (!(nccip
= find_ncci(card
, cmsg
->adr
.adrNCCI
)))
1398 len
= capidrv_del_ack(nccip
, cmsg
->DataHandle
);
1401 cmd
.command
= ISDN_STAT_BSENT
;
1402 cmd
.driver
= card
->myid
;
1403 cmd
.arg
= nccip
->chan
;
1404 cmd
.parm
.length
= len
;
1405 card
->interface
.statcallb(&cmd
);
1408 case CAPI_DISCONNECT_B3_IND
: /* ncci */
1409 if (!(nccip
= find_ncci(card
, cmsg
->adr
.adrNCCI
)))
1412 card
->bchans
[nccip
->chan
].disconnecting
= 1;
1413 ncci_change_state(card
, nccip
, EV_NCCI_DISCONNECT_B3_IND
);
1414 capi_cmsg_answer(cmsg
);
1415 send_message(card
, cmsg
);
1416 ncci_change_state(card
, nccip
, EV_NCCI_DISCONNECT_B3_RESP
);
1419 case CAPI_DISCONNECT_B3_CONF
: /* ncci */
1420 if (!(nccip
= find_ncci(card
, cmsg
->adr
.adrNCCI
)))
1423 printk(KERN_INFO
"capidrv-%d: %s info 0x%x (%s) for ncci 0x%x\n",
1425 capi_cmd2str(cmsg
->Command
, cmsg
->Subcommand
),
1426 cmsg
->Info
, capi_info2str(cmsg
->Info
),
1428 ncci_change_state(card
, nccip
, EV_NCCI_DISCONNECT_B3_CONF_ERROR
);
1432 case CAPI_RESET_B3_IND
: /* ncci */
1433 if (!(nccip
= find_ncci(card
, cmsg
->adr
.adrNCCI
)))
1435 ncci_change_state(card
, nccip
, EV_NCCI_RESET_B3_IND
);
1436 capi_cmsg_answer(cmsg
);
1437 send_message(card
, cmsg
);
1440 case CAPI_RESET_B3_CONF
: /* ncci */
1441 goto ignored
; /* $$$$ */
1443 case CAPI_FACILITY_IND
: /* Controller/plci/ncci */
1445 case CAPI_FACILITY_CONF
: /* Controller/plci/ncci */
1449 printk(KERN_ERR
"capidrv-%d: got %s for ncci 0x%x ???",
1451 capi_cmd2str(cmsg
->Command
, cmsg
->Subcommand
),
1456 printk(KERN_INFO
"capidrv-%d: %s for ncci 0x%x ignored\n",
1458 capi_cmd2str(cmsg
->Command
, cmsg
->Subcommand
),
1462 printk(KERN_ERR
"capidrv-%d: %s: ncci 0x%x not found\n",
1464 capi_cmd2str(cmsg
->Command
, cmsg
->Subcommand
),
1469 static void handle_data(_cmsg
* cmsg
, struct sk_buff
*skb
)
1471 capidrv_contr
*card
= findcontrbynumber(cmsg
->adr
.adrController
& 0x7f);
1472 capidrv_ncci
*nccip
;
1475 printk(KERN_ERR
"capidrv: %s from unknown controller 0x%x\n",
1476 capi_cmd2str(cmsg
->Command
, cmsg
->Subcommand
),
1477 cmsg
->adr
.adrController
& 0x7f);
1481 if (!(nccip
= find_ncci(card
, cmsg
->adr
.adrNCCI
))) {
1482 printk(KERN_ERR
"capidrv-%d: %s: ncci 0x%x not found\n",
1484 capi_cmd2str(cmsg
->Command
, cmsg
->Subcommand
),
1489 (void) skb_pull(skb
, CAPIMSG_LEN(skb
->data
));
1490 card
->interface
.rcvcallb_skb(card
->myid
, nccip
->chan
, skb
);
1491 capi_cmsg_answer(cmsg
);
1492 send_message(card
, cmsg
);
1495 static _cmsg s_cmsg
;
1497 static void capidrv_signal(__u16 applid
, __u32 dummy
)
1499 struct sk_buff
*skb
= 0;
1501 while ((*capifuncs
->capi_get_message
) (global
.appid
, &skb
) == CAPI_NOERROR
) {
1502 capi_message2cmsg(&s_cmsg
, skb
->data
);
1504 printk(KERN_DEBUG
"capidrv_signal: applid=%d %s\n",
1505 applid
, capi_cmsg2str(&s_cmsg
));
1507 if (s_cmsg
.Command
== CAPI_DATA_B3
1508 && s_cmsg
.Subcommand
== CAPI_IND
) {
1509 handle_data(&s_cmsg
, skb
);
1510 global
.nrecvdatapkt
++;
1513 if ((s_cmsg
.adr
.adrController
& 0xffffff00) == 0)
1514 handle_controller(&s_cmsg
);
1515 else if ((s_cmsg
.adr
.adrPLCI
& 0xffff0000) == 0)
1516 handle_plci(&s_cmsg
);
1518 handle_ncci(&s_cmsg
);
1520 * data of skb used in s_cmsg,
1521 * free data when s_cmsg is not used again
1522 * thanks to Lars Heete <hel@admin.de>
1525 global
.nrecvctlpkt
++;
1529 /* ------------------------------------------------------------------- */
1531 #define PUTBYTE_TO_STATUS(card, byte) \
1533 *(card)->q931_write++ = (byte); \
1534 if ((card)->q931_write > (card)->q931_end) \
1535 (card)->q931_write = (card)->q931_buf; \
1538 static void handle_dtrace_data(capidrv_contr
*card
,
1539 int send
, int level2
, __u8
*data
, __u16 len
)
1546 printk(KERN_DEBUG
"capidrv-%d: avmb1_q931_data: len == %d\n",
1547 card
->contrnr
, len
);
1555 PUTBYTE_TO_STATUS(card
, 'D');
1556 PUTBYTE_TO_STATUS(card
, '2');
1557 PUTBYTE_TO_STATUS(card
, send
? '>' : '<');
1558 PUTBYTE_TO_STATUS(card
, ':');
1560 PUTBYTE_TO_STATUS(card
, 'D');
1561 PUTBYTE_TO_STATUS(card
, '3');
1562 PUTBYTE_TO_STATUS(card
, send
? '>' : '<');
1563 PUTBYTE_TO_STATUS(card
, ':');
1566 for (p
= data
, end
= data
+len
; p
< end
; p
++) {
1568 PUTBYTE_TO_STATUS(card
, ' ');
1569 w
= (*p
>> 4) & 0xf;
1570 PUTBYTE_TO_STATUS(card
, (w
< 10) ? '0'+w
: 'A'-10+w
);
1572 PUTBYTE_TO_STATUS(card
, (w
< 10) ? '0'+w
: 'A'-10+w
);
1574 PUTBYTE_TO_STATUS(card
, '\n');
1576 restore_flags(flags
);
1578 cmd
.command
= ISDN_STAT_STAVAIL
;
1579 cmd
.driver
= card
->myid
;
1581 card
->interface
.statcallb(&cmd
);
1584 /* ------------------------------------------------------------------- */
1586 static _cmsg cmdcmsg
;
1588 static int capidrv_ioctl(isdn_ctrl
* c
, capidrv_contr
* card
)
1592 debugmode
= (int)(*((unsigned int *)c
->parm
.num
));
1593 printk(KERN_DEBUG
"capidrv-%d: debugmode=%d\n",
1594 card
->contrnr
, debugmode
);
1597 printk(KERN_DEBUG
"capidrv-%d: capidrv_ioctl(%ld) called ??\n",
1598 card
->contrnr
, c
->arg
);
1605 * Handle leased lines (CAPI-Bundling)
1608 struct internal_bchannelinfo
{
1609 unsigned short channelalloc
;
1610 unsigned short operation
;
1611 unsigned char cmask
[31];
1614 static int decodeFVteln(char *teln
, unsigned long *bmaskp
, int *activep
)
1616 unsigned long bmask
= 0;
1621 if (strncmp(teln
, "FV:", 3) != 0)
1624 while (*s
&& *s
== ' ') s
++;
1626 if (*s
== 'p' || *s
== 'P') {
1630 if (*s
== 'a' || *s
== 'A') {
1637 if (!isdigit(*s
)) return -3;
1638 while (isdigit(*s
)) { digit1
= digit1
*10 + (*s
- '0'); s
++; }
1639 if (digit1
<= 0 && digit1
> 30) return -4;
1640 if (*s
== 0 || *s
== ',' || *s
== ' ') {
1641 bmask
|= (1 << digit1
);
1646 if (*s
!= '-') return -5;
1648 if (!isdigit(*s
)) return -3;
1649 while (isdigit(*s
)) { digit2
= digit2
*10 + (*s
- '0'); s
++; }
1650 if (digit2
<= 0 && digit2
> 30) return -4;
1651 if (*s
== 0 || *s
== ',' || *s
== ' ') {
1652 if (digit1
> digit2
)
1653 for (i
= digit2
; i
<= digit1
; i
++)
1656 for (i
= digit1
; i
<= digit2
; i
++)
1658 digit1
= digit2
= 0;
1664 if (activep
) *activep
= active
;
1665 if (bmaskp
) *bmaskp
= bmask
;
1669 static int FVteln2capi20(char *teln
, __u8 AdditionalInfo
[1+2+2+31])
1671 unsigned long bmask
;
1675 rc
= decodeFVteln(teln
, &bmask
, &active
);
1678 AdditionalInfo
[0] = 2+2+31;
1679 /* Channel: 3 => use channel allocation */
1680 AdditionalInfo
[1] = 3; AdditionalInfo
[2] = 0;
1681 /* Operation: 0 => DTE mode, 1 => DCE mode */
1683 AdditionalInfo
[3] = 0; AdditionalInfo
[4] = 0;
1685 AdditionalInfo
[3] = 1; AdditionalInfo
[4] = 0;
1687 /* Channel mask array */
1688 AdditionalInfo
[5] = 0; /* no D-Channel */
1689 for (i
=1; i
<= 30; i
++)
1690 AdditionalInfo
[5+i
] = (bmask
& (1 << i
)) ? 0xff : 0;
1694 static int capidrv_command(isdn_ctrl
* c
, capidrv_contr
* card
)
1697 struct capidrv_bchan
*bchan
;
1698 struct capidrv_plci
*plcip
;
1699 __u8 AdditionalInfo
[1+2+2+31];
1700 int rc
, isleasedline
= 0;
1702 if (c
->command
== ISDN_CMD_IOCTL
)
1703 return capidrv_ioctl(c
, card
);
1705 switch (c
->command
) {
1706 case ISDN_CMD_DIAL
:{
1707 __u8 calling
[ISDN_MSNLEN
+ 3];
1708 __u8 called
[ISDN_MSNLEN
+ 2];
1711 printk(KERN_DEBUG
"capidrv-%d: ISDN_CMD_DIAL(ch=%ld,\"%s,%d,%d,%s\")\n",
1714 c
->parm
.setup
.phone
,
1717 c
->parm
.setup
.eazmsn
);
1719 bchan
= &card
->bchans
[c
->arg
% card
->nbchan
];
1722 printk(KERN_ERR
"capidrv-%d: dail ch=%ld,\"%s,%d,%d,%s\" in use (plci=0x%x)\n",
1725 c
->parm
.setup
.phone
,
1728 c
->parm
.setup
.eazmsn
,
1729 bchan
->plcip
->plci
);
1732 bchan
->si1
= c
->parm
.setup
.si1
;
1733 bchan
->si2
= c
->parm
.setup
.si2
;
1735 strncpy(bchan
->num
, c
->parm
.setup
.phone
, sizeof(bchan
->num
));
1736 strncpy(bchan
->mynum
, c
->parm
.setup
.eazmsn
, sizeof(bchan
->mynum
));
1737 rc
= FVteln2capi20(bchan
->num
, AdditionalInfo
);
1738 isleasedline
= (rc
== 0);
1740 printk(KERN_ERR
"capidrv-%d: WARNING: illegal leased linedefinition \"%s\"\n", card
->contrnr
, bchan
->num
);
1746 printk(KERN_DEBUG
"capidrv-%d: connecting leased line\n", card
->contrnr
);
1748 calling
[0] = strlen(bchan
->mynum
) + 2;
1751 strncpy(calling
+ 3, bchan
->mynum
, ISDN_MSNLEN
);
1752 called
[0] = strlen(bchan
->num
) + 1;
1754 strncpy(called
+ 2, bchan
->num
, ISDN_MSNLEN
);
1757 capi_fill_CONNECT_REQ(&cmdcmsg
,
1760 card
->contrnr
, /* adr */
1761 si2cip(bchan
->si1
, bchan
->si2
), /* cipvalue */
1762 called
, /* CalledPartyNumber */
1763 calling
, /* CallingPartyNumber */
1764 0, /* CalledPartySubaddress */
1765 0, /* CallingPartySubaddress */
1766 b1prot(bchan
->l2
, bchan
->l3
), /* B1protocol */
1767 b2prot(bchan
->l2
, bchan
->l3
), /* B2protocol */
1768 b3prot(bchan
->l2
, bchan
->l3
), /* B3protocol */
1769 b1config(bchan
->l2
, bchan
->l3
), /* B1configuration */
1770 0, /* B2configuration */
1771 0, /* B3configuration */
1775 /* BChannelinformation */
1776 isleasedline
? AdditionalInfo
: 0,
1777 0, /* Keypadfacility */
1778 0, /* Useruserdata */
1779 0 /* Facilitydataarray */
1781 if ((plcip
= new_plci(card
, (c
->arg
% card
->nbchan
))) == 0) {
1782 cmd
.command
= ISDN_STAT_DHUP
;
1783 cmd
.driver
= card
->myid
;
1784 cmd
.arg
= (c
->arg
% card
->nbchan
);
1785 card
->interface
.statcallb(&cmd
);
1788 plcip
->msgid
= cmdcmsg
.Messagenumber
;
1789 plcip
->leasedline
= isleasedline
;
1790 plci_change_state(card
, plcip
, EV_PLCI_CONNECT_REQ
);
1791 send_message(card
, &cmdcmsg
);
1795 case ISDN_CMD_ACCEPTD
:
1797 bchan
= &card
->bchans
[c
->arg
% card
->nbchan
];
1799 printk(KERN_DEBUG
"capidrv-%d: ISDN_CMD_ACCEPTD(ch=%ld) l2=%d l3=%d\n",
1801 c
->arg
, bchan
->l2
, bchan
->l3
);
1803 capi_fill_CONNECT_RESP(&cmdcmsg
,
1806 bchan
->plcip
->plci
, /* adr */
1808 b1prot(bchan
->l2
, bchan
->l3
), /* B1protocol */
1809 b2prot(bchan
->l2
, bchan
->l3
), /* B2protocol */
1810 b3prot(bchan
->l2
, bchan
->l3
), /* B3protocol */
1811 b1config(bchan
->l2
, bchan
->l3
), /* B1configuration */
1812 0, /* B2configuration */
1813 0, /* B3configuration */
1814 0, /* ConnectedNumber */
1815 0, /* ConnectedSubaddress */
1817 0, /* BChannelinformation */
1818 0, /* Keypadfacility */
1819 0, /* Useruserdata */
1820 0 /* Facilitydataarray */
1822 capi_cmsg2message(&cmdcmsg
, cmdcmsg
.buf
);
1823 plci_change_state(card
, bchan
->plcip
, EV_PLCI_CONNECT_RESP
);
1824 send_message(card
, &cmdcmsg
);
1827 case ISDN_CMD_ACCEPTB
:
1829 printk(KERN_DEBUG
"capidrv-%d: ISDN_CMD_ACCEPTB(ch=%ld)\n",
1834 case ISDN_CMD_HANGUP
:
1836 printk(KERN_DEBUG
"capidrv-%d: ISDN_CMD_HANGUP(ch=%ld)\n",
1839 bchan
= &card
->bchans
[c
->arg
% card
->nbchan
];
1841 if (bchan
->disconnecting
) {
1843 printk(KERN_DEBUG
"capidrv-%d: chan %ld already disconnecting ...\n",
1849 bchan
->disconnecting
= 1;
1850 capi_fill_DISCONNECT_B3_REQ(&cmdcmsg
,
1856 ncci_change_state(card
, bchan
->nccip
, EV_NCCI_DISCONNECT_B3_REQ
);
1857 send_message(card
, &cmdcmsg
);
1858 } else if (bchan
->plcip
) {
1859 bchan
->disconnecting
= 1;
1860 if (bchan
->plcip
->state
== ST_PLCI_INCOMING
) {
1861 /* just ignore, we a called from isdn_status_callback(),
1862 * which will return 0 or 2, this is handled by the
1863 * CONNECT_IND handler
1866 capi_fill_DISCONNECT_REQ(&cmdcmsg
,
1870 0, /* BChannelinformation */
1871 0, /* Keypadfacility */
1872 0, /* Useruserdata */
1873 0 /* Facilitydataarray */
1875 plci_change_state(card
, bchan
->plcip
, EV_PLCI_DISCONNECT_REQ
);
1876 send_message(card
, &cmdcmsg
);
1881 case ISDN_CMD_SETL2
:
1883 printk(KERN_DEBUG
"capidrv-%d: set L2 on chan %ld to %ld\n",
1885 (c
->arg
& 0xff), (c
->arg
>> 8));
1886 bchan
= &card
->bchans
[(c
->arg
& 0xff) % card
->nbchan
];
1887 bchan
->l2
= (c
->arg
>> 8);
1890 case ISDN_CMD_SETL3
:
1892 printk(KERN_DEBUG
"capidrv-%d: set L3 on chan %ld to %ld\n",
1894 (c
->arg
& 0xff), (c
->arg
>> 8));
1895 bchan
= &card
->bchans
[(c
->arg
& 0xff) % card
->nbchan
];
1896 bchan
->l3
= (c
->arg
>> 8);
1899 case ISDN_CMD_SETEAZ
:
1901 printk(KERN_DEBUG
"capidrv-%d: set EAZ \"%s\" on chan %ld\n",
1903 c
->parm
.num
, c
->arg
);
1904 bchan
= &card
->bchans
[c
->arg
% card
->nbchan
];
1905 strncpy(bchan
->msn
, c
->parm
.num
, ISDN_MSNLEN
);
1908 case ISDN_CMD_CLREAZ
:
1910 printk(KERN_DEBUG
"capidrv-%d: clearing EAZ on chan %ld\n",
1911 card
->contrnr
, c
->arg
);
1912 bchan
= &card
->bchans
[c
->arg
% card
->nbchan
];
1918 printk(KERN_DEBUG
"capidrv-%d: ISDN_CMD_LOCK (%ld)\n", card
->contrnr
, c
->arg
);
1922 case ISDN_CMD_UNLOCK
:
1924 printk(KERN_DEBUG
"capidrv-%d: ISDN_CMD_UNLOCK (%ld)\n",
1925 card
->contrnr
, c
->arg
);
1930 case ISDN_CMD_GETL2
:
1932 printk(KERN_DEBUG
"capidrv-%d: ISDN_CMD_GETL2\n",
1935 case ISDN_CMD_GETL3
:
1937 printk(KERN_DEBUG
"capidrv-%d: ISDN_CMD_GETL3\n",
1940 case ISDN_CMD_GETEAZ
:
1942 printk(KERN_DEBUG
"capidrv-%d: ISDN_CMD_GETEAZ\n",
1945 case ISDN_CMD_SETSIL
:
1947 printk(KERN_DEBUG
"capidrv-%d: ISDN_CMD_SETSIL\n",
1950 case ISDN_CMD_GETSIL
:
1952 printk(KERN_DEBUG
"capidrv-%d: ISDN_CMD_GETSIL\n",
1956 printk(KERN_ERR
"capidrv-%d: ISDN_CMD_%d, Huh?\n",
1957 card
->contrnr
, c
->command
);
1963 static int if_command(isdn_ctrl
* c
)
1965 capidrv_contr
*card
= findcontrbydriverid(c
->driver
);
1968 return capidrv_command(c
, card
);
1971 "capidrv-%d: if_command %d called with invalid driverId %d!\n",
1972 card
->contrnr
, c
->command
, c
->driver
);
1976 static _cmsg sendcmsg
;
1978 static int if_sendbuf(int id
, int channel
, int doack
, struct sk_buff
*skb
)
1980 capidrv_contr
*card
= findcontrbydriverid(id
);
1981 capidrv_bchan
*bchan
;
1982 capidrv_ncci
*nccip
;
1989 printk(KERN_ERR
"capidrv-%d: if_sendbuf called with invalid driverId %d!\n",
1994 printk(KERN_DEBUG
"capidrv-%d: sendbuf len=%d skb=%p doack=%d\n",
1995 card
->contrnr
, len
, skb
, doack
);
1996 bchan
= &card
->bchans
[channel
% card
->nbchan
];
1997 nccip
= bchan
->nccip
;
1998 if (!nccip
|| nccip
->state
!= ST_NCCI_ACTIVE
) {
1999 printk(KERN_ERR
"capidrv-%d: if_sendbuf: %s:%d: chan not up!\n",
2000 card
->contrnr
, card
->name
, channel
);
2003 datahandle
= nccip
->datahandle
;
2004 capi_fill_DATA_B3_REQ(&sendcmsg
, global
.appid
, card
->msgid
++,
2005 nccip
->ncci
, /* adr */
2006 (__u32
) skb
->data
, /* Data */
2007 skb
->len
, /* DataLength */
2008 datahandle
, /* DataHandle */
2012 if (capidrv_add_ack(nccip
, datahandle
, doack
? skb
->len
: -1) < 0)
2015 capi_cmsg2message(&sendcmsg
, sendcmsg
.buf
);
2016 msglen
= CAPIMSG_LEN(sendcmsg
.buf
);
2017 if (skb_headroom(skb
) < msglen
) {
2018 struct sk_buff
*nskb
= skb_realloc_headroom(skb
, msglen
);
2020 printk(KERN_ERR
"capidrv-%d: if_sendbuf: no memory\n",
2022 (void)capidrv_del_ack(nccip
, datahandle
);
2026 printk(KERN_DEBUG
"capidrv-%d: only %d bytes headroom, need %d\n",
2027 card
->contrnr
, skb_headroom(skb
), msglen
);
2029 memcpy(skb_push(nskb
, msglen
), sendcmsg
.buf
, msglen
);
2030 errcode
= (*capifuncs
->capi_put_message
) (global
.appid
, nskb
);
2031 if (errcode
== CAPI_NOERROR
) {
2033 nccip
->datahandle
++;
2034 global
.nsentdatapkt
++;
2037 (void)capidrv_del_ack(nccip
, datahandle
);
2038 dev_kfree_skb(nskb
);
2039 return errcode
== CAPI_SENDQUEUEFULL
? 0 : -1;
2041 memcpy(skb_push(skb
, msglen
), sendcmsg
.buf
, msglen
);
2042 errcode
= (*capifuncs
->capi_put_message
) (global
.appid
, skb
);
2043 if (errcode
== CAPI_NOERROR
) {
2044 nccip
->datahandle
++;
2045 global
.nsentdatapkt
++;
2048 skb_pull(skb
, msglen
);
2049 (void)capidrv_del_ack(nccip
, datahandle
);
2050 return errcode
== CAPI_SENDQUEUEFULL
? 0 : -1;
2054 static int if_readstat(__u8
*buf
, int len
, int user
, int id
, int channel
)
2056 capidrv_contr
*card
= findcontrbydriverid(id
);
2061 printk(KERN_ERR
"capidrv-%d: if_readstat called with invalid driverId %d!\n",
2066 for (p
=buf
, count
=0; count
< len
; p
++, count
++) {
2068 put_user(*card
->q931_read
++, p
);
2070 *p
= *card
->q931_read
++;
2071 if (card
->q931_read
> card
->q931_end
)
2072 card
->q931_read
= card
->q931_buf
;
2078 static void enable_dchannel_trace(capidrv_contr
*card
)
2080 __u8 manufacturer
[CAPI_MANUFACTURER_LEN
];
2081 capi_version version
;
2082 __u16 contr
= card
->contrnr
;
2084 __u16 avmversion
[3];
2086 errcode
= (*capifuncs
->capi_get_manufacturer
)(contr
, manufacturer
);
2087 if (errcode
!= CAPI_NOERROR
) {
2088 printk(KERN_ERR
"%s: can't get manufacturer (0x%x)\n",
2089 card
->name
, errcode
);
2092 if (strstr(manufacturer
, "AVM") == 0) {
2093 printk(KERN_ERR
"%s: not from AVM, no d-channel trace possible (%s)\n",
2094 card
->name
, manufacturer
);
2097 errcode
= (*capifuncs
->capi_get_version
)(contr
, &version
);
2098 if (errcode
!= CAPI_NOERROR
) {
2099 printk(KERN_ERR
"%s: can't get version (0x%x)\n",
2100 card
->name
, errcode
);
2103 avmversion
[0] = (version
.majormanuversion
>> 4) & 0x0f;
2104 avmversion
[1] = (version
.majormanuversion
<< 4) & 0xf0;
2105 avmversion
[1] |= (version
.minormanuversion
>> 4) & 0x0f;
2106 avmversion
[2] |= version
.minormanuversion
& 0x0f;
2108 if (avmversion
[0] > 3 || (avmversion
[0] == 3 && avmversion
[1] > 5)) {
2109 printk(KERN_INFO
"%s: D2 trace enabled\n", card
->name
);
2110 capi_fill_MANUFACTURER_REQ(&cmdcmsg
, global
.appid
,
2113 0x214D5641, /* ManuID */
2116 (_cstruct
)"\004\200\014\000\000");
2118 printk(KERN_INFO
"%s: D3 trace enabled\n", card
->name
);
2119 capi_fill_MANUFACTURER_REQ(&cmdcmsg
, global
.appid
,
2122 0x214D5641, /* ManuID */
2125 (_cstruct
)"\004\002\003\000\000");
2127 send_message(card
, &cmdcmsg
);
2130 static void disable_dchannel_trace(capidrv_contr
*card
)
2132 __u8 manufacturer
[CAPI_MANUFACTURER_LEN
];
2133 capi_version version
;
2134 __u16 contr
= card
->contrnr
;
2136 __u16 avmversion
[3];
2138 errcode
= (*capifuncs
->capi_get_manufacturer
)(contr
, manufacturer
);
2139 if (errcode
!= CAPI_NOERROR
) {
2140 printk(KERN_ERR
"%s: can't get manufacturer (0x%x)\n",
2141 card
->name
, errcode
);
2144 if (strstr(manufacturer
, "AVM") == 0) {
2145 printk(KERN_ERR
"%s: not from AVM, no d-channel trace possible (%s)\n",
2146 card
->name
, manufacturer
);
2149 errcode
= (*capifuncs
->capi_get_version
)(contr
, &version
);
2150 if (errcode
!= CAPI_NOERROR
) {
2151 printk(KERN_ERR
"%s: can't get version (0x%x)\n",
2152 card
->name
, errcode
);
2155 avmversion
[0] = (version
.majormanuversion
>> 4) & 0x0f;
2156 avmversion
[1] = (version
.majormanuversion
<< 4) & 0xf0;
2157 avmversion
[1] |= (version
.minormanuversion
>> 4) & 0x0f;
2158 avmversion
[2] |= version
.minormanuversion
& 0x0f;
2160 if (avmversion
[0] > 3 || (avmversion
[0] == 3 && avmversion
[1] > 5)) {
2161 printk(KERN_INFO
"%s: D2 trace disabled\n", card
->name
);
2163 printk(KERN_INFO
"%s: D3 trace disabled\n", card
->name
);
2165 capi_fill_MANUFACTURER_REQ(&cmdcmsg
, global
.appid
,
2168 0x214D5641, /* ManuID */
2171 (_cstruct
)"\004\000\000\000\000");
2172 send_message(card
, &cmdcmsg
);
2175 static int capidrv_addcontr(__u16 contr
, struct capi_profile
*profp
)
2177 capidrv_contr
*card
;
2182 sprintf(id
, "capidrv-%d", contr
);
2183 if (!(card
= (capidrv_contr
*) kmalloc(sizeof(capidrv_contr
), GFP_ATOMIC
))) {
2185 "capidrv: (%s) Could not allocate contr-struct.\n", id
);
2188 memset(card
, 0, sizeof(capidrv_contr
));
2189 strcpy(card
->name
, id
);
2190 card
->contrnr
= contr
;
2191 card
->nbchan
= profp
->nbchannel
;
2192 card
->bchans
= (capidrv_bchan
*) kmalloc(sizeof(capidrv_bchan
) * card
->nbchan
, GFP_ATOMIC
);
2193 if (!card
->bchans
) {
2195 "capidrv: (%s) Could not allocate bchan-structs.\n", id
);
2199 card
->interface
.channels
= profp
->nbchannel
;
2200 card
->interface
.maxbufsize
= 2048;
2201 card
->interface
.command
= if_command
;
2202 card
->interface
.writebuf_skb
= if_sendbuf
;
2203 card
->interface
.writecmd
= 0;
2204 card
->interface
.readstat
= if_readstat
;
2205 card
->interface
.features
= ISDN_FEATURE_L2_X75I
|
2206 ISDN_FEATURE_L2_X75UI
|
2207 ISDN_FEATURE_L2_X75BUI
|
2208 ISDN_FEATURE_L2_HDLC
|
2209 ISDN_FEATURE_L2_TRANS
|
2210 ISDN_FEATURE_L3_TRANS
|
2211 ISDN_FEATURE_L2_V11096
|
2212 ISDN_FEATURE_L2_V11019
|
2213 ISDN_FEATURE_L2_V11038
|
2215 ISDN_FEATURE_L2_FAX
|
2216 ISDN_FEATURE_L3_FAX
|
2218 ISDN_FEATURE_P_UNKNOWN
;
2219 card
->interface
.hl_hdrlen
= 22; /* len of DATA_B3_REQ */
2220 strncpy(card
->interface
.id
, id
, sizeof(card
->interface
.id
) - 1);
2221 card
->next
= global
.contr_list
;
2222 global
.contr_list
= card
;
2224 card
->q931_read
= card
->q931_buf
;
2225 card
->q931_write
= card
->q931_buf
;
2226 card
->q931_end
= card
->q931_buf
+ sizeof(card
->q931_buf
) - 1;
2228 if (!register_isdn(&card
->interface
)) {
2229 global
.contr_list
= global
.contr_list
->next
;
2230 printk(KERN_ERR
"capidrv: Unable to register contr %s\n", id
);
2231 kfree(card
->bchans
);
2235 card
->myid
= card
->interface
.channels
;
2237 memset(card
->bchans
, 0, sizeof(capidrv_bchan
) * card
->nbchan
);
2238 for (i
= 0; i
< card
->nbchan
; i
++) {
2239 card
->bchans
[i
].contr
= card
;
2242 cmd
.driver
= card
->myid
;
2243 cmd
.command
= ISDN_STAT_RUN
;
2244 card
->interface
.statcallb(&cmd
);
2246 card
->cipmask
= 0x1FFF03FF; /* any */
2249 capi_fill_LISTEN_REQ(&cmdcmsg
, global
.appid
,
2251 contr
, /* controller */
2252 1 << 6, /* Infomask */
2256 send_message(card
, &cmdcmsg
);
2257 listen_change_state(card
, EV_LISTEN_REQ
);
2259 printk(KERN_INFO
"%s: now up (%d B channels)\n",
2260 card
->name
, card
->nbchan
);
2262 enable_dchannel_trace(card
);
2267 static int capidrv_delcontr(__u16 contr
)
2269 capidrv_contr
**pp
, *card
;
2273 for (pp
= &global
.contr_list
; *pp
; pp
= &(*pp
)->next
) {
2274 if ((*pp
)->contrnr
== contr
)
2278 printk(KERN_ERR
"capidrv: delcontr: no contr %u\n", contr
);
2284 printk(KERN_DEBUG
"capidrv-%d: id=%d unloading\n",
2285 card
->contrnr
, card
->myid
);
2287 cmd
.command
= ISDN_STAT_UNLOAD
;
2288 cmd
.driver
= card
->myid
;
2289 card
->interface
.statcallb(&cmd
);
2294 for (i
= 0; i
< card
->nbchan
; i
++) {
2295 if (card
->bchans
[i
].nccip
)
2296 free_ncci(card
, card
->bchans
[i
].nccip
);
2297 if (card
->bchans
[i
].plcip
)
2298 free_plci(card
, card
->bchans
[i
].plcip
);
2299 if (card
->plci_list
)
2300 printk(KERN_ERR
"capidrv: bug in free_plci()\n");
2302 kfree(card
->bchans
);
2304 printk(KERN_INFO
"%s: now down.\n", card
->name
);
2312 static void lower_callback(unsigned int cmd
, __u16 contr
, void *data
)
2317 printk(KERN_INFO
"capidrv: controller %hu up\n", contr
);
2318 (void) capidrv_addcontr(contr
, (capi_profile
*) data
);
2321 printk(KERN_INFO
"capidrv: controller %hu down\n", contr
);
2322 (void) capidrv_delcontr(contr
);
2328 * /proc/capi/capidrv:
2329 * nrecvctlpkt nrecvdatapkt nsendctlpkt nsenddatapkt
2331 static int proc_capidrv_read_proc(char *page
, char **start
, off_t off
,
2332 int count
, int *eof
, void *data
)
2336 len
+= sprintf(page
+len
, "%lu %lu %lu %lu\n",
2338 global
.nrecvdatapkt
,
2340 global
.nsentdatapkt
);
2341 if (off
+count
>= len
)
2345 *start
= page
+ off
;
2346 return ((count
< len
-off
) ? count
: len
-off
);
2349 static struct procfsentries
{
2352 int (*read_proc
)(char *page
, char **start
, off_t off
,
2353 int count
, int *eof
, void *data
);
2354 struct proc_dir_entry
*procent
;
2355 } procfsentries
[] = {
2356 /* { "capi", S_IFDIR, 0 }, */
2357 { "capi/capidrv", 0 , proc_capidrv_read_proc
},
2360 static void proc_init(void)
2362 int nelem
= sizeof(procfsentries
)/sizeof(procfsentries
[0]);
2365 for (i
=0; i
< nelem
; i
++) {
2366 struct procfsentries
*p
= procfsentries
+ i
;
2367 p
->procent
= create_proc_entry(p
->name
, p
->mode
, 0);
2368 if (p
->procent
) p
->procent
->read_proc
= p
->read_proc
;
2372 static void proc_exit(void)
2374 int nelem
= sizeof(procfsentries
)/sizeof(procfsentries
[0]);
2377 for (i
=nelem
-1; i
>= 0; i
--) {
2378 struct procfsentries
*p
= procfsentries
+ i
;
2380 remove_proc_entry(p
->name
, 0);
2386 static struct capi_interface_user cuser
= {
2392 #define capidrv_init init_module
2395 int capidrv_init(void)
2397 struct capi_register_params rparam
;
2398 capi_profile profile
;
2401 __u32 ncontr
, contr
;
2404 capifuncs
= attach_capi_interface(&cuser
);
2409 if ((p
= strchr(revision
, ':'))) {
2411 p
= strchr(rev
, '$');
2414 strcpy(rev
, " ??? ");
2416 rparam
.level3cnt
= -2; /* number of bchannels twice */
2417 rparam
.datablkcnt
= 16;
2418 rparam
.datablklen
= 2048;
2419 errcode
= (*capifuncs
->capi_register
) (&rparam
, &global
.appid
);
2421 detach_capi_interface(&cuser
);
2425 errcode
= (*capifuncs
->capi_get_profile
) (0, &profile
);
2426 if (errcode
!= CAPI_NOERROR
) {
2427 (void) (*capifuncs
->capi_release
) (global
.appid
);
2428 detach_capi_interface(&cuser
);
2432 (void) (*capifuncs
->capi_set_signal
) (global
.appid
, capidrv_signal
, 0);
2434 ncontr
= profile
.ncontroller
;
2435 for (contr
= 1; contr
<= ncontr
; contr
++) {
2436 errcode
= (*capifuncs
->capi_get_profile
) (contr
, &profile
);
2437 if (errcode
!= CAPI_NOERROR
)
2439 (void) capidrv_addcontr(contr
, &profile
);
2447 void cleanup_module(void)
2449 capidrv_contr
*card
, *next
;
2453 if ((p
= strchr(revision
, ':'))) {
2455 p
= strchr(rev
, '$');
2458 strcpy(rev
, " ??? ");
2461 for (card
= global
.contr_list
; card
; card
= next
) {
2463 disable_dchannel_trace(card
);
2464 capidrv_delcontr(card
->contrnr
);
2467 (void) (*capifuncs
->capi_release
) (global
.appid
);
2468 detach_capi_interface(&cuser
);
2471 printk(KERN_NOTICE
"capidrv: Rev%s: unloaded\n", rev
);