1 /* $Id: isdn_common.c,v 1.101 2000/04/07 14:50:34 calle Exp $
3 * Linux ISDN subsystem, common used functions (linklevel).
5 * Copyright 1994-1999 by Fritz Elfert (fritz@isdn4linux.de)
6 * Copyright 1995,96 Thinking Objects Software GmbH Wuerzburg
7 * Copyright 1995,96 by Michael Hipp (Michael.Hipp@student.uni-tuebingen.de)
9 * This program is free software; you can redistribute it and/or modify
10 * it under the terms of the GNU General Public License as published by
11 * the Free Software Foundation; either version 2, or (at your option)
14 * This program is distributed in the hope that it will be useful,
15 * but WITHOUT ANY WARRANTY; without even the implied warranty of
16 * MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the
17 * GNU General Public License for more details.
19 * You should have received a copy of the GNU General Public License
20 * along with this program; if not, write to the Free Software
21 * Foundation, Inc., 675 Mass Ave, Cambridge, MA 02139, USA.
23 * $Log: isdn_common.c,v $
24 * Revision 1.101 2000/04/07 14:50:34 calle
25 * Bugfix: on my system 2.3.99-pre3 Dual PII 350, unload of module isdn.o
26 * hangs if vfree is called with interrupt disabled. After moving
27 * restore_flags in front of vfree it doesn't hang.
29 * Revision 1.100 2000/03/03 16:37:11 kai
30 * incorporated some cosmetic changes from the official kernel tree back
33 * Revision 1.99 2000/02/26 01:00:52 keil
36 * Revision 1.98 2000/02/16 14:56:27 paul
37 * translated ISDN_MODEM_ANZREG to ISDN_MODEM_NUMREG for english speakers
39 * Revision 1.97 2000/01/23 18:45:37 keil
40 * Change EAZ mapping to forbit the use of cards (insert a "-" for the MSN)
42 * Revision 1.96 2000/01/20 19:55:33 keil
43 * Add FAX Class 1 support
45 * Revision 1.95 2000/01/09 20:43:13 detabc
46 * exand logical bind-group's for both call's (in and out).
47 * add first part of kernel-config-help for abc-extension.
49 * Revision 1.94 1999/11/20 22:14:13 detabc
50 * added channel dial-skip in case of external use
51 * (isdn phone or another isdn device) on the same NTBA.
52 * usefull with two or more card's connected the different NTBA's.
53 * global switchable in kernel-config and also per netinterface.
55 * add auto disable of netinterface's in case of:
56 * to many connection's in short time.
57 * config mistakes (wrong encapsulation, B2-protokoll or so on) on local
59 * wrong password's or something else to a ISP (syncppp).
61 * possible encapsulations for this future are:
62 * ISDN_NET_ENCAP_SYNCPPP, ISDN_NET_ENCAP_UIHDLC, ISDN_NET_ENCAP_RAWIP,
63 * and ISDN_NET_ENCAP_CISCOHDLCK.
65 * Revision 1.93 1999/11/04 13:11:36 keil
66 * Reinit of v110 structs
68 * Revision 1.92 1999/10/31 15:59:50 he
69 * more skb headroom checks
71 * Revision 1.91 1999/10/28 22:48:45 armin
72 * Bugfix: isdn_free_channel() now frees the channel,
73 * even when the usage of the ttyI has changed.
75 * Revision 1.90 1999/10/27 21:21:17 detabc
76 * Added support for building logically-bind-group's per interface.
77 * usefull for outgoing call's with more then one isdn-card.
79 * Switchable support to dont reset the hangup-timeout for
80 * receive frames. Most part's of the timru-rules for receiving frames
81 * are now obsolete. If the input- or forwarding-firewall deny
82 * the frame, the line will be not hold open.
84 * Revision 1.89 1999/10/16 14:46:47 keil
85 * replace kmalloc with vmalloc for the big dev struct
87 * Revision 1.88 1999/10/02 00:39:26 he
88 * Fixed a 2.3.x wait queue initialization (was causing panics)
90 * Revision 1.87 1999/09/12 16:19:39 detabc
92 * low cost routing for net-interfaces (only the HL side).
93 * need more implementation in the isdnlog-utility
94 * udp info support (first part).
95 * different EAZ on outgoing call's.
96 * more checks on D-Channel callbacks (double use of channels).
97 * tested and running with kernel 2.3.17
99 * Revision 1.86 1999/07/31 12:59:42 armin
100 * Added tty fax capabilities.
102 * Revision 1.85 1999/07/29 16:58:35 armin
103 * Bugfix: DLE handling in isdn_readbchan()
105 * Revision 1.84 1999/07/25 16:21:10 keil
106 * fix number matching
108 * Revision 1.83 1999/07/13 21:02:05 werner
109 * Added limit possibilty of driver b_channel resources (ISDN_STAT_DISCH)
111 * Revision 1.82 1999/07/12 21:06:50 werner
112 * Fixed problem when loading more than one driver temporary
114 * Revision 1.81 1999/07/11 17:14:09 armin
115 * Added new layer 2 and 3 protocols for Fax and DSP functions.
116 * Moved "Add CPN to RING message" to new register S23,
117 * "Display message" is now correct on register S13 bit 7.
118 * New audio command AT+VDD implemented (deactivate DTMF decoder and
119 * activate possible existing hardware/DSP decoder).
120 * Moved some tty defines to .h file.
121 * Made whitespace possible in AT command line.
122 * Some AT-emulator output bugfixes.
123 * First Fax G3 implementations.
125 * Revision 1.80 1999/07/07 10:14:00 detabc
126 * remove unused messages
128 * Revision 1.79 1999/07/05 23:51:30 werner
129 * Allow limiting of available HiSax B-chans per card. Controlled by hisaxctrl
130 * hisaxctrl id 10 <nr. of chans 0-2>
132 * Revision 1.78 1999/07/05 20:21:15 werner
133 * changes to use diversion sources for all kernel versions.
134 * removed static device, only proc filesystem used
136 * Revision 1.77 1999/07/01 08:29:50 keil
137 * compatibility to 2.3 kernel
139 * Revision 1.76 1999/06/29 16:16:44 calle
140 * Let ISDN_CMD_UNLOAD work with open isdn devices without crash again.
141 * Also right unlocking (ISDN_CMD_UNLOCK) is done now.
142 * isdnlog should check returncode of read(2) calls.
144 * Revision 1.75 1999/04/18 14:06:47 fritz
145 * Removed TIMRU stuff.
147 * Revision 1.74 1999/04/12 13:16:45 fritz
148 * Changes from 2.0 tree.
150 * Revision 1.73 1999/04/12 12:33:15 fritz
151 * Changes from 2.0 tree.
153 * Revision 1.72 1999/03/02 12:04:44 armin
154 * -added ISDN_STAT_ADDCH to increase supported channels after
156 * -ttyI now goes on-hook on ATZ when B-Ch is connected.
157 * -added timer-function for register S7 (Wait for Carrier).
158 * -analog modem (ISDN_PROTO_L2_MODEM) implementations.
159 * -on L2_MODEM a string will be appended to the CONNECT-Message,
160 * which is provided by the HL-Driver in parm.num in ISDN_STAT_BCONN.
161 * -variable "dialing" used for ATA also, for interrupting call
162 * establishment and register S7.
164 * Revision 1.71 1999/01/28 09:10:43 armin
165 * Fixed bad while-loop in isdn_readbch().
167 * Revision 1.70 1999/01/15 19:58:54 he
168 * removed compatibiltity macro
170 * Revision 1.69 1998/09/07 21:59:58 he
171 * flush method for 2.1.118 and above
172 * updated IIOCTLNETGPN
174 * Revision 1.68 1998/08/31 21:09:45 he
175 * new ioctl IIOCNETGPN for /dev/isdninfo (get network interface'
178 * Revision 1.67 1998/06/26 15:12:21 fritz
179 * Added handling of STAT_ICALL with incomplete CPN.
180 * Added AT&L for ttyI emulator.
181 * Added more locking stuff in tty_write.
183 * Revision 1.66 1998/06/17 19:50:41 he
184 * merged with 2.1.10[34] (cosmetics and udelay() -> mdelay())
185 * brute force fix to avoid Ugh's in isdn_tty_write()
186 * cleaned up some dead code
189 * Revision 1.62 1998/04/14 16:28:43 he
190 * Fixed user space access with interrupts off and remaining
191 * copy_{to,from}_user() -> -EFAULT return codes
193 * Revision 1.61 1998/03/22 18:50:46 hipp
194 * Added BSD Compression for syncPPP .. UNTESTED at the moment
196 * Revision 1.60 1998/03/19 13:18:18 keil
197 * Start of a CAPI like interface for supplementary Service
198 * first service: SUSPEND
200 * Revision 1.59 1998/03/09 17:46:23 he
201 * merged in 2.1.89 changes
203 * Revision 1.58 1998/03/07 22:35:24 fritz
204 * Starting generic module support (Nothing usable yet).
206 * Revision 1.57 1998/03/07 18:21:01 cal
207 * Dynamic Timeout-Rule-Handling vs. 971110 included
209 * Revision 1.56 1998/02/25 17:49:38 he
210 * Changed return codes caused be failing copy_{to,from}_user to -EFAULT
212 * Revision 1.55 1998/02/23 23:35:32 fritz
213 * Eliminated some compiler warnings.
215 * Revision 1.54 1998/02/22 19:44:19 fritz
216 * Bugfixes and improvements regarding V.110, V.110 now running.
218 * Revision 1.53 1998/02/20 17:18:05 fritz
219 * Changes for recent kernels.
220 * Added common stub for sending commands to lowlevel.
223 * Revision 1.52 1998/01/31 22:05:57 keil
224 * Lots of changes for X.25 support:
225 * Added generic support for connection-controlling encapsulation protocols
226 * Added support of BHUP status message
227 * Added support for additional p_encap X25IFACE
228 * Added support for kernels >= 2.1.72
230 * Revision 1.51 1998/01/31 19:17:29 calle
231 * merged changes from and for 2.1.82
233 * Revision 1.50 1997/12/12 06:12:11 calle
234 * moved EXPORT_SYMBOL(register_isdn) from isdn_syms.c to isdn_common.c
236 * Revision 1.49 1997/11/06 17:16:52 keil
237 * Sync to 2.1.62 changes
239 * Revision 1.48 1997/11/02 23:55:50 keil
240 * Andi Kleen's changes for 2.1.60
241 * without it the isdninfo and isdnctrl devices won't work
243 * Revision 1.47 1997/10/09 21:28:46 fritz
244 * New HL<->LL interface:
245 * New BSENT callback with nr. of bytes included.
246 * Sending without ACK.
247 * New L1 error status (not yet in use).
248 * Cleaned up obsolete structures.
249 * Implemented Cisco-SLARP.
250 * Changed local net-interface data to be dynamically allocated.
251 * Removed old 2.0 compatibility stuff.
253 * Revision 1.46 1997/10/01 09:20:27 fritz
254 * Removed old compatibility stuff for 2.0.X kernels.
255 * From now on, this code is for 2.1.X ONLY!
256 * Old stuff is still in the separate branch.
258 * Revision 1.45 1997/08/21 23:11:41 fritz
259 * Added changes for kernels >= 2.1.45
261 * Revision 1.44 1997/05/27 15:17:23 fritz
262 * Added changes for recent 2.1.x kernels:
263 * changed return type of isdn_close
264 * queue_task_* -> queue_task
265 * clear/set_bit -> test_and_... where apropriate.
266 * changed type of hard_header_cache parameter.
268 * Revision 1.43 1997/03/31 14:09:43 fritz
269 * Fixed memory leak in isdn_close().
271 * Revision 1.42 1997/03/30 16:51:08 calle
272 * changed calls to copy_from_user/copy_to_user and removed verify_area
275 * Revision 1.41 1997/03/24 22:54:41 fritz
276 * Some small fixes in debug code.
278 * Revision 1.40 1997/03/08 08:13:51 fritz
279 * Bugfix: IIOCSETMAP (Set mapping) was broken.
281 * Revision 1.39 1997/03/07 01:32:54 fritz
282 * Added proper ifdef's for CONFIG_ISDN_AUDIO
284 * Revision 1.38 1997/03/05 21:15:02 fritz
285 * Fix: reduced stack usage of isdn_ioctl() and isdn_set_allcfg()
287 * Revision 1.37 1997/03/02 14:29:18 fritz
288 * More ttyI related cleanup.
290 * Revision 1.36 1997/02/28 02:32:40 fritz
291 * Cleanup: Moved some tty related stuff from isdn_common.c
293 * Bugfix: Bisync protocol did not behave like documented.
295 * Revision 1.35 1997/02/21 13:01:19 fritz
296 * Changes CAUSE message output in kernel log.
298 * Revision 1.34 1997/02/10 20:12:43 fritz
299 * Changed interface for reporting incoming calls.
301 * Revision 1.33 1997/02/10 10:05:42 fritz
302 * More changes for Kernel 2.1.X
303 * Symbol information moved to isdn_syms.c
305 * Revision 1.32 1997/02/03 22:55:26 fritz
306 * Reformatted according CodingStyle.
307 * Changed isdn_writebuf_stub static.
308 * Slow down tty-RING counter.
309 * skb->free stuff replaced by macro.
310 * Bugfix in audio-skb locking.
311 * Bugfix in HL-driver locking.
313 * Revision 1.31 1997/01/17 01:19:18 fritz
314 * Applied chargeint patch.
316 * Revision 1.30 1997/01/14 01:27:47 fritz
317 * Changed audio receive not to rely on skb->users and skb->lock.
318 * Added ATI2 and related variables.
319 * Started adding full-duplex audio capability.
321 * Revision 1.29 1997/01/12 23:33:03 fritz
322 * Made isdn_all_eaz foolproof.
324 * Revision 1.28 1996/11/13 02:33:19 fritz
325 * Fixed a race condition.
327 * Revision 1.27 1996/10/27 22:02:41 keil
328 * return codes for ISDN_STAT_ICALL
330 * Revision 1.26 1996/10/23 11:59:40 fritz
331 * More compatibility changes.
333 * Revision 1.25 1996/10/22 23:13:54 fritz
334 * Changes for compatibility to 2.0.X and 2.1.X kernels.
336 * Revision 1.24 1996/10/11 14:02:03 fritz
337 * Bugfix: call to isdn_ppp_timer_timeout() never compiled, because of
340 * Revision 1.23 1996/06/25 18:35:38 fritz
341 * Fixed bogus memory access in isdn_set_allcfg().
343 * Revision 1.22 1996/06/24 17:37:37 fritz
344 * Bugfix: isdn_timer_ctrl() did restart timer, even if it
345 * was already running.
346 * lowlevel driver locking did use wrong parameters.
348 * Revision 1.21 1996/06/15 14:58:20 fritz
349 * Added version signatures for data structures used
350 * by userlevel programs.
352 * Revision 1.20 1996/06/12 16:01:49 fritz
353 * Bugfix: Remote B-channel hangup sometimes did not result
354 * in a NO CARRIER on tty.
356 * Revision 1.19 1996/06/11 14:52:04 hipp
357 * minor bugfix in isdn_writebuf_skb_stub()
359 * Revision 1.18 1996/06/06 14:51:51 fritz
360 * Changed to support DTMF decoding on audio playback also.
362 * Revision 1.17 1996/06/05 02:24:10 fritz
363 * Added DTMF decoder for audio mode.
365 * Revision 1.16 1996/06/03 20:09:05 fritz
366 * Bugfix: called wrong function pointer for locking in
367 * isdn_get_free_channel().
369 * Revision 1.15 1996/05/31 01:10:54 fritz
371 * Lowlevel modules did not get locked correctly.
372 * Did show wrong revision when initializing.
373 * Minor fixes in ioctl code.
374 * sk_buff did not get freed, if error in writebuf_stub.
376 * Revision 1.14 1996/05/18 01:36:55 fritz
377 * Added spelling corrections and some minor changes
378 * to stay in sync with kernel.
380 * Revision 1.13 1996/05/17 15:43:30 fritz
381 * Bugfix: decrement of rcvcount in readbchan() corrected.
383 * Revision 1.12 1996/05/17 03:55:43 fritz
384 * Changed DLE handling for audio receive.
386 * Added display of isdn_audio_revision.
388 * Revision 1.11 1996/05/11 21:51:32 fritz
389 * Changed queue management to use sk_buffs.
391 * Revision 1.10 1996/05/10 08:49:16 fritz
392 * Checkin before major changes of tty-code.
394 * Revision 1.9 1996/05/07 09:19:41 fritz
395 * Adapted to changes in isdn_tty.c
397 * Revision 1.8 1996/05/06 11:34:51 hipp
400 * Revision 1.7 1996/05/02 03:55:17 fritz
402 * - B-channel connect message for modem devices
403 * sometimes did not result in a CONNECT-message.
404 * - register_isdn did not check for driverId-conflicts.
406 * Revision 1.6 1996/04/30 20:57:21 fritz
409 * Revision 1.5 1996/04/20 16:19:07 fritz
410 * Changed slow timer handlers to increase accuracy.
411 * Added statistic information for usage by xisdnload.
412 * Fixed behaviour of isdnctrl-device on non-blocked io.
413 * Fixed all io to go through generic writebuf-function without
414 * bypassing. Same for incoming data.
415 * Fixed bug: Last channel had been unusable.
416 * Fixed kfree of tty xmit_buf on ppp initialization failure.
418 * Revision 1.4 1996/02/11 02:33:26 fritz
419 * Fixed bug in main timer-dispatcher.
420 * Bugfix: Lot of tty-callbacks got called regardless of the events already
421 * been handled by network-devices.
422 * Changed ioctl-names.
424 * Revision 1.3 1996/01/22 05:16:11 fritz
425 * Changed ioctl-names.
426 * Fixed bugs in isdn_open and isdn_close regarding PPP_MINOR.
428 * Revision 1.2 1996/01/21 16:52:40 fritz
429 * Support for sk_buffs added, changed header-stuffing.
431 * Revision 1.1 1996/01/09 04:12:52 fritz
436 #include <linux/config.h>
437 #include <linux/module.h>
438 #include <linux/version.h>
439 #include <linux/poll.h>
440 #include <linux/vmalloc.h>
441 #include <linux/isdn.h>
442 #include "isdn_common.h"
443 #include "isdn_tty.h"
444 #include "isdn_net.h"
445 #include "isdn_ppp.h"
446 #ifdef CONFIG_ISDN_AUDIO
447 #include "isdn_audio.h"
449 #ifdef CONFIG_ISDN_DIVERSION
450 #include <linux/isdn_divertif.h>
451 #endif CONFIG_ISDN_DIVERSION
452 #include "isdn_v110.h"
453 #include "isdn_cards.h"
454 #include <linux/devfs_fs_kernel.h>
457 #undef ISDN_DEBUG_STATCALLB
459 isdn_dev
*dev
= (isdn_dev
*) 0;
461 static char *isdn_revision
= "$Revision: 1.101 $";
463 extern char *isdn_net_revision
;
464 extern char *isdn_tty_revision
;
465 #ifdef CONFIG_ISDN_PPP
466 extern char *isdn_ppp_revision
;
468 static char *isdn_ppp_revision
= ": none $";
470 #ifdef CONFIG_ISDN_AUDIO
471 extern char *isdn_audio_revision
;
473 static char *isdn_audio_revision
= ": none $";
475 extern char *isdn_v110_revision
;
477 #ifdef CONFIG_ISDN_DIVERSION
478 isdn_divert_if
*divert_if
= NULL
; /* interface to diversion module */
479 #endif CONFIG_ISDN_DIVERSION
482 static int isdn_writebuf_stub(int, int, const u_char
*, int, int);
483 static void set_global_features(void);
484 static void isdn_register_devfs(int);
485 static void isdn_unregister_devfs(int);
488 isdn_MOD_INC_USE_COUNT(void)
493 for (i
= 0; i
< dev
->drivers
; i
++) {
498 cmd
.command
= ISDN_CMD_LOCK
;
500 dev
->drv
[i
]->locks
++;
505 isdn_MOD_DEC_USE_COUNT(void)
510 for (i
= 0; i
< dev
->drivers
; i
++)
511 if (dev
->drv
[i
]->locks
> 0) {
516 cmd
.command
= ISDN_CMD_UNLOCK
;
518 dev
->drv
[i
]->locks
--;
522 #if defined(ISDN_DEBUG_NET_DUMP) || defined(ISDN_DEBUG_MODEM_DUMP)
524 isdn_dumppkt(char *s
, u_char
* p
, int len
, int dumplen
)
528 printk(KERN_DEBUG
"%s(%d) ", s
, len
);
529 for (dumpc
= 0; (dumpc
< dumplen
) && (len
); len
--, dumpc
++)
530 printk(" %02x", *p
++);
536 * I picked the pattern-matching-functions from an old GNU-tar version (1.10)
537 * It was originally written and put to PD by rs@mirror.TMC.COM (Rich Salz)
540 isdn_star(char *s
, char *p
)
542 while (isdn_wildmat(s
, p
)) {
550 * Shell-type Pattern-matching for incoming caller-Ids
551 * This function gets a string in s and checks, if it matches the pattern
557 * 2 = no match. Would eventually match, if s would be longer.
561 * '?' matches one character
562 * '*' matches zero or more characters
563 * [xyz] matches the set of characters in brackets.
564 * [^xyz] matches any single character not in the set of characters
568 isdn_wildmat(char *s
, char *p
)
571 register int matched
;
572 register int reverse
;
573 register int nostar
= 1;
581 * Literal match with following character,
587 return (*s
== '\0')?2:1;
590 /* Match anything. */
596 /* Trailing star matches everything. */
597 return (*++p
? isdn_star(s
, p
) : 0);
599 /* [^....] means inverse character class. */
600 if ((reverse
= (p
[1] == '^')))
602 for (last
= 0, matched
= 0; *++p
&& (*p
!= ']'); last
= *p
)
603 /* This next line requires a good C compiler. */
604 if (*p
== '-' ? *s
<= *++p
&& *s
>= last
: *s
== *p
)
606 if (matched
== reverse
)
610 return (*s
== '\0')?0:nostar
;
614 isdn_free_queue(struct sk_buff_head
*queue
)
621 if (skb_queue_len(queue
))
622 while ((skb
= skb_dequeue(queue
)))
624 restore_flags(flags
);
628 isdn_dc2minor(int di
, int ch
)
631 for (i
= 0; i
< ISDN_MAX_CHANNELS
; i
++)
632 if (dev
->chanmap
[i
] == ch
&& dev
->drvmap
[i
] == di
)
637 static int isdn_timer_cnt1
= 0;
638 static int isdn_timer_cnt2
= 0;
639 static int isdn_timer_cnt3
= 0;
640 static int isdn_timer_cnt4
= 0;
643 isdn_timer_funct(ulong dummy
)
645 int tf
= dev
->tflags
;
646 if (tf
& ISDN_TIMER_FAST
) {
647 if (tf
& ISDN_TIMER_MODEMREAD
)
648 isdn_tty_readmodem();
649 if (tf
& ISDN_TIMER_MODEMPLUS
)
650 isdn_tty_modem_escape();
651 if (tf
& ISDN_TIMER_MODEMXMIT
)
652 isdn_tty_modem_xmit();
654 if (tf
& ISDN_TIMER_SLOW
) {
655 if (++isdn_timer_cnt1
>= ISDN_TIMER_02SEC
) {
657 if (tf
& ISDN_TIMER_NETDIAL
)
660 if (++isdn_timer_cnt2
>= ISDN_TIMER_1SEC
) {
662 if (tf
& ISDN_TIMER_NETHANGUP
)
664 if (++isdn_timer_cnt3
> ISDN_TIMER_RINGING
) {
666 if (tf
& ISDN_TIMER_MODEMRING
)
667 isdn_tty_modem_ring();
669 if (++isdn_timer_cnt4
> ISDN_TIMER_KEEPINT
) {
671 if (tf
& ISDN_TIMER_KEEPALIVE
)
672 isdn_net_slarp_out();
674 if (tf
& ISDN_TIMER_CARRIER
)
675 isdn_tty_carrier_timeout();
676 #if (defined CONFIG_ISDN_PPP) && (defined CONFIG_ISDN_MPP)
677 if (tf
& ISDN_TIMER_IPPP
)
678 isdn_ppp_timer_timeout();
688 mod_timer(&dev
->timer
, jiffies
+ISDN_TIMER_RES
);
689 restore_flags(flags
);
694 isdn_timer_ctrl(int tf
, int onoff
)
700 if ((tf
& ISDN_TIMER_SLOW
) && (!(dev
->tflags
& ISDN_TIMER_SLOW
))) {
701 /* If the slow-timer wasn't activated until now */
710 mod_timer(&dev
->timer
, jiffies
+ISDN_TIMER_RES
);
711 restore_flags(flags
);
715 * Receive a packet from B-Channel. (Called from low-level-module)
718 isdn_receive_skb_callback(int di
, int channel
, struct sk_buff
*skb
)
722 if ((i
= isdn_dc2minor(di
, channel
)) == -1) {
726 /* Update statistics */
727 dev
->ibytes
[i
] += skb
->len
;
729 /* First, try to deliver data to network-device */
730 if (isdn_net_rcv_skb(i
, skb
))
734 * makes sense for async streams only, so it is
735 * called after possible net-device delivery.
738 atomic_inc(&dev
->v110use
[i
]);
739 skb
= isdn_v110_decode(dev
->v110
[i
], skb
);
740 atomic_dec(&dev
->v110use
[i
]);
745 /* No network-device found, deliver to tty or raw-channel */
747 if (isdn_tty_rcv_skb(i
, di
, channel
, skb
))
749 wake_up_interruptible(&dev
->drv
[di
]->rcv_waitq
[channel
]);
755 * Intercept command from Linklevel to Lowlevel.
756 * If layer 2 protocol is V.110 and this is not supported by current
757 * lowlevel-driver, use driver's transparent mode and handle V.110 in
761 isdn_command(isdn_ctrl
*cmd
)
763 if (cmd
->driver
== -1) {
764 printk(KERN_WARNING
"isdn_command command(%x) driver -1\n", cmd
->command
);
767 if (cmd
->command
== ISDN_CMD_SETL2
) {
768 int idx
= isdn_dc2minor(cmd
->driver
, cmd
->arg
& 255);
769 unsigned long l2prot
= (cmd
->arg
>> 8) & 255;
770 unsigned long features
= (dev
->drv
[cmd
->driver
]->interface
->features
771 >> ISDN_FEATURE_L2_SHIFT
) &
772 ISDN_FEATURE_L2_MASK
;
773 unsigned long l2_feature
= (1 << l2prot
);
776 case ISDN_PROTO_L2_V11096
:
777 case ISDN_PROTO_L2_V11019
:
778 case ISDN_PROTO_L2_V11038
:
779 /* If V.110 requested, but not supported by
780 * HL-driver, set emulator-flag and change
781 * Layer-2 to transparent
783 if (!(features
& l2_feature
)) {
784 dev
->v110emu
[idx
] = l2prot
;
785 cmd
->arg
= (cmd
->arg
& 255) |
786 (ISDN_PROTO_L2_TRANS
<< 8);
788 dev
->v110emu
[idx
] = 0;
791 return dev
->drv
[cmd
->driver
]->interface
->command(cmd
);
795 isdn_all_eaz(int di
, int ch
)
803 cmd
.command
= ISDN_CMD_SETEAZ
;
804 cmd
.parm
.num
[0] = '\0';
809 * Begin of a CAPI like LL<->HL interface, currently used only for
810 * supplementary service (CAPI 2.0 part III)
812 #include "avmb1/capicmd.h" /* this should be moved in a common place */
815 isdn_capi_rec_hl_msg(capi_msg
*cm
) {
820 di
= (cm
->adr
.Controller
& 0x7f) -1;
821 ch
= isdn_dc2minor(di
, (cm
->adr
.Controller
>>8)& 0x7f);
822 switch(cm
->Command
) {
824 /* in the moment only handled in tty */
825 return(isdn_tty_capi_facility(cm
));
832 isdn_status_callback(isdn_ctrl
* c
)
842 i
= isdn_dc2minor(di
, c
->arg
);
843 switch (c
->command
) {
844 case ISDN_STAT_BSENT
:
847 if (dev
->global_flags
& ISDN_GLOBAL_STOPPED
)
849 if (isdn_net_stat_callback(i
, c
))
851 if (isdn_v110_stat_callback(i
, c
))
853 if (isdn_tty_stat_callback(i
, c
))
855 wake_up_interruptible(&dev
->drv
[di
]->snd_waitq
[c
->arg
]);
857 case ISDN_STAT_STAVAIL
:
860 dev
->drv
[di
]->stavail
+= c
->arg
;
861 restore_flags(flags
);
862 wake_up_interruptible(&dev
->drv
[di
]->st_waitq
);
865 dev
->drv
[di
]->flags
|= DRV_FLAG_RUNNING
;
866 for (i
= 0; i
< ISDN_MAX_CHANNELS
; i
++)
867 if (dev
->drvmap
[i
] == di
)
868 isdn_all_eaz(di
, dev
->chanmap
[i
]);
869 set_global_features();
872 dev
->drv
[di
]->flags
&= ~DRV_FLAG_RUNNING
;
874 case ISDN_STAT_ICALL
:
877 #ifdef ISDN_DEBUG_STATCALLB
878 printk(KERN_DEBUG
"ICALL (net): %d %ld %s\n", di
, c
->arg
, c
->parm
.num
);
880 if (dev
->global_flags
& ISDN_GLOBAL_STOPPED
) {
883 cmd
.command
= ISDN_CMD_HANGUP
;
887 /* Try to find a network-interface which will accept incoming call */
888 r
= ((c
->command
== ISDN_STAT_ICALLW
) ? 0 : isdn_net_find_icall(di
, c
->arg
, i
, c
->parm
.setup
));
891 /* No network-device replies.
893 * These return 0 on no match, 1 on match and
894 * 3 on eventually match, if CID is longer.
896 if (c
->command
== ISDN_STAT_ICALL
)
897 if ((retval
= isdn_tty_find_icall(di
, c
->arg
, c
->parm
.setup
))) return(retval
);
898 #ifdef CONFIG_ISDN_DIVERSION
900 if ((retval
= divert_if
->stat_callback(c
)))
901 return(retval
); /* processed */
902 #endif CONFIG_ISDN_DIVERSION
903 if ((!retval
) && (dev
->drv
[di
]->flags
& DRV_FLAG_REJBUS
)) {
904 /* No tty responding */
907 cmd
.command
= ISDN_CMD_HANGUP
;
913 /* Schedule connection-setup */
917 cmd
.command
= ISDN_CMD_ACCEPTD
;
921 case 2: /* For calling back, first reject incoming call ... */
922 case 3: /* Interface found, but down, reject call actively */
924 printk(KERN_INFO
"isdn: Rejecting Call\n");
927 cmd
.command
= ISDN_CMD_HANGUP
;
933 /* ... then start callback. */
937 /* Number would eventually match, if longer */
941 #ifdef ISDN_DEBUG_STATCALLB
942 printk(KERN_DEBUG
"ICALL: ret=%d\n", retval
);
949 #ifdef ISDN_DEBUG_STATCALLB
950 printk(KERN_DEBUG
"CINF: %ld %s\n", c
->arg
, c
->parm
.num
);
952 if (dev
->global_flags
& ISDN_GLOBAL_STOPPED
)
954 if (strcmp(c
->parm
.num
, "0"))
955 isdn_net_stat_callback(i
, c
);
956 isdn_tty_stat_callback(i
, c
);
958 case ISDN_STAT_CAUSE
:
959 #ifdef ISDN_DEBUG_STATCALLB
960 printk(KERN_DEBUG
"CAUSE: %ld %s\n", c
->arg
, c
->parm
.num
);
962 printk(KERN_INFO
"isdn: %s,ch%ld cause: %s\n",
963 dev
->drvid
[di
], c
->arg
, c
->parm
.num
);
964 isdn_tty_stat_callback(i
, c
);
965 #ifdef CONFIG_ISDN_DIVERSION
967 divert_if
->stat_callback(c
);
968 #endif CONFIG_ISDN_DIVERSION
970 case ISDN_STAT_DISPLAY
:
971 #ifdef ISDN_DEBUG_STATCALLB
972 printk(KERN_DEBUG
"DISPLAY: %ld %s\n", c
->arg
, c
->parm
.display
);
974 isdn_tty_stat_callback(i
, c
);
975 #ifdef CONFIG_ISDN_DIVERSION
977 divert_if
->stat_callback(c
);
978 #endif CONFIG_ISDN_DIVERSION
980 case ISDN_STAT_DCONN
:
983 #ifdef ISDN_DEBUG_STATCALLB
984 printk(KERN_DEBUG
"DCONN: %ld\n", c
->arg
);
986 if (dev
->global_flags
& ISDN_GLOBAL_STOPPED
)
988 /* Find any net-device, waiting for D-channel setup */
989 if (isdn_net_stat_callback(i
, c
))
991 isdn_v110_stat_callback(i
, c
);
992 /* Find any ttyI, waiting for D-channel setup */
993 if (isdn_tty_stat_callback(i
, c
)) {
996 cmd
.command
= ISDN_CMD_ACCEPTB
;
1001 case ISDN_STAT_DHUP
:
1004 #ifdef ISDN_DEBUG_STATCALLB
1005 printk(KERN_DEBUG
"DHUP: %ld\n", c
->arg
);
1007 if (dev
->global_flags
& ISDN_GLOBAL_STOPPED
)
1009 dev
->drv
[di
]->online
&= ~(1 << (c
->arg
));
1011 /* Signal hangup to network-devices */
1012 if (isdn_net_stat_callback(i
, c
))
1014 isdn_v110_stat_callback(i
, c
);
1015 if (isdn_tty_stat_callback(i
, c
))
1017 #ifdef CONFIG_ISDN_DIVERSION
1019 divert_if
->stat_callback(c
);
1020 #endif CONFIG_ISDN_DIVERSION
1023 case ISDN_STAT_BCONN
:
1026 #ifdef ISDN_DEBUG_STATCALLB
1027 printk(KERN_DEBUG
"BCONN: %ld\n", c
->arg
);
1029 /* Signal B-channel-connect to network-devices */
1030 if (dev
->global_flags
& ISDN_GLOBAL_STOPPED
)
1032 dev
->drv
[di
]->online
|= (1 << (c
->arg
));
1034 if (isdn_net_stat_callback(i
, c
))
1036 isdn_v110_stat_callback(i
, c
);
1037 if (isdn_tty_stat_callback(i
, c
))
1040 case ISDN_STAT_BHUP
:
1043 #ifdef ISDN_DEBUG_STATCALLB
1044 printk(KERN_DEBUG
"BHUP: %ld\n", c
->arg
);
1046 if (dev
->global_flags
& ISDN_GLOBAL_STOPPED
)
1048 dev
->drv
[di
]->online
&= ~(1 << (c
->arg
));
1050 #ifdef CONFIG_ISDN_X25
1051 /* Signal hangup to network-devices */
1052 if (isdn_net_stat_callback(i
, c
))
1055 isdn_v110_stat_callback(i
, c
);
1056 if (isdn_tty_stat_callback(i
, c
))
1059 case ISDN_STAT_NODCH
:
1062 #ifdef ISDN_DEBUG_STATCALLB
1063 printk(KERN_DEBUG
"NODCH: %ld\n", c
->arg
);
1065 if (dev
->global_flags
& ISDN_GLOBAL_STOPPED
)
1067 if (isdn_net_stat_callback(i
, c
))
1069 if (isdn_tty_stat_callback(i
, c
))
1072 case ISDN_STAT_ADDCH
:
1073 if (isdn_add_channels(dev
->drv
[di
], di
, c
->arg
, 1))
1077 case ISDN_STAT_DISCH
:
1080 for (i
= 0; i
< ISDN_MAX_CHANNELS
; i
++)
1081 if ((dev
->drvmap
[i
] == di
) &&
1082 (dev
->chanmap
[i
] == c
->arg
)) {
1084 dev
->usage
[i
] &= ~ISDN_USAGE_DISABLED
;
1086 if (USG_NONE(dev
->usage
[i
])) {
1087 dev
->usage
[i
] |= ISDN_USAGE_DISABLED
;
1093 restore_flags(flags
);
1096 case ISDN_STAT_UNLOAD
:
1097 while (dev
->drv
[di
]->locks
> 0) {
1101 cmd
.command
= ISDN_CMD_UNLOCK
;
1103 dev
->drv
[di
]->locks
--;
1107 isdn_tty_stat_callback(i
, c
);
1108 for (i
= 0; i
< ISDN_MAX_CHANNELS
; i
++)
1109 if (dev
->drvmap
[i
] == di
) {
1110 dev
->drvmap
[i
] = -1;
1111 dev
->chanmap
[i
] = -1;
1112 dev
->usage
[i
] &= ~ISDN_USAGE_DISABLED
;
1113 isdn_unregister_devfs(i
);
1116 dev
->channels
-= dev
->drv
[di
]->channels
;
1117 kfree(dev
->drv
[di
]->rcverr
);
1118 kfree(dev
->drv
[di
]->rcvcount
);
1119 for (i
= 0; i
< dev
->drv
[di
]->channels
; i
++)
1120 isdn_free_queue(&dev
->drv
[di
]->rpqueue
[i
]);
1121 kfree(dev
->drv
[di
]->rpqueue
);
1122 kfree(dev
->drv
[di
]->rcv_waitq
);
1123 kfree(dev
->drv
[di
]);
1124 dev
->drv
[di
] = NULL
;
1125 dev
->drvid
[di
][0] = '\0';
1127 set_global_features();
1128 restore_flags(flags
);
1130 case ISDN_STAT_L1ERR
:
1132 case CAPI_PUT_MESSAGE
:
1133 return(isdn_capi_rec_hl_msg(&c
->parm
.cmsg
));
1134 #ifdef CONFIG_ISDN_TTY_FAX
1135 case ISDN_STAT_FAXIND
:
1136 isdn_tty_stat_callback(i
, c
);
1139 #ifdef CONFIG_ISDN_AUDIO
1140 case ISDN_STAT_AUDIO
:
1141 isdn_tty_stat_callback(i
, c
);
1144 #ifdef CONFIG_ISDN_DIVERSION
1145 case ISDN_STAT_PROT
:
1146 case ISDN_STAT_REDIR
:
1148 return(divert_if
->stat_callback(c
));
1149 #endif CONFIG_ISDN_DIVERSION
1157 * Get integer from char-pointer, set pointer to end of number
1160 isdn_getnum(char **p
)
1164 while (*p
[0] >= '0' && *p
[0] <= '9')
1165 v
= ((v
< 0) ? 0 : (v
* 10)) + (int) ((*p
[0]++) - '0');
1172 * isdn_readbchan() tries to get data from the read-queue.
1173 * It MUST be called with interrupts off.
1175 * Be aware that this is not an atomic operation when sleep != 0, even though
1176 * interrupts are turned off! Well, like that we are currently only called
1177 * on behalf of a read system call on raw device files (which are documented
1178 * to be dangerous and for for debugging purpose only). The inode semaphore
1179 * takes care that this is not called for the same minor device number while
1180 * we are sleeping, but access is not serialized against simultaneous read()
1181 * from the corresponding ttyI device. Can other ugly events, like changes
1182 * of the mapping (di,ch)<->minor, happen during the sleep? --he
1185 isdn_readbchan(int di
, int channel
, u_char
* buf
, u_char
* fp
, int len
, wait_queue_head_t
*sleep
)
1192 struct sk_buff
*skb
;
1197 if (skb_queue_empty(&dev
->drv
[di
]->rpqueue
[channel
])) {
1199 interruptible_sleep_on(sleep
);
1203 left
= MIN(len
, dev
->drv
[di
]->rcvcount
[channel
]);
1207 if (!(skb
= skb_peek(&dev
->drv
[di
]->rpqueue
[channel
])))
1209 #ifdef CONFIG_ISDN_AUDIO
1210 if (ISDN_AUDIO_SKB_LOCK(skb
))
1212 ISDN_AUDIO_SKB_LOCK(skb
) = 1;
1213 if ((ISDN_AUDIO_SKB_DLECOUNT(skb
)) || (dev
->drv
[di
]->DLEflag
& (1 << channel
))) {
1214 char *p
= skb
->data
;
1215 unsigned long DLEmask
= (1 << channel
);
1218 count_pull
= count_put
= 0;
1219 while ((count_pull
< skb
->len
) && (left
> 0)) {
1221 if (dev
->drv
[di
]->DLEflag
& DLEmask
) {
1223 dev
->drv
[di
]->DLEflag
&= ~DLEmask
;
1227 dev
->drv
[di
]->DLEflag
|= DLEmask
;
1228 (ISDN_AUDIO_SKB_DLECOUNT(skb
))--;
1235 if (count_pull
>= skb
->len
)
1239 /* No DLE's in buff, so simply copy it */
1241 if ((count_pull
= skb
->len
) > left
) {
1245 count_put
= count_pull
;
1246 memcpy(cp
, skb
->data
, count_put
);
1249 #ifdef CONFIG_ISDN_AUDIO
1254 memset(fp
, 0, count_put
);
1258 /* We got all the data in this buff.
1259 * Now we can dequeue it.
1263 #ifdef CONFIG_ISDN_AUDIO
1264 ISDN_AUDIO_SKB_LOCK(skb
) = 0;
1266 skb
= skb_dequeue(&dev
->drv
[di
]->rpqueue
[channel
]);
1269 /* Not yet emptied this buff, so it
1270 * must stay in the queue, for further calls
1271 * but we pull off the data we got until now.
1273 skb_pull(skb
, count_pull
);
1274 #ifdef CONFIG_ISDN_AUDIO
1275 ISDN_AUDIO_SKB_LOCK(skb
) = 0;
1278 dev
->drv
[di
]->rcvcount
[channel
] -= count_put
;
1284 isdn_minor2drv(int minor
)
1286 return (dev
->drvmap
[minor
]);
1290 isdn_minor2chan(int minor
)
1292 return (dev
->chanmap
[minor
]);
1298 static char istatbuf
[2048];
1302 sprintf(istatbuf
, "idmap:\t");
1303 p
= istatbuf
+ strlen(istatbuf
);
1304 for (i
= 0; i
< ISDN_MAX_CHANNELS
; i
++) {
1305 sprintf(p
, "%s ", (dev
->drvmap
[i
] < 0) ? "-" : dev
->drvid
[dev
->drvmap
[i
]]);
1306 p
= istatbuf
+ strlen(istatbuf
);
1308 sprintf(p
, "\nchmap:\t");
1309 p
= istatbuf
+ strlen(istatbuf
);
1310 for (i
= 0; i
< ISDN_MAX_CHANNELS
; i
++) {
1311 sprintf(p
, "%d ", dev
->chanmap
[i
]);
1312 p
= istatbuf
+ strlen(istatbuf
);
1314 sprintf(p
, "\ndrmap:\t");
1315 p
= istatbuf
+ strlen(istatbuf
);
1316 for (i
= 0; i
< ISDN_MAX_CHANNELS
; i
++) {
1317 sprintf(p
, "%d ", dev
->drvmap
[i
]);
1318 p
= istatbuf
+ strlen(istatbuf
);
1320 sprintf(p
, "\nusage:\t");
1321 p
= istatbuf
+ strlen(istatbuf
);
1322 for (i
= 0; i
< ISDN_MAX_CHANNELS
; i
++) {
1323 sprintf(p
, "%d ", dev
->usage
[i
]);
1324 p
= istatbuf
+ strlen(istatbuf
);
1326 sprintf(p
, "\nflags:\t");
1327 p
= istatbuf
+ strlen(istatbuf
);
1328 for (i
= 0; i
< ISDN_MAX_DRIVERS
; i
++) {
1330 sprintf(p
, "%ld ", dev
->drv
[i
]->online
);
1331 p
= istatbuf
+ strlen(istatbuf
);
1334 p
= istatbuf
+ strlen(istatbuf
);
1337 sprintf(p
, "\nphone:\t");
1338 p
= istatbuf
+ strlen(istatbuf
);
1339 for (i
= 0; i
< ISDN_MAX_CHANNELS
; i
++) {
1340 sprintf(p
, "%s ", dev
->num
[i
]);
1341 p
= istatbuf
+ strlen(istatbuf
);
1347 /* Module interface-code */
1350 isdn_info_update(void)
1352 infostruct
*p
= dev
->infochain
;
1356 p
= (infostruct
*) p
->next
;
1358 wake_up_interruptible(&(dev
->info_waitq
));
1362 isdn_read(struct file
*file
, char *buf
, size_t count
, loff_t
* off
)
1364 uint minor
= MINOR(file
->f_dentry
->d_inode
->i_rdev
);
1371 if (off
!= &file
->f_pos
)
1374 if (minor
== ISDN_MINOR_STATUS
) {
1375 if (!file
->private_data
) {
1376 if (file
->f_flags
& O_NONBLOCK
)
1378 interruptible_sleep_on(&(dev
->info_waitq
));
1381 file
->private_data
= 0;
1382 if ((len
= strlen(p
)) <= count
) {
1383 if (copy_to_user(buf
, p
, len
))
1392 if (minor
< ISDN_MINOR_CTRL
) {
1393 drvidx
= isdn_minor2drv(minor
);
1396 if (!(dev
->drv
[drvidx
]->flags
& DRV_FLAG_RUNNING
))
1398 chidx
= isdn_minor2chan(minor
);
1399 if( ! (p
= kmalloc(count
,GFP_KERNEL
)) ) return -ENOMEM
;
1402 len
= isdn_readbchan(drvidx
, chidx
, p
, 0, count
,
1403 &dev
->drv
[drvidx
]->rcv_waitq
[chidx
]);
1405 restore_flags(flags
);
1406 if( copy_to_user(buf
,p
,len
) ) len
= -EFAULT
;
1410 if (minor
<= ISDN_MINOR_CTRLMAX
) {
1411 drvidx
= isdn_minor2drv(minor
- ISDN_MINOR_CTRL
);
1414 if (!dev
->drv
[drvidx
]->stavail
) {
1415 if (file
->f_flags
& O_NONBLOCK
)
1417 interruptible_sleep_on(&(dev
->drv
[drvidx
]->st_waitq
));
1419 if (dev
->drv
[drvidx
]->interface
->readstat
)
1420 len
= dev
->drv
[drvidx
]->interface
->
1421 readstat(buf
, MIN(count
, dev
->drv
[drvidx
]->stavail
),
1422 1, drvidx
, isdn_minor2chan(minor
));
1428 dev
->drv
[drvidx
]->stavail
-= len
;
1430 dev
->drv
[drvidx
]->stavail
= 0;
1431 restore_flags(flags
);
1435 #ifdef CONFIG_ISDN_PPP
1436 if (minor
<= ISDN_MINOR_PPPMAX
)
1437 return (isdn_ppp_read(minor
- ISDN_MINOR_PPP
, file
, buf
, count
));
1443 isdn_lseek(struct file
*file
, loff_t offset
, int orig
)
1449 isdn_write(struct file
*file
, const char *buf
, size_t count
, loff_t
* off
)
1451 uint minor
= MINOR(file
->f_dentry
->d_inode
->i_rdev
);
1455 if (off
!= &file
->f_pos
)
1458 if (minor
== ISDN_MINOR_STATUS
)
1462 if (minor
< ISDN_MINOR_CTRL
) {
1463 drvidx
= isdn_minor2drv(minor
);
1466 if (!(dev
->drv
[drvidx
]->flags
& DRV_FLAG_RUNNING
))
1468 chidx
= isdn_minor2chan(minor
);
1469 while (isdn_writebuf_stub(drvidx
, chidx
, buf
, count
, 1) != count
)
1470 interruptible_sleep_on(&dev
->drv
[drvidx
]->snd_waitq
[chidx
]);
1473 if (minor
<= ISDN_MINOR_CTRLMAX
) {
1474 drvidx
= isdn_minor2drv(minor
- ISDN_MINOR_CTRL
);
1478 * We want to use the isdnctrl device to load the firmware
1480 if (!(dev->drv[drvidx]->flags & DRV_FLAG_RUNNING))
1483 if (dev
->drv
[drvidx
]->interface
->writecmd
)
1484 return (dev
->drv
[drvidx
]->interface
->
1485 writecmd(buf
, count
, 1, drvidx
, isdn_minor2chan(minor
)));
1489 #ifdef CONFIG_ISDN_PPP
1490 if (minor
<= ISDN_MINOR_PPPMAX
)
1491 return (isdn_ppp_write(minor
- ISDN_MINOR_PPP
, file
, buf
, count
));
1497 isdn_poll(struct file
*file
, poll_table
* wait
)
1499 unsigned int mask
= 0;
1500 unsigned int minor
= MINOR(file
->f_dentry
->d_inode
->i_rdev
);
1501 int drvidx
= isdn_minor2drv(minor
- ISDN_MINOR_CTRL
);
1503 if (minor
== ISDN_MINOR_STATUS
) {
1504 poll_wait(file
, &(dev
->info_waitq
), wait
);
1505 /* mask = POLLOUT | POLLWRNORM; */
1506 if (file
->private_data
) {
1507 mask
|= POLLIN
| POLLRDNORM
;
1511 if (minor
>= ISDN_MINOR_CTRL
&& minor
<= ISDN_MINOR_CTRLMAX
) {
1513 /* driver deregistered while file open */
1516 poll_wait(file
, &(dev
->drv
[drvidx
]->st_waitq
), wait
);
1517 mask
= POLLOUT
| POLLWRNORM
;
1518 if (dev
->drv
[drvidx
]->stavail
) {
1519 mask
|= POLLIN
| POLLRDNORM
;
1523 #ifdef CONFIG_ISDN_PPP
1524 if (minor
<= ISDN_MINOR_PPPMAX
)
1525 return (isdn_ppp_poll(file
, wait
));
1527 printk(KERN_ERR
"isdn_common: isdn_poll 2 -> what the hell\n");
1533 isdn_ioctl(struct inode
*inode
, struct file
*file
, uint cmd
, ulong arg
)
1535 uint minor
= MINOR(inode
->i_rdev
);
1546 isdn_ioctl_struct iocts
;
1547 isdn_net_ioctl_phone phone
;
1548 isdn_net_ioctl_cfg cfg
;
1551 #define name iocpar.name
1552 #define bname iocpar.bname
1553 #define iocts iocpar.iocts
1554 #define phone iocpar.phone
1555 #define cfg iocpar.cfg
1557 if (minor
== ISDN_MINOR_STATUS
) {
1565 ulong
*p
= (ulong
*) arg
;
1567 if ((ret
= verify_area(VERIFY_WRITE
, (void *) arg
,
1568 sizeof(ulong
) * ISDN_MAX_CHANNELS
* 2)))
1570 for (i
= 0; i
< ISDN_MAX_CHANNELS
; i
++) {
1571 put_user(dev
->ibytes
[i
], p
++);
1572 put_user(dev
->obytes
[i
], p
++);
1578 #ifdef CONFIG_NETDEVICES
1580 /* Get peer phone number of a connected
1581 * isdn network interface */
1583 if (copy_from_user((char *) &phone
, (char *) arg
, sizeof(phone
)))
1585 return isdn_net_getpeer(&phone
, (isdn_net_ioctl_phone
*) arg
);
1595 if (minor
< ISDN_MINOR_CTRL
) {
1596 drvidx
= isdn_minor2drv(minor
);
1599 chidx
= isdn_minor2chan(minor
);
1600 if (!(dev
->drv
[drvidx
]->flags
& DRV_FLAG_RUNNING
))
1604 if (minor
<= ISDN_MINOR_CTRLMAX
) {
1606 * isdn net devices manage lots of configuration variables as linked lists.
1607 * Those lists must only be manipulated from user space. Some of the ioctl's
1608 * service routines access user space and are not atomic. Therefor, ioctl's
1609 * manipulating the lists and ioctl's sleeping while accessing the lists
1610 * are serialized by means of a semaphore.
1614 printk(KERN_INFO
"INFO: ISDN_DW_ABC_EXTENSION not enabled\n");
1617 printk(KERN_INFO
"INFO: ISDN_ABC_LCR_SUPPORT not enabled\n");
1619 #ifdef CONFIG_NETDEVICES
1621 /* Add a network-interface */
1623 if (copy_from_user(name
, (char *) arg
, sizeof(name
)))
1629 ret
= down_interruptible(&dev
->sem
);
1630 if( ret
) return ret
;
1631 if ((s
= isdn_net_new(s
, NULL
))) {
1632 if (copy_to_user((char *) arg
, s
, strlen(s
) + 1)){
1642 /* Add a slave to a network-interface */
1644 if (copy_from_user(bname
, (char *) arg
, sizeof(bname
) - 1))
1648 ret
= down_interruptible(&dev
->sem
);
1649 if( ret
) return ret
;
1650 if ((s
= isdn_net_newslave(bname
))) {
1651 if (copy_to_user((char *) arg
, s
, strlen(s
) + 1)){
1661 /* Delete a network-interface */
1663 if (copy_from_user(name
, (char *) arg
, sizeof(name
)))
1665 ret
= down_interruptible(&dev
->sem
);
1666 if( ret
) return ret
;
1667 ret
= isdn_net_rm(name
);
1673 /* Set configurable parameters of a network-interface */
1675 if (copy_from_user((char *) &cfg
, (char *) arg
, sizeof(cfg
)))
1677 return isdn_net_setcfg(&cfg
);
1681 /* Get configurable parameters of a network-interface */
1683 if (copy_from_user((char *) &cfg
, (char *) arg
, sizeof(cfg
)))
1685 if (!(ret
= isdn_net_getcfg(&cfg
))) {
1686 if (copy_to_user((char *) arg
, (char *) &cfg
, sizeof(cfg
)))
1693 /* Add a phone-number to a network-interface */
1695 if (copy_from_user((char *) &phone
, (char *) arg
, sizeof(phone
)))
1697 ret
= down_interruptible(&dev
->sem
);
1698 if( ret
) return ret
;
1699 ret
= isdn_net_addphone(&phone
);
1705 /* Get list of phone-numbers of a network-interface */
1707 if (copy_from_user((char *) &phone
, (char *) arg
, sizeof(phone
)))
1709 ret
= down_interruptible(&dev
->sem
);
1710 if( ret
) return ret
;
1711 ret
= isdn_net_getphones(&phone
, (char *) arg
);
1717 /* Delete a phone-number of a network-interface */
1719 if (copy_from_user((char *) &phone
, (char *) arg
, sizeof(phone
)))
1721 ret
= down_interruptible(&dev
->sem
);
1722 if( ret
) return ret
;
1723 ret
= isdn_net_delphone(&phone
);
1729 /* Force dialing of a network-interface */
1731 if (copy_from_user(name
, (char *) arg
, sizeof(name
)))
1733 return isdn_net_force_dial(name
);
1736 #ifdef CONFIG_ISDN_PPP
1740 if (copy_from_user(name
, (char *) arg
, sizeof(name
)))
1742 return isdn_ppp_dial_slave(name
);
1746 if (copy_from_user(name
, (char *) arg
, sizeof(name
)))
1748 return isdn_ppp_hangup_slave(name
);
1751 /* Force hangup of a network-interface */
1754 if (copy_from_user(name
, (char *) arg
, sizeof(name
)))
1756 return isdn_net_force_hangup(name
);
1758 #endif /* CONFIG_NETDEVICES */
1760 dev
->net_verbose
= arg
;
1761 printk(KERN_INFO
"isdn: Verbose-Level is %d\n", dev
->net_verbose
);
1765 dev
->global_flags
|= ISDN_GLOBAL_STOPPED
;
1767 dev
->global_flags
&= ~ISDN_GLOBAL_STOPPED
;
1768 printk(KERN_INFO
"isdn: Global Mode %s\n",
1769 (dev
->global_flags
& ISDN_GLOBAL_STOPPED
) ? "stopped" : "running");
1776 if (copy_from_user((char *) &iocts
, (char *) arg
,
1777 sizeof(isdn_ioctl_struct
)))
1779 if (strlen(iocts
.drvid
)) {
1780 if ((p
= strchr(iocts
.drvid
, ',')))
1783 for (i
= 0; i
< ISDN_MAX_DRIVERS
; i
++)
1784 if (!(strcmp(dev
->drvid
[i
], iocts
.drvid
))) {
1793 dev
->drv
[drvidx
]->flags
|= DRV_FLAG_REJBUS
;
1795 dev
->drv
[drvidx
]->flags
&= ~DRV_FLAG_REJBUS
;
1798 dev
->profd
= current
;
1802 /* Get all Modem-Profiles */
1804 char *p
= (char *) arg
;
1807 if ((ret
= verify_area(VERIFY_WRITE
, (void *) arg
,
1808 (ISDN_MODEM_NUMREG
+ ISDN_MSNLEN
+ ISDN_LMSNLEN
)
1809 * ISDN_MAX_CHANNELS
)))
1812 for (i
= 0; i
< ISDN_MAX_CHANNELS
; i
++) {
1813 if (copy_to_user(p
, dev
->mdm
.info
[i
].emu
.profile
,
1816 p
+= ISDN_MODEM_NUMREG
;
1817 if (copy_to_user(p
, dev
->mdm
.info
[i
].emu
.pmsn
, ISDN_MSNLEN
))
1820 if (copy_to_user(p
, dev
->mdm
.info
[i
].emu
.plmsn
, ISDN_LMSNLEN
))
1824 return (ISDN_MODEM_NUMREG
+ ISDN_MSNLEN
+ ISDN_LMSNLEN
) * ISDN_MAX_CHANNELS
;
1829 /* Set all Modem-Profiles */
1831 char *p
= (char *) arg
;
1834 if ((ret
= verify_area(VERIFY_READ
, (void *) arg
,
1835 (ISDN_MODEM_NUMREG
+ ISDN_MSNLEN
)
1836 * ISDN_MAX_CHANNELS
)))
1839 for (i
= 0; i
< ISDN_MAX_CHANNELS
; i
++) {
1840 if (copy_from_user(dev
->mdm
.info
[i
].emu
.profile
, p
,
1843 p
+= ISDN_MODEM_NUMREG
;
1844 if (copy_from_user(dev
->mdm
.info
[i
].emu
.pmsn
, p
, ISDN_MSNLEN
))
1854 /* Set/Get MSN->EAZ-Mapping for a driver */
1857 if (copy_from_user((char *) &iocts
,
1859 sizeof(isdn_ioctl_struct
)))
1861 if (strlen(iocts
.drvid
)) {
1863 for (i
= 0; i
< ISDN_MAX_DRIVERS
; i
++)
1864 if (!(strcmp(dev
->drvid
[i
], iocts
.drvid
))) {
1872 if (cmd
== IIOCSETMAP
) {
1875 p
= (char *) iocts
.arg
;
1881 if ((ret
= verify_area(VERIFY_READ
, p
, 1)))
1883 get_user(bname
[j
], p
++);
1890 strcpy(dev
->drv
[drvidx
]->msn2eaz
[i
], bname
);
1896 if (j
>= ISDN_MSNLEN
)
1903 p
= (char *) iocts
.arg
;
1904 for (i
= 0; i
< 10; i
++) {
1905 sprintf(bname
, "%s%s",
1906 strlen(dev
->drv
[drvidx
]->msn2eaz
[i
]) ?
1907 dev
->drv
[drvidx
]->msn2eaz
[i
] : "_",
1908 (i
< 9) ? "," : "\0");
1909 if (copy_to_user(p
, bname
, strlen(bname
) + 1))
1919 if (copy_to_user((char *) arg
, (char *) &dev
, sizeof(ulong
)))
1926 if ((cmd
& IIOCDRVCTL
) == IIOCDRVCTL
)
1927 cmd
= ((cmd
>> _IOC_NRSHIFT
) & _IOC_NRMASK
) & ISDN_DRVIOCTL_MASK
;
1933 if (copy_from_user((char *) &iocts
, (char *) arg
, sizeof(isdn_ioctl_struct
)))
1935 if (strlen(iocts
.drvid
)) {
1936 if ((p
= strchr(iocts
.drvid
, ',')))
1939 for (i
= 0; i
< ISDN_MAX_DRIVERS
; i
++)
1940 if (!(strcmp(dev
->drvid
[i
], iocts
.drvid
))) {
1948 if ((ret
= verify_area(VERIFY_WRITE
, (void *) arg
,
1949 sizeof(isdn_ioctl_struct
))))
1952 c
.command
= ISDN_CMD_IOCTL
;
1954 memcpy(c
.parm
.num
, (char *) &iocts
.arg
, sizeof(ulong
));
1955 ret
= isdn_command(&c
);
1956 memcpy((char *) &iocts
.arg
, c
.parm
.num
, sizeof(ulong
));
1957 if (copy_to_user((char *) arg
, &iocts
, sizeof(isdn_ioctl_struct
)))
1964 #ifdef CONFIG_ISDN_PPP
1965 if (minor
<= ISDN_MINOR_PPPMAX
)
1966 return (isdn_ppp_ioctl(minor
- ISDN_MINOR_PPP
, file
, cmd
, arg
));
1978 * Open the device code.
1979 * MOD_INC_USE_COUNT make sure that the driver memory is not freed
1980 * while the device is in use.
1983 isdn_open(struct inode
*ino
, struct file
*filep
)
1985 uint minor
= MINOR(ino
->i_rdev
);
1989 if (minor
== ISDN_MINOR_STATUS
) {
1992 if ((p
= (infostruct
*) kmalloc(sizeof(infostruct
), GFP_KERNEL
))) {
1994 p
->next
= (char *) dev
->infochain
;
1995 p
->private = (char *) &(filep
->private_data
);
1997 /* At opening we allow a single update */
1998 filep
->private_data
= (char *) 1;
2005 if (minor
< ISDN_MINOR_CTRL
) {
2006 drvidx
= isdn_minor2drv(minor
);
2009 chidx
= isdn_minor2chan(minor
);
2010 if (!(dev
->drv
[drvidx
]->flags
& DRV_FLAG_RUNNING
))
2012 if (!(dev
->drv
[drvidx
]->online
& (1 << chidx
)))
2014 isdn_MOD_INC_USE_COUNT();
2017 if (minor
<= ISDN_MINOR_CTRLMAX
) {
2018 drvidx
= isdn_minor2drv(minor
- ISDN_MINOR_CTRL
);
2021 isdn_MOD_INC_USE_COUNT();
2024 #ifdef CONFIG_ISDN_PPP
2025 if (minor
<= ISDN_MINOR_PPPMAX
) {
2027 if (!(ret
= isdn_ppp_open(minor
- ISDN_MINOR_PPP
, filep
)))
2028 isdn_MOD_INC_USE_COUNT();
2036 isdn_close(struct inode
*ino
, struct file
*filep
)
2038 uint minor
= MINOR(ino
->i_rdev
);
2040 if (minor
== ISDN_MINOR_STATUS
) {
2041 infostruct
*p
= dev
->infochain
;
2042 infostruct
*q
= NULL
;
2046 if (p
->private == (char *) &(filep
->private_data
)) {
2050 dev
->infochain
= (infostruct
*) (p
->next
);
2055 p
= (infostruct
*) (p
->next
);
2057 printk(KERN_WARNING
"isdn: No private data while closing isdnctrl\n");
2060 isdn_MOD_DEC_USE_COUNT();
2061 if (minor
< ISDN_MINOR_CTRL
)
2063 if (minor
<= ISDN_MINOR_CTRLMAX
) {
2064 if (dev
->profd
== current
)
2068 #ifdef CONFIG_ISDN_PPP
2069 if (minor
<= ISDN_MINOR_PPPMAX
)
2070 isdn_ppp_release(minor
- ISDN_MINOR_PPP
, filep
);
2075 static struct file_operations isdn_fops
=
2083 release
: isdn_close
,
2087 isdn_map_eaz2msn(char *msn
, int di
)
2089 driver
*this = dev
->drv
[di
];
2092 if (strlen(msn
) == 1) {
2094 if ((i
>= 0) && (i
<= 9))
2095 if (strlen(this->msn2eaz
[i
]))
2096 return (this->msn2eaz
[i
]);
2102 * Find an unused ISDN-channel, whose feature-flags match the
2103 * given L2- and L3-protocols.
2105 #define L2V (~(ISDN_FEATURE_L2_V11096|ISDN_FEATURE_L2_V11019|ISDN_FEATURE_L2_V11038))
2108 isdn_get_free_channel(int usage
, int l2_proto
, int l3_proto
, int pre_dev
2109 ,int pre_chan
, char *msn
)
2118 features
= ((1 << l2_proto
) | (0x10000 << l3_proto
));
2119 vfeatures
= (((1 << l2_proto
) | (0x10000 << l3_proto
)) &
2120 ~(ISDN_FEATURE_L2_V11096
|ISDN_FEATURE_L2_V11019
|ISDN_FEATURE_L2_V11038
));
2121 /* If Layer-2 protocol is V.110, accept drivers with
2122 * transparent feature even if these don't support V.110
2123 * because we can emulate this in linklevel.
2125 for (i
= 0; i
< ISDN_MAX_CHANNELS
; i
++)
2126 if (USG_NONE(dev
->usage
[i
]) &&
2127 (dev
->drvmap
[i
] != -1)) {
2128 int d
= dev
->drvmap
[i
];
2129 if ((dev
->usage
[i
] & ISDN_USAGE_EXCLUSIVE
) &&
2130 ((pre_dev
!= d
) || (pre_chan
!= dev
->chanmap
[i
])))
2132 if (!strcmp(isdn_map_eaz2msn(msn
, d
), "-"))
2134 if (dev
->usage
[i
] & ISDN_USAGE_DISABLED
)
2135 continue; /* usage not allowed */
2136 if (dev
->drv
[d
]->flags
& DRV_FLAG_RUNNING
) {
2137 if (((dev
->drv
[d
]->interface
->features
& features
) == features
) ||
2138 (((dev
->drv
[d
]->interface
->features
& vfeatures
) == vfeatures
) &&
2139 (dev
->drv
[d
]->interface
->features
& ISDN_FEATURE_L2_TRANS
))) {
2140 if ((pre_dev
< 0) || (pre_chan
< 0)) {
2141 dev
->usage
[i
] &= ISDN_USAGE_EXCLUSIVE
;
2142 dev
->usage
[i
] |= usage
;
2144 restore_flags(flags
);
2147 if ((pre_dev
== d
) && (pre_chan
== dev
->chanmap
[i
])) {
2148 dev
->usage
[i
] &= ISDN_USAGE_EXCLUSIVE
;
2149 dev
->usage
[i
] |= usage
;
2151 restore_flags(flags
);
2158 restore_flags(flags
);
2163 * Set state of ISDN-channel to 'unused'
2166 isdn_free_channel(int di
, int ch
, int usage
)
2173 for (i
= 0; i
< ISDN_MAX_CHANNELS
; i
++)
2174 if (((!usage
) || ((dev
->usage
[i
] & ISDN_USAGE_MASK
) == usage
)) &&
2175 (dev
->drvmap
[i
] == di
) &&
2176 (dev
->chanmap
[i
] == ch
)) {
2177 dev
->usage
[i
] &= (ISDN_USAGE_NONE
| ISDN_USAGE_EXCLUSIVE
);
2178 strcpy(dev
->num
[i
], "???");
2181 // 20.10.99 JIM, try to reinitialize v110 !
2182 dev
->v110emu
[i
] = 0;
2183 atomic_set(&(dev
->v110use
[i
]), 0);
2184 isdn_v110_close(dev
->v110
[i
]);
2185 dev
->v110
[i
] = NULL
;
2186 // 20.10.99 JIM, try to reinitialize v110 !
2188 isdn_free_queue(&dev
->drv
[di
]->rpqueue
[ch
]);
2190 restore_flags(flags
);
2194 * Cancel Exclusive-Flag for ISDN-channel
2197 isdn_unexclusive_channel(int di
, int ch
)
2204 for (i
= 0; i
< ISDN_MAX_CHANNELS
; i
++)
2205 if ((dev
->drvmap
[i
] == di
) &&
2206 (dev
->chanmap
[i
] == ch
)) {
2207 dev
->usage
[i
] &= ~ISDN_USAGE_EXCLUSIVE
;
2209 restore_flags(flags
);
2212 restore_flags(flags
);
2216 * writebuf replacement for SKB_ABLE drivers
2219 isdn_writebuf_stub(int drvidx
, int chan
, const u_char
* buf
, int len
,
2223 int hl
= dev
->drv
[drvidx
]->interface
->hl_hdrlen
;
2224 struct sk_buff
*skb
= alloc_skb(hl
+ len
, GFP_ATOMIC
);
2228 skb_reserve(skb
, hl
);
2230 copy_from_user(skb_put(skb
, len
), buf
, len
);
2232 memcpy(skb_put(skb
, len
), buf
, len
);
2233 ret
= dev
->drv
[drvidx
]->interface
->writebuf_skb(drvidx
, chan
, 1, skb
);
2237 dev
->obytes
[isdn_dc2minor(drvidx
, chan
)] += ret
;
2242 * Return: length of data on success, -ERRcode on failure.
2245 isdn_writebuf_skb_stub(int drvidx
, int chan
, int ack
, struct sk_buff
*skb
)
2248 struct sk_buff
*nskb
= NULL
;
2249 int v110_ret
= skb
->len
;
2250 int idx
= isdn_dc2minor(drvidx
, chan
);
2252 if (dev
->v110
[idx
]) {
2253 atomic_inc(&dev
->v110use
[idx
]);
2254 nskb
= isdn_v110_encode(dev
->v110
[idx
], skb
);
2255 atomic_dec(&dev
->v110use
[idx
]);
2258 v110_ret
= *((int *)nskb
->data
);
2259 skb_pull(nskb
, sizeof(int));
2261 dev_kfree_skb(nskb
);
2265 /* V.110 must always be acknowledged */
2267 ret
= dev
->drv
[drvidx
]->interface
->writebuf_skb(drvidx
, chan
, ack
, nskb
);
2269 int hl
= dev
->drv
[drvidx
]->interface
->hl_hdrlen
;
2271 if( skb_headroom(skb
) < hl
){
2273 * This should only occur when new HL driver with
2274 * increased hl_hdrlen was loaded after netdevice
2275 * was created and connected to the new driver.
2277 * The V.110 branch (re-allocates on its own) does
2280 struct sk_buff
* skb_tmp
;
2282 skb_tmp
= skb_realloc_headroom(skb
, hl
);
2283 printk(KERN_DEBUG
"isdn_writebuf_skb_stub: reallocating headroom%s\n", skb_tmp
? "" : " failed");
2284 if (!skb_tmp
) return -ENOMEM
; /* 0 better? */
2285 ret
= dev
->drv
[drvidx
]->interface
->writebuf_skb(drvidx
, chan
, ack
, skb_tmp
);
2289 dev_kfree_skb(skb_tmp
);
2292 ret
= dev
->drv
[drvidx
]->interface
->writebuf_skb(drvidx
, chan
, ack
, skb
);
2296 dev
->obytes
[idx
] += ret
;
2297 if (dev
->v110
[idx
]) {
2298 atomic_inc(&dev
->v110use
[idx
]);
2299 dev
->v110
[idx
]->skbuser
++;
2300 atomic_dec(&dev
->v110use
[idx
]);
2302 /* For V.110 return unencoded data length */
2304 if (ret
== skb
->len
)
2309 dev_kfree_skb(nskb
);
2314 register_isdn_module(isdn_module
*m
) {
2319 unregister_isdn_module(isdn_module
*m
) {
2324 isdn_add_channels(driver
*d
, int drvidx
, int n
, int adding
)
2329 init_waitqueue_head(&d
->st_waitq
);
2330 if (d
->flags
& DRV_FLAG_RUNNING
)
2332 if (n
< 1) return 0;
2334 m
= (adding
) ? d
->channels
+ n
: n
;
2336 if (dev
->channels
+ n
> ISDN_MAX_CHANNELS
) {
2337 printk(KERN_WARNING
"register_isdn: Max. %d channels supported\n",
2342 if ((adding
) && (d
->rcverr
))
2344 if (!(d
->rcverr
= (int *) kmalloc(sizeof(int) * m
, GFP_KERNEL
))) {
2345 printk(KERN_WARNING
"register_isdn: Could not alloc rcverr\n");
2348 memset((char *) d
->rcverr
, 0, sizeof(int) * m
);
2350 if ((adding
) && (d
->rcvcount
))
2352 if (!(d
->rcvcount
= (int *) kmalloc(sizeof(int) * m
, GFP_KERNEL
))) {
2353 printk(KERN_WARNING
"register_isdn: Could not alloc rcvcount\n");
2354 if (!adding
) kfree(d
->rcverr
);
2357 memset((char *) d
->rcvcount
, 0, sizeof(int) * m
);
2359 if ((adding
) && (d
->rpqueue
)) {
2360 for (j
= 0; j
< d
->channels
; j
++)
2361 isdn_free_queue(&d
->rpqueue
[j
]);
2365 (struct sk_buff_head
*) kmalloc(sizeof(struct sk_buff_head
) * m
, GFP_KERNEL
))) {
2366 printk(KERN_WARNING
"register_isdn: Could not alloc rpqueue\n");
2373 for (j
= 0; j
< m
; j
++) {
2374 skb_queue_head_init(&d
->rpqueue
[j
]);
2377 if ((adding
) && (d
->rcv_waitq
))
2378 kfree(d
->rcv_waitq
);
2379 d
->rcv_waitq
= (wait_queue_head_t
*)
2380 kmalloc(sizeof(wait_queue_head_t
) * 2 * m
, GFP_KERNEL
);
2381 if (!d
->rcv_waitq
) {
2382 printk(KERN_WARNING
"register_isdn: Could not alloc rcv_waitq\n");
2390 d
->snd_waitq
= d
->rcv_waitq
+ m
;
2391 for (j
= 0; j
< m
; j
++) {
2392 init_waitqueue_head(&d
->rcv_waitq
[j
]);
2393 init_waitqueue_head(&d
->snd_waitq
[j
]);
2399 for (j
= d
->channels
; j
< m
; j
++)
2400 for (k
= 0; k
< ISDN_MAX_CHANNELS
; k
++)
2401 if (dev
->chanmap
[k
] < 0) {
2402 dev
->chanmap
[k
] = j
;
2403 dev
->drvmap
[k
] = drvidx
;
2404 isdn_register_devfs(k
);
2407 restore_flags(flags
);
2413 * Low-level-driver registration
2417 set_global_features(void)
2421 dev
->global_features
= 0;
2422 for (drvidx
= 0; drvidx
< ISDN_MAX_DRIVERS
; drvidx
++) {
2423 if (!dev
->drv
[drvidx
])
2425 if (dev
->drv
[drvidx
]->interface
)
2426 dev
->global_features
|= dev
->drv
[drvidx
]->interface
->features
;
2430 #ifdef CONFIG_ISDN_DIVERSION
2431 extern isdn_divert_if
*divert_if
;
2433 static char *map_drvname(int di
)
2435 if ((di
< 0) || (di
>= ISDN_MAX_DRIVERS
))
2437 return(dev
->drvid
[di
]); /* driver name */
2440 static int map_namedrv(char *id
)
2443 for (i
= 0; i
< ISDN_MAX_DRIVERS
; i
++)
2444 { if (!strcmp(dev
->drvid
[i
],id
))
2450 int DIVERT_REG_NAME(isdn_divert_if
*i_div
)
2452 if (i_div
->if_magic
!= DIVERT_IF_MAGIC
)
2453 return(DIVERT_VER_ERR
);
2456 case DIVERT_CMD_REL
:
2457 if (divert_if
!= i_div
)
2458 return(DIVERT_REL_ERR
);
2459 divert_if
= NULL
; /* free interface */
2461 return(DIVERT_NO_ERR
);
2463 case DIVERT_CMD_REG
:
2465 return(DIVERT_REG_ERR
);
2466 i_div
->ll_cmd
= isdn_command
; /* set command function */
2467 i_div
->drv_to_name
= map_drvname
;
2468 i_div
->name_to_drv
= map_namedrv
;
2470 divert_if
= i_div
; /* remember interface */
2471 return(DIVERT_NO_ERR
);
2474 return(DIVERT_CMD_ERR
);
2476 } /* DIVERT_REG_NAME */
2478 EXPORT_SYMBOL(DIVERT_REG_NAME
);
2480 #endif CONFIG_ISDN_DIVERSION
2483 EXPORT_SYMBOL(register_isdn
);
2484 EXPORT_SYMBOL(register_isdn_module
);
2485 EXPORT_SYMBOL(unregister_isdn_module
);
2486 #ifdef CONFIG_ISDN_PPP
2487 EXPORT_SYMBOL(isdn_ppp_register_compressor
);
2488 EXPORT_SYMBOL(isdn_ppp_unregister_compressor
);
2492 register_isdn(isdn_if
* i
)
2499 if (dev
->drivers
>= ISDN_MAX_DRIVERS
) {
2500 printk(KERN_WARNING
"register_isdn: Max. %d drivers supported\n",
2504 if (!i
->writebuf_skb
) {
2505 printk(KERN_WARNING
"register_isdn: No write routine given.\n");
2508 if (!(d
= (driver
*) kmalloc(sizeof(driver
), GFP_KERNEL
))) {
2509 printk(KERN_WARNING
"register_isdn: Could not alloc driver-struct\n");
2512 memset((char *) d
, 0, sizeof(driver
));
2514 d
->maxbufsize
= i
->maxbufsize
;
2517 d
->flags
= DRV_FLAG_LOADED
;
2521 for (drvidx
= 0; drvidx
< ISDN_MAX_DRIVERS
; drvidx
++)
2522 if (!dev
->drv
[drvidx
])
2524 if (isdn_add_channels(d
, drvidx
, i
->channels
, 0)) {
2528 i
->channels
= drvidx
;
2529 i
->rcvcallb_skb
= isdn_receive_skb_callback
;
2530 i
->statcallb
= isdn_status_callback
;
2532 sprintf(i
->id
, "line%d", drvidx
);
2535 for (j
= 0; j
< drvidx
; j
++)
2536 if (!strcmp(i
->id
, dev
->drvid
[j
]))
2537 sprintf(i
->id
, "line%d", drvidx
);
2538 dev
->drv
[drvidx
] = d
;
2539 strcpy(dev
->drvid
[drvidx
], i
->id
);
2542 set_global_features();
2543 restore_flags(flags
);
2548 *****************************************************************************
2549 * And now the modules code.
2550 *****************************************************************************
2553 extern int printk(const char *fmt
,...);
2556 #define isdn_init init_module
2560 isdn_getrev(const char *revision
)
2565 if ((p
= strchr(revision
, ':'))) {
2567 p
= strchr(rev
, '$');
2574 #ifdef CONFIG_DEVFS_FS
2576 static devfs_handle_t devfs_handle
= NULL
;
2578 static void isdn_register_devfs(int k
)
2582 sprintf (buf
, "isdn%d", k
);
2583 dev
->devfs_handle_isdnX
[k
] =
2584 devfs_register (devfs_handle
, buf
, DEVFS_FL_DEFAULT
,
2585 ISDN_MAJOR
, ISDN_MINOR_B
+ k
,0600 | S_IFCHR
,
2587 sprintf (buf
, "isdnctrl%d", k
);
2588 dev
->devfs_handle_isdnctrlX
[k
] =
2589 devfs_register (devfs_handle
, buf
, DEVFS_FL_DEFAULT
,
2590 ISDN_MAJOR
, ISDN_MINOR_CTRL
+ k
, 0600 | S_IFCHR
,
2594 static void isdn_unregister_devfs(int k
)
2596 devfs_unregister (dev
->devfs_handle_isdnX
[k
]);
2597 devfs_unregister (dev
->devfs_handle_isdnctrlX
[k
]);
2600 static void isdn_init_devfs(void)
2602 # ifdef CONFIG_ISDN_PPP
2606 devfs_handle
= devfs_mk_dir (NULL
, "isdn", 4, NULL
);
2607 # ifdef CONFIG_ISDN_PPP
2608 for (i
= 0; i
< ISDN_MAX_CHANNELS
; i
++) {
2611 sprintf (buf
, "ippp%d", i
);
2612 dev
->devfs_handle_ipppX
[i
] =
2613 devfs_register (devfs_handle
, buf
, DEVFS_FL_DEFAULT
,
2614 ISDN_MAJOR
, ISDN_MINOR_PPP
+ i
,
2615 0600 | S_IFCHR
, &isdn_fops
, NULL
);
2619 dev
->devfs_handle_isdninfo
=
2620 devfs_register (devfs_handle
, "isdninfo", DEVFS_FL_DEFAULT
,
2621 ISDN_MAJOR
, ISDN_MINOR_STATUS
, 0600 | S_IFCHR
,
2623 dev
->devfs_handle_isdnctrl
=
2624 devfs_register (devfs_handle
, "isdnctrl", DEVFS_FL_DEFAULT
,
2625 ISDN_MAJOR
, ISDN_MINOR_CTRL
, 0600 | S_IFCHR
,
2629 static void isdn_cleanup_devfs(void)
2631 # ifdef CONFIG_ISDN_PPP
2633 for (i
= 0; i
< ISDN_MAX_CHANNELS
; i
++)
2634 devfs_unregister (dev
->devfs_handle_ipppX
[i
]);
2636 devfs_unregister (dev
->devfs_handle_isdninfo
);
2637 devfs_unregister (dev
->devfs_handle_isdnctrl
);
2638 devfs_unregister (devfs_handle
);
2641 #else /* CONFIG_DEVFS_FS */
2642 static void isdn_register_devfs(int dummy
)
2647 static void isdn_unregister_devfs(int dummy
)
2652 static void isdn_init_devfs(void)
2657 static void isdn_cleanup_devfs(void)
2662 #endif /* CONFIG_DEVFS_FS */
2665 * Allocate and initialize all data, register modem-devices
2673 if (!(dev
= (isdn_dev
*) vmalloc(sizeof(isdn_dev
)))) {
2674 printk(KERN_WARNING
"isdn: Could not allocate device-struct.\n");
2677 memset((char *) dev
, 0, sizeof(isdn_dev
));
2678 init_timer(&dev
->timer
);
2679 dev
->timer
.function
= isdn_timer_funct
;
2680 init_MUTEX(&dev
->sem
);
2681 init_waitqueue_head(&dev
->info_waitq
);
2682 for (i
= 0; i
< ISDN_MAX_CHANNELS
; i
++) {
2683 dev
->drvmap
[i
] = -1;
2684 dev
->chanmap
[i
] = -1;
2686 strcpy(dev
->num
[i
], "???");
2687 init_waitqueue_head(&dev
->mdm
.info
[i
].open_wait
);
2688 init_waitqueue_head(&dev
->mdm
.info
[i
].close_wait
);
2690 if (devfs_register_chrdev(ISDN_MAJOR
, "isdn", &isdn_fops
)) {
2691 printk(KERN_WARNING
"isdn: Could not register control devices\n");
2696 if ((i
= isdn_tty_modem_init()) < 0) {
2697 printk(KERN_WARNING
"isdn: Could not register tty devices\n");
2699 tty_unregister_driver(&dev
->mdm
.cua_modem
);
2701 tty_unregister_driver(&dev
->mdm
.tty_modem
);
2703 isdn_cleanup_devfs();
2704 devfs_unregister_chrdev(ISDN_MAJOR
, "isdn");
2707 #ifdef CONFIG_ISDN_PPP
2708 if (isdn_ppp_init() < 0) {
2709 printk(KERN_WARNING
"isdn: Could not create PPP-device-structs\n");
2710 tty_unregister_driver(&dev
->mdm
.tty_modem
);
2711 tty_unregister_driver(&dev
->mdm
.cua_modem
);
2712 for (i
= 0; i
< ISDN_MAX_CHANNELS
; i
++)
2713 kfree(dev
->mdm
.info
[i
].xmit_buf
- 4);
2714 isdn_cleanup_devfs();
2715 devfs_unregister_chrdev(ISDN_MAJOR
, "isdn");
2719 #endif /* CONFIG_ISDN_PPP */
2721 strcpy(tmprev
, isdn_revision
);
2722 printk(KERN_NOTICE
"ISDN subsystem Rev: %s/", isdn_getrev(tmprev
));
2723 strcpy(tmprev
, isdn_tty_revision
);
2724 printk("%s/", isdn_getrev(tmprev
));
2725 strcpy(tmprev
, isdn_net_revision
);
2726 printk("%s/", isdn_getrev(tmprev
));
2727 strcpy(tmprev
, isdn_ppp_revision
);
2728 printk("%s/", isdn_getrev(tmprev
));
2729 strcpy(tmprev
, isdn_audio_revision
);
2730 printk("%s/", isdn_getrev(tmprev
));
2731 strcpy(tmprev
, isdn_v110_revision
);
2732 printk("%s", isdn_getrev(tmprev
));
2735 printk(" loaded\n");
2749 cleanup_module(void)
2754 #ifdef CONFIG_ISDN_PPP
2759 if (isdn_net_rmall() < 0) {
2760 printk(KERN_WARNING
"isdn: net-device busy, remove cancelled\n");
2761 restore_flags(flags
);
2764 if (tty_unregister_driver(&dev
->mdm
.tty_modem
)) {
2765 printk(KERN_WARNING
"isdn: ttyI-device busy, remove cancelled\n");
2766 restore_flags(flags
);
2769 if (tty_unregister_driver(&dev
->mdm
.cua_modem
)) {
2770 printk(KERN_WARNING
"isdn: cui-device busy, remove cancelled\n");
2771 restore_flags(flags
);
2774 for (i
= 0; i
< ISDN_MAX_CHANNELS
; i
++) {
2775 isdn_tty_cleanup_xmit(&dev
->mdm
.info
[i
]);
2776 kfree(dev
->mdm
.info
[i
].xmit_buf
- 4);
2777 #ifdef CONFIG_ISDN_TTY_FAX
2778 kfree(dev
->mdm
.info
[i
].fax
);
2781 if (devfs_unregister_chrdev(ISDN_MAJOR
, "isdn") != 0) {
2782 printk(KERN_WARNING
"isdn: controldevice busy, remove cancelled\n");
2783 restore_flags(flags
);
2785 isdn_cleanup_devfs();
2786 del_timer(&dev
->timer
);
2787 restore_flags(flags
);
2788 /* call vfree with interrupts enabled, else it will hang */
2790 printk(KERN_NOTICE
"ISDN-subsystem unloaded\n");