Linux-2.4.0-test2
[davej-history.git] / drivers / isdn / isdn_common.c
blobfa5a3d844413f04223ac036b813c7cb1a832d2ab
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)
12 * any later version.
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
31 * into CVS
33 * Revision 1.99 2000/02/26 01:00:52 keil
34 * changes from 2.3.47
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
58 * or remote side.
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
91 * added abc features
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
155 * register_isdn().
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'
176 * peer phone number)
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.
221 * Added V.110.
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
273 * were possible.
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
292 * to isdn_tty.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
338 * typo in #ifdef.
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
370 * Bugfixes:
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.
385 * Some cleanup.
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
398 * fixed a few bugs
400 * Revision 1.7 1996/05/02 03:55:17 fritz
401 * Bugfixes:
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
407 * Commit test
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
432 * Initial revision
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"
448 #endif
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>
456 /* Debugflags */
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;
467 #else
468 static char *isdn_ppp_revision = ": none $";
469 #endif
470 #ifdef CONFIG_ISDN_AUDIO
471 extern char *isdn_audio_revision;
472 #else
473 static char *isdn_audio_revision = ": none $";
474 #endif
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);
487 void
488 isdn_MOD_INC_USE_COUNT(void)
490 int i;
492 MOD_INC_USE_COUNT;
493 for (i = 0; i < dev->drivers; i++) {
494 isdn_ctrl cmd;
496 cmd.driver = i;
497 cmd.arg = 0;
498 cmd.command = ISDN_CMD_LOCK;
499 isdn_command(&cmd);
500 dev->drv[i]->locks++;
504 void
505 isdn_MOD_DEC_USE_COUNT(void)
507 int i;
509 MOD_DEC_USE_COUNT;
510 for (i = 0; i < dev->drivers; i++)
511 if (dev->drv[i]->locks > 0) {
512 isdn_ctrl cmd;
514 cmd.driver = i;
515 cmd.arg = 0;
516 cmd.command = ISDN_CMD_UNLOCK;
517 isdn_command(&cmd);
518 dev->drv[i]->locks--;
522 #if defined(ISDN_DEBUG_NET_DUMP) || defined(ISDN_DEBUG_MODEM_DUMP)
523 void
524 isdn_dumppkt(char *s, u_char * p, int len, int dumplen)
526 int dumpc;
528 printk(KERN_DEBUG "%s(%d) ", s, len);
529 for (dumpc = 0; (dumpc < dumplen) && (len); len--, dumpc++)
530 printk(" %02x", *p++);
531 printk("\n");
533 #endif
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)
539 static int
540 isdn_star(char *s, char *p)
542 while (isdn_wildmat(s, p)) {
543 if (*++s == '\0')
544 return (2);
546 return (0);
550 * Shell-type Pattern-matching for incoming caller-Ids
551 * This function gets a string in s and checks, if it matches the pattern
552 * given in p.
554 * Return:
555 * 0 = match.
556 * 1 = no match.
557 * 2 = no match. Would eventually match, if s would be longer.
559 * Possible Patterns:
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)
570 register int last;
571 register int matched;
572 register int reverse;
573 register int nostar = 1;
575 if (!(*s) && !(*p))
576 return(1);
577 for (; *p; s++, p++)
578 switch (*p) {
579 case '\\':
581 * Literal match with following character,
582 * fall through.
584 p++;
585 default:
586 if (*s != *p)
587 return (*s == '\0')?2:1;
588 continue;
589 case '?':
590 /* Match anything. */
591 if (*s == '\0')
592 return (2);
593 continue;
594 case '*':
595 nostar = 0;
596 /* Trailing star matches everything. */
597 return (*++p ? isdn_star(s, p) : 0);
598 case '[':
599 /* [^....] means inverse character class. */
600 if ((reverse = (p[1] == '^')))
601 p++;
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)
605 matched = 1;
606 if (matched == reverse)
607 return (1);
608 continue;
610 return (*s == '\0')?0:nostar;
613 static void
614 isdn_free_queue(struct sk_buff_head *queue)
616 struct sk_buff *skb;
617 unsigned long flags;
619 save_flags(flags);
620 cli();
621 if (skb_queue_len(queue))
622 while ((skb = skb_dequeue(queue)))
623 dev_kfree_skb(skb);
624 restore_flags(flags);
628 isdn_dc2minor(int di, int ch)
630 int i;
631 for (i = 0; i < ISDN_MAX_CHANNELS; i++)
632 if (dev->chanmap[i] == ch && dev->drvmap[i] == di)
633 return i;
634 return -1;
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;
642 static void
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) {
656 isdn_timer_cnt1 = 0;
657 if (tf & ISDN_TIMER_NETDIAL)
658 isdn_net_dial();
660 if (++isdn_timer_cnt2 >= ISDN_TIMER_1SEC) {
661 isdn_timer_cnt2 = 0;
662 if (tf & ISDN_TIMER_NETHANGUP)
663 isdn_net_autohup();
664 if (++isdn_timer_cnt3 > ISDN_TIMER_RINGING) {
665 isdn_timer_cnt3 = 0;
666 if (tf & ISDN_TIMER_MODEMRING)
667 isdn_tty_modem_ring();
669 if (++isdn_timer_cnt4 > ISDN_TIMER_KEEPINT) {
670 isdn_timer_cnt4 = 0;
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();
679 #endif
682 if (tf)
684 int flags;
686 save_flags(flags);
687 cli();
688 mod_timer(&dev->timer, jiffies+ISDN_TIMER_RES);
689 restore_flags(flags);
693 void
694 isdn_timer_ctrl(int tf, int onoff)
696 int flags;
698 save_flags(flags);
699 cli();
700 if ((tf & ISDN_TIMER_SLOW) && (!(dev->tflags & ISDN_TIMER_SLOW))) {
701 /* If the slow-timer wasn't activated until now */
702 isdn_timer_cnt1 = 0;
703 isdn_timer_cnt2 = 0;
705 if (onoff)
706 dev->tflags |= tf;
707 else
708 dev->tflags &= ~tf;
709 if (dev->tflags)
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)
717 static void
718 isdn_receive_skb_callback(int di, int channel, struct sk_buff *skb)
720 int i;
722 if ((i = isdn_dc2minor(di, channel)) == -1) {
723 dev_kfree_skb(skb);
724 return;
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))
731 return;
733 /* V.110 handling
734 * makes sense for async streams only, so it is
735 * called after possible net-device delivery.
737 if (dev->v110[i]) {
738 atomic_inc(&dev->v110use[i]);
739 skb = isdn_v110_decode(dev->v110[i], skb);
740 atomic_dec(&dev->v110use[i]);
741 if (!skb)
742 return;
745 /* No network-device found, deliver to tty or raw-channel */
746 if (skb->len) {
747 if (isdn_tty_rcv_skb(i, di, channel, skb))
748 return;
749 wake_up_interruptible(&dev->drv[di]->rcv_waitq[channel]);
750 } else
751 dev_kfree_skb(skb);
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
758 * linklevel instead.
761 isdn_command(isdn_ctrl *cmd)
763 if (cmd->driver == -1) {
764 printk(KERN_WARNING "isdn_command command(%x) driver -1\n", cmd->command);
765 return(1);
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);
775 switch (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);
787 } else
788 dev->v110emu[idx] = 0;
791 return dev->drv[cmd->driver]->interface->command(cmd);
794 void
795 isdn_all_eaz(int di, int ch)
797 isdn_ctrl cmd;
799 if (di < 0)
800 return;
801 cmd.driver = di;
802 cmd.arg = ch;
803 cmd.command = ISDN_CMD_SETEAZ;
804 cmd.parm.num[0] = '\0';
805 isdn_command(&cmd);
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) {
817 int di;
818 int ch;
820 di = (cm->adr.Controller & 0x7f) -1;
821 ch = isdn_dc2minor(di, (cm->adr.Controller>>8)& 0x7f);
822 switch(cm->Command) {
823 case CAPI_FACILITY:
824 /* in the moment only handled in tty */
825 return(isdn_tty_capi_facility(cm));
826 default:
827 return(-1);
831 static int
832 isdn_status_callback(isdn_ctrl * c)
834 int di;
835 ulong flags;
836 int i;
837 int r;
838 int retval = 0;
839 isdn_ctrl cmd;
841 di = c->driver;
842 i = isdn_dc2minor(di, c->arg);
843 switch (c->command) {
844 case ISDN_STAT_BSENT:
845 if (i < 0)
846 return -1;
847 if (dev->global_flags & ISDN_GLOBAL_STOPPED)
848 return 0;
849 if (isdn_net_stat_callback(i, c))
850 return 0;
851 if (isdn_v110_stat_callback(i, c))
852 return 0;
853 if (isdn_tty_stat_callback(i, c))
854 return 0;
855 wake_up_interruptible(&dev->drv[di]->snd_waitq[c->arg]);
856 break;
857 case ISDN_STAT_STAVAIL:
858 save_flags(flags);
859 cli();
860 dev->drv[di]->stavail += c->arg;
861 restore_flags(flags);
862 wake_up_interruptible(&dev->drv[di]->st_waitq);
863 break;
864 case ISDN_STAT_RUN:
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();
870 break;
871 case ISDN_STAT_STOP:
872 dev->drv[di]->flags &= ~DRV_FLAG_RUNNING;
873 break;
874 case ISDN_STAT_ICALL:
875 if (i < 0)
876 return -1;
877 #ifdef ISDN_DEBUG_STATCALLB
878 printk(KERN_DEBUG "ICALL (net): %d %ld %s\n", di, c->arg, c->parm.num);
879 #endif
880 if (dev->global_flags & ISDN_GLOBAL_STOPPED) {
881 cmd.driver = di;
882 cmd.arg = c->arg;
883 cmd.command = ISDN_CMD_HANGUP;
884 isdn_command(&cmd);
885 return 0;
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));
889 switch (r) {
890 case 0:
891 /* No network-device replies.
892 * Try ttyI's.
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
899 if (divert_if)
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 */
905 cmd.driver = di;
906 cmd.arg = c->arg;
907 cmd.command = ISDN_CMD_HANGUP;
908 isdn_command(&cmd);
909 retval = 2;
911 break;
912 case 1:
913 /* Schedule connection-setup */
914 isdn_net_dial();
915 cmd.driver = di;
916 cmd.arg = c->arg;
917 cmd.command = ISDN_CMD_ACCEPTD;
918 isdn_command(&cmd);
919 retval = 1;
920 break;
921 case 2: /* For calling back, first reject incoming call ... */
922 case 3: /* Interface found, but down, reject call actively */
923 retval = 2;
924 printk(KERN_INFO "isdn: Rejecting Call\n");
925 cmd.driver = di;
926 cmd.arg = c->arg;
927 cmd.command = ISDN_CMD_HANGUP;
928 isdn_command(&cmd);
929 if (r == 3)
930 break;
931 /* Fall through */
932 case 4:
933 /* ... then start callback. */
934 isdn_net_dial();
935 break;
936 case 5:
937 /* Number would eventually match, if longer */
938 retval = 3;
939 break;
941 #ifdef ISDN_DEBUG_STATCALLB
942 printk(KERN_DEBUG "ICALL: ret=%d\n", retval);
943 #endif
944 return retval;
945 break;
946 case ISDN_STAT_CINF:
947 if (i < 0)
948 return -1;
949 #ifdef ISDN_DEBUG_STATCALLB
950 printk(KERN_DEBUG "CINF: %ld %s\n", c->arg, c->parm.num);
951 #endif
952 if (dev->global_flags & ISDN_GLOBAL_STOPPED)
953 return 0;
954 if (strcmp(c->parm.num, "0"))
955 isdn_net_stat_callback(i, c);
956 isdn_tty_stat_callback(i, c);
957 break;
958 case ISDN_STAT_CAUSE:
959 #ifdef ISDN_DEBUG_STATCALLB
960 printk(KERN_DEBUG "CAUSE: %ld %s\n", c->arg, c->parm.num);
961 #endif
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
966 if (divert_if)
967 divert_if->stat_callback(c);
968 #endif CONFIG_ISDN_DIVERSION
969 break;
970 case ISDN_STAT_DISPLAY:
971 #ifdef ISDN_DEBUG_STATCALLB
972 printk(KERN_DEBUG "DISPLAY: %ld %s\n", c->arg, c->parm.display);
973 #endif
974 isdn_tty_stat_callback(i, c);
975 #ifdef CONFIG_ISDN_DIVERSION
976 if (divert_if)
977 divert_if->stat_callback(c);
978 #endif CONFIG_ISDN_DIVERSION
979 break;
980 case ISDN_STAT_DCONN:
981 if (i < 0)
982 return -1;
983 #ifdef ISDN_DEBUG_STATCALLB
984 printk(KERN_DEBUG "DCONN: %ld\n", c->arg);
985 #endif
986 if (dev->global_flags & ISDN_GLOBAL_STOPPED)
987 return 0;
988 /* Find any net-device, waiting for D-channel setup */
989 if (isdn_net_stat_callback(i, c))
990 break;
991 isdn_v110_stat_callback(i, c);
992 /* Find any ttyI, waiting for D-channel setup */
993 if (isdn_tty_stat_callback(i, c)) {
994 cmd.driver = di;
995 cmd.arg = c->arg;
996 cmd.command = ISDN_CMD_ACCEPTB;
997 isdn_command(&cmd);
998 break;
1000 break;
1001 case ISDN_STAT_DHUP:
1002 if (i < 0)
1003 return -1;
1004 #ifdef ISDN_DEBUG_STATCALLB
1005 printk(KERN_DEBUG "DHUP: %ld\n", c->arg);
1006 #endif
1007 if (dev->global_flags & ISDN_GLOBAL_STOPPED)
1008 return 0;
1009 dev->drv[di]->online &= ~(1 << (c->arg));
1010 isdn_info_update();
1011 /* Signal hangup to network-devices */
1012 if (isdn_net_stat_callback(i, c))
1013 break;
1014 isdn_v110_stat_callback(i, c);
1015 if (isdn_tty_stat_callback(i, c))
1016 break;
1017 #ifdef CONFIG_ISDN_DIVERSION
1018 if (divert_if)
1019 divert_if->stat_callback(c);
1020 #endif CONFIG_ISDN_DIVERSION
1021 break;
1022 break;
1023 case ISDN_STAT_BCONN:
1024 if (i < 0)
1025 return -1;
1026 #ifdef ISDN_DEBUG_STATCALLB
1027 printk(KERN_DEBUG "BCONN: %ld\n", c->arg);
1028 #endif
1029 /* Signal B-channel-connect to network-devices */
1030 if (dev->global_flags & ISDN_GLOBAL_STOPPED)
1031 return 0;
1032 dev->drv[di]->online |= (1 << (c->arg));
1033 isdn_info_update();
1034 if (isdn_net_stat_callback(i, c))
1035 break;
1036 isdn_v110_stat_callback(i, c);
1037 if (isdn_tty_stat_callback(i, c))
1038 break;
1039 break;
1040 case ISDN_STAT_BHUP:
1041 if (i < 0)
1042 return -1;
1043 #ifdef ISDN_DEBUG_STATCALLB
1044 printk(KERN_DEBUG "BHUP: %ld\n", c->arg);
1045 #endif
1046 if (dev->global_flags & ISDN_GLOBAL_STOPPED)
1047 return 0;
1048 dev->drv[di]->online &= ~(1 << (c->arg));
1049 isdn_info_update();
1050 #ifdef CONFIG_ISDN_X25
1051 /* Signal hangup to network-devices */
1052 if (isdn_net_stat_callback(i, c))
1053 break;
1054 #endif
1055 isdn_v110_stat_callback(i, c);
1056 if (isdn_tty_stat_callback(i, c))
1057 break;
1058 break;
1059 case ISDN_STAT_NODCH:
1060 if (i < 0)
1061 return -1;
1062 #ifdef ISDN_DEBUG_STATCALLB
1063 printk(KERN_DEBUG "NODCH: %ld\n", c->arg);
1064 #endif
1065 if (dev->global_flags & ISDN_GLOBAL_STOPPED)
1066 return 0;
1067 if (isdn_net_stat_callback(i, c))
1068 break;
1069 if (isdn_tty_stat_callback(i, c))
1070 break;
1071 break;
1072 case ISDN_STAT_ADDCH:
1073 if (isdn_add_channels(dev->drv[di], di, c->arg, 1))
1074 return -1;
1075 isdn_info_update();
1076 break;
1077 case ISDN_STAT_DISCH:
1078 save_flags(flags);
1079 cli();
1080 for (i = 0; i < ISDN_MAX_CHANNELS; i++)
1081 if ((dev->drvmap[i] == di) &&
1082 (dev->chanmap[i] == c->arg)) {
1083 if (c->parm.num[0])
1084 dev->usage[i] &= ~ISDN_USAGE_DISABLED;
1085 else
1086 if (USG_NONE(dev->usage[i])) {
1087 dev->usage[i] |= ISDN_USAGE_DISABLED;
1089 else
1090 retval = -1;
1091 break;
1093 restore_flags(flags);
1094 isdn_info_update();
1095 break;
1096 case ISDN_STAT_UNLOAD:
1097 while (dev->drv[di]->locks > 0) {
1098 isdn_ctrl cmd;
1099 cmd.driver = di;
1100 cmd.arg = 0;
1101 cmd.command = ISDN_CMD_UNLOCK;
1102 isdn_command(&cmd);
1103 dev->drv[di]->locks--;
1105 save_flags(flags);
1106 cli();
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);
1115 dev->drivers--;
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';
1126 isdn_info_update();
1127 set_global_features();
1128 restore_flags(flags);
1129 return 0;
1130 case ISDN_STAT_L1ERR:
1131 break;
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);
1137 break;
1138 #endif
1139 #ifdef CONFIG_ISDN_AUDIO
1140 case ISDN_STAT_AUDIO:
1141 isdn_tty_stat_callback(i, c);
1142 break;
1143 #endif
1144 #ifdef CONFIG_ISDN_DIVERSION
1145 case ISDN_STAT_PROT:
1146 case ISDN_STAT_REDIR:
1147 if (divert_if)
1148 return(divert_if->stat_callback(c));
1149 #endif CONFIG_ISDN_DIVERSION
1150 default:
1151 return -1;
1153 return 0;
1157 * Get integer from char-pointer, set pointer to end of number
1160 isdn_getnum(char **p)
1162 int v = -1;
1164 while (*p[0] >= '0' && *p[0] <= '9')
1165 v = ((v < 0) ? 0 : (v * 10)) + (int) ((*p[0]++) - '0');
1166 return v;
1169 #define DLE 0x10
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)
1187 int left;
1188 int count;
1189 int count_pull;
1190 int count_put;
1191 int dflag;
1192 struct sk_buff *skb;
1193 u_char *cp;
1195 if (!dev->drv[di])
1196 return 0;
1197 if (skb_queue_empty(&dev->drv[di]->rpqueue[channel])) {
1198 if (sleep)
1199 interruptible_sleep_on(sleep);
1200 else
1201 return 0;
1203 left = MIN(len, dev->drv[di]->rcvcount[channel]);
1204 cp = buf;
1205 count = 0;
1206 while (left) {
1207 if (!(skb = skb_peek(&dev->drv[di]->rpqueue[channel])))
1208 break;
1209 #ifdef CONFIG_ISDN_AUDIO
1210 if (ISDN_AUDIO_SKB_LOCK(skb))
1211 break;
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);
1217 dflag = 0;
1218 count_pull = count_put = 0;
1219 while ((count_pull < skb->len) && (left > 0)) {
1220 left--;
1221 if (dev->drv[di]->DLEflag & DLEmask) {
1222 *cp++ = DLE;
1223 dev->drv[di]->DLEflag &= ~DLEmask;
1224 } else {
1225 *cp++ = *p;
1226 if (*p == DLE) {
1227 dev->drv[di]->DLEflag |= DLEmask;
1228 (ISDN_AUDIO_SKB_DLECOUNT(skb))--;
1230 p++;
1231 count_pull++;
1233 count_put++;
1235 if (count_pull >= skb->len)
1236 dflag = 1;
1237 } else {
1238 #endif
1239 /* No DLE's in buff, so simply copy it */
1240 dflag = 1;
1241 if ((count_pull = skb->len) > left) {
1242 count_pull = left;
1243 dflag = 0;
1245 count_put = count_pull;
1246 memcpy(cp, skb->data, count_put);
1247 cp += count_put;
1248 left -= count_put;
1249 #ifdef CONFIG_ISDN_AUDIO
1251 #endif
1252 count += count_put;
1253 if (fp) {
1254 memset(fp, 0, count_put);
1255 fp += count_put;
1257 if (dflag) {
1258 /* We got all the data in this buff.
1259 * Now we can dequeue it.
1261 if (fp)
1262 *(fp - 1) = 0xff;
1263 #ifdef CONFIG_ISDN_AUDIO
1264 ISDN_AUDIO_SKB_LOCK(skb) = 0;
1265 #endif
1266 skb = skb_dequeue(&dev->drv[di]->rpqueue[channel]);
1267 dev_kfree_skb(skb);
1268 } else {
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;
1276 #endif
1278 dev->drv[di]->rcvcount[channel] -= count_put;
1280 return count;
1283 static __inline int
1284 isdn_minor2drv(int minor)
1286 return (dev->drvmap[minor]);
1289 static __inline int
1290 isdn_minor2chan(int minor)
1292 return (dev->chanmap[minor]);
1295 static char *
1296 isdn_statstr(void)
1298 static char istatbuf[2048];
1299 char *p;
1300 int i;
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++) {
1329 if (dev->drv[i]) {
1330 sprintf(p, "%ld ", dev->drv[i]->online);
1331 p = istatbuf + strlen(istatbuf);
1332 } else {
1333 sprintf(p, "? ");
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);
1343 sprintf(p, "\n");
1344 return istatbuf;
1347 /* Module interface-code */
1349 void
1350 isdn_info_update(void)
1352 infostruct *p = dev->infochain;
1354 while (p) {
1355 *(p->private) = 1;
1356 p = (infostruct *) p->next;
1358 wake_up_interruptible(&(dev->info_waitq));
1361 static ssize_t
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);
1365 int len = 0;
1366 ulong flags;
1367 int drvidx;
1368 int chidx;
1369 char *p;
1371 if (off != &file->f_pos)
1372 return -ESPIPE;
1374 if (minor == ISDN_MINOR_STATUS) {
1375 if (!file->private_data) {
1376 if (file->f_flags & O_NONBLOCK)
1377 return -EAGAIN;
1378 interruptible_sleep_on(&(dev->info_waitq));
1380 p = isdn_statstr();
1381 file->private_data = 0;
1382 if ((len = strlen(p)) <= count) {
1383 if (copy_to_user(buf, p, len))
1384 return -EFAULT;
1385 *off += len;
1386 return len;
1388 return 0;
1390 if (!dev->drivers)
1391 return -ENODEV;
1392 if (minor < ISDN_MINOR_CTRL) {
1393 drvidx = isdn_minor2drv(minor);
1394 if (drvidx < 0)
1395 return -ENODEV;
1396 if (!(dev->drv[drvidx]->flags & DRV_FLAG_RUNNING))
1397 return -ENODEV;
1398 chidx = isdn_minor2chan(minor);
1399 if( ! (p = kmalloc(count,GFP_KERNEL)) ) return -ENOMEM;
1400 save_flags(flags);
1401 cli();
1402 len = isdn_readbchan(drvidx, chidx, p, 0, count,
1403 &dev->drv[drvidx]->rcv_waitq[chidx]);
1404 *off += len;
1405 restore_flags(flags);
1406 if( copy_to_user(buf,p,len) ) len = -EFAULT;
1407 kfree(p);
1408 return len;
1410 if (minor <= ISDN_MINOR_CTRLMAX) {
1411 drvidx = isdn_minor2drv(minor - ISDN_MINOR_CTRL);
1412 if (drvidx < 0)
1413 return -ENODEV;
1414 if (!dev->drv[drvidx]->stavail) {
1415 if (file->f_flags & O_NONBLOCK)
1416 return -EAGAIN;
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));
1423 else
1424 len = 0;
1425 save_flags(flags);
1426 cli();
1427 if (len)
1428 dev->drv[drvidx]->stavail -= len;
1429 else
1430 dev->drv[drvidx]->stavail = 0;
1431 restore_flags(flags);
1432 *off += len;
1433 return len;
1435 #ifdef CONFIG_ISDN_PPP
1436 if (minor <= ISDN_MINOR_PPPMAX)
1437 return (isdn_ppp_read(minor - ISDN_MINOR_PPP, file, buf, count));
1438 #endif
1439 return -ENODEV;
1442 static loff_t
1443 isdn_lseek(struct file *file, loff_t offset, int orig)
1445 return -ESPIPE;
1448 static ssize_t
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);
1452 int drvidx;
1453 int chidx;
1455 if (off != &file->f_pos)
1456 return -ESPIPE;
1458 if (minor == ISDN_MINOR_STATUS)
1459 return -EPERM;
1460 if (!dev->drivers)
1461 return -ENODEV;
1462 if (minor < ISDN_MINOR_CTRL) {
1463 drvidx = isdn_minor2drv(minor);
1464 if (drvidx < 0)
1465 return -ENODEV;
1466 if (!(dev->drv[drvidx]->flags & DRV_FLAG_RUNNING))
1467 return -ENODEV;
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]);
1471 return count;
1473 if (minor <= ISDN_MINOR_CTRLMAX) {
1474 drvidx = isdn_minor2drv(minor - ISDN_MINOR_CTRL);
1475 if (drvidx < 0)
1476 return -ENODEV;
1478 * We want to use the isdnctrl device to load the firmware
1480 if (!(dev->drv[drvidx]->flags & DRV_FLAG_RUNNING))
1481 return -ENODEV;
1483 if (dev->drv[drvidx]->interface->writecmd)
1484 return (dev->drv[drvidx]->interface->
1485 writecmd(buf, count, 1, drvidx, isdn_minor2chan(minor)));
1486 else
1487 return count;
1489 #ifdef CONFIG_ISDN_PPP
1490 if (minor <= ISDN_MINOR_PPPMAX)
1491 return (isdn_ppp_write(minor - ISDN_MINOR_PPP, file, buf, count));
1492 #endif
1493 return -ENODEV;
1496 static unsigned int
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;
1509 return mask;
1511 if (minor >= ISDN_MINOR_CTRL && minor <= ISDN_MINOR_CTRLMAX) {
1512 if (drvidx < 0) {
1513 /* driver deregistered while file open */
1514 return POLLHUP;
1516 poll_wait(file, &(dev->drv[drvidx]->st_waitq), wait);
1517 mask = POLLOUT | POLLWRNORM;
1518 if (dev->drv[drvidx]->stavail) {
1519 mask |= POLLIN | POLLRDNORM;
1521 return mask;
1523 #ifdef CONFIG_ISDN_PPP
1524 if (minor <= ISDN_MINOR_PPPMAX)
1525 return (isdn_ppp_poll(file, wait));
1526 #endif
1527 printk(KERN_ERR "isdn_common: isdn_poll 2 -> what the hell\n");
1528 return POLLERR;
1532 static int
1533 isdn_ioctl(struct inode *inode, struct file *file, uint cmd, ulong arg)
1535 uint minor = MINOR(inode->i_rdev);
1536 isdn_ctrl c;
1537 int drvidx;
1538 int chidx;
1539 int ret;
1540 int i;
1541 char *p;
1542 char *s;
1543 union iocpar {
1544 char name[10];
1545 char bname[22];
1546 isdn_ioctl_struct iocts;
1547 isdn_net_ioctl_phone phone;
1548 isdn_net_ioctl_cfg cfg;
1549 } iocpar;
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) {
1558 switch (cmd) {
1559 case IIOCGETDVR:
1560 return (TTY_DV +
1561 (NET_DV << 8) +
1562 (INF_DV << 16));
1563 case IIOCGETCPS:
1564 if (arg) {
1565 ulong *p = (ulong *) arg;
1566 int i;
1567 if ((ret = verify_area(VERIFY_WRITE, (void *) arg,
1568 sizeof(ulong) * ISDN_MAX_CHANNELS * 2)))
1569 return ret;
1570 for (i = 0; i < ISDN_MAX_CHANNELS; i++) {
1571 put_user(dev->ibytes[i], p++);
1572 put_user(dev->obytes[i], p++);
1574 return 0;
1575 } else
1576 return -EINVAL;
1577 break;
1578 #ifdef CONFIG_NETDEVICES
1579 case IIOCNETGPN:
1580 /* Get peer phone number of a connected
1581 * isdn network interface */
1582 if (arg) {
1583 if (copy_from_user((char *) &phone, (char *) arg, sizeof(phone)))
1584 return -EFAULT;
1585 return isdn_net_getpeer(&phone, (isdn_net_ioctl_phone *) arg);
1586 } else
1587 return -EINVAL;
1588 #endif
1589 default:
1590 return -EINVAL;
1593 if (!dev->drivers)
1594 return -ENODEV;
1595 if (minor < ISDN_MINOR_CTRL) {
1596 drvidx = isdn_minor2drv(minor);
1597 if (drvidx < 0)
1598 return -ENODEV;
1599 chidx = isdn_minor2chan(minor);
1600 if (!(dev->drv[drvidx]->flags & DRV_FLAG_RUNNING))
1601 return -ENODEV;
1602 return 0;
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.
1612 switch (cmd) {
1613 case IIOCNETDWRSET:
1614 printk(KERN_INFO "INFO: ISDN_DW_ABC_EXTENSION not enabled\n");
1615 return(-EINVAL);
1616 case IIOCNETLCR:
1617 printk(KERN_INFO "INFO: ISDN_ABC_LCR_SUPPORT not enabled\n");
1618 return -ENODEV;
1619 #ifdef CONFIG_NETDEVICES
1620 case IIOCNETAIF:
1621 /* Add a network-interface */
1622 if (arg) {
1623 if (copy_from_user(name, (char *) arg, sizeof(name)))
1624 return -EFAULT;
1625 s = name;
1626 } else {
1627 s = NULL;
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)){
1633 ret = -EFAULT;
1634 } else {
1635 ret = 0;
1637 } else
1638 ret = -ENODEV;
1639 up(&dev->sem);
1640 return ret;
1641 case IIOCNETASL:
1642 /* Add a slave to a network-interface */
1643 if (arg) {
1644 if (copy_from_user(bname, (char *) arg, sizeof(bname) - 1))
1645 return -EFAULT;
1646 } else
1647 return -EINVAL;
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)){
1652 ret = -EFAULT;
1653 } else {
1654 ret = 0;
1656 } else
1657 ret = -ENODEV;
1658 up(&dev->sem);
1659 return ret;
1660 case IIOCNETDIF:
1661 /* Delete a network-interface */
1662 if (arg) {
1663 if (copy_from_user(name, (char *) arg, sizeof(name)))
1664 return -EFAULT;
1665 ret = down_interruptible(&dev->sem);
1666 if( ret ) return ret;
1667 ret = isdn_net_rm(name);
1668 up(&dev->sem);
1669 return ret;
1670 } else
1671 return -EINVAL;
1672 case IIOCNETSCF:
1673 /* Set configurable parameters of a network-interface */
1674 if (arg) {
1675 if (copy_from_user((char *) &cfg, (char *) arg, sizeof(cfg)))
1676 return -EFAULT;
1677 return isdn_net_setcfg(&cfg);
1678 } else
1679 return -EINVAL;
1680 case IIOCNETGCF:
1681 /* Get configurable parameters of a network-interface */
1682 if (arg) {
1683 if (copy_from_user((char *) &cfg, (char *) arg, sizeof(cfg)))
1684 return -EFAULT;
1685 if (!(ret = isdn_net_getcfg(&cfg))) {
1686 if (copy_to_user((char *) arg, (char *) &cfg, sizeof(cfg)))
1687 return -EFAULT;
1689 return ret;
1690 } else
1691 return -EINVAL;
1692 case IIOCNETANM:
1693 /* Add a phone-number to a network-interface */
1694 if (arg) {
1695 if (copy_from_user((char *) &phone, (char *) arg, sizeof(phone)))
1696 return -EFAULT;
1697 ret = down_interruptible(&dev->sem);
1698 if( ret ) return ret;
1699 ret = isdn_net_addphone(&phone);
1700 up(&dev->sem);
1701 return ret;
1702 } else
1703 return -EINVAL;
1704 case IIOCNETGNM:
1705 /* Get list of phone-numbers of a network-interface */
1706 if (arg) {
1707 if (copy_from_user((char *) &phone, (char *) arg, sizeof(phone)))
1708 return -EFAULT;
1709 ret = down_interruptible(&dev->sem);
1710 if( ret ) return ret;
1711 ret = isdn_net_getphones(&phone, (char *) arg);
1712 up(&dev->sem);
1713 return ret;
1714 } else
1715 return -EINVAL;
1716 case IIOCNETDNM:
1717 /* Delete a phone-number of a network-interface */
1718 if (arg) {
1719 if (copy_from_user((char *) &phone, (char *) arg, sizeof(phone)))
1720 return -EFAULT;
1721 ret = down_interruptible(&dev->sem);
1722 if( ret ) return ret;
1723 ret = isdn_net_delphone(&phone);
1724 up(&dev->sem);
1725 return ret;
1726 } else
1727 return -EINVAL;
1728 case IIOCNETDIL:
1729 /* Force dialing of a network-interface */
1730 if (arg) {
1731 if (copy_from_user(name, (char *) arg, sizeof(name)))
1732 return -EFAULT;
1733 return isdn_net_force_dial(name);
1734 } else
1735 return -EINVAL;
1736 #ifdef CONFIG_ISDN_PPP
1737 case IIOCNETALN:
1738 if (!arg)
1739 return -EINVAL;
1740 if (copy_from_user(name, (char *) arg, sizeof(name)))
1741 return -EFAULT;
1742 return isdn_ppp_dial_slave(name);
1743 case IIOCNETDLN:
1744 if (!arg)
1745 return -EINVAL;
1746 if (copy_from_user(name, (char *) arg, sizeof(name)))
1747 return -EFAULT;
1748 return isdn_ppp_hangup_slave(name);
1749 #endif
1750 case IIOCNETHUP:
1751 /* Force hangup of a network-interface */
1752 if (!arg)
1753 return -EINVAL;
1754 if (copy_from_user(name, (char *) arg, sizeof(name)))
1755 return -EFAULT;
1756 return isdn_net_force_hangup(name);
1757 break;
1758 #endif /* CONFIG_NETDEVICES */
1759 case IIOCSETVER:
1760 dev->net_verbose = arg;
1761 printk(KERN_INFO "isdn: Verbose-Level is %d\n", dev->net_verbose);
1762 return 0;
1763 case IIOCSETGST:
1764 if (arg)
1765 dev->global_flags |= ISDN_GLOBAL_STOPPED;
1766 else
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");
1770 return 0;
1771 case IIOCSETBRJ:
1772 drvidx = -1;
1773 if (arg) {
1774 int i;
1775 char *p;
1776 if (copy_from_user((char *) &iocts, (char *) arg,
1777 sizeof(isdn_ioctl_struct)))
1778 return -EFAULT;
1779 if (strlen(iocts.drvid)) {
1780 if ((p = strchr(iocts.drvid, ',')))
1781 *p = 0;
1782 drvidx = -1;
1783 for (i = 0; i < ISDN_MAX_DRIVERS; i++)
1784 if (!(strcmp(dev->drvid[i], iocts.drvid))) {
1785 drvidx = i;
1786 break;
1790 if (drvidx == -1)
1791 return -ENODEV;
1792 if (iocts.arg)
1793 dev->drv[drvidx]->flags |= DRV_FLAG_REJBUS;
1794 else
1795 dev->drv[drvidx]->flags &= ~DRV_FLAG_REJBUS;
1796 return 0;
1797 case IIOCSIGPRF:
1798 dev->profd = current;
1799 return 0;
1800 break;
1801 case IIOCGETPRF:
1802 /* Get all Modem-Profiles */
1803 if (arg) {
1804 char *p = (char *) arg;
1805 int i;
1807 if ((ret = verify_area(VERIFY_WRITE, (void *) arg,
1808 (ISDN_MODEM_NUMREG + ISDN_MSNLEN + ISDN_LMSNLEN)
1809 * ISDN_MAX_CHANNELS)))
1810 return ret;
1812 for (i = 0; i < ISDN_MAX_CHANNELS; i++) {
1813 if (copy_to_user(p, dev->mdm.info[i].emu.profile,
1814 ISDN_MODEM_NUMREG))
1815 return -EFAULT;
1816 p += ISDN_MODEM_NUMREG;
1817 if (copy_to_user(p, dev->mdm.info[i].emu.pmsn, ISDN_MSNLEN))
1818 return -EFAULT;
1819 p += ISDN_MSNLEN;
1820 if (copy_to_user(p, dev->mdm.info[i].emu.plmsn, ISDN_LMSNLEN))
1821 return -EFAULT;
1822 p += ISDN_LMSNLEN;
1824 return (ISDN_MODEM_NUMREG + ISDN_MSNLEN + ISDN_LMSNLEN) * ISDN_MAX_CHANNELS;
1825 } else
1826 return -EINVAL;
1827 break;
1828 case IIOCSETPRF:
1829 /* Set all Modem-Profiles */
1830 if (arg) {
1831 char *p = (char *) arg;
1832 int i;
1834 if ((ret = verify_area(VERIFY_READ, (void *) arg,
1835 (ISDN_MODEM_NUMREG + ISDN_MSNLEN)
1836 * ISDN_MAX_CHANNELS)))
1837 return ret;
1839 for (i = 0; i < ISDN_MAX_CHANNELS; i++) {
1840 if (copy_from_user(dev->mdm.info[i].emu.profile, p,
1841 ISDN_MODEM_NUMREG))
1842 return -EFAULT;
1843 p += ISDN_MODEM_NUMREG;
1844 if (copy_from_user(dev->mdm.info[i].emu.pmsn, p, ISDN_MSNLEN))
1845 return -EFAULT;
1846 p += ISDN_MSNLEN;
1848 return 0;
1849 } else
1850 return -EINVAL;
1851 break;
1852 case IIOCSETMAP:
1853 case IIOCGETMAP:
1854 /* Set/Get MSN->EAZ-Mapping for a driver */
1855 if (arg) {
1857 if (copy_from_user((char *) &iocts,
1858 (char *) arg,
1859 sizeof(isdn_ioctl_struct)))
1860 return -EFAULT;
1861 if (strlen(iocts.drvid)) {
1862 drvidx = -1;
1863 for (i = 0; i < ISDN_MAX_DRIVERS; i++)
1864 if (!(strcmp(dev->drvid[i], iocts.drvid))) {
1865 drvidx = i;
1866 break;
1868 } else
1869 drvidx = 0;
1870 if (drvidx == -1)
1871 return -ENODEV;
1872 if (cmd == IIOCSETMAP) {
1873 int loop = 1;
1875 p = (char *) iocts.arg;
1876 i = 0;
1877 while (loop) {
1878 int j = 0;
1880 while (1) {
1881 if ((ret = verify_area(VERIFY_READ, p, 1)))
1882 return ret;
1883 get_user(bname[j], p++);
1884 switch (bname[j]) {
1885 case '\0':
1886 loop = 0;
1887 /* Fall through */
1888 case ',':
1889 bname[j] = '\0';
1890 strcpy(dev->drv[drvidx]->msn2eaz[i], bname);
1891 j = ISDN_MSNLEN;
1892 break;
1893 default:
1894 j++;
1896 if (j >= ISDN_MSNLEN)
1897 break;
1899 if (++i > 9)
1900 break;
1902 } else {
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))
1910 return -EFAULT;
1911 p += strlen(bname);
1914 return 0;
1915 } else
1916 return -EINVAL;
1917 case IIOCDBGVAR:
1918 if (arg) {
1919 if (copy_to_user((char *) arg, (char *) &dev, sizeof(ulong)))
1920 return -EFAULT;
1921 return 0;
1922 } else
1923 return -EINVAL;
1924 break;
1925 default:
1926 if ((cmd & IIOCDRVCTL) == IIOCDRVCTL)
1927 cmd = ((cmd >> _IOC_NRSHIFT) & _IOC_NRMASK) & ISDN_DRVIOCTL_MASK;
1928 else
1929 return -EINVAL;
1930 if (arg) {
1931 int i;
1932 char *p;
1933 if (copy_from_user((char *) &iocts, (char *) arg, sizeof(isdn_ioctl_struct)))
1934 return -EFAULT;
1935 if (strlen(iocts.drvid)) {
1936 if ((p = strchr(iocts.drvid, ',')))
1937 *p = 0;
1938 drvidx = -1;
1939 for (i = 0; i < ISDN_MAX_DRIVERS; i++)
1940 if (!(strcmp(dev->drvid[i], iocts.drvid))) {
1941 drvidx = i;
1942 break;
1944 } else
1945 drvidx = 0;
1946 if (drvidx == -1)
1947 return -ENODEV;
1948 if ((ret = verify_area(VERIFY_WRITE, (void *) arg,
1949 sizeof(isdn_ioctl_struct))))
1950 return ret;
1951 c.driver = drvidx;
1952 c.command = ISDN_CMD_IOCTL;
1953 c.arg = cmd;
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)))
1958 return -EFAULT;
1959 return ret;
1960 } else
1961 return -EINVAL;
1964 #ifdef CONFIG_ISDN_PPP
1965 if (minor <= ISDN_MINOR_PPPMAX)
1966 return (isdn_ppp_ioctl(minor - ISDN_MINOR_PPP, file, cmd, arg));
1967 #endif
1968 return -ENODEV;
1970 #undef name
1971 #undef bname
1972 #undef iocts
1973 #undef phone
1974 #undef cfg
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.
1982 static int
1983 isdn_open(struct inode *ino, struct file *filep)
1985 uint minor = MINOR(ino->i_rdev);
1986 int drvidx;
1987 int chidx;
1989 if (minor == ISDN_MINOR_STATUS) {
1990 infostruct *p;
1992 if ((p = (infostruct *) kmalloc(sizeof(infostruct), GFP_KERNEL))) {
1993 MOD_INC_USE_COUNT;
1994 p->next = (char *) dev->infochain;
1995 p->private = (char *) &(filep->private_data);
1996 dev->infochain = p;
1997 /* At opening we allow a single update */
1998 filep->private_data = (char *) 1;
1999 return 0;
2000 } else
2001 return -ENOMEM;
2003 if (!dev->channels)
2004 return -ENODEV;
2005 if (minor < ISDN_MINOR_CTRL) {
2006 drvidx = isdn_minor2drv(minor);
2007 if (drvidx < 0)
2008 return -ENODEV;
2009 chidx = isdn_minor2chan(minor);
2010 if (!(dev->drv[drvidx]->flags & DRV_FLAG_RUNNING))
2011 return -ENODEV;
2012 if (!(dev->drv[drvidx]->online & (1 << chidx)))
2013 return -ENODEV;
2014 isdn_MOD_INC_USE_COUNT();
2015 return 0;
2017 if (minor <= ISDN_MINOR_CTRLMAX) {
2018 drvidx = isdn_minor2drv(minor - ISDN_MINOR_CTRL);
2019 if (drvidx < 0)
2020 return -ENODEV;
2021 isdn_MOD_INC_USE_COUNT();
2022 return 0;
2024 #ifdef CONFIG_ISDN_PPP
2025 if (minor <= ISDN_MINOR_PPPMAX) {
2026 int ret;
2027 if (!(ret = isdn_ppp_open(minor - ISDN_MINOR_PPP, filep)))
2028 isdn_MOD_INC_USE_COUNT();
2029 return ret;
2031 #endif
2032 return -ENODEV;
2035 static int
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;
2044 MOD_DEC_USE_COUNT;
2045 while (p) {
2046 if (p->private == (char *) &(filep->private_data)) {
2047 if (q)
2048 q->next = p->next;
2049 else
2050 dev->infochain = (infostruct *) (p->next);
2051 kfree(p);
2052 return 0;
2054 q = p;
2055 p = (infostruct *) (p->next);
2057 printk(KERN_WARNING "isdn: No private data while closing isdnctrl\n");
2058 return 0;
2060 isdn_MOD_DEC_USE_COUNT();
2061 if (minor < ISDN_MINOR_CTRL)
2062 return 0;
2063 if (minor <= ISDN_MINOR_CTRLMAX) {
2064 if (dev->profd == current)
2065 dev->profd = NULL;
2066 return 0;
2068 #ifdef CONFIG_ISDN_PPP
2069 if (minor <= ISDN_MINOR_PPPMAX)
2070 isdn_ppp_release(minor - ISDN_MINOR_PPP, filep);
2071 #endif
2072 return 0;
2075 static struct file_operations isdn_fops =
2077 llseek: isdn_lseek,
2078 read: isdn_read,
2079 write: isdn_write,
2080 poll: isdn_poll,
2081 ioctl: isdn_ioctl,
2082 open: isdn_open,
2083 release: isdn_close,
2086 char *
2087 isdn_map_eaz2msn(char *msn, int di)
2089 driver *this = dev->drv[di];
2090 int i;
2092 if (strlen(msn) == 1) {
2093 i = msn[0] - '0';
2094 if ((i >= 0) && (i <= 9))
2095 if (strlen(this->msn2eaz[i]))
2096 return (this->msn2eaz[i]);
2098 return (msn);
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)
2111 int i;
2112 ulong flags;
2113 ulong features;
2114 ulong vfeatures;
2116 save_flags(flags);
2117 cli();
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])))
2131 continue;
2132 if (!strcmp(isdn_map_eaz2msn(msn, d), "-"))
2133 continue;
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;
2143 isdn_info_update();
2144 restore_flags(flags);
2145 return i;
2146 } else {
2147 if ((pre_dev == d) && (pre_chan == dev->chanmap[i])) {
2148 dev->usage[i] &= ISDN_USAGE_EXCLUSIVE;
2149 dev->usage[i] |= usage;
2150 isdn_info_update();
2151 restore_flags(flags);
2152 return i;
2158 restore_flags(flags);
2159 return -1;
2163 * Set state of ISDN-channel to 'unused'
2165 void
2166 isdn_free_channel(int di, int ch, int usage)
2168 int i;
2169 ulong flags;
2171 save_flags(flags);
2172 cli();
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], "???");
2179 dev->ibytes[i] = 0;
2180 dev->obytes[i] = 0;
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 !
2187 isdn_info_update();
2188 isdn_free_queue(&dev->drv[di]->rpqueue[ch]);
2190 restore_flags(flags);
2194 * Cancel Exclusive-Flag for ISDN-channel
2196 void
2197 isdn_unexclusive_channel(int di, int ch)
2199 int i;
2200 ulong flags;
2202 save_flags(flags);
2203 cli();
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;
2208 isdn_info_update();
2209 restore_flags(flags);
2210 return;
2212 restore_flags(flags);
2216 * writebuf replacement for SKB_ABLE drivers
2218 static int
2219 isdn_writebuf_stub(int drvidx, int chan, const u_char * buf, int len,
2220 int user)
2222 int ret;
2223 int hl = dev->drv[drvidx]->interface->hl_hdrlen;
2224 struct sk_buff *skb = alloc_skb(hl + len, GFP_ATOMIC);
2226 if (!skb)
2227 return 0;
2228 skb_reserve(skb, hl);
2229 if (user)
2230 copy_from_user(skb_put(skb, len), buf, len);
2231 else
2232 memcpy(skb_put(skb, len), buf, len);
2233 ret = dev->drv[drvidx]->interface->writebuf_skb(drvidx, chan, 1, skb);
2234 if (ret <= 0)
2235 dev_kfree_skb(skb);
2236 if (ret > 0)
2237 dev->obytes[isdn_dc2minor(drvidx, chan)] += ret;
2238 return 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)
2247 int ret;
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]);
2256 if (!nskb)
2257 return 0;
2258 v110_ret = *((int *)nskb->data);
2259 skb_pull(nskb, sizeof(int));
2260 if (!nskb->len) {
2261 dev_kfree_skb(nskb);
2262 dev_kfree_skb(skb);
2263 return v110_ret;
2265 /* V.110 must always be acknowledged */
2266 ack = 1;
2267 ret = dev->drv[drvidx]->interface->writebuf_skb(drvidx, chan, ack, nskb);
2268 } else {
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
2278 * not need this
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);
2286 if( ret > 0 ){
2287 dev_kfree_skb(skb);
2288 } else {
2289 dev_kfree_skb(skb_tmp);
2291 } else {
2292 ret = dev->drv[drvidx]->interface->writebuf_skb(drvidx, chan, ack, skb);
2295 if (ret > 0) {
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]);
2301 dev_kfree_skb(skb);
2302 /* For V.110 return unencoded data length */
2303 ret = v110_ret;
2304 if (ret == skb->len)
2305 dev_kfree_skb(skb);
2307 } else
2308 if (dev->v110[idx])
2309 dev_kfree_skb(nskb);
2310 return ret;
2314 register_isdn_module(isdn_module *m) {
2315 return 0;
2319 unregister_isdn_module(isdn_module *m) {
2320 return 0;
2324 isdn_add_channels(driver *d, int drvidx, int n, int adding)
2326 int j, k, m;
2327 ulong flags;
2329 init_waitqueue_head(&d->st_waitq);
2330 if (d->flags & DRV_FLAG_RUNNING)
2331 return -1;
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",
2338 ISDN_MAX_CHANNELS);
2339 return -1;
2342 if ((adding) && (d->rcverr))
2343 kfree(d->rcverr);
2344 if (!(d->rcverr = (int *) kmalloc(sizeof(int) * m, GFP_KERNEL))) {
2345 printk(KERN_WARNING "register_isdn: Could not alloc rcverr\n");
2346 return -1;
2348 memset((char *) d->rcverr, 0, sizeof(int) * m);
2350 if ((adding) && (d->rcvcount))
2351 kfree(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);
2355 return -1;
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]);
2362 kfree(d->rpqueue);
2364 if (!(d->rpqueue =
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");
2367 if (!adding) {
2368 kfree(d->rcvcount);
2369 kfree(d->rcverr);
2371 return -1;
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");
2383 if (!adding) {
2384 kfree(d->rpqueue);
2385 kfree(d->rcvcount);
2386 kfree(d->rcverr);
2388 return -1;
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]);
2396 dev->channels += n;
2397 save_flags(flags);
2398 cli();
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);
2405 break;
2407 restore_flags(flags);
2408 d->channels = m;
2409 return 0;
2413 * Low-level-driver registration
2416 static void
2417 set_global_features(void)
2419 int drvidx;
2421 dev->global_features = 0;
2422 for (drvidx = 0; drvidx < ISDN_MAX_DRIVERS; drvidx++) {
2423 if (!dev->drv[drvidx])
2424 continue;
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))
2436 return(NULL);
2437 return(dev->drvid[di]); /* driver name */
2438 } /* map_drvname */
2440 static int map_namedrv(char *id)
2441 { int i;
2443 for (i = 0; i < ISDN_MAX_DRIVERS; i++)
2444 { if (!strcmp(dev->drvid[i],id))
2445 return(i);
2447 return(-1);
2448 } /* map_namedrv */
2450 int DIVERT_REG_NAME(isdn_divert_if *i_div)
2452 if (i_div->if_magic != DIVERT_IF_MAGIC)
2453 return(DIVERT_VER_ERR);
2454 switch (i_div->cmd)
2456 case DIVERT_CMD_REL:
2457 if (divert_if != i_div)
2458 return(DIVERT_REL_ERR);
2459 divert_if = NULL; /* free interface */
2460 MOD_DEC_USE_COUNT;
2461 return(DIVERT_NO_ERR);
2463 case DIVERT_CMD_REG:
2464 if (divert_if)
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;
2469 MOD_INC_USE_COUNT;
2470 divert_if = i_div; /* remember interface */
2471 return(DIVERT_NO_ERR);
2473 default:
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);
2489 #endif
2492 register_isdn(isdn_if * i)
2494 driver *d;
2495 int j;
2496 ulong flags;
2497 int drvidx;
2499 if (dev->drivers >= ISDN_MAX_DRIVERS) {
2500 printk(KERN_WARNING "register_isdn: Max. %d drivers supported\n",
2501 ISDN_MAX_DRIVERS);
2502 return 0;
2504 if (!i->writebuf_skb) {
2505 printk(KERN_WARNING "register_isdn: No write routine given.\n");
2506 return 0;
2508 if (!(d = (driver *) kmalloc(sizeof(driver), GFP_KERNEL))) {
2509 printk(KERN_WARNING "register_isdn: Could not alloc driver-struct\n");
2510 return 0;
2512 memset((char *) d, 0, sizeof(driver));
2514 d->maxbufsize = i->maxbufsize;
2515 d->pktcount = 0;
2516 d->stavail = 0;
2517 d->flags = DRV_FLAG_LOADED;
2518 d->online = 0;
2519 d->interface = i;
2520 d->channels = 0;
2521 for (drvidx = 0; drvidx < ISDN_MAX_DRIVERS; drvidx++)
2522 if (!dev->drv[drvidx])
2523 break;
2524 if (isdn_add_channels(d, drvidx, i->channels, 0)) {
2525 kfree(d);
2526 return 0;
2528 i->channels = drvidx;
2529 i->rcvcallb_skb = isdn_receive_skb_callback;
2530 i->statcallb = isdn_status_callback;
2531 if (!strlen(i->id))
2532 sprintf(i->id, "line%d", drvidx);
2533 save_flags(flags);
2534 cli();
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);
2540 isdn_info_update();
2541 dev->drivers++;
2542 set_global_features();
2543 restore_flags(flags);
2544 return 1;
2548 *****************************************************************************
2549 * And now the modules code.
2550 *****************************************************************************
2553 extern int printk(const char *fmt,...);
2555 #ifdef MODULE
2556 #define isdn_init init_module
2557 #endif
2559 static char *
2560 isdn_getrev(const char *revision)
2562 char *rev;
2563 char *p;
2565 if ((p = strchr(revision, ':'))) {
2566 rev = p + 2;
2567 p = strchr(rev, '$');
2568 *--p = 0;
2569 } else
2570 rev = "???";
2571 return rev;
2574 #ifdef CONFIG_DEVFS_FS
2576 static devfs_handle_t devfs_handle = NULL;
2578 static void isdn_register_devfs(int k)
2580 char buf[11];
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,
2586 &isdn_fops, NULL);
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,
2591 &isdn_fops, NULL);
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
2603 int i;
2604 # endif
2606 devfs_handle = devfs_mk_dir (NULL, "isdn", 4, NULL);
2607 # ifdef CONFIG_ISDN_PPP
2608 for (i = 0; i < ISDN_MAX_CHANNELS; i++) {
2609 char buf[8];
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);
2617 # endif
2619 dev->devfs_handle_isdninfo =
2620 devfs_register (devfs_handle, "isdninfo", DEVFS_FL_DEFAULT,
2621 ISDN_MAJOR, ISDN_MINOR_STATUS, 0600 | S_IFCHR,
2622 &isdn_fops, NULL);
2623 dev->devfs_handle_isdnctrl =
2624 devfs_register (devfs_handle, "isdnctrl", DEVFS_FL_DEFAULT,
2625 ISDN_MAJOR, ISDN_MINOR_CTRL, 0600 | S_IFCHR,
2626 &isdn_fops, NULL);
2629 static void isdn_cleanup_devfs(void)
2631 # ifdef CONFIG_ISDN_PPP
2632 int i;
2633 for (i = 0; i < ISDN_MAX_CHANNELS; i++)
2634 devfs_unregister (dev->devfs_handle_ipppX[i]);
2635 # endif
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)
2644 return;
2647 static void isdn_unregister_devfs(int dummy)
2649 return;
2652 static void isdn_init_devfs(void)
2654 return;
2657 static void isdn_cleanup_devfs(void)
2659 return;
2662 #endif /* CONFIG_DEVFS_FS */
2665 * Allocate and initialize all data, register modem-devices
2668 isdn_init(void)
2670 int i;
2671 char tmprev[50];
2673 if (!(dev = (isdn_dev *) vmalloc(sizeof(isdn_dev)))) {
2674 printk(KERN_WARNING "isdn: Could not allocate device-struct.\n");
2675 return -EIO;
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;
2685 dev->m_idx[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");
2692 vfree(dev);
2693 return -EIO;
2695 isdn_init_devfs();
2696 if ((i = isdn_tty_modem_init()) < 0) {
2697 printk(KERN_WARNING "isdn: Could not register tty devices\n");
2698 if (i == -3)
2699 tty_unregister_driver(&dev->mdm.cua_modem);
2700 if (i <= -2)
2701 tty_unregister_driver(&dev->mdm.tty_modem);
2702 vfree(dev);
2703 isdn_cleanup_devfs();
2704 devfs_unregister_chrdev(ISDN_MAJOR, "isdn");
2705 return -EIO;
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");
2716 vfree(dev);
2717 return -EIO;
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));
2734 #ifdef MODULE
2735 printk(" loaded\n");
2736 #else
2737 printk("\n");
2738 isdn_cards_init();
2739 #endif
2740 isdn_info_update();
2741 return 0;
2744 #ifdef MODULE
2746 * Unload module
2748 void
2749 cleanup_module(void)
2751 int flags;
2752 int i;
2754 #ifdef CONFIG_ISDN_PPP
2755 isdn_ppp_cleanup();
2756 #endif
2757 save_flags(flags);
2758 cli();
2759 if (isdn_net_rmall() < 0) {
2760 printk(KERN_WARNING "isdn: net-device busy, remove cancelled\n");
2761 restore_flags(flags);
2762 return;
2764 if (tty_unregister_driver(&dev->mdm.tty_modem)) {
2765 printk(KERN_WARNING "isdn: ttyI-device busy, remove cancelled\n");
2766 restore_flags(flags);
2767 return;
2769 if (tty_unregister_driver(&dev->mdm.cua_modem)) {
2770 printk(KERN_WARNING "isdn: cui-device busy, remove cancelled\n");
2771 restore_flags(flags);
2772 return;
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);
2779 #endif
2781 if (devfs_unregister_chrdev(ISDN_MAJOR, "isdn") != 0) {
2782 printk(KERN_WARNING "isdn: controldevice busy, remove cancelled\n");
2783 restore_flags(flags);
2784 } else {
2785 isdn_cleanup_devfs();
2786 del_timer(&dev->timer);
2787 restore_flags(flags);
2788 /* call vfree with interrupts enabled, else it will hang */
2789 vfree(dev);
2790 printk(KERN_NOTICE "ISDN-subsystem unloaded\n");
2793 #endif