2 * $Id: capidrv.c,v 1.36 2000/06/26 15:13:41 keil Exp $
4 * ISDN4Linux Driver, using capi20 interface (kernelcapi)
6 * Copyright 1997 by Carsten Paeth (calle@calle.in-berlin.de)
9 * Revision 1.36 2000/06/26 15:13:41 keil
10 * features should be or'ed
12 * Revision 1.35 2000/06/19 15:11:25 keil
13 * avoid use of freed structs
14 * changes from 2.4.0-ac21
16 * Revision 1.34 2000/06/19 13:13:55 calle
19 * Revision 1.33 2000/05/06 00:52:36 kai
20 * merged changes from kernel tree
21 * fixed timer and net_device->name breakage
23 * Revision 1.32 2000/04/07 15:19:58 calle
26 * Revision 1.31 2000/04/06 15:01:25 calle
27 * Bugfix: crash in capidrv.c when reseting a capi controller.
28 * - changed code order on remove of controller.
29 * - using tq_schedule for notifier in kcapi.c.
30 * - now using spin_lock_irqsave() and spin_unlock_irqrestore().
31 * strange: sometimes even MP hang on unload of isdn.o ...
33 * Revision 1.30 2000/03/03 15:50:42 calle
35 * - Changed parameter "param" in capi_signal from __u32 to void *.
36 * - rewrote notifier handling in kcapi.c
37 * - new notifier NCCI_UP and NCCI_DOWN
39 * - /dev/capi20 is now a cloning device.
40 * - middleware extentions prepared.
42 * - locking of list operations and module count updates.
44 * Revision 1.29 1999/12/06 17:13:06 calle
45 * Added controller watchdog.
47 * Revision 1.28 1999/11/05 16:22:37 calle
48 * Bugfix: Missing break in switch on ISDN_CMD_HANGUP.
50 * Revision 1.27 1999/09/16 15:13:04 calle
51 * forgot to change paramter type of contr for lower_callback ...
53 * Revision 1.26 1999/08/06 07:41:16 calle
54 * Added the "vbox patch". if (si1 == 1) si2 = 0;
56 * Revision 1.25 1999/08/04 10:10:11 calle
57 * Bugfix: corrected /proc functions, added structure for new AVM cards.
59 * Revision 1.24 1999/07/20 06:48:02 calle
60 * Bugfix: firmware version check for D2 trace was too restrictiv.
62 * Revision 1.23 1999/07/09 15:05:44 keil
63 * compat.h is now isdn_compat.h
65 * Revision 1.22 1999/07/06 07:24:14 calle
66 * Bugfix: call to kfree_skb in capidrv_signal was too early,
67 * thanks to Lars Heete <hel@admin.de>.
69 * Revision 1.21 1999/07/01 15:26:34 calle
70 * complete new version (I love it):
71 * + new hardware independed "capi_driver" interface that will make it easy to:
72 * - support other controllers with CAPI-2.0 (i.e. USB Controller)
73 * - write a CAPI-2.0 for the passive cards
74 * - support serial link CAPI-2.0 boxes.
75 * + wrote "capi_driver" for all supported cards.
76 * + "capi_driver" (supported cards) now have to be configured with
77 * make menuconfig, in the past all supported cards where included
79 * + new and better informations in /proc/capi/
80 * + new ioctl to switch trace of capi messages per controller
81 * using "avmcapictrl trace [contr] on|off|...."
82 * + complete testcircle with all supported cards and also the
83 * PCMCIA cards (now patch for pcmcia-cs-3.0.13 needed) done.
85 * Revision 1.20 1999/07/01 08:22:59 keil
86 * compatibility macros now in <linux/isdn_compat.h>
88 * Revision 1.19 1999/06/29 16:16:54 calle
89 * Let ISDN_CMD_UNLOAD work with open isdn devices without crash again.
90 * Also right unlocking (ISDN_CMD_UNLOCK) is done now.
91 * isdnlog should check returncode of read(2) calls.
93 * Revision 1.18 1999/06/21 15:24:15 calle
94 * extend information in /proc.
96 * Revision 1.17 1999/06/10 16:53:55 calle
97 * Removing of module b1pci will now remove card from lower level.
99 * Revision 1.16 1999/05/31 11:50:33 calle
100 * Bugfix: In if_sendbuf, skb_push'ed DATA_B3 header was not skb_pull'ed
101 * on failure, result in data block with DATA_B3 header transmitted
103 * Revision 1.15 1999/05/25 21:26:16 calle
104 * Include CAPI-Channelallocation (leased lines) from the 2.0 tree.
106 * Revision 1.14 1999/05/22 07:55:06 calle
107 * Added *V110* to AVM B1 driver.
109 * Revision 1.13 1998/06/26 15:12:55 fritz
110 * Added handling of STAT_ICALL with incomplete CPN.
111 * Added AT&L for ttyI emulator.
112 * Added more locking stuff in tty_write.
114 * Revision 1.12 1998/03/29 16:06:03 calle
115 * changes from 2.0 tree merged.
117 * Revision 1.3.2.10 1998/03/20 14:38:24 calle
118 * capidrv: prepared state machines for suspend/resume/hold
119 * capidrv: fix bug in state machine if B1/T1 is out of nccis
120 * b1capi: changed some errno returns.
121 * b1capi: detect if you try to add same T1 to different io address.
122 * b1capi: change number of nccis depending on number of channels.
125 * Revision 1.3.2.9 1998/03/20 09:01:12 calle
126 * Changes capi_register handling to get full support for 30 bchannels.
128 * Revision 1.3.2.8 1998/03/18 17:51:28 calle
129 * added controller number to error messages
131 * Revision 1.3.2.7 1998/02/27 15:40:47 calle
132 * T1 running with slow link. bugfix in capi_release.
134 * Revision 1.11 1998/02/13 07:09:15 calle
135 * change for 2.1.86 (removing FREE_READ/FREE_WRITE from [dev]_kfree_skb()
137 * Revision 1.10 1998/02/02 19:52:23 calle
138 * Fixed vbox (audio) acceptb.
140 * Revision 1.9 1998/01/31 11:14:45 calle
141 * merged changes to 2.0 tree, prepare 2.1.82 to work.
143 * Revision 1.8 1997/11/04 06:12:09 calle
144 * capi.c: new read/write in file_ops since 2.1.60
145 * capidrv.c: prepared isdnlog interface for d2-trace in newer firmware.
146 * capiutil.c: needs config.h (CONFIG_ISDN_DRV_AVMB1_VERBOSE_REASON)
147 * compat.h: added #define LinuxVersionCode
149 * Revision 1.7 1997/10/11 10:36:34 calle
150 * Added isdnlog support. patch to isdnlog needed.
152 * Revision 1.6 1997/10/11 10:25:55 calle
153 * New interface for lowlevel drivers. BSENT with nr. of bytes sent,
154 * allow sending without ACK.
156 * Revision 1.5 1997/10/01 09:21:16 fritz
157 * Removed old compatibility stuff for 2.0.X kernels.
158 * From now on, this code is for 2.1.X ONLY!
159 * Old stuff is still in the separate branch.
161 * Revision 1.4 1997/07/13 12:22:43 calle
162 * bug fix for more than one controller in connect_req.
163 * debugoutput now with contrnr.
165 * Revision 1.3 1997/05/18 09:24:15 calle
166 * added verbose disconnect reason reporting to avmb1.
167 * some fixes in capi20 interface.
168 * changed info messages for B1-PCI
170 * Revision 1.2 1997/03/05 21:19:59 fritz
171 * Removed include of config.h (mkdep stated this is unneded).
173 * Revision 1.1 1997/03/04 21:50:31 calle
174 * Frirst version in isdn4linux
176 * Revision 2.2 1997/02/12 09:31:39 calle
179 * Revision 1.1 1997/01/31 10:32:20 calle
184 #include <linux/module.h>
185 #include <linux/errno.h>
186 #include <linux/kernel.h>
187 #include <linux/major.h>
188 #include <linux/sched.h>
189 #include <linux/malloc.h>
190 #include <linux/fcntl.h>
191 #include <linux/fs.h>
192 #include <linux/signal.h>
193 #include <linux/mm.h>
194 #include <linux/timer.h>
195 #include <linux/wait.h>
196 #include <linux/skbuff.h>
197 #include <linux/isdn.h>
198 #include <linux/isdnif.h>
199 #include <linux/proc_fs.h>
200 #include <linux/capi.h>
201 #include <linux/kernelcapi.h>
202 #include <linux/ctype.h>
203 #include <asm/segment.h>
205 #include "capiutil.h"
209 static char *revision
= "$Revision: 1.36 $";
210 static int debugmode
= 0;
212 MODULE_AUTHOR("Carsten Paeth <calle@calle.in-berlin.de>");
213 MODULE_PARM(debugmode
, "i");
215 /* -------- type definitions ----------------------------------------- */
218 struct capidrv_contr
{
220 struct capidrv_contr
*next
;
237 struct timer_list listentimer
;
240 * ID of capi message sent
248 struct capidrv_bchan
{
249 struct capidrv_contr
*contr
;
250 __u8 msn
[ISDN_MSNLEN
];
253 __u8 num
[ISDN_MSNLEN
];
254 __u8 mynum
[ISDN_MSNLEN
];
259 struct capidrv_plci
{
260 struct capidrv_plci
*next
;
262 __u32 ncci
; /* ncci for CONNECT_ACTIVE_IND */
263 __u16 msgid
; /* to identfy CONNECT_CONF */
267 struct capidrv_ncci
{
268 struct capidrv_ncci
*next
;
269 struct capidrv_plci
*plcip
;
271 __u16 msgid
; /* to identfy CONNECT_B3_CONF */
277 struct ncci_datahandle_queue
{
278 struct ncci_datahandle_queue
*next
;
284 struct capidrv_ncci
*nccip
;
287 struct capidrv_plci
*plci_list
;
297 struct capidrv_data
{
300 struct capidrv_contr
*contr_list
;
303 unsigned long nrecvctlpkt
;
304 unsigned long nrecvdatapkt
;
305 unsigned long nsentctlpkt
;
306 unsigned long nsentdatapkt
;
309 typedef struct capidrv_plci capidrv_plci
;
310 typedef struct capidrv_ncci capidrv_ncci
;
311 typedef struct capidrv_contr capidrv_contr
;
312 typedef struct capidrv_data capidrv_data
;
313 typedef struct capidrv_bchan capidrv_bchan
;
315 /* -------- data definitions ----------------------------------------- */
317 static capidrv_data global
;
318 static spinlock_t global_lock
= SPIN_LOCK_UNLOCKED
;
319 static struct capi_interface
*capifuncs
;
321 static void handle_dtrace_data(capidrv_contr
*card
,
322 int send
, int level2
, __u8
*data
, __u16 len
);
324 /* -------- convert functions ---------------------------------------- */
326 static inline __u32
b1prot(int l2
, int l3
)
329 case ISDN_PROTO_L2_X75I
:
330 case ISDN_PROTO_L2_X75UI
:
331 case ISDN_PROTO_L2_X75BUI
:
333 case ISDN_PROTO_L2_HDLC
:
336 case ISDN_PROTO_L2_TRANS
:
338 case ISDN_PROTO_L2_V11096
:
339 case ISDN_PROTO_L2_V11019
:
340 case ISDN_PROTO_L2_V11038
:
342 case ISDN_PROTO_L2_FAX
:
344 case ISDN_PROTO_L2_MODEM
:
349 static inline __u32
b2prot(int l2
, int l3
)
352 case ISDN_PROTO_L2_X75I
:
353 case ISDN_PROTO_L2_X75UI
:
354 case ISDN_PROTO_L2_X75BUI
:
357 case ISDN_PROTO_L2_HDLC
:
358 case ISDN_PROTO_L2_TRANS
:
359 case ISDN_PROTO_L2_V11096
:
360 case ISDN_PROTO_L2_V11019
:
361 case ISDN_PROTO_L2_V11038
:
362 case ISDN_PROTO_L2_MODEM
:
364 case ISDN_PROTO_L2_FAX
:
369 static inline __u32
b3prot(int l2
, int l3
)
372 case ISDN_PROTO_L2_X75I
:
373 case ISDN_PROTO_L2_X75UI
:
374 case ISDN_PROTO_L2_X75BUI
:
375 case ISDN_PROTO_L2_HDLC
:
376 case ISDN_PROTO_L2_TRANS
:
377 case ISDN_PROTO_L2_V11096
:
378 case ISDN_PROTO_L2_V11019
:
379 case ISDN_PROTO_L2_V11038
:
380 case ISDN_PROTO_L2_MODEM
:
383 case ISDN_PROTO_L2_FAX
:
388 static _cstruct
b1config_sync_v110(__u16 rate
)
390 /* CAPI-Spec "B1 Configuration" */
391 static unsigned char buf
[9];
392 buf
[0] = 8; /* len */
393 /* maximum bitrate */
394 buf
[1] = rate
& 0xff; buf
[2] = (rate
>> 8) & 0xff;
395 buf
[3] = buf
[4] = 0; /* reserved, bits per character */
396 buf
[5] = buf
[6] = 0; /* reserved, parity */
397 buf
[7] = buf
[9] = 0; /* reserved, stop bits */
401 static _cstruct
b1config(int l2
, int l3
)
404 case ISDN_PROTO_L2_X75I
:
405 case ISDN_PROTO_L2_X75UI
:
406 case ISDN_PROTO_L2_X75BUI
:
407 case ISDN_PROTO_L2_HDLC
:
408 case ISDN_PROTO_L2_TRANS
:
411 case ISDN_PROTO_L2_V11096
:
412 return b1config_sync_v110(9600);
413 case ISDN_PROTO_L2_V11019
:
414 return b1config_sync_v110(19200);
415 case ISDN_PROTO_L2_V11038
:
416 return b1config_sync_v110(38400);
420 static inline __u16
si2cip(__u8 si1
, __u8 si2
)
422 static const __u8 cip
[17][5] =
425 {0, 0, 0, 0, 0}, /*0 */
426 {16, 16, 4, 26, 16}, /*1 */
427 {17, 17, 17, 4, 4}, /*2 */
428 {2, 2, 2, 2, 2}, /*3 */
429 {18, 18, 18, 18, 18}, /*4 */
430 {2, 2, 2, 2, 2}, /*5 */
431 {0, 0, 0, 0, 0}, /*6 */
432 {2, 2, 2, 2, 2}, /*7 */
433 {2, 2, 2, 2, 2}, /*8 */
434 {21, 21, 21, 21, 21}, /*9 */
435 {19, 19, 19, 19, 19}, /*10 */
436 {0, 0, 0, 0, 0}, /*11 */
437 {0, 0, 0, 0, 0}, /*12 */
438 {0, 0, 0, 0, 0}, /*13 */
439 {0, 0, 0, 0, 0}, /*14 */
440 {22, 22, 22, 22, 22}, /*15 */
441 {27, 27, 27, 28, 27} /*16 */
448 return (__u16
) cip
[si1
][si2
];
451 static inline __u8
cip2si1(__u16 cipval
)
453 static const __u8 si
[32] =
454 {7, 1, 7, 7, 1, 1, 7, 7, /*0-7 */
455 7, 1, 0, 0, 0, 0, 0, 0, /*8-15 */
456 1, 2, 4, 10, 9, 9, 15, 7, /*16-23 */
457 7, 7, 1, 16, 16, 0, 0, 0}; /*24-31 */
460 cipval
= 0; /* .... */
464 static inline __u8
cip2si2(__u16 cipval
)
466 static const __u8 si
[32] =
467 {0, 0, 0, 0, 2, 3, 0, 0, /*0-7 */
468 0, 3, 0, 0, 0, 0, 0, 0, /*8-15 */
469 1, 2, 0, 0, 9, 0, 0, 0, /*16-23 */
470 0, 0, 3, 2, 3, 0, 0, 0}; /*24-31 */
473 cipval
= 0; /* .... */
478 /* -------- controller managment ------------------------------------- */
480 static inline capidrv_contr
*findcontrbydriverid(int driverid
)
485 spin_lock_irqsave(&global_lock
, flags
);
486 for (p
= global
.contr_list
; p
; p
= p
->next
)
487 if (p
->myid
== driverid
)
489 spin_unlock_irqrestore(&global_lock
, flags
);
493 static capidrv_contr
*findcontrbynumber(__u32 contr
)
496 capidrv_contr
*p
= global
.contr_list
;
498 spin_lock_irqsave(&global_lock
, flags
);
499 for (p
= global
.contr_list
; p
; p
= p
->next
)
500 if (p
->contrnr
== contr
)
502 spin_unlock_irqrestore(&global_lock
, flags
);
507 /* -------- plci management ------------------------------------------ */
509 static capidrv_plci
*new_plci(capidrv_contr
* card
, int chan
)
513 plcip
= (capidrv_plci
*) kmalloc(sizeof(capidrv_plci
), GFP_ATOMIC
);
518 memset(plcip
, 0, sizeof(capidrv_plci
));
519 plcip
->state
= ST_PLCI_NONE
;
523 plcip
->next
= card
->plci_list
;
524 card
->plci_list
= plcip
;
525 card
->bchans
[chan
].plcip
= plcip
;
530 static capidrv_plci
*find_plci_by_plci(capidrv_contr
* card
, __u32 plci
)
533 for (p
= card
->plci_list
; p
; p
= p
->next
)
539 static capidrv_plci
*find_plci_by_msgid(capidrv_contr
* card
, __u16 msgid
)
542 for (p
= card
->plci_list
; p
; p
= p
->next
)
543 if (p
->msgid
== msgid
)
548 static capidrv_plci
*find_plci_by_ncci(capidrv_contr
* card
, __u32 ncci
)
551 for (p
= card
->plci_list
; p
; p
= p
->next
)
552 if (p
->plci
== (ncci
& 0xffff))
557 static void free_plci(capidrv_contr
* card
, capidrv_plci
* plcip
)
561 for (pp
= &card
->plci_list
; *pp
; pp
= &(*pp
)->next
) {
564 card
->bchans
[plcip
->chan
].plcip
= 0;
565 card
->bchans
[plcip
->chan
].disconnecting
= 0;
566 card
->bchans
[plcip
->chan
].incoming
= 0;
571 printk(KERN_ERR
"capidrv-%d: free_plci %p (0x%x) not found, Huh?\n",
572 card
->contrnr
, plcip
, plcip
->plci
);
575 /* -------- ncci management ------------------------------------------ */
577 static inline capidrv_ncci
*new_ncci(capidrv_contr
* card
,
578 capidrv_plci
* plcip
,
583 nccip
= (capidrv_ncci
*) kmalloc(sizeof(capidrv_ncci
), GFP_ATOMIC
);
588 memset(nccip
, 0, sizeof(capidrv_ncci
));
590 nccip
->state
= ST_NCCI_NONE
;
591 nccip
->plcip
= plcip
;
592 nccip
->chan
= plcip
->chan
;
593 nccip
->datahandle
= 0;
595 nccip
->next
= plcip
->ncci_list
;
596 plcip
->ncci_list
= nccip
;
598 card
->bchans
[plcip
->chan
].nccip
= nccip
;
603 static inline capidrv_ncci
*find_ncci(capidrv_contr
* card
, __u32 ncci
)
608 if ((plcip
= find_plci_by_ncci(card
, ncci
)) == 0)
611 for (p
= plcip
->ncci_list
; p
; p
= p
->next
)
617 static inline capidrv_ncci
*find_ncci_by_msgid(capidrv_contr
* card
,
618 __u32 ncci
, __u16 msgid
)
623 if ((plcip
= find_plci_by_ncci(card
, ncci
)) == 0)
626 for (p
= plcip
->ncci_list
; p
; p
= p
->next
)
627 if (p
->msgid
== msgid
)
632 static void free_ncci(capidrv_contr
* card
, struct capidrv_ncci
*nccip
)
634 struct capidrv_ncci
**pp
;
636 for (pp
= &(nccip
->plcip
->ncci_list
); *pp
; pp
= &(*pp
)->next
) {
642 card
->bchans
[nccip
->chan
].nccip
= 0;
646 static int capidrv_add_ack(struct capidrv_ncci
*nccip
,
647 __u16 datahandle
, int len
)
649 struct ncci_datahandle_queue
*n
, **pp
;
651 n
= (struct ncci_datahandle_queue
*)
652 kmalloc(sizeof(struct ncci_datahandle_queue
), GFP_ATOMIC
);
654 printk(KERN_ERR
"capidrv: kmalloc ncci_datahandle failed\n");
658 n
->datahandle
= datahandle
;
660 for (pp
= &nccip
->ackqueue
; *pp
; pp
= &(*pp
)->next
) ;
665 static int capidrv_del_ack(struct capidrv_ncci
*nccip
, __u16 datahandle
)
667 struct ncci_datahandle_queue
**pp
, *p
;
670 for (pp
= &nccip
->ackqueue
; *pp
; pp
= &(*pp
)->next
) {
671 if ((*pp
)->datahandle
== datahandle
) {
682 /* -------- convert and send capi message ---------------------------- */
684 static void send_message(capidrv_contr
* card
, _cmsg
* cmsg
)
688 capi_cmsg2message(cmsg
, cmsg
->buf
);
689 len
= CAPIMSG_LEN(cmsg
->buf
);
690 skb
= alloc_skb(len
, GFP_ATOMIC
);
691 memcpy(skb_put(skb
, len
), cmsg
->buf
, len
);
692 (*capifuncs
->capi_put_message
) (global
.appid
, skb
);
693 global
.nsentctlpkt
++;
696 /* -------- state machine -------------------------------------------- */
698 struct listenstatechange
{
704 static struct listenstatechange listentable
[] =
706 {ST_LISTEN_NONE
, ST_LISTEN_WAIT_CONF
, EV_LISTEN_REQ
},
707 {ST_LISTEN_ACTIVE
, ST_LISTEN_ACTIVE_WAIT_CONF
, EV_LISTEN_REQ
},
708 {ST_LISTEN_WAIT_CONF
, ST_LISTEN_NONE
, EV_LISTEN_CONF_ERROR
},
709 {ST_LISTEN_ACTIVE_WAIT_CONF
, ST_LISTEN_ACTIVE
, EV_LISTEN_CONF_ERROR
},
710 {ST_LISTEN_WAIT_CONF
, ST_LISTEN_NONE
, EV_LISTEN_CONF_EMPTY
},
711 {ST_LISTEN_ACTIVE_WAIT_CONF
, ST_LISTEN_NONE
, EV_LISTEN_CONF_EMPTY
},
712 {ST_LISTEN_WAIT_CONF
, ST_LISTEN_ACTIVE
, EV_LISTEN_CONF_OK
},
713 {ST_LISTEN_ACTIVE_WAIT_CONF
, ST_LISTEN_ACTIVE
, EV_LISTEN_CONF_OK
},
717 static void listen_change_state(capidrv_contr
* card
, int event
)
719 struct listenstatechange
*p
= listentable
;
721 if (card
->state
== p
->actstate
&& p
->event
== event
) {
723 printk(KERN_DEBUG
"capidrv-%d: listen_change_state %d -> %d\n",
724 card
->contrnr
, card
->state
, p
->nextstate
);
725 card
->state
= p
->nextstate
;
730 printk(KERN_ERR
"capidrv-%d: listen_change_state state=%d event=%d ????\n",
731 card
->contrnr
, card
->state
, event
);
735 /* ------------------------------------------------------------------ */
737 static void p0(capidrv_contr
* card
, capidrv_plci
* plci
)
741 card
->bchans
[plci
->chan
].contr
= 0;
742 cmd
.command
= ISDN_STAT_DHUP
;
743 cmd
.driver
= card
->myid
;
744 cmd
.arg
= plci
->chan
;
745 card
->interface
.statcallb(&cmd
);
746 free_plci(card
, plci
);
749 /* ------------------------------------------------------------------ */
751 struct plcistatechange
{
755 void (*changefunc
) (capidrv_contr
* card
, capidrv_plci
* plci
);
758 static struct plcistatechange plcitable
[] =
761 {ST_PLCI_NONE
, ST_PLCI_OUTGOING
, EV_PLCI_CONNECT_REQ
, 0},
762 {ST_PLCI_NONE
, ST_PLCI_ALLOCATED
, EV_PLCI_FACILITY_IND_UP
, 0},
763 {ST_PLCI_NONE
, ST_PLCI_INCOMING
, EV_PLCI_CONNECT_IND
, 0},
764 {ST_PLCI_NONE
, ST_PLCI_RESUMEING
, EV_PLCI_RESUME_REQ
, 0},
766 {ST_PLCI_OUTGOING
, ST_PLCI_NONE
, EV_PLCI_CONNECT_CONF_ERROR
, p0
},
767 {ST_PLCI_OUTGOING
, ST_PLCI_ALLOCATED
, EV_PLCI_CONNECT_CONF_OK
, 0},
769 {ST_PLCI_ALLOCATED
, ST_PLCI_ACTIVE
, EV_PLCI_CONNECT_ACTIVE_IND
, 0},
770 {ST_PLCI_ALLOCATED
, ST_PLCI_DISCONNECTING
, EV_PLCI_DISCONNECT_REQ
, 0},
771 {ST_PLCI_ALLOCATED
, ST_PLCI_DISCONNECTING
, EV_PLCI_FACILITY_IND_DOWN
, 0},
772 {ST_PLCI_ALLOCATED
, ST_PLCI_DISCONNECTED
, EV_PLCI_DISCONNECT_IND
, 0},
774 {ST_PLCI_ACTIVE
, ST_PLCI_DISCONNECTING
, EV_PLCI_DISCONNECT_REQ
, 0},
775 {ST_PLCI_ACTIVE
, ST_PLCI_DISCONNECTING
, EV_PLCI_FACILITY_IND_DOWN
, 0},
776 {ST_PLCI_ACTIVE
, ST_PLCI_DISCONNECTED
, EV_PLCI_DISCONNECT_IND
, 0},
777 {ST_PLCI_ACTIVE
, ST_PLCI_HELD
, EV_PLCI_HOLD_IND
, 0},
778 {ST_PLCI_ACTIVE
, ST_PLCI_DISCONNECTING
, EV_PLCI_SUSPEND_IND
, 0},
780 {ST_PLCI_INCOMING
, ST_PLCI_DISCONNECTING
, EV_PLCI_CONNECT_REJECT
, 0},
781 {ST_PLCI_INCOMING
, ST_PLCI_FACILITY_IND
, EV_PLCI_FACILITY_IND_UP
, 0},
782 {ST_PLCI_INCOMING
, ST_PLCI_ACCEPTING
, EV_PLCI_CONNECT_RESP
, 0},
783 {ST_PLCI_INCOMING
, ST_PLCI_DISCONNECTING
, EV_PLCI_DISCONNECT_REQ
, 0},
784 {ST_PLCI_INCOMING
, ST_PLCI_DISCONNECTING
, EV_PLCI_FACILITY_IND_DOWN
, 0},
785 {ST_PLCI_INCOMING
, ST_PLCI_DISCONNECTED
, EV_PLCI_DISCONNECT_IND
, 0},
786 {ST_PLCI_INCOMING
, ST_PLCI_DISCONNECTING
, EV_PLCI_CD_IND
, 0},
788 {ST_PLCI_FACILITY_IND
, ST_PLCI_DISCONNECTING
, EV_PLCI_CONNECT_REJECT
, 0},
789 {ST_PLCI_FACILITY_IND
, ST_PLCI_ACCEPTING
, EV_PLCI_CONNECT_ACTIVE_IND
, 0},
790 {ST_PLCI_FACILITY_IND
, ST_PLCI_DISCONNECTING
, EV_PLCI_DISCONNECT_REQ
, 0},
791 {ST_PLCI_FACILITY_IND
, ST_PLCI_DISCONNECTING
, EV_PLCI_FACILITY_IND_DOWN
, 0},
792 {ST_PLCI_FACILITY_IND
, ST_PLCI_DISCONNECTED
, EV_PLCI_DISCONNECT_IND
, 0},
794 {ST_PLCI_ACCEPTING
, ST_PLCI_ACTIVE
, EV_PLCI_CONNECT_ACTIVE_IND
, 0},
795 {ST_PLCI_ACCEPTING
, ST_PLCI_DISCONNECTING
, EV_PLCI_DISCONNECT_REQ
, 0},
796 {ST_PLCI_ACCEPTING
, ST_PLCI_DISCONNECTING
, EV_PLCI_FACILITY_IND_DOWN
, 0},
797 {ST_PLCI_ACCEPTING
, ST_PLCI_DISCONNECTED
, EV_PLCI_DISCONNECT_IND
, 0},
799 {ST_PLCI_DISCONNECTING
, ST_PLCI_DISCONNECTED
, EV_PLCI_DISCONNECT_IND
, 0},
801 {ST_PLCI_DISCONNECTED
, ST_PLCI_NONE
, EV_PLCI_DISCONNECT_RESP
, p0
},
803 {ST_PLCI_RESUMEING
, ST_PLCI_NONE
, EV_PLCI_RESUME_CONF_ERROR
, p0
},
804 {ST_PLCI_RESUMEING
, ST_PLCI_RESUME
, EV_PLCI_RESUME_CONF_OK
, 0},
806 {ST_PLCI_RESUME
, ST_PLCI_ACTIVE
, EV_PLCI_RESUME_IND
, 0},
808 {ST_PLCI_HELD
, ST_PLCI_ACTIVE
, EV_PLCI_RETRIEVE_IND
, 0},
812 static void plci_change_state(capidrv_contr
* card
, capidrv_plci
* plci
, int event
)
814 struct plcistatechange
*p
= plcitable
;
816 if (plci
->state
== p
->actstate
&& p
->event
== event
) {
818 printk(KERN_DEBUG
"capidrv-%d: plci_change_state:0x%x %d -> %d\n",
819 card
->contrnr
, plci
->plci
, plci
->state
, p
->nextstate
);
820 plci
->state
= p
->nextstate
;
822 p
->changefunc(card
, plci
);
827 printk(KERN_ERR
"capidrv-%d: plci_change_state:0x%x state=%d event=%d ????\n",
828 card
->contrnr
, plci
->plci
, plci
->state
, event
);
831 /* ------------------------------------------------------------------ */
835 static void n0(capidrv_contr
* card
, capidrv_ncci
* ncci
)
839 capi_fill_DISCONNECT_REQ(&cmsg
,
843 0, /* BChannelinformation */
844 0, /* Keypadfacility */
845 0, /* Useruserdata */ /* $$$$ */
846 0 /* Facilitydataarray */
848 send_message(card
, &cmsg
);
849 plci_change_state(card
, ncci
->plcip
, EV_PLCI_DISCONNECT_REQ
);
851 cmd
.command
= ISDN_STAT_BHUP
;
852 cmd
.driver
= card
->myid
;
853 cmd
.arg
= ncci
->chan
;
854 card
->interface
.statcallb(&cmd
);
855 free_ncci(card
, ncci
);
858 /* ------------------------------------------------------------------ */
860 struct nccistatechange
{
864 void (*changefunc
) (capidrv_contr
* card
, capidrv_ncci
* ncci
);
867 static struct nccistatechange nccitable
[] =
870 {ST_NCCI_NONE
, ST_NCCI_OUTGOING
, EV_NCCI_CONNECT_B3_REQ
, 0},
871 {ST_NCCI_NONE
, ST_NCCI_INCOMING
, EV_NCCI_CONNECT_B3_IND
, 0},
873 {ST_NCCI_OUTGOING
, ST_NCCI_ALLOCATED
, EV_NCCI_CONNECT_B3_CONF_OK
, 0},
874 {ST_NCCI_OUTGOING
, ST_NCCI_NONE
, EV_NCCI_CONNECT_B3_CONF_ERROR
, n0
},
876 {ST_NCCI_INCOMING
, ST_NCCI_DISCONNECTING
, EV_NCCI_CONNECT_B3_REJECT
, 0},
877 {ST_NCCI_INCOMING
, ST_NCCI_ALLOCATED
, EV_NCCI_CONNECT_B3_RESP
, 0},
878 {ST_NCCI_INCOMING
, ST_NCCI_DISCONNECTED
, EV_NCCI_DISCONNECT_B3_IND
, 0},
879 {ST_NCCI_INCOMING
, ST_NCCI_DISCONNECTING
, EV_NCCI_DISCONNECT_B3_REQ
, 0},
881 {ST_NCCI_ALLOCATED
, ST_NCCI_ACTIVE
, EV_NCCI_CONNECT_B3_ACTIVE_IND
, 0},
882 {ST_NCCI_ALLOCATED
, ST_NCCI_DISCONNECTED
, EV_NCCI_DISCONNECT_B3_IND
, 0},
883 {ST_NCCI_ALLOCATED
, ST_NCCI_DISCONNECTING
, EV_NCCI_DISCONNECT_B3_REQ
, 0},
885 {ST_NCCI_ACTIVE
, ST_NCCI_ACTIVE
, EV_NCCI_RESET_B3_IND
, 0},
886 {ST_NCCI_ACTIVE
, ST_NCCI_RESETING
, EV_NCCI_RESET_B3_REQ
, 0},
887 {ST_NCCI_ACTIVE
, ST_NCCI_DISCONNECTED
, EV_NCCI_DISCONNECT_B3_IND
, 0},
888 {ST_NCCI_ACTIVE
, ST_NCCI_DISCONNECTING
, EV_NCCI_DISCONNECT_B3_REQ
, 0},
890 {ST_NCCI_RESETING
, ST_NCCI_ACTIVE
, EV_NCCI_RESET_B3_IND
, 0},
891 {ST_NCCI_RESETING
, ST_NCCI_DISCONNECTED
, EV_NCCI_DISCONNECT_B3_IND
, 0},
892 {ST_NCCI_RESETING
, ST_NCCI_DISCONNECTING
, EV_NCCI_DISCONNECT_B3_REQ
, 0},
894 {ST_NCCI_DISCONNECTING
, ST_NCCI_DISCONNECTED
, EV_NCCI_DISCONNECT_B3_IND
, 0},
895 {ST_NCCI_DISCONNECTING
, ST_NCCI_PREVIOUS
, EV_NCCI_DISCONNECT_B3_CONF_ERROR
,0},
897 {ST_NCCI_DISCONNECTED
, ST_NCCI_NONE
, EV_NCCI_DISCONNECT_B3_RESP
, n0
},
901 static void ncci_change_state(capidrv_contr
* card
, capidrv_ncci
* ncci
, int event
)
903 struct nccistatechange
*p
= nccitable
;
905 if (ncci
->state
== p
->actstate
&& p
->event
== event
) {
907 printk(KERN_DEBUG
"capidrv-%d: ncci_change_state:0x%x %d -> %d\n",
908 card
->contrnr
, ncci
->ncci
, ncci
->state
, p
->nextstate
);
909 if (p
->nextstate
== ST_NCCI_PREVIOUS
) {
910 ncci
->state
= ncci
->oldstate
;
911 ncci
->oldstate
= p
->actstate
;
913 ncci
->oldstate
= p
->actstate
;
914 ncci
->state
= p
->nextstate
;
917 p
->changefunc(card
, ncci
);
922 printk(KERN_ERR
"capidrv-%d: ncci_change_state:0x%x state=%d event=%d ????\n",
923 card
->contrnr
, ncci
->ncci
, ncci
->state
, event
);
926 /* ------------------------------------------------------------------- */
928 static inline int new_bchan(capidrv_contr
* card
)
931 for (i
= 0; i
< card
->nbchan
; i
++) {
932 if (card
->bchans
[i
].plcip
== 0) {
933 card
->bchans
[i
].disconnecting
= 0;
940 /* ------------------------------------------------------------------- */
942 static void handle_controller(_cmsg
* cmsg
)
944 capidrv_contr
*card
= findcontrbynumber(cmsg
->adr
.adrController
& 0x7f);
947 printk(KERN_ERR
"capidrv: %s from unknown controller 0x%x\n",
948 capi_cmd2str(cmsg
->Command
, cmsg
->Subcommand
),
949 cmsg
->adr
.adrController
& 0x7f);
952 switch (CAPICMD(cmsg
->Command
, cmsg
->Subcommand
)) {
954 case CAPI_LISTEN_CONF
: /* Controller */
956 printk(KERN_DEBUG
"capidrv-%d: listenconf Info=0x%4x (%s) cipmask=0x%x\n",
957 card
->contrnr
, cmsg
->Info
, capi_info2str(cmsg
->Info
), card
->cipmask
);
959 listen_change_state(card
, EV_LISTEN_CONF_ERROR
);
960 } else if (card
->cipmask
== 0) {
961 listen_change_state(card
, EV_LISTEN_CONF_EMPTY
);
963 listen_change_state(card
, EV_LISTEN_CONF_OK
);
967 case CAPI_MANUFACTURER_IND
: /* Controller */
968 if ( cmsg
->ManuID
== 0x214D5641
970 && cmsg
->Function
== 1) {
971 __u8
*data
= cmsg
->ManuData
+3;
972 __u16 len
= cmsg
->ManuData
[0];
976 len
= (cmsg
->ManuData
[1] | (cmsg
->ManuData
[2] << 8));
980 layer
= ((*(data
-1)) << 8) | *(data
-2);
982 direction
= (layer
& 0x200) ? 0 : 1;
983 else direction
= (layer
& 0x800) ? 0 : 1;
984 if (layer
& 0x0C00) {
985 if ((layer
& 0xff) == 0x80) {
986 handle_dtrace_data(card
, direction
, 1, data
, len
);
989 } else if ((layer
& 0xff) < 0x80) {
990 handle_dtrace_data(card
, direction
, 0, data
, len
);
993 printk(KERN_INFO
"capidrv-%d: %s from controller 0x%x layer 0x%x, ignored\n",
995 capi_cmd2str(cmsg
->Command
, cmsg
->Subcommand
),
996 cmsg
->adr
.adrController
, layer
);
1000 case CAPI_MANUFACTURER_CONF
: /* Controller */
1001 if (cmsg
->ManuID
== 0x214D5641) {
1003 switch (cmsg
->Class
) {
1005 case 1: s
= "unknown class"; break;
1006 case 2: s
= "unknown function"; break;
1007 default: s
= "unkown error"; break;
1010 printk(KERN_INFO
"capidrv-%d: %s from controller 0x%x function %d: %s\n",
1012 capi_cmd2str(cmsg
->Command
, cmsg
->Subcommand
),
1013 cmsg
->adr
.adrController
,
1018 case CAPI_FACILITY_IND
: /* Controller/plci/ncci */
1020 case CAPI_FACILITY_CONF
: /* Controller/plci/ncci */
1022 case CAPI_INFO_IND
: /* Controller/plci */
1024 case CAPI_INFO_CONF
: /* Controller/plci */
1028 printk(KERN_ERR
"capidrv-%d: got %s from controller 0x%x ???",
1030 capi_cmd2str(cmsg
->Command
, cmsg
->Subcommand
),
1031 cmsg
->adr
.adrController
);
1036 printk(KERN_INFO
"capidrv-%d: %s from controller 0x%x ignored\n",
1038 capi_cmd2str(cmsg
->Command
, cmsg
->Subcommand
),
1039 cmsg
->adr
.adrController
);
1042 static void handle_incoming_call(capidrv_contr
* card
, _cmsg
* cmsg
)
1044 capidrv_plci
*plcip
;
1045 capidrv_bchan
*bchan
;
1049 if ((chan
= new_bchan(card
)) == -1) {
1050 printk(KERN_ERR
"capidrv-%d: incoming call on not existing bchan ?\n", card
->contrnr
);
1053 bchan
= &card
->bchans
[chan
];
1054 if ((plcip
= new_plci(card
, chan
)) == 0) {
1055 printk(KERN_ERR
"capidrv-%d: incoming call: no memory, sorry.\n", card
->contrnr
);
1058 bchan
->incoming
= 1;
1059 plcip
->plci
= cmsg
->adr
.adrPLCI
;
1060 plci_change_state(card
, plcip
, EV_PLCI_CONNECT_IND
);
1062 cmd
.command
= ISDN_STAT_ICALL
;
1063 cmd
.driver
= card
->myid
;
1065 memset(&cmd
.parm
.setup
, 0, sizeof(cmd
.parm
.setup
));
1066 strncpy(cmd
.parm
.setup
.phone
,
1067 cmsg
->CallingPartyNumber
+ 3,
1068 cmsg
->CallingPartyNumber
[0] - 2);
1069 strncpy(cmd
.parm
.setup
.eazmsn
,
1070 cmsg
->CalledPartyNumber
+ 2,
1071 cmsg
->CalledPartyNumber
[0] - 1);
1072 cmd
.parm
.setup
.si1
= cip2si1(cmsg
->CIPValue
);
1073 cmd
.parm
.setup
.si2
= cip2si2(cmsg
->CIPValue
);
1074 cmd
.parm
.setup
.plan
= cmsg
->CallingPartyNumber
[1];
1075 cmd
.parm
.setup
.screen
= cmsg
->CallingPartyNumber
[2];
1077 printk(KERN_INFO
"capidrv-%d: incoming call %s,%d,%d,%s\n",
1079 cmd
.parm
.setup
.phone
,
1082 cmd
.parm
.setup
.eazmsn
);
1084 if (cmd
.parm
.setup
.si1
== 1 && cmd
.parm
.setup
.si2
!= 0) {
1085 printk(KERN_INFO
"capidrv-%d: patching si2=%d to 0 for VBOX\n",
1087 cmd
.parm
.setup
.si2
);
1088 cmd
.parm
.setup
.si2
= 0;
1091 switch (card
->interface
.statcallb(&cmd
)) {
1094 /* No device matching this call.
1095 * and isdn_common.c has send a HANGUP command
1096 * which is ignored in state ST_PLCI_INCOMING,
1097 * so we send RESP to ignore the call
1099 capi_cmsg_answer(cmsg
);
1100 cmsg
->Reject
= 1; /* ignore */
1101 send_message(card
, cmsg
);
1102 plci_change_state(card
, plcip
, EV_PLCI_CONNECT_REJECT
);
1103 printk(KERN_INFO
"capidrv-%d: incoming call %s,%d,%d,%s ignored\n",
1105 cmd
.parm
.setup
.phone
,
1108 cmd
.parm
.setup
.eazmsn
);
1111 /* At least one device matching this call (RING on ttyI)
1112 * HL-driver may send ALERTING on the D-channel in this
1114 * really means: RING on ttyI or a net interface
1115 * accepted this call already.
1117 * If the call was accepted, state has already changed,
1118 * and CONNECT_RESP already sent.
1120 if (plcip
->state
== ST_PLCI_INCOMING
) {
1121 printk(KERN_INFO
"capidrv-%d: incoming call %s,%d,%d,%s tty alerting\n",
1123 cmd
.parm
.setup
.phone
,
1126 cmd
.parm
.setup
.eazmsn
);
1127 capi_fill_ALERT_REQ(cmsg
,
1130 plcip
->plci
, /* adr */
1131 0, /* BChannelinformation */
1132 0, /* Keypadfacility */
1133 0, /* Useruserdata */
1134 0 /* Facilitydataarray */
1136 plcip
->msgid
= cmsg
->Messagenumber
;
1137 send_message(card
, cmsg
);
1139 printk(KERN_INFO
"capidrv-%d: incoming call %s,%d,%d,%s on netdev\n",
1141 cmd
.parm
.setup
.phone
,
1144 cmd
.parm
.setup
.eazmsn
);
1148 case 2: /* Call will be rejected. */
1149 capi_cmsg_answer(cmsg
);
1150 cmsg
->Reject
= 2; /* reject call, normal call clearing */
1151 send_message(card
, cmsg
);
1152 plci_change_state(card
, plcip
, EV_PLCI_CONNECT_REJECT
);
1156 /* An error happened. (Invalid parameters for example.) */
1157 capi_cmsg_answer(cmsg
);
1158 cmsg
->Reject
= 8; /* reject call,
1159 destination out of order */
1160 send_message(card
, cmsg
);
1161 plci_change_state(card
, plcip
, EV_PLCI_CONNECT_REJECT
);
1167 static void handle_plci(_cmsg
* cmsg
)
1169 capidrv_contr
*card
= findcontrbynumber(cmsg
->adr
.adrController
& 0x7f);
1170 capidrv_plci
*plcip
;
1174 printk(KERN_ERR
"capidrv: %s from unknown controller 0x%x\n",
1175 capi_cmd2str(cmsg
->Command
, cmsg
->Subcommand
),
1176 cmsg
->adr
.adrController
& 0x7f);
1179 switch (CAPICMD(cmsg
->Command
, cmsg
->Subcommand
)) {
1181 case CAPI_DISCONNECT_IND
: /* plci */
1183 printk(KERN_INFO
"capidrv-%d: %s reason 0x%x (%s) for plci 0x%x\n",
1185 capi_cmd2str(cmsg
->Command
, cmsg
->Subcommand
),
1186 cmsg
->Reason
, capi_info2str(cmsg
->Reason
), cmsg
->adr
.adrPLCI
);
1188 if (!(plcip
= find_plci_by_plci(card
, cmsg
->adr
.adrPLCI
))) {
1189 capi_cmsg_answer(cmsg
);
1190 send_message(card
, cmsg
);
1193 card
->bchans
[plcip
->chan
].disconnecting
= 1;
1194 plci_change_state(card
, plcip
, EV_PLCI_DISCONNECT_IND
);
1195 capi_cmsg_answer(cmsg
);
1196 send_message(card
, cmsg
);
1197 plci_change_state(card
, plcip
, EV_PLCI_DISCONNECT_RESP
);
1200 case CAPI_DISCONNECT_CONF
: /* plci */
1202 printk(KERN_INFO
"capidrv-%d: %s info 0x%x (%s) for plci 0x%x\n",
1204 capi_cmd2str(cmsg
->Command
, cmsg
->Subcommand
),
1205 cmsg
->Info
, capi_info2str(cmsg
->Info
),
1208 if (!(plcip
= find_plci_by_plci(card
, cmsg
->adr
.adrPLCI
)))
1211 card
->bchans
[plcip
->chan
].disconnecting
= 1;
1214 case CAPI_ALERT_CONF
: /* plci */
1216 printk(KERN_INFO
"capidrv-%d: %s info 0x%x (%s) for plci 0x%x\n",
1218 capi_cmd2str(cmsg
->Command
, cmsg
->Subcommand
),
1219 cmsg
->Info
, capi_info2str(cmsg
->Info
),
1224 case CAPI_CONNECT_IND
: /* plci */
1225 handle_incoming_call(card
, cmsg
);
1228 case CAPI_CONNECT_CONF
: /* plci */
1230 printk(KERN_INFO
"capidrv-%d: %s info 0x%x (%s) for plci 0x%x\n",
1232 capi_cmd2str(cmsg
->Command
, cmsg
->Subcommand
),
1233 cmsg
->Info
, capi_info2str(cmsg
->Info
),
1236 if (!(plcip
= find_plci_by_msgid(card
, cmsg
->Messagenumber
)))
1239 plcip
->plci
= cmsg
->adr
.adrPLCI
;
1241 plci_change_state(card
, plcip
, EV_PLCI_CONNECT_CONF_ERROR
);
1243 plci_change_state(card
, plcip
, EV_PLCI_CONNECT_CONF_OK
);
1247 case CAPI_CONNECT_ACTIVE_IND
: /* plci */
1249 if (!(plcip
= find_plci_by_plci(card
, cmsg
->adr
.adrPLCI
)))
1252 if (card
->bchans
[plcip
->chan
].incoming
) {
1253 capi_cmsg_answer(cmsg
);
1254 send_message(card
, cmsg
);
1255 plci_change_state(card
, plcip
, EV_PLCI_CONNECT_ACTIVE_IND
);
1257 capidrv_ncci
*nccip
;
1258 capi_cmsg_answer(cmsg
);
1259 send_message(card
, cmsg
);
1261 nccip
= new_ncci(card
, plcip
, cmsg
->adr
.adrPLCI
);
1264 printk(KERN_ERR
"capidrv-%d: no mem for ncci, sorry\n", card
->contrnr
);
1267 capi_fill_CONNECT_B3_REQ(cmsg
,
1270 plcip
->plci
, /* adr */
1273 nccip
->msgid
= cmsg
->Messagenumber
;
1274 send_message(card
, cmsg
);
1275 cmd
.command
= ISDN_STAT_DCONN
;
1276 cmd
.driver
= card
->myid
;
1277 cmd
.arg
= plcip
->chan
;
1278 card
->interface
.statcallb(&cmd
);
1279 plci_change_state(card
, plcip
, EV_PLCI_CONNECT_ACTIVE_IND
);
1280 ncci_change_state(card
, nccip
, EV_NCCI_CONNECT_B3_REQ
);
1284 case CAPI_INFO_IND
: /* Controller/plci */
1286 if (!(plcip
= find_plci_by_plci(card
, cmsg
->adr
.adrPLCI
)))
1289 if (cmsg
->InfoNumber
== 0x4000) {
1290 if (cmsg
->InfoElement
[0] == 4) {
1291 cmd
.command
= ISDN_STAT_CINF
;
1292 cmd
.driver
= card
->myid
;
1293 cmd
.arg
= plcip
->chan
;
1294 sprintf(cmd
.parm
.num
, "%lu",
1296 ((__u32
) cmsg
->InfoElement
[1]
1297 | ((__u32
) (cmsg
->InfoElement
[2]) << 8)
1298 | ((__u32
) (cmsg
->InfoElement
[3]) << 16)
1299 | ((__u32
) (cmsg
->InfoElement
[4]) << 24)));
1300 card
->interface
.statcallb(&cmd
);
1304 printk(KERN_ERR
"capidrv-%d: %s\n",
1305 card
->contrnr
, capi_cmsg2str(cmsg
));
1308 case CAPI_CONNECT_ACTIVE_CONF
: /* plci */
1310 case CAPI_SELECT_B_PROTOCOL_CONF
: /* plci */
1312 case CAPI_FACILITY_IND
: /* Controller/plci/ncci */
1314 case CAPI_FACILITY_CONF
: /* Controller/plci/ncci */
1317 case CAPI_INFO_CONF
: /* Controller/plci */
1321 printk(KERN_ERR
"capidrv-%d: got %s for plci 0x%x ???",
1323 capi_cmd2str(cmsg
->Command
, cmsg
->Subcommand
),
1328 printk(KERN_INFO
"capidrv-%d: %s for plci 0x%x ignored\n",
1330 capi_cmd2str(cmsg
->Command
, cmsg
->Subcommand
),
1334 printk(KERN_ERR
"capidrv-%d: %s: plci 0x%x not found\n",
1336 capi_cmd2str(cmsg
->Command
, cmsg
->Subcommand
),
1341 static void handle_ncci(_cmsg
* cmsg
)
1343 capidrv_contr
*card
= findcontrbynumber(cmsg
->adr
.adrController
& 0x7f);
1344 capidrv_plci
*plcip
;
1345 capidrv_ncci
*nccip
;
1350 printk(KERN_ERR
"capidrv: %s from unknown controller 0x%x\n",
1351 capi_cmd2str(cmsg
->Command
, cmsg
->Subcommand
),
1352 cmsg
->adr
.adrController
& 0x7f);
1355 switch (CAPICMD(cmsg
->Command
, cmsg
->Subcommand
)) {
1357 case CAPI_CONNECT_B3_ACTIVE_IND
: /* ncci */
1358 if (!(nccip
= find_ncci(card
, cmsg
->adr
.adrNCCI
)))
1361 capi_cmsg_answer(cmsg
);
1362 send_message(card
, cmsg
);
1363 ncci_change_state(card
, nccip
, EV_NCCI_CONNECT_B3_ACTIVE_IND
);
1365 cmd
.command
= ISDN_STAT_BCONN
;
1366 cmd
.driver
= card
->myid
;
1367 cmd
.arg
= nccip
->chan
;
1368 card
->interface
.statcallb(&cmd
);
1370 printk(KERN_INFO
"capidrv-%d: chan %d up with ncci 0x%x\n",
1371 card
->contrnr
, nccip
->chan
, nccip
->ncci
);
1374 case CAPI_CONNECT_B3_ACTIVE_CONF
: /* ncci */
1377 case CAPI_CONNECT_B3_IND
: /* ncci */
1379 plcip
= find_plci_by_ncci(card
, cmsg
->adr
.adrNCCI
);
1381 nccip
= new_ncci(card
, plcip
, cmsg
->adr
.adrNCCI
);
1383 ncci_change_state(card
, nccip
, EV_NCCI_CONNECT_B3_IND
);
1384 capi_fill_CONNECT_B3_RESP(cmsg
,
1387 nccip
->ncci
, /* adr */
1391 send_message(card
, cmsg
);
1392 ncci_change_state(card
, nccip
, EV_NCCI_CONNECT_B3_RESP
);
1395 printk(KERN_ERR
"capidrv-%d: no mem for ncci, sorry\n", card
->contrnr
);
1397 printk(KERN_ERR
"capidrv-%d: %s: plci for ncci 0x%x not found\n",
1399 capi_cmd2str(cmsg
->Command
, cmsg
->Subcommand
),
1402 capi_fill_CONNECT_B3_RESP(cmsg
,
1409 send_message(card
, cmsg
);
1412 case CAPI_CONNECT_B3_CONF
: /* ncci */
1414 if (!(nccip
= find_ncci_by_msgid(card
,
1416 cmsg
->Messagenumber
)))
1419 nccip
->ncci
= cmsg
->adr
.adrNCCI
;
1421 printk(KERN_INFO
"capidrv-%d: %s info 0x%x (%s) for ncci 0x%x\n",
1423 capi_cmd2str(cmsg
->Command
, cmsg
->Subcommand
),
1424 cmsg
->Info
, capi_info2str(cmsg
->Info
),
1429 ncci_change_state(card
, nccip
, EV_NCCI_CONNECT_B3_CONF_ERROR
);
1431 ncci_change_state(card
, nccip
, EV_NCCI_CONNECT_B3_CONF_OK
);
1434 case CAPI_CONNECT_B3_T90_ACTIVE_IND
: /* ncci */
1435 capi_cmsg_answer(cmsg
);
1436 send_message(card
, cmsg
);
1439 case CAPI_DATA_B3_IND
: /* ncci */
1440 /* handled in handle_data() */
1443 case CAPI_DATA_B3_CONF
: /* ncci */
1444 if (!(nccip
= find_ncci(card
, cmsg
->adr
.adrNCCI
)))
1447 len
= capidrv_del_ack(nccip
, cmsg
->DataHandle
);
1450 cmd
.command
= ISDN_STAT_BSENT
;
1451 cmd
.driver
= card
->myid
;
1452 cmd
.arg
= nccip
->chan
;
1453 cmd
.parm
.length
= len
;
1454 card
->interface
.statcallb(&cmd
);
1457 case CAPI_DISCONNECT_B3_IND
: /* ncci */
1458 if (!(nccip
= find_ncci(card
, cmsg
->adr
.adrNCCI
)))
1461 card
->bchans
[nccip
->chan
].disconnecting
= 1;
1462 ncci_change_state(card
, nccip
, EV_NCCI_DISCONNECT_B3_IND
);
1463 capi_cmsg_answer(cmsg
);
1464 send_message(card
, cmsg
);
1465 ncci_change_state(card
, nccip
, EV_NCCI_DISCONNECT_B3_RESP
);
1468 case CAPI_DISCONNECT_B3_CONF
: /* ncci */
1469 if (!(nccip
= find_ncci(card
, cmsg
->adr
.adrNCCI
)))
1472 printk(KERN_INFO
"capidrv-%d: %s info 0x%x (%s) for ncci 0x%x\n",
1474 capi_cmd2str(cmsg
->Command
, cmsg
->Subcommand
),
1475 cmsg
->Info
, capi_info2str(cmsg
->Info
),
1477 ncci_change_state(card
, nccip
, EV_NCCI_DISCONNECT_B3_CONF_ERROR
);
1481 case CAPI_RESET_B3_IND
: /* ncci */
1482 if (!(nccip
= find_ncci(card
, cmsg
->adr
.adrNCCI
)))
1484 ncci_change_state(card
, nccip
, EV_NCCI_RESET_B3_IND
);
1485 capi_cmsg_answer(cmsg
);
1486 send_message(card
, cmsg
);
1489 case CAPI_RESET_B3_CONF
: /* ncci */
1490 goto ignored
; /* $$$$ */
1492 case CAPI_FACILITY_IND
: /* Controller/plci/ncci */
1494 case CAPI_FACILITY_CONF
: /* Controller/plci/ncci */
1498 printk(KERN_ERR
"capidrv-%d: got %s for ncci 0x%x ???",
1500 capi_cmd2str(cmsg
->Command
, cmsg
->Subcommand
),
1505 printk(KERN_INFO
"capidrv-%d: %s for ncci 0x%x ignored\n",
1507 capi_cmd2str(cmsg
->Command
, cmsg
->Subcommand
),
1511 printk(KERN_ERR
"capidrv-%d: %s: ncci 0x%x not found\n",
1513 capi_cmd2str(cmsg
->Command
, cmsg
->Subcommand
),
1518 static void handle_data(_cmsg
* cmsg
, struct sk_buff
*skb
)
1520 capidrv_contr
*card
= findcontrbynumber(cmsg
->adr
.adrController
& 0x7f);
1521 capidrv_ncci
*nccip
;
1524 printk(KERN_ERR
"capidrv: %s from unknown controller 0x%x\n",
1525 capi_cmd2str(cmsg
->Command
, cmsg
->Subcommand
),
1526 cmsg
->adr
.adrController
& 0x7f);
1530 if (!(nccip
= find_ncci(card
, cmsg
->adr
.adrNCCI
))) {
1531 printk(KERN_ERR
"capidrv-%d: %s: ncci 0x%x not found\n",
1533 capi_cmd2str(cmsg
->Command
, cmsg
->Subcommand
),
1538 (void) skb_pull(skb
, CAPIMSG_LEN(skb
->data
));
1539 card
->interface
.rcvcallb_skb(card
->myid
, nccip
->chan
, skb
);
1540 capi_cmsg_answer(cmsg
);
1541 send_message(card
, cmsg
);
1544 static _cmsg s_cmsg
;
1546 static void capidrv_signal(__u16 applid
, void *dummy
)
1548 struct sk_buff
*skb
= 0;
1550 while ((*capifuncs
->capi_get_message
) (global
.appid
, &skb
) == CAPI_NOERROR
) {
1551 capi_message2cmsg(&s_cmsg
, skb
->data
);
1553 printk(KERN_DEBUG
"capidrv_signal: applid=%d %s\n",
1554 applid
, capi_cmsg2str(&s_cmsg
));
1556 if (s_cmsg
.Command
== CAPI_DATA_B3
1557 && s_cmsg
.Subcommand
== CAPI_IND
) {
1558 handle_data(&s_cmsg
, skb
);
1559 global
.nrecvdatapkt
++;
1562 if ((s_cmsg
.adr
.adrController
& 0xffffff00) == 0)
1563 handle_controller(&s_cmsg
);
1564 else if ((s_cmsg
.adr
.adrPLCI
& 0xffff0000) == 0)
1565 handle_plci(&s_cmsg
);
1567 handle_ncci(&s_cmsg
);
1569 * data of skb used in s_cmsg,
1570 * free data when s_cmsg is not used again
1571 * thanks to Lars Heete <hel@admin.de>
1574 global
.nrecvctlpkt
++;
1578 /* ------------------------------------------------------------------- */
1580 #define PUTBYTE_TO_STATUS(card, byte) \
1582 *(card)->q931_write++ = (byte); \
1583 if ((card)->q931_write > (card)->q931_end) \
1584 (card)->q931_write = (card)->q931_buf; \
1587 static void handle_dtrace_data(capidrv_contr
*card
,
1588 int send
, int level2
, __u8
*data
, __u16 len
)
1594 printk(KERN_DEBUG
"capidrv-%d: avmb1_q931_data: len == %d\n",
1595 card
->contrnr
, len
);
1600 PUTBYTE_TO_STATUS(card
, 'D');
1601 PUTBYTE_TO_STATUS(card
, '2');
1602 PUTBYTE_TO_STATUS(card
, send
? '>' : '<');
1603 PUTBYTE_TO_STATUS(card
, ':');
1605 PUTBYTE_TO_STATUS(card
, 'D');
1606 PUTBYTE_TO_STATUS(card
, '3');
1607 PUTBYTE_TO_STATUS(card
, send
? '>' : '<');
1608 PUTBYTE_TO_STATUS(card
, ':');
1611 for (p
= data
, end
= data
+len
; p
< end
; p
++) {
1613 PUTBYTE_TO_STATUS(card
, ' ');
1614 w
= (*p
>> 4) & 0xf;
1615 PUTBYTE_TO_STATUS(card
, (w
< 10) ? '0'+w
: 'A'-10+w
);
1617 PUTBYTE_TO_STATUS(card
, (w
< 10) ? '0'+w
: 'A'-10+w
);
1619 PUTBYTE_TO_STATUS(card
, '\n');
1621 cmd
.command
= ISDN_STAT_STAVAIL
;
1622 cmd
.driver
= card
->myid
;
1624 card
->interface
.statcallb(&cmd
);
1627 /* ------------------------------------------------------------------- */
1629 static _cmsg cmdcmsg
;
1631 static int capidrv_ioctl(isdn_ctrl
* c
, capidrv_contr
* card
)
1635 debugmode
= (int)(*((unsigned int *)c
->parm
.num
));
1636 printk(KERN_DEBUG
"capidrv-%d: debugmode=%d\n",
1637 card
->contrnr
, debugmode
);
1640 printk(KERN_DEBUG
"capidrv-%d: capidrv_ioctl(%ld) called ??\n",
1641 card
->contrnr
, c
->arg
);
1648 * Handle leased lines (CAPI-Bundling)
1651 struct internal_bchannelinfo
{
1652 unsigned short channelalloc
;
1653 unsigned short operation
;
1654 unsigned char cmask
[31];
1657 static int decodeFVteln(char *teln
, unsigned long *bmaskp
, int *activep
)
1659 unsigned long bmask
= 0;
1664 if (strncmp(teln
, "FV:", 3) != 0)
1667 while (*s
&& *s
== ' ') s
++;
1669 if (*s
== 'p' || *s
== 'P') {
1673 if (*s
== 'a' || *s
== 'A') {
1680 if (!isdigit(*s
)) return -3;
1681 while (isdigit(*s
)) { digit1
= digit1
*10 + (*s
- '0'); s
++; }
1682 if (digit1
<= 0 && digit1
> 30) return -4;
1683 if (*s
== 0 || *s
== ',' || *s
== ' ') {
1684 bmask
|= (1 << digit1
);
1689 if (*s
!= '-') return -5;
1691 if (!isdigit(*s
)) return -3;
1692 while (isdigit(*s
)) { digit2
= digit2
*10 + (*s
- '0'); s
++; }
1693 if (digit2
<= 0 && digit2
> 30) return -4;
1694 if (*s
== 0 || *s
== ',' || *s
== ' ') {
1695 if (digit1
> digit2
)
1696 for (i
= digit2
; i
<= digit1
; i
++)
1699 for (i
= digit1
; i
<= digit2
; i
++)
1701 digit1
= digit2
= 0;
1707 if (activep
) *activep
= active
;
1708 if (bmaskp
) *bmaskp
= bmask
;
1712 static int FVteln2capi20(char *teln
, __u8 AdditionalInfo
[1+2+2+31])
1714 unsigned long bmask
;
1718 rc
= decodeFVteln(teln
, &bmask
, &active
);
1721 AdditionalInfo
[0] = 2+2+31;
1722 /* Channel: 3 => use channel allocation */
1723 AdditionalInfo
[1] = 3; AdditionalInfo
[2] = 0;
1724 /* Operation: 0 => DTE mode, 1 => DCE mode */
1726 AdditionalInfo
[3] = 0; AdditionalInfo
[4] = 0;
1728 AdditionalInfo
[3] = 1; AdditionalInfo
[4] = 0;
1730 /* Channel mask array */
1731 AdditionalInfo
[5] = 0; /* no D-Channel */
1732 for (i
=1; i
<= 30; i
++)
1733 AdditionalInfo
[5+i
] = (bmask
& (1 << i
)) ? 0xff : 0;
1737 static int capidrv_command(isdn_ctrl
* c
, capidrv_contr
* card
)
1740 struct capidrv_bchan
*bchan
;
1741 struct capidrv_plci
*plcip
;
1742 __u8 AdditionalInfo
[1+2+2+31];
1743 int rc
, isleasedline
= 0;
1745 if (c
->command
== ISDN_CMD_IOCTL
)
1746 return capidrv_ioctl(c
, card
);
1748 switch (c
->command
) {
1749 case ISDN_CMD_DIAL
:{
1750 __u8 calling
[ISDN_MSNLEN
+ 3];
1751 __u8 called
[ISDN_MSNLEN
+ 2];
1754 printk(KERN_DEBUG
"capidrv-%d: ISDN_CMD_DIAL(ch=%ld,\"%s,%d,%d,%s\")\n",
1757 c
->parm
.setup
.phone
,
1760 c
->parm
.setup
.eazmsn
);
1762 bchan
= &card
->bchans
[c
->arg
% card
->nbchan
];
1765 printk(KERN_ERR
"capidrv-%d: dail ch=%ld,\"%s,%d,%d,%s\" in use (plci=0x%x)\n",
1768 c
->parm
.setup
.phone
,
1771 c
->parm
.setup
.eazmsn
,
1772 bchan
->plcip
->plci
);
1775 bchan
->si1
= c
->parm
.setup
.si1
;
1776 bchan
->si2
= c
->parm
.setup
.si2
;
1778 strncpy(bchan
->num
, c
->parm
.setup
.phone
, sizeof(bchan
->num
));
1779 strncpy(bchan
->mynum
, c
->parm
.setup
.eazmsn
, sizeof(bchan
->mynum
));
1780 rc
= FVteln2capi20(bchan
->num
, AdditionalInfo
);
1781 isleasedline
= (rc
== 0);
1783 printk(KERN_ERR
"capidrv-%d: WARNING: illegal leased linedefinition \"%s\"\n", card
->contrnr
, bchan
->num
);
1789 printk(KERN_DEBUG
"capidrv-%d: connecting leased line\n", card
->contrnr
);
1791 calling
[0] = strlen(bchan
->mynum
) + 2;
1794 strncpy(calling
+ 3, bchan
->mynum
, ISDN_MSNLEN
);
1795 called
[0] = strlen(bchan
->num
) + 1;
1797 strncpy(called
+ 2, bchan
->num
, ISDN_MSNLEN
);
1800 capi_fill_CONNECT_REQ(&cmdcmsg
,
1803 card
->contrnr
, /* adr */
1804 si2cip(bchan
->si1
, bchan
->si2
), /* cipvalue */
1805 called
, /* CalledPartyNumber */
1806 calling
, /* CallingPartyNumber */
1807 0, /* CalledPartySubaddress */
1808 0, /* CallingPartySubaddress */
1809 b1prot(bchan
->l2
, bchan
->l3
), /* B1protocol */
1810 b2prot(bchan
->l2
, bchan
->l3
), /* B2protocol */
1811 b3prot(bchan
->l2
, bchan
->l3
), /* B3protocol */
1812 b1config(bchan
->l2
, bchan
->l3
), /* B1configuration */
1813 0, /* B2configuration */
1814 0, /* B3configuration */
1818 /* BChannelinformation */
1819 isleasedline
? AdditionalInfo
: 0,
1820 0, /* Keypadfacility */
1821 0, /* Useruserdata */
1822 0 /* Facilitydataarray */
1824 if ((plcip
= new_plci(card
, (c
->arg
% card
->nbchan
))) == 0) {
1825 cmd
.command
= ISDN_STAT_DHUP
;
1826 cmd
.driver
= card
->myid
;
1827 cmd
.arg
= (c
->arg
% card
->nbchan
);
1828 card
->interface
.statcallb(&cmd
);
1831 plcip
->msgid
= cmdcmsg
.Messagenumber
;
1832 plcip
->leasedline
= isleasedline
;
1833 plci_change_state(card
, plcip
, EV_PLCI_CONNECT_REQ
);
1834 send_message(card
, &cmdcmsg
);
1838 case ISDN_CMD_ACCEPTD
:
1840 bchan
= &card
->bchans
[c
->arg
% card
->nbchan
];
1842 printk(KERN_DEBUG
"capidrv-%d: ISDN_CMD_ACCEPTD(ch=%ld) l2=%d l3=%d\n",
1844 c
->arg
, bchan
->l2
, bchan
->l3
);
1846 capi_fill_CONNECT_RESP(&cmdcmsg
,
1849 bchan
->plcip
->plci
, /* adr */
1851 b1prot(bchan
->l2
, bchan
->l3
), /* B1protocol */
1852 b2prot(bchan
->l2
, bchan
->l3
), /* B2protocol */
1853 b3prot(bchan
->l2
, bchan
->l3
), /* B3protocol */
1854 b1config(bchan
->l2
, bchan
->l3
), /* B1configuration */
1855 0, /* B2configuration */
1856 0, /* B3configuration */
1857 0, /* ConnectedNumber */
1858 0, /* ConnectedSubaddress */
1860 0, /* BChannelinformation */
1861 0, /* Keypadfacility */
1862 0, /* Useruserdata */
1863 0 /* Facilitydataarray */
1865 capi_cmsg2message(&cmdcmsg
, cmdcmsg
.buf
);
1866 plci_change_state(card
, bchan
->plcip
, EV_PLCI_CONNECT_RESP
);
1867 send_message(card
, &cmdcmsg
);
1870 case ISDN_CMD_ACCEPTB
:
1872 printk(KERN_DEBUG
"capidrv-%d: ISDN_CMD_ACCEPTB(ch=%ld)\n",
1877 case ISDN_CMD_HANGUP
:
1879 printk(KERN_DEBUG
"capidrv-%d: ISDN_CMD_HANGUP(ch=%ld)\n",
1882 bchan
= &card
->bchans
[c
->arg
% card
->nbchan
];
1884 if (bchan
->disconnecting
) {
1886 printk(KERN_DEBUG
"capidrv-%d: chan %ld already disconnecting ...\n",
1892 bchan
->disconnecting
= 1;
1893 capi_fill_DISCONNECT_B3_REQ(&cmdcmsg
,
1899 ncci_change_state(card
, bchan
->nccip
, EV_NCCI_DISCONNECT_B3_REQ
);
1900 send_message(card
, &cmdcmsg
);
1902 } else if (bchan
->plcip
) {
1903 if (bchan
->plcip
->state
== ST_PLCI_INCOMING
) {
1905 * just ignore, we a called from
1906 * isdn_status_callback(),
1907 * which will return 0 or 2, this is handled
1908 * by the CONNECT_IND handler
1910 bchan
->disconnecting
= 1;
1912 } else if (bchan
->plcip
->plci
) {
1913 bchan
->disconnecting
= 1;
1914 capi_fill_DISCONNECT_REQ(&cmdcmsg
,
1918 0, /* BChannelinformation */
1919 0, /* Keypadfacility */
1920 0, /* Useruserdata */
1921 0 /* Facilitydataarray */
1923 plci_change_state(card
, bchan
->plcip
, EV_PLCI_DISCONNECT_REQ
);
1924 send_message(card
, &cmdcmsg
);
1927 printk(KERN_ERR
"capidrv-%d: chan %ld disconnect request while waiting for CONNECT_CONF\n",
1933 printk(KERN_ERR
"capidrv-%d: chan %ld disconnect request on free channel\n",
1939 case ISDN_CMD_SETL2
:
1941 printk(KERN_DEBUG
"capidrv-%d: set L2 on chan %ld to %ld\n",
1943 (c
->arg
& 0xff), (c
->arg
>> 8));
1944 bchan
= &card
->bchans
[(c
->arg
& 0xff) % card
->nbchan
];
1945 bchan
->l2
= (c
->arg
>> 8);
1948 case ISDN_CMD_SETL3
:
1950 printk(KERN_DEBUG
"capidrv-%d: set L3 on chan %ld to %ld\n",
1952 (c
->arg
& 0xff), (c
->arg
>> 8));
1953 bchan
= &card
->bchans
[(c
->arg
& 0xff) % card
->nbchan
];
1954 bchan
->l3
= (c
->arg
>> 8);
1957 case ISDN_CMD_SETEAZ
:
1959 printk(KERN_DEBUG
"capidrv-%d: set EAZ \"%s\" on chan %ld\n",
1961 c
->parm
.num
, c
->arg
);
1962 bchan
= &card
->bchans
[c
->arg
% card
->nbchan
];
1963 strncpy(bchan
->msn
, c
->parm
.num
, ISDN_MSNLEN
);
1966 case ISDN_CMD_CLREAZ
:
1968 printk(KERN_DEBUG
"capidrv-%d: clearing EAZ on chan %ld\n",
1969 card
->contrnr
, c
->arg
);
1970 bchan
= &card
->bchans
[c
->arg
% card
->nbchan
];
1976 printk(KERN_DEBUG
"capidrv-%d: ISDN_CMD_LOCK (%ld)\n", card
->contrnr
, c
->arg
);
1980 case ISDN_CMD_UNLOCK
:
1982 printk(KERN_DEBUG
"capidrv-%d: ISDN_CMD_UNLOCK (%ld)\n",
1983 card
->contrnr
, c
->arg
);
1988 case ISDN_CMD_GETL2
:
1990 printk(KERN_DEBUG
"capidrv-%d: ISDN_CMD_GETL2\n",
1993 case ISDN_CMD_GETL3
:
1995 printk(KERN_DEBUG
"capidrv-%d: ISDN_CMD_GETL3\n",
1998 case ISDN_CMD_GETEAZ
:
2000 printk(KERN_DEBUG
"capidrv-%d: ISDN_CMD_GETEAZ\n",
2003 case ISDN_CMD_SETSIL
:
2005 printk(KERN_DEBUG
"capidrv-%d: ISDN_CMD_SETSIL\n",
2008 case ISDN_CMD_GETSIL
:
2010 printk(KERN_DEBUG
"capidrv-%d: ISDN_CMD_GETSIL\n",
2014 printk(KERN_ERR
"capidrv-%d: ISDN_CMD_%d, Huh?\n",
2015 card
->contrnr
, c
->command
);
2021 static int if_command(isdn_ctrl
* c
)
2023 capidrv_contr
*card
= findcontrbydriverid(c
->driver
);
2026 return capidrv_command(c
, card
);
2029 "capidrv: if_command %d called with invalid driverId %d!\n",
2030 c
->command
, c
->driver
);
2034 static _cmsg sendcmsg
;
2036 static int if_sendbuf(int id
, int channel
, int doack
, struct sk_buff
*skb
)
2038 capidrv_contr
*card
= findcontrbydriverid(id
);
2039 capidrv_bchan
*bchan
;
2040 capidrv_ncci
*nccip
;
2047 printk(KERN_ERR
"capidrv-%d: if_sendbuf called with invalid driverId %d!\n",
2052 printk(KERN_DEBUG
"capidrv-%d: sendbuf len=%d skb=%p doack=%d\n",
2053 card
->contrnr
, len
, skb
, doack
);
2054 bchan
= &card
->bchans
[channel
% card
->nbchan
];
2055 nccip
= bchan
->nccip
;
2056 if (!nccip
|| nccip
->state
!= ST_NCCI_ACTIVE
) {
2057 printk(KERN_ERR
"capidrv-%d: if_sendbuf: %s:%d: chan not up!\n",
2058 card
->contrnr
, card
->name
, channel
);
2061 datahandle
= nccip
->datahandle
;
2062 capi_fill_DATA_B3_REQ(&sendcmsg
, global
.appid
, card
->msgid
++,
2063 nccip
->ncci
, /* adr */
2064 (__u32
) skb
->data
, /* Data */
2065 skb
->len
, /* DataLength */
2066 datahandle
, /* DataHandle */
2070 if (capidrv_add_ack(nccip
, datahandle
, doack
? skb
->len
: -1) < 0)
2073 capi_cmsg2message(&sendcmsg
, sendcmsg
.buf
);
2074 msglen
= CAPIMSG_LEN(sendcmsg
.buf
);
2075 if (skb_headroom(skb
) < msglen
) {
2076 struct sk_buff
*nskb
= skb_realloc_headroom(skb
, msglen
);
2078 printk(KERN_ERR
"capidrv-%d: if_sendbuf: no memory\n",
2080 (void)capidrv_del_ack(nccip
, datahandle
);
2083 printk(KERN_DEBUG
"capidrv-%d: only %d bytes headroom, need %d\n",
2084 card
->contrnr
, skb_headroom(skb
), msglen
);
2085 memcpy(skb_push(nskb
, msglen
), sendcmsg
.buf
, msglen
);
2086 errcode
= (*capifuncs
->capi_put_message
) (global
.appid
, nskb
);
2087 if (errcode
== CAPI_NOERROR
) {
2089 nccip
->datahandle
++;
2090 global
.nsentdatapkt
++;
2093 (void)capidrv_del_ack(nccip
, datahandle
);
2094 dev_kfree_skb(nskb
);
2095 return errcode
== CAPI_SENDQUEUEFULL
? 0 : -1;
2097 memcpy(skb_push(skb
, msglen
), sendcmsg
.buf
, msglen
);
2098 errcode
= (*capifuncs
->capi_put_message
) (global
.appid
, skb
);
2099 if (errcode
== CAPI_NOERROR
) {
2100 nccip
->datahandle
++;
2101 global
.nsentdatapkt
++;
2104 skb_pull(skb
, msglen
);
2105 (void)capidrv_del_ack(nccip
, datahandle
);
2106 return errcode
== CAPI_SENDQUEUEFULL
? 0 : -1;
2110 static int if_readstat(__u8
*buf
, int len
, int user
, int id
, int channel
)
2112 capidrv_contr
*card
= findcontrbydriverid(id
);
2117 printk(KERN_ERR
"capidrv-%d: if_readstat called with invalid driverId %d!\n",
2122 for (p
=buf
, count
=0; count
< len
; p
++, count
++) {
2124 put_user(*card
->q931_read
++, p
);
2126 *p
= *card
->q931_read
++;
2127 if (card
->q931_read
> card
->q931_end
)
2128 card
->q931_read
= card
->q931_buf
;
2134 static void enable_dchannel_trace(capidrv_contr
*card
)
2136 __u8 manufacturer
[CAPI_MANUFACTURER_LEN
];
2137 capi_version version
;
2138 __u16 contr
= card
->contrnr
;
2140 __u16 avmversion
[3];
2142 errcode
= (*capifuncs
->capi_get_manufacturer
)(contr
, manufacturer
);
2143 if (errcode
!= CAPI_NOERROR
) {
2144 printk(KERN_ERR
"%s: can't get manufacturer (0x%x)\n",
2145 card
->name
, errcode
);
2148 if (strstr(manufacturer
, "AVM") == 0) {
2149 printk(KERN_ERR
"%s: not from AVM, no d-channel trace possible (%s)\n",
2150 card
->name
, manufacturer
);
2153 errcode
= (*capifuncs
->capi_get_version
)(contr
, &version
);
2154 if (errcode
!= CAPI_NOERROR
) {
2155 printk(KERN_ERR
"%s: can't get version (0x%x)\n",
2156 card
->name
, errcode
);
2159 avmversion
[0] = (version
.majormanuversion
>> 4) & 0x0f;
2160 avmversion
[1] = (version
.majormanuversion
<< 4) & 0xf0;
2161 avmversion
[1] |= (version
.minormanuversion
>> 4) & 0x0f;
2162 avmversion
[2] |= version
.minormanuversion
& 0x0f;
2164 if (avmversion
[0] > 3 || (avmversion
[0] == 3 && avmversion
[1] > 5)) {
2165 printk(KERN_INFO
"%s: D2 trace enabled\n", card
->name
);
2166 capi_fill_MANUFACTURER_REQ(&cmdcmsg
, global
.appid
,
2169 0x214D5641, /* ManuID */
2172 (_cstruct
)"\004\200\014\000\000");
2174 printk(KERN_INFO
"%s: D3 trace enabled\n", card
->name
);
2175 capi_fill_MANUFACTURER_REQ(&cmdcmsg
, global
.appid
,
2178 0x214D5641, /* ManuID */
2181 (_cstruct
)"\004\002\003\000\000");
2183 send_message(card
, &cmdcmsg
);
2187 static void send_listen(capidrv_contr
*card
)
2189 capi_fill_LISTEN_REQ(&cmdcmsg
, global
.appid
,
2191 card
->contrnr
, /* controller */
2192 1 << 6, /* Infomask */
2196 send_message(card
, &cmdcmsg
);
2197 listen_change_state(card
, EV_LISTEN_REQ
);
2200 static void listentimerfunc(unsigned long x
)
2202 capidrv_contr
*card
= (capidrv_contr
*)x
;
2203 if (card
->state
!= ST_LISTEN_NONE
&& card
->state
!= ST_LISTEN_ACTIVE
)
2204 printk(KERN_ERR
"%s: controller dead ??\n", card
->name
);
2206 mod_timer(&card
->listentimer
, jiffies
+ 60*HZ
);
2210 static int capidrv_addcontr(__u16 contr
, struct capi_profile
*profp
)
2212 capidrv_contr
*card
;
2220 sprintf(id
, "capidrv-%d", contr
);
2221 if (!(card
= (capidrv_contr
*) kmalloc(sizeof(capidrv_contr
), GFP_ATOMIC
))) {
2223 "capidrv: (%s) Could not allocate contr-struct.\n", id
);
2227 memset(card
, 0, sizeof(capidrv_contr
));
2228 init_timer(&card
->listentimer
);
2229 strcpy(card
->name
, id
);
2230 card
->contrnr
= contr
;
2231 card
->nbchan
= profp
->nbchannel
;
2232 card
->bchans
= (capidrv_bchan
*) kmalloc(sizeof(capidrv_bchan
) * card
->nbchan
, GFP_ATOMIC
);
2233 if (!card
->bchans
) {
2235 "capidrv: (%s) Could not allocate bchan-structs.\n", id
);
2240 card
->interface
.channels
= profp
->nbchannel
;
2241 card
->interface
.maxbufsize
= 2048;
2242 card
->interface
.command
= if_command
;
2243 card
->interface
.writebuf_skb
= if_sendbuf
;
2244 card
->interface
.writecmd
= 0;
2245 card
->interface
.readstat
= if_readstat
;
2246 card
->interface
.features
= ISDN_FEATURE_L2_HDLC
|
2247 ISDN_FEATURE_L2_TRANS
|
2248 ISDN_FEATURE_L3_TRANS
|
2249 ISDN_FEATURE_P_UNKNOWN
|
2250 ISDN_FEATURE_L2_X75I
|
2251 ISDN_FEATURE_L2_X75UI
|
2252 ISDN_FEATURE_L2_X75BUI
;
2253 if (profp
->support1
& (1<<2))
2254 card
->interface
.features
|= ISDN_FEATURE_L2_V11096
|
2255 ISDN_FEATURE_L2_V11019
|
2256 ISDN_FEATURE_L2_V11038
;
2257 if (profp
->support1
& (1<<8))
2258 card
->interface
.features
|= ISDN_FEATURE_L2_MODEM
;
2259 card
->interface
.hl_hdrlen
= 22; /* len of DATA_B3_REQ */
2260 strncpy(card
->interface
.id
, id
, sizeof(card
->interface
.id
) - 1);
2263 card
->q931_read
= card
->q931_buf
;
2264 card
->q931_write
= card
->q931_buf
;
2265 card
->q931_end
= card
->q931_buf
+ sizeof(card
->q931_buf
) - 1;
2267 if (!register_isdn(&card
->interface
)) {
2268 printk(KERN_ERR
"capidrv: Unable to register contr %s\n", id
);
2269 kfree(card
->bchans
);
2274 card
->myid
= card
->interface
.channels
;
2276 spin_lock_irqsave(&global_lock
, flags
);
2277 card
->next
= global
.contr_list
;
2278 global
.contr_list
= card
;
2280 spin_unlock_irqrestore(&global_lock
, flags
);
2282 memset(card
->bchans
, 0, sizeof(capidrv_bchan
) * card
->nbchan
);
2283 for (i
= 0; i
< card
->nbchan
; i
++) {
2284 card
->bchans
[i
].contr
= card
;
2287 cmd
.command
= ISDN_STAT_RUN
;
2288 cmd
.driver
= card
->myid
;
2289 card
->interface
.statcallb(&cmd
);
2291 card
->cipmask
= 0x1FFF03FF; /* any */
2296 card
->listentimer
.data
= (unsigned long)card
;
2297 card
->listentimer
.function
= listentimerfunc
;
2298 mod_timer(&card
->listentimer
, jiffies
+ 60*HZ
);
2300 printk(KERN_INFO
"%s: now up (%d B channels)\n",
2301 card
->name
, card
->nbchan
);
2303 enable_dchannel_trace(card
);
2308 static int capidrv_delcontr(__u16 contr
)
2310 capidrv_contr
**pp
, *card
;
2311 unsigned long flags
;
2314 spin_lock_irqsave(&global_lock
, flags
);
2315 for (card
= global
.contr_list
; card
; card
= card
->next
) {
2316 if (card
->contrnr
== contr
)
2320 spin_unlock_irqrestore(&global_lock
, flags
);
2321 printk(KERN_ERR
"capidrv: delcontr: no contr %u\n", contr
);
2324 spin_unlock_irqrestore(&global_lock
, flags
);
2326 del_timer(&card
->listentimer
);
2329 printk(KERN_DEBUG
"capidrv-%d: id=%d unloading\n",
2330 card
->contrnr
, card
->myid
);
2332 cmd
.command
= ISDN_STAT_STOP
;
2333 cmd
.driver
= card
->myid
;
2334 card
->interface
.statcallb(&cmd
);
2336 while (card
->nbchan
) {
2338 cmd
.command
= ISDN_STAT_DISCH
;
2339 cmd
.driver
= card
->myid
;
2340 cmd
.arg
= card
->nbchan
-1;
2341 cmd
.parm
.num
[0] = 0;
2343 printk(KERN_DEBUG
"capidrv-%d: id=%d disable chan=%ld\n",
2344 card
->contrnr
, card
->myid
, cmd
.arg
);
2345 card
->interface
.statcallb(&cmd
);
2347 if (card
->bchans
[card
->nbchan
-1].nccip
)
2348 free_ncci(card
, card
->bchans
[card
->nbchan
-1].nccip
);
2349 if (card
->bchans
[card
->nbchan
-1].plcip
)
2350 free_plci(card
, card
->bchans
[card
->nbchan
-1].plcip
);
2351 if (card
->plci_list
)
2352 printk(KERN_ERR
"capidrv: bug in free_plci()\n");
2355 kfree(card
->bchans
);
2359 printk(KERN_DEBUG
"capidrv-%d: id=%d isdn unload\n",
2360 card
->contrnr
, card
->myid
);
2362 cmd
.command
= ISDN_STAT_UNLOAD
;
2363 cmd
.driver
= card
->myid
;
2364 card
->interface
.statcallb(&cmd
);
2367 printk(KERN_DEBUG
"capidrv-%d: id=%d remove contr from list\n",
2368 card
->contrnr
, card
->myid
);
2370 spin_lock_irqsave(&global_lock
, flags
);
2371 for (pp
= &global
.contr_list
; *pp
; pp
= &(*pp
)->next
) {
2379 spin_unlock_irqrestore(&global_lock
, flags
);
2381 printk(KERN_INFO
"%s: now down.\n", card
->name
);
2391 static void lower_callback(unsigned int cmd
, __u32 contr
, void *data
)
2396 printk(KERN_INFO
"capidrv: controller %hu up\n", contr
);
2397 (void) capidrv_addcontr(contr
, (capi_profile
*) data
);
2400 printk(KERN_INFO
"capidrv: controller %hu down\n", contr
);
2401 (void) capidrv_delcontr(contr
);
2407 * /proc/capi/capidrv:
2408 * nrecvctlpkt nrecvdatapkt nsendctlpkt nsenddatapkt
2410 static int proc_capidrv_read_proc(char *page
, char **start
, off_t off
,
2411 int count
, int *eof
, void *data
)
2415 len
+= sprintf(page
+len
, "%lu %lu %lu %lu\n",
2417 global
.nrecvdatapkt
,
2419 global
.nsentdatapkt
);
2420 if (off
+count
>= len
)
2424 *start
= page
+ off
;
2425 return ((count
< len
-off
) ? count
: len
-off
);
2428 static struct procfsentries
{
2431 int (*read_proc
)(char *page
, char **start
, off_t off
,
2432 int count
, int *eof
, void *data
);
2433 struct proc_dir_entry
*procent
;
2434 } procfsentries
[] = {
2435 /* { "capi", S_IFDIR, 0 }, */
2436 { "capi/capidrv", 0 , proc_capidrv_read_proc
},
2439 static void proc_init(void)
2441 int nelem
= sizeof(procfsentries
)/sizeof(procfsentries
[0]);
2444 for (i
=0; i
< nelem
; i
++) {
2445 struct procfsentries
*p
= procfsentries
+ i
;
2446 p
->procent
= create_proc_entry(p
->name
, p
->mode
, 0);
2447 if (p
->procent
) p
->procent
->read_proc
= p
->read_proc
;
2451 static void proc_exit(void)
2453 int nelem
= sizeof(procfsentries
)/sizeof(procfsentries
[0]);
2456 for (i
=nelem
-1; i
>= 0; i
--) {
2457 struct procfsentries
*p
= procfsentries
+ i
;
2459 remove_proc_entry(p
->name
, 0);
2465 static struct capi_interface_user cuser
= {
2471 #define capidrv_init init_module
2474 int capidrv_init(void)
2476 struct capi_register_params rparam
;
2477 capi_profile profile
;
2480 __u32 ncontr
, contr
;
2485 capifuncs
= attach_capi_interface(&cuser
);
2492 if ((p
= strchr(revision
, ':'))) {
2494 p
= strchr(rev
, '$');
2497 strcpy(rev
, " ??? ");
2499 rparam
.level3cnt
= -2; /* number of bchannels twice */
2500 rparam
.datablkcnt
= 16;
2501 rparam
.datablklen
= 2048;
2502 errcode
= (*capifuncs
->capi_register
) (&rparam
, &global
.appid
);
2504 detach_capi_interface(&cuser
);
2509 errcode
= (*capifuncs
->capi_get_profile
) (0, &profile
);
2510 if (errcode
!= CAPI_NOERROR
) {
2511 (void) (*capifuncs
->capi_release
) (global
.appid
);
2512 detach_capi_interface(&cuser
);
2517 (void) (*capifuncs
->capi_set_signal
) (global
.appid
, capidrv_signal
, 0);
2519 ncontr
= profile
.ncontroller
;
2520 for (contr
= 1; contr
<= ncontr
; contr
++) {
2521 errcode
= (*capifuncs
->capi_get_profile
) (contr
, &profile
);
2522 if (errcode
!= CAPI_NOERROR
)
2524 (void) capidrv_addcontr(contr
, &profile
);
2528 printk(KERN_NOTICE
"capidrv: Rev%s: loaded\n", rev
);
2535 void cleanup_module(void)
2540 if ((p
= strchr(revision
, ':')) != 0) {
2542 p
= strchr(rev
, '$');
2545 strcpy(rev
, " ??? ");
2548 (void) (*capifuncs
->capi_release
) (global
.appid
);
2550 detach_capi_interface(&cuser
);
2554 printk(KERN_NOTICE
"capidrv: Rev%s: unloaded\n", rev
);