1 /* $Id: isdn_common.c,v 1.55 1998/02/23 23:35:32 fritz Exp $
3 * Linux ISDN subsystem, common used functions (linklevel).
5 * Copyright 1994,95,96 by Fritz Elfert (fritz@wuemaus.franken.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 * Note: This file differs from the corresponding revision as present in the
24 * isdn4linux CVS repository because some later bug fixes have been extracted
25 * from the repository and merged into this file. -- Henner Eisen
27 * $Log: isdn_common.c,v $
28 * Revision 1.55 1998/02/23 23:35:32 fritz
29 * Eliminated some compiler warnings.
31 * Revision 1.54 1998/02/22 19:44:19 fritz
32 * Bugfixes and improvements regarding V.110, V.110 now running.
34 * Revision 1.53 1998/02/20 17:18:05 fritz
35 * Changes for recent kernels.
36 * Added common stub for sending commands to lowlevel.
39 * Revision 1.52 1998/01/31 22:05:57 keil
40 * Lots of changes for X.25 support:
41 * Added generic support for connection-controlling encapsulation protocols
42 * Added support of BHUP status message
43 * Added support for additional p_encap X25IFACE
44 * Added support for kernels >= 2.1.72
46 * Revision 1.51 1998/01/31 19:17:29 calle
47 * merged changes from and for 2.1.82
49 * Revision 1.50 1997/12/12 06:12:11 calle
50 * moved EXPORT_SYMBOL(register_isdn) from isdn_syms.c to isdn_common.c
52 * Revision 1.49 1997/11/06 17:16:52 keil
53 * Sync to 2.1.62 changes
55 * Revision 1.48 1997/11/02 23:55:50 keil
56 * Andi Kleen's changes for 2.1.60
57 * without it the isdninfo and isdnctrl devices won't work
59 * Revision 1.47 1997/10/09 21:28:46 fritz
60 * New HL<->LL interface:
61 * New BSENT callback with nr. of bytes included.
62 * Sending without ACK.
63 * New L1 error status (not yet in use).
64 * Cleaned up obsolete structures.
65 * Implemented Cisco-SLARP.
66 * Changed local net-interface data to be dynamically allocated.
67 * Removed old 2.0 compatibility stuff.
69 * Revision 1.46 1997/10/01 09:20:27 fritz
70 * Removed old compatibility stuff for 2.0.X kernels.
71 * From now on, this code is for 2.1.X ONLY!
72 * Old stuff is still in the separate branch.
74 * Revision 1.45 1997/08/21 23:11:41 fritz
75 * Added changes for kernels >= 2.1.45
77 * Revision 1.44 1997/05/27 15:17:23 fritz
78 * Added changes for recent 2.1.x kernels:
79 * changed return type of isdn_close
80 * queue_task_* -> queue_task
81 * clear/set_bit -> test_and_... where apropriate.
82 * changed type of hard_header_cache parameter.
84 * Revision 1.43 1997/03/31 14:09:43 fritz
85 * Fixed memory leak in isdn_close().
87 * Revision 1.42 1997/03/30 16:51:08 calle
88 * changed calls to copy_from_user/copy_to_user and removed verify_area
91 * Revision 1.41 1997/03/24 22:54:41 fritz
92 * Some small fixes in debug code.
94 * Revision 1.40 1997/03/08 08:13:51 fritz
95 * Bugfix: IIOCSETMAP (Set mapping) was broken.
97 * Revision 1.39 1997/03/07 01:32:54 fritz
98 * Added proper ifdef's for CONFIG_ISDN_AUDIO
100 * Revision 1.38 1997/03/05 21:15:02 fritz
101 * Fix: reduced stack usage of isdn_ioctl() and isdn_set_allcfg()
103 * Revision 1.37 1997/03/02 14:29:18 fritz
104 * More ttyI related cleanup.
106 * Revision 1.36 1997/02/28 02:32:40 fritz
107 * Cleanup: Moved some tty related stuff from isdn_common.c
109 * Bugfix: Bisync protocol did not behave like documented.
111 * Revision 1.35 1997/02/21 13:01:19 fritz
112 * Changes CAUSE message output in kernel log.
114 * Revision 1.34 1997/02/10 20:12:43 fritz
115 * Changed interface for reporting incoming calls.
117 * Revision 1.33 1997/02/10 10:05:42 fritz
118 * More changes for Kernel 2.1.X
119 * Symbol information moved to isdn_syms.c
121 * Revision 1.32 1997/02/03 22:55:26 fritz
122 * Reformatted according CodingStyle.
123 * Changed isdn_writebuf_stub static.
124 * Slow down tty-RING counter.
125 * skb->free stuff replaced by macro.
126 * Bugfix in audio-skb locking.
127 * Bugfix in HL-driver locking.
129 * Revision 1.31 1997/01/17 01:19:18 fritz
130 * Applied chargeint patch.
132 * Revision 1.30 1997/01/14 01:27:47 fritz
133 * Changed audio receive not to rely on skb->users and skb->lock.
134 * Added ATI2 and related variables.
135 * Started adding full-duplex audio capability.
137 * Revision 1.29 1997/01/12 23:33:03 fritz
138 * Made isdn_all_eaz foolproof.
140 * Revision 1.28 1996/11/13 02:33:19 fritz
141 * Fixed a race condition.
143 * Revision 1.27 1996/10/27 22:02:41 keil
144 * return codes for ISDN_STAT_ICALL
146 * Revision 1.26 1996/10/23 11:59:40 fritz
147 * More compatibility changes.
149 * Revision 1.25 1996/10/22 23:13:54 fritz
150 * Changes for compatibility to 2.0.X and 2.1.X kernels.
152 * Revision 1.24 1996/10/11 14:02:03 fritz
153 * Bugfix: call to isdn_ppp_timer_timeout() never compiled, because of
156 * Revision 1.23 1996/06/25 18:35:38 fritz
157 * Fixed bogus memory access in isdn_set_allcfg().
159 * Revision 1.22 1996/06/24 17:37:37 fritz
160 * Bugfix: isdn_timer_ctrl() did restart timer, even if it
161 * was already running.
162 * lowlevel driver locking did use wrong parameters.
164 * Revision 1.21 1996/06/15 14:58:20 fritz
165 * Added version signatures for data structures used
166 * by userlevel programs.
168 * Revision 1.20 1996/06/12 16:01:49 fritz
169 * Bugfix: Remote B-channel hangup sometimes did not result
170 * in a NO CARRIER on tty.
172 * Revision 1.19 1996/06/11 14:52:04 hipp
173 * minor bugfix in isdn_writebuf_skb_stub()
175 * Revision 1.18 1996/06/06 14:51:51 fritz
176 * Changed to support DTMF decoding on audio playback also.
178 * Revision 1.17 1996/06/05 02:24:10 fritz
179 * Added DTMF decoder for audio mode.
181 * Revision 1.16 1996/06/03 20:09:05 fritz
182 * Bugfix: called wrong function pointer for locking in
183 * isdn_get_free_channel().
185 * Revision 1.15 1996/05/31 01:10:54 fritz
187 * Lowlevel modules did not get locked correctly.
188 * Did show wrong revision when initializing.
189 * Minor fixes in ioctl code.
190 * sk_buff did not get freed, if error in writebuf_stub.
192 * Revision 1.14 1996/05/18 01:36:55 fritz
193 * Added spelling corrections and some minor changes
194 * to stay in sync with kernel.
196 * Revision 1.13 1996/05/17 15:43:30 fritz
197 * Bugfix: decrement of rcvcount in readbchan() corrected.
199 * Revision 1.12 1996/05/17 03:55:43 fritz
200 * Changed DLE handling for audio receive.
202 * Added display of isdn_audio_revision.
204 * Revision 1.11 1996/05/11 21:51:32 fritz
205 * Changed queue management to use sk_buffs.
207 * Revision 1.10 1996/05/10 08:49:16 fritz
208 * Checkin before major changes of tty-code.
210 * Revision 1.9 1996/05/07 09:19:41 fritz
211 * Adapted to changes in isdn_tty.c
213 * Revision 1.8 1996/05/06 11:34:51 hipp
216 * Revision 1.7 1996/05/02 03:55:17 fritz
218 * - B-channel connect message for modem devices
219 * sometimes did not result in a CONNECT-message.
220 * - register_isdn did not check for driverId-conflicts.
222 * Revision 1.6 1996/04/30 20:57:21 fritz
225 * Revision 1.5 1996/04/20 16:19:07 fritz
226 * Changed slow timer handlers to increase accuracy.
227 * Added statistic information for usage by xisdnload.
228 * Fixed behaviour of isdnctrl-device on non-blocked io.
229 * Fixed all io to go through generic writebuf-function without
230 * bypassing. Same for incoming data.
231 * Fixed bug: Last channel had been unusable.
232 * Fixed kfree of tty xmit_buf on ppp initialization failure.
234 * Revision 1.4 1996/02/11 02:33:26 fritz
235 * Fixed bug in main timer-dispatcher.
236 * Bugfix: Lot of tty-callbacks got called regardless of the events already
237 * been handled by network-devices.
238 * Changed ioctl-names.
240 * Revision 1.3 1996/01/22 05:16:11 fritz
241 * Changed ioctl-names.
242 * Fixed bugs in isdn_open and isdn_close regarding PPP_MINOR.
244 * Revision 1.2 1996/01/21 16:52:40 fritz
245 * Support for sk_buffs added, changed header-stuffing.
247 * Revision 1.1 1996/01/09 04:12:52 fritz
252 #include <linux/config.h>
253 #include <linux/module.h>
254 #include <linux/version.h>
255 #include <linux/poll.h>
256 #include <linux/isdn.h>
257 #include "isdn_common.h"
258 #include "isdn_tty.h"
259 #include "isdn_net.h"
260 #include "isdn_ppp.h"
261 #ifdef CONFIG_ISDN_AUDIO
262 #include "isdn_audio.h"
264 #include "isdn_v110.h"
265 #include "isdn_cards.h"
268 #undef ISDN_DEBUG_STATCALLB
270 isdn_dev
*dev
= (isdn_dev
*) 0;
272 static char *isdn_revision
= "$Revision: 1.55 $";
274 extern char *isdn_net_revision
;
275 extern char *isdn_tty_revision
;
276 #ifdef CONFIG_ISDN_PPP
277 extern char *isdn_ppp_revision
;
279 static char *isdn_ppp_revision
= ": none $";
281 #ifdef CONFIG_ISDN_AUDIO
282 extern char *isdn_audio_revision
;
284 static char *isdn_audio_revision
= ": none $";
286 extern char *isdn_v110_revision
;
288 static int isdn_writebuf_stub(int, int, const u_char
*, int, int);
291 isdn_MOD_INC_USE_COUNT(void)
297 isdn_MOD_DEC_USE_COUNT(void)
302 #if defined(ISDN_DEBUG_NET_DUMP) || defined(ISDN_DEBUG_MODEM_DUMP)
304 isdn_dumppkt(char *s
, u_char
* p
, int len
, int dumplen
)
308 printk(KERN_DEBUG
"%s(%d) ", s
, len
);
309 for (dumpc
= 0; (dumpc
< dumplen
) && (len
); len
--, dumpc
++)
310 printk(" %02x", *p
++);
316 isdn_free_queue(struct sk_buff_head
*queue
)
323 if (skb_queue_len(queue
))
324 while ((skb
= skb_dequeue(queue
)))
326 restore_flags(flags
);
330 isdn_dc2minor(int di
, int ch
)
333 for (i
= 0; i
< ISDN_MAX_CHANNELS
; i
++)
334 if (dev
->chanmap
[i
] == ch
&& dev
->drvmap
[i
] == di
)
339 static int isdn_timer_cnt1
= 0;
340 static int isdn_timer_cnt2
= 0;
341 static int isdn_timer_cnt3
= 0;
342 static int isdn_timer_cnt4
= 0;
345 isdn_timer_funct(ulong dummy
)
347 int tf
= dev
->tflags
;
349 if (tf
& ISDN_TIMER_FAST
) {
350 if (tf
& ISDN_TIMER_MODEMREAD
)
351 isdn_tty_readmodem();
352 if (tf
& ISDN_TIMER_MODEMPLUS
)
353 isdn_tty_modem_escape();
354 if (tf
& ISDN_TIMER_MODEMXMIT
)
355 isdn_tty_modem_xmit();
357 if (tf
& ISDN_TIMER_SLOW
) {
358 if (++isdn_timer_cnt1
>= ISDN_TIMER_02SEC
) {
360 if (tf
& ISDN_TIMER_NETDIAL
)
363 if (++isdn_timer_cnt2
>= ISDN_TIMER_1SEC
) {
365 if (tf
& ISDN_TIMER_NETHANGUP
)
367 if (++isdn_timer_cnt3
> ISDN_TIMER_RINGING
) {
369 if (tf
& ISDN_TIMER_MODEMRING
)
370 isdn_tty_modem_ring();
372 if (++isdn_timer_cnt4
> ISDN_TIMER_KEEPINT
) {
374 if (tf
& ISDN_TIMER_KEEPALIVE
)
375 isdn_net_slarp_out();
377 #if (defined CONFIG_ISDN_PPP) && (defined CONFIG_ISDN_MPP)
378 if (tf
& ISDN_TIMER_IPPP
)
379 isdn_ppp_timer_timeout();
388 del_timer(&dev
->timer
);
389 dev
->timer
.expires
= jiffies
+ ISDN_TIMER_RES
;
390 add_timer(&dev
->timer
);
391 restore_flags(flags
);
396 isdn_timer_ctrl(int tf
, int onoff
)
402 if ((tf
& ISDN_TIMER_SLOW
) && (!(dev
->tflags
& ISDN_TIMER_SLOW
))) {
403 /* If the slow-timer wasn't activated until now */
412 if (!del_timer(&dev
->timer
)) /* del_timer is 1, when active */
413 dev
->timer
.expires
= jiffies
+ ISDN_TIMER_RES
;
414 add_timer(&dev
->timer
);
416 restore_flags(flags
);
420 * Receive a packet from B-Channel. (Called from low-level-module)
423 isdn_receive_skb_callback(int di
, int channel
, struct sk_buff
*skb
)
427 if ((i
= isdn_dc2minor(di
, channel
)) == -1) {
431 /* Update statistics */
432 dev
->ibytes
[i
] += skb
->len
;
434 /* First, try to deliver data to network-device */
435 if (isdn_net_rcv_skb(i
, skb
))
439 * makes sense for async streams only, so it is
440 * called after possible net-device delivery.
443 atomic_inc(&dev
->v110use
[i
]);
444 skb
= isdn_v110_decode(dev
->v110
[i
], skb
);
445 atomic_dec(&dev
->v110use
[i
]);
450 /* No network-device found, deliver to tty or raw-channel */
452 if (isdn_tty_rcv_skb(i
, di
, channel
, skb
))
454 wake_up_interruptible(&dev
->drv
[di
]->rcv_waitq
[channel
]);
460 * Intercept command from Linklevel to Lowlevel.
461 * If layer 2 protocol is V.110 and this is not supported by current
462 * lowlevel-driver, use driver's transparent mode and handle V.110 in
466 isdn_command(isdn_ctrl
*cmd
)
468 if (cmd
->command
== ISDN_CMD_SETL2
) {
469 int idx
= isdn_dc2minor(cmd
->driver
, cmd
->arg
& 255);
470 unsigned long l2prot
= (cmd
->arg
>> 8) & 255;
471 unsigned long features
= (dev
->drv
[cmd
->driver
]->interface
->features
472 >> ISDN_FEATURE_L2_SHIFT
) &
473 ISDN_FEATURE_L2_MASK
;
474 unsigned long l2_feature
= (1 << l2prot
);
477 case ISDN_PROTO_L2_V11096
:
478 case ISDN_PROTO_L2_V11019
:
479 case ISDN_PROTO_L2_V11038
:
480 /* If V.110 requested, but not supported by
481 * HL-driver, set emulator-flag and change
482 * Layer-2 to transparent
484 if (!(features
& l2_feature
)) {
485 dev
->v110emu
[idx
] = l2prot
;
486 cmd
->arg
= (cmd
->arg
& 255) |
487 (ISDN_PROTO_L2_TRANS
<< 8);
489 dev
->v110emu
[idx
] = 0;
492 return dev
->drv
[cmd
->driver
]->interface
->command(cmd
);
496 isdn_all_eaz(int di
, int ch
)
504 cmd
.command
= ISDN_CMD_SETEAZ
;
505 cmd
.parm
.num
[0] = '\0';
510 isdn_status_callback(isdn_ctrl
* c
)
520 i
= isdn_dc2minor(di
, c
->arg
);
521 switch (c
->command
) {
522 case ISDN_STAT_BSENT
:
525 if (dev
->global_flags
& ISDN_GLOBAL_STOPPED
)
527 if (isdn_net_stat_callback(i
, c
))
529 if (isdn_v110_stat_callback(i
, c
))
531 if (isdn_tty_stat_callback(i
, c
))
533 wake_up_interruptible(&dev
->drv
[di
]->snd_waitq
[c
->arg
]);
535 case ISDN_STAT_STAVAIL
:
538 dev
->drv
[di
]->stavail
+= c
->arg
;
539 restore_flags(flags
);
540 wake_up_interruptible(&dev
->drv
[di
]->st_waitq
);
543 dev
->drv
[di
]->running
= 1;
544 for (i
= 0; i
< ISDN_MAX_CHANNELS
; i
++)
545 if (dev
->drvmap
[i
] == di
)
546 isdn_all_eaz(di
, dev
->chanmap
[i
]);
549 dev
->drv
[di
]->running
= 0;
551 case ISDN_STAT_ICALL
:
554 #ifdef ISDN_DEBUG_STATCALLB
555 printk(KERN_DEBUG
"ICALL (net): %d %ld %s\n", di
, c
->arg
, c
->parm
.num
);
557 if (dev
->global_flags
& ISDN_GLOBAL_STOPPED
) {
560 cmd
.command
= ISDN_CMD_HANGUP
;
564 /* Try to find a network-interface which will accept incoming call */
567 cmd
.command
= ISDN_CMD_LOCK
;
569 r
= isdn_net_find_icall(di
, c
->arg
, i
, c
->parm
.setup
);
572 /* No network-device replies.
575 if (isdn_tty_find_icall(di
, c
->arg
, c
->parm
.setup
) >= 0)
577 else if (dev
->drv
[di
]->reject_bus
) {
580 cmd
.command
= ISDN_CMD_HANGUP
;
586 /* Schedule connection-setup */
590 cmd
.command
= ISDN_CMD_ACCEPTD
;
594 case 2: /* For calling back, first reject incoming call ... */
595 case 3: /* Interface found, but down, reject call actively */
597 printk(KERN_INFO
"isdn: Rejecting Call\n");
600 cmd
.command
= ISDN_CMD_HANGUP
;
606 /* ... then start callback. */
613 cmd
.command
= ISDN_CMD_UNLOCK
;
621 #ifdef ISDN_DEBUG_STATCALLB
622 printk(KERN_DEBUG
"CINF: %ld %s\n", c
->arg
, c
->parm
.num
);
624 if (dev
->global_flags
& ISDN_GLOBAL_STOPPED
)
626 if (strcmp(c
->parm
.num
, "0"))
627 isdn_net_stat_callback(i
, c
);
628 isdn_tty_stat_callback(i
, c
);
630 case ISDN_STAT_CAUSE
:
631 #ifdef ISDN_DEBUG_STATCALLB
632 printk(KERN_DEBUG
"CAUSE: %ld %s\n", c
->arg
, c
->parm
.num
);
634 printk(KERN_INFO
"isdn: %s,ch%ld cause: %s\n",
635 dev
->drvid
[di
], c
->arg
, c
->parm
.num
);
636 isdn_tty_stat_callback(i
, c
);
638 case ISDN_STAT_DCONN
:
641 #ifdef ISDN_DEBUG_STATCALLB
642 printk(KERN_DEBUG
"DCONN: %ld\n", c
->arg
);
644 if (dev
->global_flags
& ISDN_GLOBAL_STOPPED
)
646 /* Find any net-device, waiting for D-channel setup */
647 if (isdn_net_stat_callback(i
, c
))
649 isdn_v110_stat_callback(i
, c
);
650 /* Find any ttyI, waiting for D-channel setup */
651 if (isdn_tty_stat_callback(i
, c
)) {
654 cmd
.command
= ISDN_CMD_ACCEPTB
;
662 #ifdef ISDN_DEBUG_STATCALLB
663 printk(KERN_DEBUG
"DHUP: %ld\n", c
->arg
);
665 if (dev
->global_flags
& ISDN_GLOBAL_STOPPED
)
667 dev
->drv
[di
]->flags
&= ~(1 << (c
->arg
));
669 /* Signal hangup to network-devices */
670 if (isdn_net_stat_callback(i
, c
))
672 isdn_v110_stat_callback(i
, c
);
673 if (isdn_tty_stat_callback(i
, c
))
676 case ISDN_STAT_BCONN
:
679 #ifdef ISDN_DEBUG_STATCALLB
680 printk(KERN_DEBUG
"BCONN: %ld\n", c
->arg
);
682 /* Signal B-channel-connect to network-devices */
683 if (dev
->global_flags
& ISDN_GLOBAL_STOPPED
)
685 dev
->drv
[di
]->flags
|= (1 << (c
->arg
));
687 if (isdn_net_stat_callback(i
, c
))
689 isdn_v110_stat_callback(i
, c
);
690 if (isdn_tty_stat_callback(i
, c
))
696 #ifdef ISDN_DEBUG_STATCALLB
697 printk(KERN_DEBUG
"BHUP: %ld\n", c
->arg
);
699 if (dev
->global_flags
& ISDN_GLOBAL_STOPPED
)
701 dev
->drv
[di
]->flags
&= ~(1 << (c
->arg
));
703 #ifdef CONFIG_ISDN_X25
704 /* Signal hangup to network-devices */
705 if (isdn_net_stat_callback(i
, c
))
708 isdn_v110_stat_callback(i
, c
);
709 if (isdn_tty_stat_callback(i
, c
))
712 case ISDN_STAT_NODCH
:
715 #ifdef ISDN_DEBUG_STATCALLB
716 printk(KERN_DEBUG
"NODCH: %ld\n", c
->arg
);
718 if (dev
->global_flags
& ISDN_GLOBAL_STOPPED
)
720 if (isdn_net_stat_callback(i
, c
))
722 if (isdn_tty_stat_callback(i
, c
))
725 case ISDN_STAT_ADDCH
:
727 case ISDN_STAT_UNLOAD
:
730 isdn_tty_stat_callback(i
, c
);
731 for (i
= 0; i
< ISDN_MAX_CHANNELS
; i
++)
732 if (dev
->drvmap
[i
] == di
) {
734 dev
->chanmap
[i
] = -1;
737 dev
->channels
-= dev
->drv
[di
]->channels
;
738 kfree(dev
->drv
[di
]->rcverr
);
739 kfree(dev
->drv
[di
]->rcvcount
);
740 for (i
= 0; i
< dev
->drv
[di
]->channels
; i
++)
741 isdn_free_queue(&dev
->drv
[di
]->rpqueue
[i
]);
742 kfree(dev
->drv
[di
]->rpqueue
);
743 kfree(dev
->drv
[di
]->rcv_waitq
);
744 kfree(dev
->drv
[di
]->snd_waitq
);
747 dev
->drvid
[di
][0] = '\0';
749 restore_flags(flags
);
751 case ISDN_STAT_L1ERR
:
760 * Get integer from char-pointer, set pointer to end of number
763 isdn_getnum(char **p
)
767 while (*p
[0] >= '0' && *p
[0] <= '9')
768 v
= ((v
< 0) ? 0 : (v
* 10)) + (int) ((*p
[0]++) - '0');
775 * isdn_readbchan() tries to get data from the read-queue.
776 * It MUST be called with interrupts off.
778 * Be aware that this is not an atomic operation when sleep != 0, even though
779 * interrupts are turned off! Well, like that we are currently only called
780 * on behalf of a read system call on raw device files (which are documented
781 * to be dangerous and for for debugging purpose only). The inode semaphore
782 * takes care that this is not called for the same minor device number while
783 * we are sleeping, but access is not serialized against simultaneous read()
784 * from the corresponding ttyI device. Can other ugly events, like changes
785 * of the mapping (di,ch)<->minor, happen during the sleep? --he
788 isdn_readbchan(int di
, int channel
, u_char
* buf
, u_char
* fp
, int len
, struct wait_queue
**sleep
)
800 if (skb_queue_empty(&dev
->drv
[di
]->rpqueue
[channel
])) {
802 interruptible_sleep_on(sleep
);
806 left
= MIN(len
, dev
->drv
[di
]->rcvcount
[channel
]);
810 if (!(skb
= skb_peek(&dev
->drv
[di
]->rpqueue
[channel
])))
812 #ifdef CONFIG_ISDN_AUDIO
813 if (ISDN_AUDIO_SKB_LOCK(skb
))
815 ISDN_AUDIO_SKB_LOCK(skb
) = 1;
816 if (ISDN_AUDIO_SKB_DLECOUNT(skb
)) {
818 unsigned long DLEmask
= (1 << channel
);
821 count_pull
= count_put
= 0;
822 while ((count_pull
< skb
->len
) && (left
-- > 0)) {
823 if (dev
->drv
[di
]->DLEflag
& DLEmask
) {
825 dev
->drv
[di
]->DLEflag
&= ~DLEmask
;
829 dev
->drv
[di
]->DLEflag
|= DLEmask
;
830 (ISDN_AUDIO_SKB_DLECOUNT(skb
))--;
837 if (count_pull
>= skb
->len
)
841 /* No DLE's in buff, so simply copy it */
843 if ((count_pull
= skb
->len
) > left
) {
847 count_put
= count_pull
;
848 memcpy(cp
, skb
->data
, count_put
);
851 #ifdef CONFIG_ISDN_AUDIO
856 memset(fp
, 0, count_put
);
860 /* We got all the data in this buff.
861 * Now we can dequeue it.
865 #ifdef CONFIG_ISDN_AUDIO
866 ISDN_AUDIO_SKB_LOCK(skb
) = 0;
868 skb
= skb_dequeue(&dev
->drv
[di
]->rpqueue
[channel
]);
871 /* Not yet emptied this buff, so it
872 * must stay in the queue, for further calls
873 * but we pull off the data we got until now.
875 skb_pull(skb
, count_pull
);
876 #ifdef CONFIG_ISDN_AUDIO
877 ISDN_AUDIO_SKB_LOCK(skb
) = 0;
880 dev
->drv
[di
]->rcvcount
[channel
] -= count_put
;
886 isdn_minor2drv(int minor
)
888 return (dev
->drvmap
[minor
]);
892 isdn_minor2chan(int minor
)
894 return (dev
->chanmap
[minor
]);
897 #define INF_DV 0x01 /* Data version for /dev/isdninfo */
902 static char istatbuf
[2048];
906 sprintf(istatbuf
, "idmap:\t");
907 p
= istatbuf
+ strlen(istatbuf
);
908 for (i
= 0; i
< ISDN_MAX_CHANNELS
; i
++) {
909 sprintf(p
, "%s ", (dev
->drvmap
[i
] < 0) ? "-" : dev
->drvid
[dev
->drvmap
[i
]]);
910 p
= istatbuf
+ strlen(istatbuf
);
912 sprintf(p
, "\nchmap:\t");
913 p
= istatbuf
+ strlen(istatbuf
);
914 for (i
= 0; i
< ISDN_MAX_CHANNELS
; i
++) {
915 sprintf(p
, "%d ", dev
->chanmap
[i
]);
916 p
= istatbuf
+ strlen(istatbuf
);
918 sprintf(p
, "\ndrmap:\t");
919 p
= istatbuf
+ strlen(istatbuf
);
920 for (i
= 0; i
< ISDN_MAX_CHANNELS
; i
++) {
921 sprintf(p
, "%d ", dev
->drvmap
[i
]);
922 p
= istatbuf
+ strlen(istatbuf
);
924 sprintf(p
, "\nusage:\t");
925 p
= istatbuf
+ strlen(istatbuf
);
926 for (i
= 0; i
< ISDN_MAX_CHANNELS
; i
++) {
927 sprintf(p
, "%d ", dev
->usage
[i
]);
928 p
= istatbuf
+ strlen(istatbuf
);
930 sprintf(p
, "\nflags:\t");
931 p
= istatbuf
+ strlen(istatbuf
);
932 for (i
= 0; i
< ISDN_MAX_DRIVERS
; i
++) {
934 sprintf(p
, "%ld ", dev
->drv
[i
]->flags
);
935 p
= istatbuf
+ strlen(istatbuf
);
938 p
= istatbuf
+ strlen(istatbuf
);
941 sprintf(p
, "\nphone:\t");
942 p
= istatbuf
+ strlen(istatbuf
);
943 for (i
= 0; i
< ISDN_MAX_CHANNELS
; i
++) {
944 sprintf(p
, "%s ", dev
->num
[i
]);
945 p
= istatbuf
+ strlen(istatbuf
);
951 /* Module interface-code */
954 isdn_info_update(void)
956 infostruct
*p
= dev
->infochain
;
960 p
= (infostruct
*) p
->next
;
962 wake_up_interruptible(&(dev
->info_waitq
));
966 isdn_read(struct file
*file
, char *buf
, size_t count
, loff_t
* off
)
968 uint minor
= MINOR(file
->f_dentry
->d_inode
->i_rdev
);
975 if (off
!= &file
->f_pos
)
978 if (minor
== ISDN_MINOR_STATUS
) {
979 if (!file
->private_data
) {
980 if (file
->f_flags
& O_NONBLOCK
)
982 interruptible_sleep_on(&(dev
->info_waitq
));
985 file
->private_data
= 0;
986 if ((len
= strlen(p
)) <= count
) {
987 if (copy_to_user(buf
, p
, len
))
996 if (minor
< ISDN_MINOR_CTRL
) {
997 drvidx
= isdn_minor2drv(minor
);
1000 if (!dev
->drv
[drvidx
]->running
)
1002 chidx
= isdn_minor2chan(minor
);
1003 if( ! (p
= kmalloc(count
,GFP_KERNEL
)) ) return -ENOMEM
;
1006 len
= isdn_readbchan(drvidx
, chidx
, p
, 0, count
,
1007 &dev
->drv
[drvidx
]->rcv_waitq
[chidx
]);
1009 restore_flags(flags
);
1010 if( copy_to_user(buf
,p
,len
) ) len
= -EFAULT
;
1014 if (minor
<= ISDN_MINOR_CTRLMAX
) {
1015 drvidx
= isdn_minor2drv(minor
- ISDN_MINOR_CTRL
);
1018 if (!dev
->drv
[drvidx
]->stavail
) {
1019 if (file
->f_flags
& O_NONBLOCK
)
1021 interruptible_sleep_on(&(dev
->drv
[drvidx
]->st_waitq
));
1023 if (dev
->drv
[drvidx
]->interface
->readstat
)
1024 len
= dev
->drv
[drvidx
]->interface
->
1025 readstat(buf
, MIN(count
, dev
->drv
[drvidx
]->stavail
),
1026 1, drvidx
, isdn_minor2chan(minor
));
1032 dev
->drv
[drvidx
]->stavail
-= len
;
1034 dev
->drv
[drvidx
]->stavail
= 0;
1035 restore_flags(flags
);
1039 #ifdef CONFIG_ISDN_PPP
1040 if (minor
<= ISDN_MINOR_PPPMAX
)
1041 return (isdn_ppp_read(minor
- ISDN_MINOR_PPP
, file
, buf
, count
));
1047 isdn_lseek(struct file
*file
, loff_t offset
, int orig
)
1053 isdn_write(struct file
*file
, const char *buf
, size_t count
, loff_t
* off
)
1055 uint minor
= MINOR(file
->f_dentry
->d_inode
->i_rdev
);
1059 if (off
!= &file
->f_pos
)
1062 if (minor
== ISDN_MINOR_STATUS
)
1066 if (minor
< ISDN_MINOR_CTRL
) {
1067 drvidx
= isdn_minor2drv(minor
);
1070 if (!dev
->drv
[drvidx
]->running
)
1072 chidx
= isdn_minor2chan(minor
);
1073 while (isdn_writebuf_stub(drvidx
, chidx
, buf
, count
, 1) != count
)
1074 interruptible_sleep_on(&dev
->drv
[drvidx
]->snd_waitq
[chidx
]);
1077 if (minor
<= ISDN_MINOR_CTRLMAX
) {
1078 drvidx
= isdn_minor2drv(minor
- ISDN_MINOR_CTRL
);
1082 * We want to use the isdnctrl device to load the firmware
1084 if (!dev->drv[drvidx]->running)
1087 if (dev
->drv
[drvidx
]->interface
->writecmd
)
1088 return (dev
->drv
[drvidx
]->interface
->
1089 writecmd(buf
, count
, 1, drvidx
, isdn_minor2chan(minor
)));
1093 #ifdef CONFIG_ISDN_PPP
1094 if (minor
<= ISDN_MINOR_PPPMAX
)
1095 return (isdn_ppp_write(minor
- ISDN_MINOR_PPP
, file
, buf
, count
));
1101 isdn_poll(struct file
*file
, poll_table
* wait
)
1103 unsigned int mask
= 0;
1104 unsigned int minor
= MINOR(file
->f_dentry
->d_inode
->i_rdev
);
1105 int drvidx
= isdn_minor2drv(minor
- ISDN_MINOR_CTRL
);
1107 if (minor
== ISDN_MINOR_STATUS
) {
1108 poll_wait(file
, &(dev
->info_waitq
), wait
);
1109 /* mask = POLLOUT | POLLWRNORM; */
1110 if (file
->private_data
) {
1111 mask
|= POLLIN
| POLLRDNORM
;
1115 if (minor
>= ISDN_MINOR_CTRL
&& minor
<= ISDN_MINOR_CTRLMAX
) {
1116 poll_wait(file
, &(dev
->drv
[drvidx
]->st_waitq
), wait
);
1118 printk(KERN_ERR
"isdn_common: isdn_poll 1 -> what the hell\n");
1121 mask
= POLLOUT
| POLLWRNORM
;
1122 if (dev
->drv
[drvidx
]->stavail
) {
1123 mask
|= POLLIN
| POLLRDNORM
;
1127 #ifdef CONFIG_ISDN_PPP
1128 if (minor
<= ISDN_MINOR_PPPMAX
)
1129 return (isdn_ppp_poll(file
, wait
));
1131 printk(KERN_ERR
"isdn_common: isdn_poll 2 -> what the hell\n");
1136 * This accesses user space with interrupts off, but is not needed by
1137 * any of the isdn4k-util programs anyway. Thus, in contrast to your
1138 * first impression after looking at the code, fixing is trival!*/
1141 isdn_set_allcfg(char *src
)
1146 isdn_net_ioctl_cfg cfg
;
1147 isdn_net_ioctl_phone phone
;
1149 if ((ret
= isdn_net_rmall()))
1151 if (copy_from_user((char *) &i
, src
, sizeof(int))) return -EFAULT
;
1159 if (copy_from_user((char *) &cfg
, src
, sizeof(cfg
))) {
1160 restore_flags(flags
);
1164 if (!isdn_net_new(cfg
.name
, NULL
)) {
1165 restore_flags(flags
);
1168 if ((ret
= isdn_net_setcfg(&cfg
))) {
1169 restore_flags(flags
);
1172 phone_len
= out_flag
= 0;
1173 while (out_flag
< 2) {
1174 if ((ret
= verify_area(VERIFY_READ
, src
, 1))) {
1175 restore_flags(flags
);
1178 get_user(phone
.phone
[phone_len
], src
++);
1179 if ((phone
.phone
[phone_len
] == ' ') ||
1180 (phone
.phone
[phone_len
] == '\0')) {
1182 phone
.phone
[phone_len
] = '\0';
1183 strcpy(phone
.name
, cfg
.name
);
1184 phone
.outgoing
= out_flag
;
1185 if ((ret
= isdn_net_addphone(&phone
))) {
1186 restore_flags(flags
);
1193 if (++phone_len
>= sizeof(phone
.phone
))
1195 "%s: IIOCSETSET phone number too long, ignored\n",
1200 restore_flags(flags
);
1205 isdn_get_allcfg(char *dest
)
1207 isdn_net_ioctl_cfg cfg
;
1208 isdn_net_ioctl_phone phone
;
1213 /* Walk through netdev-chain */
1218 isdn_net_local
*lp
= p
->local
;
1220 if ((ret
= verify_area(VERIFY_WRITE
, (void *) dest
, sizeof(cfg
) + 200))) {
1221 restore_flags(flags
);
1224 strcpy(cfg
.eaz
, lp
->msn
);
1225 cfg
.exclusive
= lp
->exclusive
;
1226 if (lp
->pre_device
>= 0) {
1227 sprintf(cfg
.drvid
, "%s,%d", dev
->drvid
[lp
->pre_device
],
1230 cfg
.drvid
[0] = '\0';
1231 cfg
.onhtime
= lp
->onhtime
;
1232 cfg
.charge
= lp
->charge
;
1233 cfg
.l2_proto
= lp
->l2_proto
;
1234 cfg
.l3_proto
= lp
->l3_proto
;
1235 cfg
.p_encap
= lp
->p_encap
;
1236 cfg
.secure
= (lp
->flags
& ISDN_NET_SECURE
) ? 1 : 0;
1237 cfg
.callback
= (lp
->flags
& ISDN_NET_CALLBACK
) ? 1 : 0;
1238 cfg
.chargehup
= (lp
->hupflags
& ISDN_CHARGEHUP
) ? 1 : 0;
1239 cfg
.ihup
= (lp
->hupflags
& ISDN_INHUP
) ? 1 : 0;
1240 cfg
.chargeint
= lp
->chargeint
;
1241 if (copy_to_user(dest
, lp
->name
, 10)) {
1242 restore_flags(flags
);
1246 if (copy_to_user(dest
, (char *) &cfg
, sizeof(cfg
))) {
1247 restore_flags(flags
);
1250 dest
+= sizeof(cfg
);
1251 strcpy(phone
.name
, lp
->name
);
1253 if ((ret
= isdn_net_getphones(&phone
, dest
)) < 0) {
1254 restore_flags(flags
);
1258 strcpy(phone
.name
, lp
->name
);
1260 if ((ret
= isdn_net_getphones(&phone
, dest
)) < 0) {
1261 restore_flags(flags
);
1268 restore_flags(flags
);
1274 isdn_ioctl(struct inode
*inode
, struct file
*file
, uint cmd
, ulong arg
)
1276 uint minor
= MINOR(inode
->i_rdev
);
1287 isdn_ioctl_struct iocts
;
1288 isdn_net_ioctl_phone phone
;
1289 isdn_net_ioctl_cfg cfg
;
1292 #define name iocpar.name
1293 #define bname iocpar.bname
1294 #define iocts iocpar.iocts
1295 #define phone iocpar.phone
1296 #define cfg iocpar.cfg
1298 if (minor
== ISDN_MINOR_STATUS
) {
1306 ulong
*p
= (ulong
*) arg
;
1308 if ((ret
= verify_area(VERIFY_WRITE
, (void *) arg
,
1309 sizeof(ulong
) * ISDN_MAX_CHANNELS
* 2)))
1311 for (i
= 0; i
< ISDN_MAX_CHANNELS
; i
++) {
1312 put_user(dev
->ibytes
[i
], p
++);
1313 put_user(dev
->obytes
[i
], p
++);
1325 if (minor
< ISDN_MINOR_CTRL
) {
1326 drvidx
= isdn_minor2drv(minor
);
1329 chidx
= isdn_minor2chan(minor
);
1330 if (!dev
->drv
[drvidx
]->running
)
1334 if (minor
<= ISDN_MINOR_CTRLMAX
) {
1336 * isdn net devices manage lots of configuration variables as linked lists.
1337 * Those lists must only be manipulated from user space. Some of the ioctl's
1338 * service routines access user space and are not atomic. Therefor, ioctl's
1339 * manipulating the lists and ioctl's sleeping while accessing the lists
1340 * are serialized by means of a semaphore.
1343 #ifdef CONFIG_NETDEVICES
1345 /* Add a network-interface */
1347 if (copy_from_user(name
, (char *) arg
, sizeof(name
)))
1353 ret
= down_interruptible(&dev
->sem
);
1354 if( ret
) return ret
;
1355 if ((s
= isdn_net_new(s
, NULL
))) {
1356 if (copy_to_user((char *) arg
, s
, strlen(s
) + 1)){
1366 /* Add a slave to a network-interface */
1368 if (copy_from_user(bname
, (char *) arg
, sizeof(bname
) - 1))
1372 ret
= down_interruptible(&dev
->sem
);
1373 if( ret
) return ret
;
1374 if ((s
= isdn_net_newslave(bname
))) {
1375 if (copy_to_user((char *) arg
, s
, strlen(s
) + 1)){
1385 /* Delete a network-interface */
1387 if (copy_from_user(name
, (char *) arg
, sizeof(name
)))
1389 ret
= down_interruptible(&dev
->sem
);
1390 if( ret
) return ret
;
1391 ret
= isdn_net_rm(name
);
1397 /* Set configurable parameters of a network-interface */
1399 if (copy_from_user((char *) &cfg
, (char *) arg
, sizeof(cfg
)))
1401 return isdn_net_setcfg(&cfg
);
1405 /* Get configurable parameters of a network-interface */
1407 if (copy_from_user((char *) &cfg
, (char *) arg
, sizeof(cfg
)))
1409 if (!(ret
= isdn_net_getcfg(&cfg
))) {
1410 if (copy_to_user((char *) arg
, (char *) &cfg
, sizeof(cfg
)))
1417 /* Add a phone-number to a network-interface */
1419 if (copy_from_user((char *) &phone
, (char *) arg
, sizeof(phone
)))
1421 ret
= down_interruptible(&dev
->sem
);
1422 if( ret
) return ret
;
1423 ret
= isdn_net_addphone(&phone
);
1429 /* Get list of phone-numbers of a network-interface */
1431 if (copy_from_user((char *) &phone
, (char *) arg
, sizeof(phone
)))
1433 ret
= down_interruptible(&dev
->sem
);
1434 if( ret
) return ret
;
1435 ret
= isdn_net_getphones(&phone
, (char *) arg
);
1441 /* Delete a phone-number of a network-interface */
1443 if (copy_from_user((char *) &phone
, (char *) arg
, sizeof(phone
)))
1445 ret
= down_interruptible(&dev
->sem
);
1446 if( ret
) return ret
;
1447 ret
= isdn_net_delphone(&phone
);
1453 /* Force dialing of a network-interface */
1455 if (copy_from_user(name
, (char *) arg
, sizeof(name
)))
1457 return isdn_net_force_dial(name
);
1460 #ifdef CONFIG_ISDN_PPP
1464 if (copy_from_user(name
, (char *) arg
, sizeof(name
)))
1466 return isdn_ppp_dial_slave(name
);
1470 if (copy_from_user(name
, (char *) arg
, sizeof(name
)))
1472 return isdn_ppp_hangup_slave(name
);
1475 /* Force hangup of a network-interface */
1478 if (copy_from_user(name
, (char *) arg
, sizeof(name
)))
1480 return isdn_net_force_hangup(name
);
1482 #endif /* CONFIG_NETDEVICES */
1484 dev
->net_verbose
= arg
;
1485 printk(KERN_INFO
"isdn: Verbose-Level is %d\n", dev
->net_verbose
);
1489 dev
->global_flags
|= ISDN_GLOBAL_STOPPED
;
1491 dev
->global_flags
&= ~ISDN_GLOBAL_STOPPED
;
1492 printk(KERN_INFO
"isdn: Global Mode %s\n",
1493 (dev
->global_flags
& ISDN_GLOBAL_STOPPED
) ? "stopped" : "running");
1500 if (copy_from_user((char *) &iocts
, (char *) arg
,
1501 sizeof(isdn_ioctl_struct
)))
1503 if (strlen(iocts
.drvid
)) {
1504 if ((p
= strchr(iocts
.drvid
, ',')))
1507 for (i
= 0; i
< ISDN_MAX_DRIVERS
; i
++)
1508 if (!(strcmp(dev
->drvid
[i
], iocts
.drvid
))) {
1516 dev
->drv
[drvidx
]->reject_bus
= iocts
.arg
;
1520 /* Get complete setup (all network-interfaces and profile-
1521 settings of all tty-devices */
1523 return (isdn_get_allcfg((char *) arg
));
1528 /* Set complete setup (all network-interfaces and profile-
1529 settings of all tty-devices */
1531 return (isdn_set_allcfg((char *) arg
));
1537 dev
->profd
= current
;
1541 /* Get all Modem-Profiles */
1543 char *p
= (char *) arg
;
1546 if ((ret
= verify_area(VERIFY_WRITE
, (void *) arg
,
1547 (ISDN_MODEM_ANZREG
+ ISDN_MSNLEN
)
1548 * ISDN_MAX_CHANNELS
)))
1551 for (i
= 0; i
< ISDN_MAX_CHANNELS
; i
++) {
1552 if (copy_to_user(p
, dev
->mdm
.info
[i
].emu
.profile
,
1555 p
+= ISDN_MODEM_ANZREG
;
1556 if (copy_to_user(p
, dev
->mdm
.info
[i
].emu
.pmsn
, ISDN_MSNLEN
))
1560 return (ISDN_MODEM_ANZREG
+ ISDN_MSNLEN
) * ISDN_MAX_CHANNELS
;
1565 /* Set all Modem-Profiles */
1567 char *p
= (char *) arg
;
1570 if ((ret
= verify_area(VERIFY_READ
, (void *) arg
,
1571 (ISDN_MODEM_ANZREG
+ ISDN_MSNLEN
)
1572 * ISDN_MAX_CHANNELS
)))
1575 for (i
= 0; i
< ISDN_MAX_CHANNELS
; i
++) {
1576 if (copy_from_user(dev
->mdm
.info
[i
].emu
.profile
, p
,
1579 p
+= ISDN_MODEM_ANZREG
;
1580 if (copy_from_user(dev
->mdm
.info
[i
].emu
.pmsn
, p
, ISDN_MSNLEN
))
1590 /* Set/Get MSN->EAZ-Mapping for a driver */
1593 if (copy_from_user((char *) &iocts
,
1595 sizeof(isdn_ioctl_struct
)))
1597 if (strlen(iocts
.drvid
)) {
1599 for (i
= 0; i
< ISDN_MAX_DRIVERS
; i
++)
1600 if (!(strcmp(dev
->drvid
[i
], iocts
.drvid
))) {
1608 if (cmd
== IIOCSETMAP
) {
1611 p
= (char *) iocts
.arg
;
1617 if ((ret
= verify_area(VERIFY_READ
, p
, 1)))
1619 get_user(bname
[j
], p
++);
1626 strcpy(dev
->drv
[drvidx
]->msn2eaz
[i
], bname
);
1632 if (j
>= ISDN_MSNLEN
)
1639 p
= (char *) iocts
.arg
;
1640 for (i
= 0; i
< 10; i
++) {
1641 sprintf(bname
, "%s%s",
1642 strlen(dev
->drv
[drvidx
]->msn2eaz
[i
]) ?
1643 dev
->drv
[drvidx
]->msn2eaz
[i
] : "-",
1644 (i
< 9) ? "," : "\0");
1645 if (copy_to_user(p
, bname
, strlen(bname
) + 1))
1655 if (copy_to_user((char *) arg
, (char *) &dev
, sizeof(ulong
)))
1662 if ((cmd
& IIOCDRVCTL
) == IIOCDRVCTL
)
1663 cmd
= ((cmd
>> _IOC_NRSHIFT
) & _IOC_NRMASK
) & ISDN_DRVIOCTL_MASK
;
1669 if (copy_from_user((char *) &iocts
, (char *) arg
, sizeof(isdn_ioctl_struct
)))
1671 if (strlen(iocts
.drvid
)) {
1672 if ((p
= strchr(iocts
.drvid
, ',')))
1675 for (i
= 0; i
< ISDN_MAX_DRIVERS
; i
++)
1676 if (!(strcmp(dev
->drvid
[i
], iocts
.drvid
))) {
1684 if ((ret
= verify_area(VERIFY_WRITE
, (void *) arg
,
1685 sizeof(isdn_ioctl_struct
))))
1688 c
.command
= ISDN_CMD_IOCTL
;
1690 memcpy(c
.parm
.num
, (char *) &iocts
.arg
, sizeof(ulong
));
1691 ret
= isdn_command(&c
);
1692 memcpy((char *) &iocts
.arg
, c
.parm
.num
, sizeof(ulong
));
1693 if (copy_to_user((char *) arg
, &iocts
, sizeof(isdn_ioctl_struct
)))
1700 #ifdef CONFIG_ISDN_PPP
1701 if (minor
<= ISDN_MINOR_PPPMAX
)
1702 return (isdn_ppp_ioctl(minor
- ISDN_MINOR_PPP
, file
, cmd
, arg
));
1714 * Open the device code.
1715 * MOD_INC_USE_COUNT make sure that the driver memory is not freed
1716 * while the device is in use.
1719 isdn_open(struct inode
*ino
, struct file
*filep
)
1721 uint minor
= MINOR(ino
->i_rdev
);
1726 if (minor
== ISDN_MINOR_STATUS
) {
1729 if ((p
= (infostruct
*) kmalloc(sizeof(infostruct
), GFP_KERNEL
))) {
1731 p
->next
= (char *) dev
->infochain
;
1732 p
->private = (char *) &(filep
->private_data
);
1734 /* At opening we allow a single update */
1735 filep
->private_data
= (char *) 1;
1742 if (minor
< ISDN_MINOR_CTRL
) {
1743 drvidx
= isdn_minor2drv(minor
);
1746 chidx
= isdn_minor2chan(minor
);
1747 if (!dev
->drv
[drvidx
]->running
)
1749 if (!(dev
->drv
[drvidx
]->flags
& (1 << chidx
)))
1751 c
.command
= ISDN_CMD_LOCK
;
1757 if (minor
<= ISDN_MINOR_CTRLMAX
) {
1758 drvidx
= isdn_minor2drv(minor
- ISDN_MINOR_CTRL
);
1761 c
.command
= ISDN_CMD_LOCK
;
1767 #ifdef CONFIG_ISDN_PPP
1768 if (minor
<= ISDN_MINOR_PPPMAX
) {
1770 if (!(ret
= isdn_ppp_open(minor
- ISDN_MINOR_PPP
, filep
)))
1779 isdn_close(struct inode
*ino
, struct file
*filep
)
1781 uint minor
= MINOR(ino
->i_rdev
);
1786 if (minor
== ISDN_MINOR_STATUS
) {
1787 infostruct
*p
= dev
->infochain
;
1788 infostruct
*q
= NULL
;
1790 if (p
->private == (char *) &(filep
->private_data
)) {
1794 dev
->infochain
= (infostruct
*) (p
->next
);
1799 p
= (infostruct
*) (p
->next
);
1801 printk(KERN_WARNING
"isdn: No private data while closing isdnctrl\n");
1804 if (minor
< ISDN_MINOR_CTRL
) {
1805 drvidx
= isdn_minor2drv(minor
);
1808 c
.command
= ISDN_CMD_UNLOCK
;
1813 if (minor
<= ISDN_MINOR_CTRLMAX
) {
1814 drvidx
= isdn_minor2drv(minor
- ISDN_MINOR_CTRL
);
1817 if (dev
->profd
== current
)
1819 c
.command
= ISDN_CMD_UNLOCK
;
1824 #ifdef CONFIG_ISDN_PPP
1825 if (minor
<= ISDN_MINOR_PPPMAX
)
1826 isdn_ppp_release(minor
- ISDN_MINOR_PPP
, filep
);
1831 static struct file_operations isdn_fops
=
1836 NULL
, /* isdn_readdir */
1837 isdn_poll
, /* isdn_poll */
1838 isdn_ioctl
, /* isdn_ioctl */
1839 NULL
, /* isdn_mmap */
1847 isdn_map_eaz2msn(char *msn
, int di
)
1849 driver
*this = dev
->drv
[di
];
1852 if (strlen(msn
) == 1) {
1854 if ((i
>= 0) && (i
<= 9))
1855 if (strlen(this->msn2eaz
[i
]))
1856 return (this->msn2eaz
[i
]);
1862 * Find an unused ISDN-channel, whose feature-flags match the
1863 * given L2- and L3-protocols.
1865 #define L2V (~(ISDN_FEATURE_L2_V11096|ISDN_FEATURE_L2_V11019|ISDN_FEATURE_L2_V11038))
1868 isdn_get_free_channel(int usage
, int l2_proto
, int l3_proto
, int pre_dev
1879 features
= ((1 << l2_proto
) | (0x10000 << l3_proto
));
1880 vfeatures
= (((1 << l2_proto
) | (0x10000 << l3_proto
)) &
1881 ~(ISDN_FEATURE_L2_V11096
|ISDN_FEATURE_L2_V11019
|ISDN_FEATURE_L2_V11038
));
1882 /* If Layer-2 protocol is V.110, accept drivers with
1883 * transparent feature even if these don't support V.110
1884 * because we can emulate this in linklevel.
1886 for (i
= 0; i
< ISDN_MAX_CHANNELS
; i
++)
1887 if (USG_NONE(dev
->usage
[i
]) &&
1888 (dev
->drvmap
[i
] != -1)) {
1889 int d
= dev
->drvmap
[i
];
1890 if ((dev
->usage
[i
] & ISDN_USAGE_EXCLUSIVE
) &&
1891 ((pre_dev
!= d
) || (pre_chan
!= dev
->chanmap
[i
])))
1893 if ((dev
->drv
[d
]->running
)) {
1894 if (((dev
->drv
[d
]->interface
->features
& features
) == features
) ||
1895 (((dev
->drv
[d
]->interface
->features
& vfeatures
) == vfeatures
) &&
1896 (dev
->drv
[d
]->interface
->features
& ISDN_FEATURE_L2_TRANS
))) {
1897 if ((pre_dev
< 0) || (pre_chan
< 0)) {
1898 dev
->usage
[i
] &= ISDN_USAGE_EXCLUSIVE
;
1899 dev
->usage
[i
] |= usage
;
1903 cmd
.command
= ISDN_CMD_LOCK
;
1905 restore_flags(flags
);
1908 if ((pre_dev
== d
) && (pre_chan
== dev
->chanmap
[i
])) {
1909 dev
->usage
[i
] &= ISDN_USAGE_EXCLUSIVE
;
1910 dev
->usage
[i
] |= usage
;
1914 cmd
.command
= ISDN_CMD_LOCK
;
1916 restore_flags(flags
);
1923 restore_flags(flags
);
1928 * Set state of ISDN-channel to 'unused'
1931 isdn_free_channel(int di
, int ch
, int usage
)
1939 for (i
= 0; i
< ISDN_MAX_CHANNELS
; i
++)
1940 if (((dev
->usage
[i
] & ISDN_USAGE_MASK
) == usage
) &&
1941 (dev
->drvmap
[i
] == di
) &&
1942 (dev
->chanmap
[i
] == ch
)) {
1943 dev
->usage
[i
] &= (ISDN_USAGE_NONE
| ISDN_USAGE_EXCLUSIVE
);
1944 strcpy(dev
->num
[i
], "???");
1948 isdn_free_queue(&dev
->drv
[di
]->rpqueue
[ch
]);
1951 cmd
.command
= ISDN_CMD_UNLOCK
;
1952 restore_flags(flags
);
1956 restore_flags(flags
);
1960 * Cancel Exclusive-Flag for ISDN-channel
1963 isdn_unexclusive_channel(int di
, int ch
)
1970 for (i
= 0; i
< ISDN_MAX_CHANNELS
; i
++)
1971 if ((dev
->drvmap
[i
] == di
) &&
1972 (dev
->chanmap
[i
] == ch
)) {
1973 dev
->usage
[i
] &= ~ISDN_USAGE_EXCLUSIVE
;
1975 restore_flags(flags
);
1978 restore_flags(flags
);
1982 * writebuf replacement for SKB_ABLE drivers
1985 isdn_writebuf_stub(int drvidx
, int chan
, const u_char
* buf
, int len
,
1989 int hl
= dev
->drv
[drvidx
]->interface
->hl_hdrlen
;
1990 struct sk_buff
*skb
= alloc_skb(hl
+ len
, GFP_ATOMIC
);
1994 skb_reserve(skb
, hl
);
1996 copy_from_user(skb_put(skb
, len
), buf
, len
);
1998 memcpy(skb_put(skb
, len
), buf
, len
);
2000 ret
= dev
->drv
[drvidx
]->interface
->writebuf_skb(drvidx
, chan
, 1, skb
);
2004 dev
->obytes
[isdn_dc2minor(drvidx
, chan
)] += ret
;
2009 * Return: length of data on success, -ERRcode on failure.
2012 isdn_writebuf_skb_stub(int drvidx
, int chan
, int ack
, struct sk_buff
*skb
)
2015 struct sk_buff
*nskb
= NULL
;
2016 int v110_ret
= skb
->len
;
2017 int idx
= isdn_dc2minor(drvidx
, chan
);
2019 if (dev
->v110
[idx
]) {
2020 atomic_inc(&dev
->v110use
[idx
]);
2021 nskb
= isdn_v110_encode(dev
->v110
[idx
], skb
);
2022 atomic_dec(&dev
->v110use
[idx
]);
2025 v110_ret
= *((int *)nskb
->data
);
2026 skb_pull(nskb
, sizeof(int));
2028 dev_kfree_skb(nskb
);
2032 /* V.110 must always be acknowledged */
2034 ret
= dev
->drv
[drvidx
]->interface
->writebuf_skb(drvidx
, chan
, ack
, nskb
);
2036 ret
= dev
->drv
[drvidx
]->interface
->writebuf_skb(drvidx
, chan
, ack
, skb
);
2038 dev
->obytes
[idx
] += ret
;
2039 if (dev
->v110
[idx
]) {
2040 atomic_inc(&dev
->v110use
[idx
]);
2041 dev
->v110
[idx
]->skbuser
++;
2042 atomic_dec(&dev
->v110use
[idx
]);
2044 /* For V.110 return unencoded data length */
2046 if (ret
== skb
->len
)
2051 dev_kfree_skb(nskb
);
2056 * Low-level-driver registration
2059 EXPORT_SYMBOL(register_isdn
);
2062 register_isdn(isdn_if
* i
)
2071 if (dev
->drivers
>= ISDN_MAX_DRIVERS
) {
2072 printk(KERN_WARNING
"register_isdn: Max. %d drivers supported\n",
2077 if (dev
->channels
+ n
> ISDN_MAX_CHANNELS
) {
2078 printk(KERN_WARNING
"register_isdn: Max. %d channels supported\n",
2082 if (!i
->writebuf_skb
) {
2083 printk(KERN_WARNING
"register_isdn: No write routine given.\n");
2086 if (!(d
= (driver
*) kmalloc(sizeof(driver
), GFP_KERNEL
))) {
2087 printk(KERN_WARNING
"register_isdn: Could not alloc driver-struct\n");
2090 memset((char *) d
, 0, sizeof(driver
));
2091 if (!(d
->rcverr
= (int *) kmalloc(sizeof(int) * n
, GFP_KERNEL
))) {
2092 printk(KERN_WARNING
"register_isdn: Could not alloc rcverr\n");
2096 memset((char *) d
->rcverr
, 0, sizeof(int) * n
);
2097 if (!(d
->rcvcount
= (int *) kmalloc(sizeof(int) * n
, GFP_KERNEL
))) {
2098 printk(KERN_WARNING
"register_isdn: Could not alloc rcvcount\n");
2103 memset((char *) d
->rcvcount
, 0, sizeof(int) * n
);
2105 (struct sk_buff_head
*) kmalloc(sizeof(struct sk_buff_head
) * n
, GFP_KERNEL
))) {
2106 printk(KERN_WARNING
"register_isdn: Could not alloc rpqueue\n");
2112 for (j
= 0; j
< n
; j
++) {
2113 skb_queue_head_init(&d
->rpqueue
[j
]);
2115 if (!(d
->rcv_waitq
= (struct wait_queue
**)
2116 kmalloc(sizeof(struct wait_queue
*) * n
, GFP_KERNEL
))) {
2117 printk(KERN_WARNING
"register_isdn: Could not alloc rcv_waitq\n");
2124 memset((char *) d
->rcv_waitq
, 0, sizeof(struct wait_queue
*) * n
);
2125 if (!(d
->snd_waitq
= (struct wait_queue
**)
2126 kmalloc(sizeof(struct wait_queue
*) * n
, GFP_KERNEL
))) {
2127 printk(KERN_WARNING
"register_isdn: Could not alloc snd_waitq\n");
2128 kfree(d
->rcv_waitq
);
2135 memset((char *) d
->snd_waitq
, 0, sizeof(struct wait_queue
*) * n
);
2138 d
->maxbufsize
= i
->maxbufsize
;
2144 for (drvidx
= 0; drvidx
< ISDN_MAX_DRIVERS
; drvidx
++)
2145 if (!dev
->drv
[drvidx
])
2147 i
->channels
= drvidx
;
2149 i
->rcvcallb_skb
= isdn_receive_skb_callback
;
2150 i
->statcallb
= isdn_status_callback
;
2152 sprintf(i
->id
, "line%d", drvidx
);
2155 for (j
= 0; j
< drvidx
; j
++)
2156 if (!strcmp(i
->id
, dev
->drvid
[j
]))
2157 sprintf(i
->id
, "line%d", drvidx
);
2158 for (j
= 0; j
< n
; j
++)
2159 for (k
= 0; k
< ISDN_MAX_CHANNELS
; k
++)
2160 if (dev
->chanmap
[k
] < 0) {
2161 dev
->chanmap
[k
] = j
;
2162 dev
->drvmap
[k
] = drvidx
;
2165 dev
->drv
[drvidx
] = d
;
2167 strcpy(dev
->drvid
[drvidx
], i
->id
);
2170 restore_flags(flags
);
2175 *****************************************************************************
2176 * And now the modules code.
2177 *****************************************************************************
2180 extern int printk(const char *fmt
,...);
2183 #define isdn_init init_module
2187 isdn_getrev(const char *revision
)
2192 if ((p
= strchr(revision
, ':'))) {
2194 p
= strchr(rev
, '$');
2202 * Allocate and initialize all data, register modem-devices
2211 if (!(dev
= (isdn_dev
*) kmalloc(sizeof(isdn_dev
), GFP_KERNEL
))) {
2212 printk(KERN_WARNING
"isdn: Could not allocate device-struct.\n");
2215 memset((char *) dev
, 0, sizeof(isdn_dev
));
2216 init_timer(&dev
->timer
);
2217 dev
->timer
.function
= isdn_timer_funct
;
2219 for (i
= 0; i
< ISDN_MAX_CHANNELS
; i
++) {
2220 dev
->drvmap
[i
] = -1;
2221 dev
->chanmap
[i
] = -1;
2223 strcpy(dev
->num
[i
], "???");
2225 if (register_chrdev(ISDN_MAJOR
, "isdn", &isdn_fops
)) {
2226 printk(KERN_WARNING
"isdn: Could not register control devices\n");
2230 if ((i
= isdn_tty_modem_init()) < 0) {
2231 printk(KERN_WARNING
"isdn: Could not register tty devices\n");
2233 tty_unregister_driver(&dev
->mdm
.cua_modem
);
2235 tty_unregister_driver(&dev
->mdm
.tty_modem
);
2237 unregister_chrdev(ISDN_MAJOR
, "isdn");
2240 #ifdef CONFIG_ISDN_PPP
2241 if (isdn_ppp_init() < 0) {
2242 printk(KERN_WARNING
"isdn: Could not create PPP-device-structs\n");
2243 tty_unregister_driver(&dev
->mdm
.tty_modem
);
2244 tty_unregister_driver(&dev
->mdm
.cua_modem
);
2245 for (i
= 0; i
< ISDN_MAX_CHANNELS
; i
++)
2246 kfree(dev
->mdm
.info
[i
].xmit_buf
- 4);
2247 unregister_chrdev(ISDN_MAJOR
, "isdn");
2251 #endif /* CONFIG_ISDN_PPP */
2253 strcpy(tmprev
, isdn_revision
);
2254 printk(KERN_NOTICE
"ISDN subsystem Rev: %s/", isdn_getrev(tmprev
));
2255 strcpy(tmprev
, isdn_tty_revision
);
2256 printk("%s/", isdn_getrev(tmprev
));
2257 strcpy(tmprev
, isdn_net_revision
);
2258 printk("%s/", isdn_getrev(tmprev
));
2259 strcpy(tmprev
, isdn_ppp_revision
);
2260 printk("%s/", isdn_getrev(tmprev
));
2261 strcpy(tmprev
, isdn_audio_revision
);
2262 printk("%s/", isdn_getrev(tmprev
));
2263 strcpy(tmprev
, isdn_v110_revision
);
2264 printk("%s", isdn_getrev(tmprev
));
2267 printk(" loaded\n");
2281 cleanup_module(void)
2286 #ifdef CONFIG_ISDN_PPP
2291 if (isdn_net_rmall() < 0) {
2292 printk(KERN_WARNING
"isdn: net-device busy, remove cancelled\n");
2293 restore_flags(flags
);
2296 if (tty_unregister_driver(&dev
->mdm
.tty_modem
)) {
2297 printk(KERN_WARNING
"isdn: ttyI-device busy, remove cancelled\n");
2298 restore_flags(flags
);
2301 if (tty_unregister_driver(&dev
->mdm
.cua_modem
)) {
2302 printk(KERN_WARNING
"isdn: cui-device busy, remove cancelled\n");
2303 restore_flags(flags
);
2306 for (i
= 0; i
< ISDN_MAX_CHANNELS
; i
++) {
2307 isdn_tty_cleanup_xmit(&dev
->mdm
.info
[i
]);
2308 kfree(dev
->mdm
.info
[i
].xmit_buf
- 4);
2310 if (unregister_chrdev(ISDN_MAJOR
, "isdn") != 0) {
2311 printk(KERN_WARNING
"isdn: controldevice busy, remove cancelled\n");
2313 del_timer(&dev
->timer
);
2315 printk(KERN_NOTICE
"ISDN-subsystem unloaded\n");
2317 restore_flags(flags
);