Skip to content
Projects
Groups
Snippets
Help
Loading...
Help
Support
Keyboard shortcuts
?
Submit feedback
Contribute to GitLab
Sign in / Register
Toggle navigation
L
linux
Project overview
Project overview
Details
Activity
Releases
Repository
Repository
Files
Commits
Branches
Tags
Contributors
Graph
Compare
Issues
0
Issues
0
List
Boards
Labels
Milestones
Merge Requests
0
Merge Requests
0
Analytics
Analytics
Repository
Value Stream
Wiki
Wiki
Snippets
Snippets
Members
Members
Collapse sidebar
Close sidebar
Activity
Graph
Create a new issue
Commits
Issue Boards
Open sidebar
Kirill Smelkov
linux
Commits
b14ebcfc
Commit
b14ebcfc
authored
Aug 06, 2002
by
Linus Torvalds
Browse files
Options
Browse Files
Download
Plain Diff
Merge
bk://thebsh.namesys.com/bk/reiser3-linux-2.5
into home.transmeta.com:/home/torvalds/v2.5/linux
parents
cb7ada82
16b39f5f
Changes
32
Hide whitespace changes
Inline
Side-by-side
Showing
32 changed files
with
1739 additions
and
1649 deletions
+1739
-1649
Documentation/filesystems/ntfs.txt
Documentation/filesystems/ntfs.txt
+11
-0
drivers/isdn/act2000/capi.h
drivers/isdn/act2000/capi.h
+1
-1
drivers/isdn/i4l/isdn_audio.c
drivers/isdn/i4l/isdn_audio.c
+4
-4
drivers/isdn/i4l/isdn_common.c
drivers/isdn/i4l/isdn_common.c
+416
-314
drivers/isdn/i4l/isdn_common.h
drivers/isdn/i4l/isdn_common.h
+62
-6
drivers/isdn/i4l/isdn_net.c
drivers/isdn/i4l/isdn_net.c
+631
-715
drivers/isdn/i4l/isdn_net.h
drivers/isdn/i4l/isdn_net.h
+3
-4
drivers/isdn/i4l/isdn_ppp.c
drivers/isdn/i4l/isdn_ppp.c
+20
-19
drivers/isdn/i4l/isdn_tty.c
drivers/isdn/i4l/isdn_tty.c
+134
-186
drivers/isdn/i4l/isdn_tty.h
drivers/isdn/i4l/isdn_tty.h
+4
-1
drivers/isdn/i4l/isdn_ttyfax.c
drivers/isdn/i4l/isdn_ttyfax.c
+14
-35
drivers/isdn/i4l/isdn_v110.c
drivers/isdn/i4l/isdn_v110.c
+17
-19
drivers/isdn/i4l/isdn_v110.h
drivers/isdn/i4l/isdn_v110.h
+9
-3
drivers/isdn/isdnloop/isdnloop.c
drivers/isdn/isdnloop/isdnloop.c
+6
-2
fs/ntfs/ChangeLog
fs/ntfs/ChangeLog
+30
-0
fs/ntfs/Makefile
fs/ntfs/Makefile
+1
-1
fs/ntfs/aops.c
fs/ntfs/aops.c
+5
-5
fs/ntfs/attrib.c
fs/ntfs/attrib.c
+14
-9
fs/ntfs/compress.c
fs/ntfs/compress.c
+23
-3
fs/ntfs/dir.c
fs/ntfs/dir.c
+109
-93
fs/ntfs/file.c
fs/ntfs/file.c
+8
-1
fs/ntfs/inode.c
fs/ntfs/inode.c
+34
-17
fs/ntfs/inode.h
fs/ntfs/inode.h
+1
-2
fs/ntfs/malloc.h
fs/ntfs/malloc.h
+2
-15
fs/ntfs/mft.c
fs/ntfs/mft.c
+72
-123
fs/ntfs/mft.h
fs/ntfs/mft.h
+3
-3
fs/ntfs/namei.c
fs/ntfs/namei.c
+21
-17
fs/ntfs/super.c
fs/ntfs/super.c
+20
-7
fs/ntfs/volume.h
fs/ntfs/volume.h
+2
-0
include/linux/isdn.h
include/linux/isdn.h
+7
-29
include/linux/isdnif.h
include/linux/isdnif.h
+0
-2
mm/mmap.c
mm/mmap.c
+55
-13
No files found.
Documentation/filesystems/ntfs.txt
View file @
b14ebcfc
...
...
@@ -247,6 +247,17 @@ ChangeLog
Note, a technical ChangeLog aimed at kernel hackers is in fs/ntfs/ChangeLog.
2.0.24:
- Small internal cleanups.
- Support for sendfile system call. (Christoph Hellwig)
2.0.23:
- Massive internal locking changes to mft record locking. Fixes
various race conditions and deadlocks.
- Fix ntfs over loopback for compressed files by adding an
optimization barrier. (gcc was screwing up otherwise ?)
Thanks go to Christoph Hellwig for pointing these two out:
- Remove now unused function fs/ntfs/malloc.h::vmalloc_nofs().
- Fix ntfs_free() for ia64 and parisc.
2.0.22:
- Small internal cleanups.
2.0.21:
...
...
drivers/isdn/act2000/capi.h
View file @
b14ebcfc
...
...
@@ -138,7 +138,7 @@ typedef struct actcapi_ncpd {
typedef
struct
actcapi_msg
{
actcapi_msghdr
hdr
;
union
msg
{
union
{
__u16
manuf_msg
;
struct
manufacturer_req_net
{
__u16
manuf_msg
;
...
...
drivers/isdn/i4l/isdn_audio.c
View file @
b14ebcfc
...
...
@@ -564,8 +564,8 @@ isdn_audio_eval_dtmf(modem_info * info)
ISDN_AUDIO_SKB_LOCK
(
skb
)
=
0
;
save_flags
(
flags
);
cli
();
di
=
i
nfo
->
isdn_driver
;
ch
=
i
nfo
->
isdn_channel
;
di
=
i
sdn_slot_driver
(
info
->
isdn_slot
)
;
ch
=
i
sdn_slot_channel
(
info
->
isdn_slot
)
;
__skb_queue_tail
(
&
dev
->
drv
[
di
]
->
rpqueue
[
ch
],
skb
);
dev
->
drv
[
di
]
->
rcvcount
[
ch
]
+=
2
;
restore_flags
(
flags
);
...
...
@@ -685,8 +685,8 @@ isdn_audio_put_dle_code(modem_info * info, u_char code)
ISDN_AUDIO_SKB_LOCK
(
skb
)
=
0
;
save_flags
(
flags
);
cli
();
di
=
i
nfo
->
isdn_driver
;
ch
=
i
nfo
->
isdn_channel
;
di
=
i
sdn_slot_driver
(
info
->
isdn_slot
)
;
ch
=
i
sdn_slot_channel
(
info
->
isdn_slot
)
;
__skb_queue_tail
(
&
dev
->
drv
[
di
]
->
rpqueue
[
ch
],
skb
);
dev
->
drv
[
di
]
->
rcvcount
[
ch
]
+=
2
;
restore_flags
(
flags
);
...
...
drivers/isdn/i4l/isdn_common.c
View file @
b14ebcfc
...
...
@@ -19,6 +19,7 @@
#include <linux/vmalloc.h>
#include <linux/isdn.h>
#include <linux/smp_lock.h>
#include <linux/ctype.h>
#include "isdn_common.h"
#include "isdn_tty.h"
#include "isdn_net.h"
...
...
@@ -26,24 +27,31 @@
#ifdef CONFIG_ISDN_AUDIO
#include "isdn_audio.h"
#endif
#ifdef CONFIG_ISDN_DIVERSION_MODULE
#define CONFIG_ISDN_DIVERSION
#endif
#ifdef CONFIG_ISDN_DIVERSION
#include <linux/isdn_divertif.h>
#endif
/* CONFIG_ISDN_DIVERSION */
#include "isdn_v110.h"
#include <linux/devfs_fs_kernel.h>
/* Debugflags */
#undef ISDN_DEBUG_STATCALLB
MODULE_DESCRIPTION
(
"ISDN4Linux: link layer"
);
MODULE_AUTHOR
(
"Fritz Elfert"
);
MODULE_LICENSE
(
"GPL"
);
isdn_dev
*
dev
;
struct
isdn_slot
{
int
di
;
/* driver index */
int
ch
;
/* channel index (per driver) */
int
usage
;
/* how is it used */
char
num
[
ISDN_MSNLEN
];
/* the current phone number */
unsigned
long
ibytes
;
/* Statistics incoming bytes */
unsigned
long
obytes
;
/* Statistics outgoing bytes */
struct
isdn_v110
iv110
;
/* For V.110 */
int
m_idx
;
/* Index for mdm.... */
isdn_net_dev
*
rx_netdev
;
/* rx netdev-pointers */
isdn_net_dev
*
st_netdev
;
/* stat netdev-pointers */
};
static
struct
isdn_slot
slot
[
ISDN_MAX_CHANNELS
];
static
char
*
isdn_revision
=
"$Revision: 1.114.6.16 $"
;
extern
char
*
isdn_net_revision
;
...
...
@@ -60,15 +68,18 @@ static char *isdn_audio_revision = ": none $";
#endif
extern
char
*
isdn_v110_revision
;
#if
def CONFIG_ISDN_DIVERSION
#if
defined(CONFIG_ISDN_DIVERSION) || defined(CONFIG_ISDN_DIVERSION_MODULE)
static
isdn_divert_if
*
divert_if
;
/* = NULL */
#endif
/* CONFIG_ISDN_DIVERSION */
#else
#define divert_if ((isdn_divert_if *) NULL)
#endif
static
void
set_global_features
(
void
);
static
void
isdn_register_devfs
(
int
);
static
void
isdn_unregister_devfs
(
int
);
static
int
isdn_wildmat
(
char
*
s
,
char
*
p
);
static
int
isdn_command
(
isdn_ctrl
*
cmd
);
void
isdn_lock_drivers
(
void
)
...
...
@@ -230,12 +241,11 @@ isdn_dc2minor(int di, int ch)
{
int
i
;
for
(
i
=
0
;
i
<
ISDN_MAX_CHANNELS
;
i
++
)
if
(
dev
->
chanmap
[
i
]
==
ch
&&
dev
->
drvmap
[
i
]
==
di
)
if
(
slot
[
i
].
ch
==
ch
&&
slot
[
i
].
di
==
di
)
return
i
;
return
-
1
;
}
static
int
isdn_timer_cnt1
=
0
;
static
int
isdn_timer_cnt2
=
0
;
static
int
isdn_timer_cnt3
=
0
;
...
...
@@ -252,11 +262,6 @@ isdn_timer_funct(ulong dummy)
isdn_tty_modem_xmit
();
}
if
(
tf
&
ISDN_TIMER_SLOW
)
{
if
(
++
isdn_timer_cnt1
>=
ISDN_TIMER_02SEC
)
{
isdn_timer_cnt1
=
0
;
if
(
tf
&
ISDN_TIMER_NETDIAL
)
isdn_net_dial
();
}
if
(
++
isdn_timer_cnt2
>=
ISDN_TIMER_1SEC
)
{
isdn_timer_cnt2
=
0
;
if
(
tf
&
ISDN_TIMER_NETHANGUP
)
...
...
@@ -291,7 +296,6 @@ isdn_timer_ctrl(int tf, int onoff)
cli
();
if
((
tf
&
ISDN_TIMER_SLOW
)
&&
(
!
(
dev
->
tflags
&
ISDN_TIMER_SLOW
)))
{
/* If the slow-timer wasn't activated until now */
isdn_timer_cnt1
=
0
;
isdn_timer_cnt2
=
0
;
}
old_tflags
=
dev
->
tflags
;
...
...
@@ -317,7 +321,7 @@ isdn_receive_skb_callback(int di, int channel, struct sk_buff *skb)
return
;
}
/* Update statistics */
dev
->
ibytes
[
i
]
+=
skb
->
len
;
slot
[
i
].
ibytes
+=
skb
->
len
;
/* First, try to deliver data to network-device */
if
(
isdn_net_rcv_skb
(
i
,
skb
))
...
...
@@ -327,10 +331,10 @@ isdn_receive_skb_callback(int di, int channel, struct sk_buff *skb)
* makes sense for async streams only, so it is
* called after possible net-device delivery.
*/
if
(
dev
->
v110
[
i
]
)
{
atomic_inc
(
&
dev
->
v110use
[
i
]
);
skb
=
isdn_v110_decode
(
dev
->
v110
[
i
]
,
skb
);
atomic_dec
(
&
dev
->
v110use
[
i
]
);
if
(
slot
[
i
].
iv110
.
v110
)
{
atomic_inc
(
&
slot
[
i
].
iv110
.
v110use
);
skb
=
isdn_v110_decode
(
slot
[
i
].
iv110
.
v110
,
skb
);
atomic_dec
(
&
slot
[
i
].
iv110
.
v110use
);
if
(
!
skb
)
return
;
}
...
...
@@ -350,15 +354,16 @@ isdn_receive_skb_callback(int di, int channel, struct sk_buff *skb)
* lowlevel-driver, use driver's transparent mode and handle V.110 in
* linklevel instead.
*/
int
static
int
isdn_command
(
isdn_ctrl
*
cmd
)
{
int
idx
=
isdn_dc2minor
(
cmd
->
driver
,
cmd
->
arg
&
255
);
if
(
cmd
->
driver
==
-
1
)
{
printk
(
KERN_WARNING
"isdn_command command(%x) driver -1
\n
"
,
cmd
->
command
);
return
(
1
);
}
if
(
cmd
->
command
==
ISDN_CMD_SETL2
)
{
int
idx
=
isdn_dc2minor
(
cmd
->
driver
,
cmd
->
arg
&
255
);
unsigned
long
l2prot
=
(
cmd
->
arg
>>
8
)
&
255
;
unsigned
long
features
=
(
dev
->
drv
[
cmd
->
driver
]
->
interface
->
features
>>
ISDN_FEATURE_L2_SHIFT
)
&
...
...
@@ -374,30 +379,38 @@ isdn_command(isdn_ctrl *cmd)
* Layer-2 to transparent
*/
if
(
!
(
features
&
l2_feature
))
{
dev
->
v110emu
[
idx
]
=
l2prot
;
slot
[
idx
].
iv110
.
v110emu
=
l2prot
;
cmd
->
arg
=
(
cmd
->
arg
&
255
)
|
(
ISDN_PROTO_L2_TRANS
<<
8
);
}
else
dev
->
v110emu
[
idx
]
=
0
;
slot
[
idx
].
iv110
.
v110emu
=
0
;
}
}
#ifdef ISDN_DEBUG_COMMAND
switch
(
cmd
->
command
)
{
case
ISDN_CMD_SETL2
:
printk
(
KERN_DEBUG
"ISDN_CMD_SETL2 %d
\n
"
,
idx
);
break
;
case
ISDN_CMD_SETL3
:
printk
(
KERN_DEBUG
"ISDN_CMD_SETL3 %d
\n
"
,
idx
);
break
;
case
ISDN_CMD_DIAL
:
printk
(
KERN_DEBUG
"ISDN_CMD_DIAL %d
\n
"
,
idx
);
break
;
case
ISDN_CMD_ACCEPTD
:
printk
(
KERN_DEBUG
"ISDN_CMD_ACCEPTD %d
\n
"
,
idx
);
break
;
case
ISDN_CMD_ACCEPTB
:
printk
(
KERN_DEBUG
"ISDN_CMD_ACCEPTB %d
\n
"
,
idx
);
break
;
case
ISDN_CMD_HANGUP
:
printk
(
KERN_DEBUG
"ISDN_CMD_HANGUP %d
\n
"
,
idx
);
break
;
case
ISDN_CMD_CLREAZ
:
printk
(
KERN_DEBUG
"ISDN_CMD_CLREAZ %d
\n
"
,
idx
);
break
;
case
ISDN_CMD_SETEAZ
:
printk
(
KERN_DEBUG
"ISDN_CMD_SETEAZ %d
\n
"
,
idx
);
break
;
default:
printk
(
KERN_DEBUG
"%s: cmd = %d
\n
"
,
__FUNCTION__
,
cmd
->
command
);
}
#endif
return
dev
->
drv
[
cmd
->
driver
]
->
interface
->
command
(
cmd
);
}
void
isdn_all_eaz
(
int
di
,
int
ch
)
{
isdn_ctrl
cmd
;
if
(
di
<
0
)
return
;
cmd
.
driver
=
di
;
cmd
.
arg
=
ch
;
cmd
.
command
=
ISDN_CMD_SETEAZ
;
cmd
.
parm
.
num
[
0
]
=
'\0'
;
isdn_command
(
&
cmd
);
}
/*
* Begin of a CAPI like LL<->HL interface, currently used only for
* supplementary service (CAPI 2.0 part III)
...
...
@@ -430,7 +443,7 @@ isdn_status_callback(isdn_ctrl * c)
int
r
;
int
retval
=
0
;
isdn_ctrl
cmd
;
isdn_net_dev
*
p
;
struct
list_head
*
l
;
di
=
c
->
driver
;
i
=
isdn_dc2minor
(
di
,
c
->
arg
);
...
...
@@ -442,7 +455,7 @@ isdn_status_callback(isdn_ctrl * c)
return
0
;
if
(
isdn_net_stat_callback
(
i
,
c
))
return
0
;
if
(
isdn_v110_stat_callback
(
i
,
c
))
if
(
isdn_v110_stat_callback
(
&
slot
[
i
].
iv110
,
c
))
return
0
;
if
(
isdn_tty_stat_callback
(
i
,
c
))
return
0
;
...
...
@@ -458,8 +471,8 @@ isdn_status_callback(isdn_ctrl * c)
case
ISDN_STAT_RUN
:
dev
->
drv
[
di
]
->
flags
|=
DRV_FLAG_RUNNING
;
for
(
i
=
0
;
i
<
ISDN_MAX_CHANNELS
;
i
++
)
if
(
dev
->
drvmap
[
i
]
==
di
)
isdn_
all_eaz
(
di
,
dev
->
chanmap
[
i
]
);
if
(
slot
[
i
].
di
==
di
)
isdn_
slot_all_eaz
(
i
);
set_global_features
();
break
;
case
ISDN_STAT_STOP
:
...
...
@@ -468,9 +481,7 @@ isdn_status_callback(isdn_ctrl * c)
case
ISDN_STAT_ICALL
:
if
(
i
<
0
)
return
-
1
;
#ifdef ISDN_DEBUG_STATCALLB
printk
(
KERN_DEBUG
"ICALL (net): %d %ld %s
\n
"
,
di
,
c
->
arg
,
c
->
parm
.
num
);
#endif
dbg_statcallb
(
"ICALL: %d (%d,%ld) %s
\n
"
,
i
,
di
,
c
->
arg
,
c
->
parm
.
num
);
if
(
dev
->
global_flags
&
ISDN_GLOBAL_STOPPED
)
{
cmd
.
driver
=
di
;
cmd
.
arg
=
c
->
arg
;
...
...
@@ -488,12 +499,10 @@ isdn_status_callback(isdn_ctrl * c)
* 3 on eventually match, if CID is longer.
*/
if
(
c
->
command
==
ISDN_STAT_ICALL
)
if
((
retval
=
isdn_tty_find_icall
(
di
,
c
->
arg
,
&
c
->
parm
.
setup
)))
return
(
retval
);
#ifdef CONFIG_ISDN_DIVERSION
if
((
retval
=
isdn_tty_find_icall
(
di
,
c
->
arg
,
&
c
->
parm
.
setup
)))
return
(
retval
);
if
(
divert_if
)
if
((
retval
=
divert_if
->
stat_callback
(
c
)))
return
(
retval
);
/* processed */
#endif
/* CONFIG_ISDN_DIVERSION */
if
((
retval
=
divert_if
->
stat_callback
(
c
)))
return
(
retval
);
/* processed */
if
((
!
retval
)
&&
(
dev
->
drv
[
di
]
->
flags
&
DRV_FLAG_REJBUS
))
{
/* No tty responding */
cmd
.
driver
=
di
;
...
...
@@ -504,19 +513,15 @@ isdn_status_callback(isdn_ctrl * c)
}
break
;
case
1
:
/* Schedule connection-setup */
isdn_net_dial
();
cmd
.
driver
=
di
;
cmd
.
arg
=
c
->
arg
;
cmd
.
command
=
ISDN_CMD_ACCEPTD
;
for
(
p
=
dev
->
netdev
;
p
;
p
=
p
->
next
)
if
(
p
->
local
->
isdn_channel
==
cmd
.
arg
)
{
strcpy
(
cmd
.
parm
.
setup
.
eazmsn
,
p
->
local
->
msn
);
isdn_command
(
&
cmd
);
list_for_each
(
l
,
&
isdn_net_devs
)
{
isdn_net_dev
*
p
=
list_entry
(
l
,
isdn_net_dev
,
global_list
);
if
(
p
->
local
.
isdn_slot
==
i
)
{
strcpy
(
cmd
.
parm
.
setup
.
eazmsn
,
p
->
local
.
msn
);
isdn_slot_command
(
i
,
ISDN_CMD_ACCEPTD
,
&
cmd
);
retval
=
1
;
break
;
}
}
break
;
case
2
:
/* For calling back, first reject incoming call ... */
...
...
@@ -532,24 +537,19 @@ isdn_status_callback(isdn_ctrl * c)
/* Fall through */
case
4
:
/* ... then start callback. */
isdn_net_dial
();
break
;
case
5
:
/* Number would eventually match, if longer */
retval
=
3
;
break
;
}
#ifdef ISDN_DEBUG_STATCALLB
printk
(
KERN_DEBUG
"ICALL: ret=%d
\n
"
,
retval
);
#endif
dbg_statcallb
(
"ICALL: ret=%d
\n
"
,
retval
);
return
retval
;
break
;
case
ISDN_STAT_CINF
:
if
(
i
<
0
)
return
-
1
;
#ifdef ISDN_DEBUG_STATCALLB
printk
(
KERN_DEBUG
"CINF: %ld %s
\n
"
,
c
->
arg
,
c
->
parm
.
num
);
#endif
dbg_statcallb
(
"CINF: %d %s
\n
"
,
i
,
c
->
parm
.
num
);
if
(
dev
->
global_flags
&
ISDN_GLOBAL_STOPPED
)
return
0
;
if
(
strcmp
(
c
->
parm
.
num
,
"0"
))
...
...
@@ -557,39 +557,29 @@ isdn_status_callback(isdn_ctrl * c)
isdn_tty_stat_callback
(
i
,
c
);
break
;
case
ISDN_STAT_CAUSE
:
#ifdef ISDN_DEBUG_STATCALLB
printk
(
KERN_DEBUG
"CAUSE: %ld %s
\n
"
,
c
->
arg
,
c
->
parm
.
num
);
#endif
dbg_statcallb
(
"CAUSE: %d %s
\n
"
,
i
,
c
->
parm
.
num
);
printk
(
KERN_INFO
"isdn: %s,ch%ld cause: %s
\n
"
,
dev
->
drvid
[
di
],
c
->
arg
,
c
->
parm
.
num
);
isdn_tty_stat_callback
(
i
,
c
);
#ifdef CONFIG_ISDN_DIVERSION
if
(
divert_if
)
divert_if
->
stat_callback
(
c
);
#endif
/* CONFIG_ISDN_DIVERSION */
divert_if
->
stat_callback
(
c
);
break
;
case
ISDN_STAT_DISPLAY
:
#ifdef ISDN_DEBUG_STATCALLB
printk
(
KERN_DEBUG
"DISPLAY: %ld %s
\n
"
,
c
->
arg
,
c
->
parm
.
display
);
#endif
dbg_statcallb
(
"DISPLAY: %d %s
\n
"
,
i
,
c
->
parm
.
display
);
isdn_tty_stat_callback
(
i
,
c
);
#ifdef CONFIG_ISDN_DIVERSION
if
(
divert_if
)
divert_if
->
stat_callback
(
c
);
#endif
/* CONFIG_ISDN_DIVERSION */
divert_if
->
stat_callback
(
c
);
break
;
case
ISDN_STAT_DCONN
:
if
(
i
<
0
)
return
-
1
;
#ifdef ISDN_DEBUG_STATCALLB
printk
(
KERN_DEBUG
"DCONN: %ld
\n
"
,
c
->
arg
);
#endif
dbg_statcallb
(
"DCONN: %d
\n
"
,
i
);
if
(
dev
->
global_flags
&
ISDN_GLOBAL_STOPPED
)
return
0
;
/* Find any net-device, waiting for D-channel setup */
if
(
isdn_net_stat_callback
(
i
,
c
))
break
;
isdn_v110_stat_callback
(
i
,
c
);
isdn_v110_stat_callback
(
&
slot
[
i
].
iv110
,
c
);
/* Find any ttyI, waiting for D-channel setup */
if
(
isdn_tty_stat_callback
(
i
,
c
))
{
cmd
.
driver
=
di
;
...
...
@@ -602,9 +592,7 @@ isdn_status_callback(isdn_ctrl * c)
case
ISDN_STAT_DHUP
:
if
(
i
<
0
)
return
-
1
;
#ifdef ISDN_DEBUG_STATCALLB
printk
(
KERN_DEBUG
"DHUP: %ld
\n
"
,
c
->
arg
);
#endif
dbg_statcallb
(
"DHUP: %d
\n
"
,
i
);
if
(
dev
->
global_flags
&
ISDN_GLOBAL_STOPPED
)
return
0
;
dev
->
drv
[
di
]
->
online
&=
~
(
1
<<
(
c
->
arg
));
...
...
@@ -612,21 +600,16 @@ isdn_status_callback(isdn_ctrl * c)
/* Signal hangup to network-devices */
if
(
isdn_net_stat_callback
(
i
,
c
))
break
;
isdn_v110_stat_callback
(
i
,
c
);
isdn_v110_stat_callback
(
&
slot
[
i
].
iv110
,
c
);
if
(
isdn_tty_stat_callback
(
i
,
c
))
break
;
#ifdef CONFIG_ISDN_DIVERSION
if
(
divert_if
)
divert_if
->
stat_callback
(
c
);
#endif
/* CONFIG_ISDN_DIVERSION */
break
;
divert_if
->
stat_callback
(
c
);
break
;
case
ISDN_STAT_BCONN
:
if
(
i
<
0
)
return
-
1
;
#ifdef ISDN_DEBUG_STATCALLB
printk
(
KERN_DEBUG
"BCONN: %ld
\n
"
,
c
->
arg
);
#endif
dbg_statcallb
(
"BCONN: %ld
\n
"
,
c
->
arg
);
/* Signal B-channel-connect to network-devices */
if
(
dev
->
global_flags
&
ISDN_GLOBAL_STOPPED
)
return
0
;
...
...
@@ -634,16 +617,14 @@ isdn_status_callback(isdn_ctrl * c)
isdn_info_update
();
if
(
isdn_net_stat_callback
(
i
,
c
))
break
;
isdn_v110_stat_callback
(
i
,
c
);
isdn_v110_stat_callback
(
&
slot
[
i
].
iv110
,
c
);
if
(
isdn_tty_stat_callback
(
i
,
c
))
break
;
break
;
case
ISDN_STAT_BHUP
:
if
(
i
<
0
)
return
-
1
;
#ifdef ISDN_DEBUG_STATCALLB
printk
(
KERN_DEBUG
"BHUP: %ld
\n
"
,
c
->
arg
);
#endif
dbg_statcallb
(
"BHUP: %d
\n
"
,
i
);
if
(
dev
->
global_flags
&
ISDN_GLOBAL_STOPPED
)
return
0
;
dev
->
drv
[
di
]
->
online
&=
~
(
1
<<
(
c
->
arg
));
...
...
@@ -653,16 +634,14 @@ isdn_status_callback(isdn_ctrl * c)
if
(
isdn_net_stat_callback
(
i
,
c
))
break
;
#endif
isdn_v110_stat_callback
(
i
,
c
);
isdn_v110_stat_callback
(
&
slot
[
i
].
iv110
,
c
);
if
(
isdn_tty_stat_callback
(
i
,
c
))
break
;
break
;
case
ISDN_STAT_NODCH
:
if
(
i
<
0
)
return
-
1
;
#ifdef ISDN_DEBUG_STATCALLB
printk
(
KERN_DEBUG
"NODCH: %ld
\n
"
,
c
->
arg
);
#endif
dbg_statcallb
(
"NODCH: %ld
\n
"
,
c
->
arg
);
if
(
dev
->
global_flags
&
ISDN_GLOBAL_STOPPED
)
return
0
;
if
(
isdn_net_stat_callback
(
i
,
c
))
...
...
@@ -679,20 +658,17 @@ isdn_status_callback(isdn_ctrl * c)
save_flags
(
flags
);
cli
();
for
(
i
=
0
;
i
<
ISDN_MAX_CHANNELS
;
i
++
)
if
((
dev
->
drvmap
[
i
]
==
di
)
&&
(
dev
->
chanmap
[
i
]
==
c
->
arg
))
{
if
(
c
->
parm
.
num
[
0
])
dev
->
usage
[
i
]
&=
~
ISDN_USAGE_DISABLED
;
else
if
(
USG_NONE
(
dev
->
usage
[
i
]))
{
dev
->
usage
[
i
]
|=
ISDN_USAGE_DISABLED
;
}
else
retval
=
-
1
;
break
;
if
((
slot
[
i
].
di
==
di
)
&&
(
slot
[
i
].
ch
==
c
->
arg
))
{
if
(
c
->
parm
.
num
[
0
])
isdn_slot_set_usage
(
i
,
isdn_slot_usage
(
i
)
&
~
ISDN_USAGE_DISABLED
);
else
if
(
USG_NONE
(
isdn_slot_usage
(
i
)))
isdn_slot_set_usage
(
i
,
isdn_slot_usage
(
i
)
|
ISDN_USAGE_DISABLED
);
else
retval
=
-
1
;
break
;
}
restore_flags
(
flags
);
isdn_info_update
();
break
;
case
ISDN_STAT_UNLOAD
:
while
(
dev
->
drv
[
di
]
->
locks
>
0
)
{
...
...
@@ -707,10 +683,10 @@ isdn_status_callback(isdn_ctrl * c)
cli
();
isdn_tty_stat_callback
(
i
,
c
);
for
(
i
=
0
;
i
<
ISDN_MAX_CHANNELS
;
i
++
)
if
(
dev
->
drvmap
[
i
]
==
di
)
{
dev
->
drvmap
[
i
]
=
-
1
;
dev
->
chanmap
[
i
]
=
-
1
;
dev
->
usage
[
i
]
&=
~
ISDN_USAGE_DISABLED
;
if
(
slot
[
i
].
di
==
di
)
{
slot
[
i
].
di
=
-
1
;
slot
[
i
].
ch
=
-
1
;
slot
[
i
].
usage
&=
~
ISDN_USAGE_DISABLED
;
isdn_unregister_devfs
(
i
);
}
dev
->
drivers
--
;
...
...
@@ -742,12 +718,10 @@ isdn_status_callback(isdn_ctrl * c)
isdn_tty_stat_callback
(
i
,
c
);
break
;
#endif
#ifdef CONFIG_ISDN_DIVERSION
case
ISDN_STAT_PROT
:
case
ISDN_STAT_REDIR
:
if
(
divert_if
)
return
(
divert_if
->
stat_callback
(
c
));
#endif
/* CONFIG_ISDN_DIVERSION */
return
(
divert_if
->
stat_callback
(
c
));
default:
return
-
1
;
}
...
...
@@ -770,50 +744,40 @@ isdn_getnum(char **p)
#define DLE 0x10
/*
* isdn_readbchan() tries to get data from the read-queue.
* isdn_
slot_
readbchan() tries to get data from the read-queue.
* It MUST be called with interrupts off.
*
* Be aware that this is not an atomic operation when sleep != 0, even though
* interrupts are turned off! Well, like that we are currently only called
* on behalf of a read system call on raw device files (which are documented
* to be dangerous and for for debugging purpose only). The inode semaphore
* takes care that this is not called for the same minor device number while
* we are sleeping, but access is not serialized against simultaneous read()
* from the corresponding ttyI device. Can other ugly events, like changes
* of the mapping (di,ch)<->minor, happen during the sleep? --he
*/
int
isdn_
readbchan
(
int
di
,
int
channel
,
u_char
*
buf
,
u_char
*
fp
,
int
len
,
wait_queue_head_t
*
sleep
)
isdn_
slot_readbchan
(
int
sl
,
u_char
*
buf
,
u_char
*
fp
,
int
len
)
{
int
count
;
int
count_pull
;
int
count_put
;
int
dflag
;
int
di
=
isdn_slot_driver
(
sl
);
int
ch
=
isdn_slot_channel
(
sl
);
struct
sk_buff
*
skb
;
u_char
*
cp
;
if
(
!
dev
->
drv
[
di
])
return
0
;
if
(
skb_queue_empty
(
&
dev
->
drv
[
di
]
->
rpqueue
[
channel
]))
{
if
(
sleep
)
interruptible_sleep_on
(
sleep
);
else
return
0
;
}
if
(
len
>
dev
->
drv
[
di
]
->
rcvcount
[
channel
])
len
=
dev
->
drv
[
di
]
->
rcvcount
[
channel
];
if
(
skb_queue_empty
(
&
dev
->
drv
[
di
]
->
rpqueue
[
ch
]))
return
0
;
if
(
len
>
dev
->
drv
[
di
]
->
rcvcount
[
ch
])
len
=
dev
->
drv
[
di
]
->
rcvcount
[
ch
];
cp
=
buf
;
count
=
0
;
while
(
len
)
{
if
(
!
(
skb
=
skb_peek
(
&
dev
->
drv
[
di
]
->
rpqueue
[
ch
annel
])))
if
(
!
(
skb
=
skb_peek
(
&
dev
->
drv
[
di
]
->
rpqueue
[
ch
])))
break
;
#ifdef CONFIG_ISDN_AUDIO
if
(
ISDN_AUDIO_SKB_LOCK
(
skb
))
break
;
ISDN_AUDIO_SKB_LOCK
(
skb
)
=
1
;
if
((
ISDN_AUDIO_SKB_DLECOUNT
(
skb
))
||
(
dev
->
drv
[
di
]
->
DLEflag
&
(
1
<<
ch
annel
)))
{
if
((
ISDN_AUDIO_SKB_DLECOUNT
(
skb
))
||
(
dev
->
drv
[
di
]
->
DLEflag
&
(
1
<<
ch
)))
{
char
*
p
=
skb
->
data
;
unsigned
long
DLEmask
=
(
1
<<
ch
annel
);
unsigned
long
DLEmask
=
(
1
<<
ch
);
dflag
=
0
;
count_pull
=
count_put
=
0
;
...
...
@@ -864,7 +828,7 @@ isdn_readbchan(int di, int channel, u_char * buf, u_char * fp, int len, wait_que
#ifdef CONFIG_ISDN_AUDIO
ISDN_AUDIO_SKB_LOCK
(
skb
)
=
0
;
#endif
skb
=
skb_dequeue
(
&
dev
->
drv
[
di
]
->
rpqueue
[
ch
annel
]);
skb
=
skb_dequeue
(
&
dev
->
drv
[
di
]
->
rpqueue
[
ch
]);
dev_kfree_skb
(
skb
);
}
else
{
/* Not yet emptied this buff, so it
...
...
@@ -876,7 +840,7 @@ isdn_readbchan(int di, int channel, u_char * buf, u_char * fp, int len, wait_que
ISDN_AUDIO_SKB_LOCK
(
skb
)
=
0
;
#endif
}
dev
->
drv
[
di
]
->
rcvcount
[
ch
annel
]
-=
count_put
;
dev
->
drv
[
di
]
->
rcvcount
[
ch
]
-=
count_put
;
}
return
count
;
}
...
...
@@ -884,13 +848,13 @@ isdn_readbchan(int di, int channel, u_char * buf, u_char * fp, int len, wait_que
static
__inline
int
isdn_minor2drv
(
int
minor
)
{
return
(
dev
->
drvmap
[
minor
])
;
return
slot
[
minor
].
di
;
}
static
__inline
int
isdn_minor2chan
(
int
minor
)
{
return
(
dev
->
chanmap
[
minor
])
;
return
slot
[
minor
].
ch
;
}
static
char
*
...
...
@@ -903,25 +867,25 @@ isdn_statstr(void)
sprintf
(
istatbuf
,
"idmap:
\t
"
);
p
=
istatbuf
+
strlen
(
istatbuf
);
for
(
i
=
0
;
i
<
ISDN_MAX_CHANNELS
;
i
++
)
{
sprintf
(
p
,
"%s "
,
(
dev
->
drvmap
[
i
]
<
0
)
?
"-"
:
dev
->
drvid
[
dev
->
drvmap
[
i
]
]);
sprintf
(
p
,
"%s "
,
(
slot
[
i
].
di
<
0
)
?
"-"
:
dev
->
drvid
[
slot
[
i
].
di
]);
p
=
istatbuf
+
strlen
(
istatbuf
);
}
sprintf
(
p
,
"
\n
chmap:
\t
"
);
p
=
istatbuf
+
strlen
(
istatbuf
);
for
(
i
=
0
;
i
<
ISDN_MAX_CHANNELS
;
i
++
)
{
sprintf
(
p
,
"%d "
,
dev
->
chanmap
[
i
]
);
sprintf
(
p
,
"%d "
,
slot
[
i
].
ch
);
p
=
istatbuf
+
strlen
(
istatbuf
);
}
sprintf
(
p
,
"
\n
drmap:
\t
"
);
p
=
istatbuf
+
strlen
(
istatbuf
);
for
(
i
=
0
;
i
<
ISDN_MAX_CHANNELS
;
i
++
)
{
sprintf
(
p
,
"%d "
,
dev
->
drvmap
[
i
]
);
sprintf
(
p
,
"%d "
,
slot
[
i
].
di
);
p
=
istatbuf
+
strlen
(
istatbuf
);
}
sprintf
(
p
,
"
\n
usage:
\t
"
);
p
=
istatbuf
+
strlen
(
istatbuf
);
for
(
i
=
0
;
i
<
ISDN_MAX_CHANNELS
;
i
++
)
{
sprintf
(
p
,
"%d "
,
dev
->
usage
[
i
]
);
sprintf
(
p
,
"%d "
,
slot
[
i
].
usage
);
p
=
istatbuf
+
strlen
(
istatbuf
);
}
sprintf
(
p
,
"
\n
flags:
\t
"
);
...
...
@@ -938,7 +902,7 @@ isdn_statstr(void)
sprintf
(
p
,
"
\n
phone:
\t
"
);
p
=
istatbuf
+
strlen
(
istatbuf
);
for
(
i
=
0
;
i
<
ISDN_MAX_CHANNELS
;
i
++
)
{
sprintf
(
p
,
"%s "
,
dev
->
num
[
i
]
);
sprintf
(
p
,
"%s "
,
isdn_slot_num
(
i
)
);
p
=
istatbuf
+
strlen
(
istatbuf
);
}
sprintf
(
p
,
"
\n
"
);
...
...
@@ -1095,8 +1059,8 @@ isdn_status_ioctl(struct inode *inode, struct file *file, uint cmd, ulong arg)
sizeof
(
ulong
)
*
ISDN_MAX_CHANNELS
*
2
)))
return
ret
;
for
(
i
=
0
;
i
<
ISDN_MAX_CHANNELS
;
i
++
)
{
put_user
(
dev
->
ibytes
[
i
]
,
p
++
);
put_user
(
dev
->
obytes
[
i
]
,
p
++
);
put_user
(
slot
[
i
].
ibytes
,
p
++
);
put_user
(
slot
[
i
].
obytes
,
p
++
);
}
return
0
;
}
else
...
...
@@ -1279,10 +1243,9 @@ isdn_ctrl_ioctl(struct inode *inode, struct file *file, uint cmd, ulong arg)
int
ret
;
int
i
;
char
*
p
;
char
*
s
;
union
iocpar
{
char
name
[
10
];
char
bname
[
2
2
];
char
bname
[
2
0
];
isdn_ioctl_struct
iocts
;
isdn_net_ioctl_phone
phone
;
isdn_net_ioctl_cfg
cfg
;
...
...
@@ -1310,42 +1273,24 @@ isdn_ctrl_ioctl(struct inode *inode, struct file *file, uint cmd, ulong arg)
#ifdef CONFIG_NETDEVICES
case
IIOCNETAIF
:
/* Add a network-interface */
if
(
arg
)
{
if
(
copy_from_user
(
name
,
(
char
*
)
arg
,
sizeof
(
name
)))
return
-
EFAULT
;
s
=
name
;
}
else
{
s
=
NULL
;
}
if
(
copy_from_user
(
name
,
(
char
*
)
arg
,
sizeof
(
name
)
-
1
))
return
-
EFAULT
;
name
[
sizeof
(
name
)
-
1
]
=
0
;
ret
=
down_interruptible
(
&
dev
->
sem
);
if
(
ret
)
return
ret
;
if
((
s
=
isdn_net_new
(
s
,
NULL
)))
{
if
(
copy_to_user
((
char
*
)
arg
,
s
,
strlen
(
s
)
+
1
)){
ret
=
-
EFAULT
;
}
else
{
ret
=
0
;
}
}
else
ret
=
-
ENODEV
;
if
(
ret
)
return
ret
;
ret
=
isdn_net_new
(
name
,
NULL
);
up
(
&
dev
->
sem
);
return
ret
;
case
IIOCNETASL
:
/* Add a slave to a network-interface */
if
(
arg
)
{
if
(
copy_from_user
(
bname
,
(
char
*
)
arg
,
sizeof
(
bname
)
-
1
))
return
-
EFAULT
;
}
else
return
-
EINVAL
;
if
(
copy_from_user
(
bname
,
(
char
*
)
arg
,
sizeof
(
bname
)
-
1
))
return
-
EFAULT
;
bname
[
sizeof
(
bname
)
-
1
]
=
0
;
ret
=
down_interruptible
(
&
dev
->
sem
);
if
(
ret
)
return
ret
;
if
((
s
=
isdn_net_newslave
(
bname
)))
{
if
(
copy_to_user
((
char
*
)
arg
,
s
,
strlen
(
s
)
+
1
)){
ret
=
-
EFAULT
;
}
else
{
ret
=
0
;
}
}
else
ret
=
-
ENODEV
;
if
(
ret
)
return
ret
;
ret
=
isdn_net_newslave
(
bname
);
up
(
&
dev
->
sem
);
return
ret
;
case
IIOCNETDIF
:
...
...
@@ -1742,8 +1687,8 @@ isdn_map_eaz2msn(char *msn, int di)
#define L2V (~(ISDN_FEATURE_L2_V11096|ISDN_FEATURE_L2_V11019|ISDN_FEATURE_L2_V11038))
int
isdn_get_free_
channel
(
int
usage
,
int
l2_proto
,
int
l3_proto
,
int
pre_dev
,
int
pre_chan
,
char
*
msn
)
isdn_get_free_
slot
(
int
usage
,
int
l2_proto
,
int
l3_proto
,
int
pre_dev
,
int
pre_chan
,
char
*
msn
)
{
int
i
;
ulong
flags
;
...
...
@@ -1760,34 +1705,28 @@ isdn_get_free_channel(int usage, int l2_proto, int l3_proto, int pre_dev
* because we can emulate this in linklevel.
*/
for
(
i
=
0
;
i
<
ISDN_MAX_CHANNELS
;
i
++
)
if
(
USG_NONE
(
dev
->
usage
[
i
]
)
&&
(
dev
->
drvmap
[
i
]
!=
-
1
))
{
int
d
=
dev
->
drvmap
[
i
]
;
if
((
dev
->
usage
[
i
]
&
ISDN_USAGE_EXCLUSIVE
)
&&
((
pre_dev
!=
d
)
||
(
pre_chan
!=
dev
->
chanmap
[
i
]
)))
if
(
USG_NONE
(
slot
[
i
].
usage
)
&&
(
slot
[
i
].
di
!=
-
1
))
{
int
d
=
slot
[
i
].
di
;
if
((
slot
[
i
].
usage
&
ISDN_USAGE_EXCLUSIVE
)
&&
((
pre_dev
!=
d
)
||
(
pre_chan
!=
slot
[
i
].
ch
)))
continue
;
if
(
!
strcmp
(
isdn_map_eaz2msn
(
msn
,
d
),
"-"
))
continue
;
if
(
dev
->
usage
[
i
]
&
ISDN_USAGE_DISABLED
)
if
(
slot
[
i
].
usage
&
ISDN_USAGE_DISABLED
)
continue
;
/* usage not allowed */
if
(
dev
->
drv
[
d
]
->
flags
&
DRV_FLAG_RUNNING
)
{
if
(((
dev
->
drv
[
d
]
->
interface
->
features
&
features
)
==
features
)
||
(((
dev
->
drv
[
d
]
->
interface
->
features
&
vfeatures
)
==
vfeatures
)
&&
(
dev
->
drv
[
d
]
->
interface
->
features
&
ISDN_FEATURE_L2_TRANS
)))
{
if
((
pre_dev
<
0
)
||
(
pre_chan
<
0
))
{
dev
->
usage
[
i
]
&=
ISDN_USAGE_EXCLUSIVE
;
dev
->
usage
[
i
]
|=
usage
;
isdn_info_update
();
isdn_slot_set_usage
(
i
,
(
isdn_slot_usage
(
i
)
&
ISDN_USAGE_EXCLUSIVE
)
|
usage
);
restore_flags
(
flags
);
return
i
;
}
else
if
((
pre_dev
==
d
)
&&
(
pre_chan
==
slot
[
i
].
ch
))
{
isdn_slot_set_usage
(
i
,
(
isdn_slot_usage
(
i
)
&
ISDN_USAGE_EXCLUSIVE
)
|
usage
);
restore_flags
(
flags
);
return
i
;
}
else
{
if
((
pre_dev
==
d
)
&&
(
pre_chan
==
dev
->
chanmap
[
i
]))
{
dev
->
usage
[
i
]
&=
ISDN_USAGE_EXCLUSIVE
;
dev
->
usage
[
i
]
|=
usage
;
isdn_info_update
();
restore_flags
(
flags
);
return
i
;
}
}
}
}
...
...
@@ -1802,28 +1741,32 @@ isdn_get_free_channel(int usage, int l2_proto, int l3_proto, int pre_dev
void
isdn_free_channel
(
int
di
,
int
ch
,
int
usage
)
{
int
i
;
ulong
flags
;
int
sl
;
sl
=
isdn_dc2minor
(
di
,
ch
);
isdn_slot_free
(
sl
,
usage
);
}
void
isdn_slot_free
(
int
sl
,
int
usage
)
{
unsigned
long
flags
;
save_flags
(
flags
);
cli
();
for
(
i
=
0
;
i
<
ISDN_MAX_CHANNELS
;
i
++
)
if
(((
!
usage
)
||
((
dev
->
usage
[
i
]
&
ISDN_USAGE_MASK
)
==
usage
))
&&
(
dev
->
drvmap
[
i
]
==
di
)
&&
(
dev
->
chanmap
[
i
]
==
ch
))
{
dev
->
usage
[
i
]
&=
(
ISDN_USAGE_NONE
|
ISDN_USAGE_EXCLUSIVE
);
strcpy
(
dev
->
num
[
i
],
"???"
);
dev
->
ibytes
[
i
]
=
0
;
dev
->
obytes
[
i
]
=
0
;
if
(
!
usage
||
(
slot
[
sl
].
usage
&
ISDN_USAGE_MASK
)
==
usage
)
{
strcpy
(
isdn_slot_num
(
sl
),
"???"
);
slot
[
sl
].
ibytes
=
0
;
slot
[
sl
].
obytes
=
0
;
// 20.10.99 JIM, try to reinitialize v110 !
dev
->
v110emu
[
i
]
=
0
;
atomic_set
(
&
(
dev
->
v110use
[
i
])
,
0
);
isdn_v110_close
(
dev
->
v110
[
i
]
);
dev
->
v110
[
i
]
=
NULL
;
slot
[
sl
].
iv110
.
v110emu
=
0
;
atomic_set
(
&
slot
[
sl
].
iv110
.
v110use
,
0
);
isdn_v110_close
(
slot
[
sl
].
iv110
.
v110
);
slot
[
sl
].
iv110
.
v110
=
NULL
;
// 20.10.99 JIM, try to reinitialize v110 !
isdn_info_update
(
);
skb_queue_purge
(
&
dev
->
drv
[
di
]
->
rpqueue
[
ch
]);
}
isdn_slot_set_usage
(
sl
,
isdn_slot_usage
(
sl
)
&
(
ISDN_USAGE_NONE
|
ISDN_USAGE_EXCLUSIVE
)
);
skb_queue_purge
(
&
dev
->
drv
[
isdn_slot_driver
(
sl
)]
->
rpqueue
[
isdn_slot_channel
(
sl
)
]);
}
restore_flags
(
flags
);
}
...
...
@@ -1839,10 +1782,9 @@ isdn_unexclusive_channel(int di, int ch)
save_flags
(
flags
);
cli
();
for
(
i
=
0
;
i
<
ISDN_MAX_CHANNELS
;
i
++
)
if
((
dev
->
drvmap
[
i
]
==
di
)
&&
(
dev
->
chanmap
[
i
]
==
ch
))
{
dev
->
usage
[
i
]
&=
~
ISDN_USAGE_EXCLUSIVE
;
isdn_info_update
();
if
((
slot
[
i
].
di
==
di
)
&&
(
slot
[
i
].
ch
==
ch
))
{
isdn_slot_set_usage
(
i
,
isdn_slot_usage
(
i
)
&
~
ISDN_USAGE_EXCLUSIVE
);
restore_flags
(
flags
);
return
;
}
...
...
@@ -1853,17 +1795,20 @@ isdn_unexclusive_channel(int di, int ch)
* Return: length of data on success, -ERRcode on failure.
*/
int
isdn_
writebuf_skb_stub
(
int
drvidx
,
int
chan
,
int
ack
,
struct
sk_buff
*
skb
)
isdn_
slot_write
(
int
sl
,
struct
sk_buff
*
skb
)
{
int
ret
;
struct
sk_buff
*
nskb
=
NULL
;
int
v110_ret
=
skb
->
len
;
int
idx
=
isdn_dc2minor
(
drvidx
,
chan
);
int
di
=
isdn_slot_driver
(
sl
);
int
ch
=
isdn_slot_channel
(
sl
);
BUG_ON
(
sl
<
0
);
if
(
dev
->
v110
[
idx
]
)
{
atomic_inc
(
&
dev
->
v110use
[
idx
]
);
nskb
=
isdn_v110_encode
(
dev
->
v110
[
idx
]
,
skb
);
atomic_dec
(
&
dev
->
v110use
[
idx
]
);
if
(
slot
[
sl
].
iv110
.
v110
)
{
atomic_inc
(
&
slot
[
sl
].
iv110
.
v110use
);
nskb
=
isdn_v110_encode
(
slot
[
sl
].
iv110
.
v110
,
skb
);
atomic_dec
(
&
slot
[
sl
].
iv110
.
v110use
);
if
(
!
nskb
)
return
0
;
v110_ret
=
*
((
int
*
)
nskb
->
data
);
...
...
@@ -1873,10 +1818,9 @@ isdn_writebuf_skb_stub(int drvidx, int chan, int ack, struct sk_buff *skb)
return
v110_ret
;
}
/* V.110 must always be acknowledged */
ack
=
1
;
ret
=
dev
->
drv
[
drvidx
]
->
interface
->
writebuf_skb
(
drvidx
,
chan
,
ack
,
nskb
);
ret
=
dev
->
drv
[
di
]
->
interface
->
writebuf_skb
(
di
,
ch
,
1
,
nskb
);
}
else
{
int
hl
=
dev
->
drv
[
drvidx
]
->
interface
->
hl_hdrlen
;
int
hl
=
isdn_slot_hdrlen
(
sl
)
;
if
(
skb_headroom
(
skb
)
<
hl
){
/*
...
...
@@ -1892,22 +1836,22 @@ isdn_writebuf_skb_stub(int drvidx, int chan, int ack, struct sk_buff *skb)
skb_tmp
=
skb_realloc_headroom
(
skb
,
hl
);
printk
(
KERN_DEBUG
"isdn_writebuf_skb_stub: reallocating headroom%s
\n
"
,
skb_tmp
?
""
:
" failed"
);
if
(
!
skb_tmp
)
return
-
ENOMEM
;
/* 0 better? */
ret
=
dev
->
drv
[
d
rvidx
]
->
interface
->
writebuf_skb
(
drvidx
,
chan
,
ack
,
skb_tmp
);
ret
=
dev
->
drv
[
d
i
]
->
interface
->
writebuf_skb
(
di
,
ch
,
1
,
skb_tmp
);
if
(
ret
>
0
){
dev_kfree_skb
(
skb
);
}
else
{
dev_kfree_skb
(
skb_tmp
);
}
}
else
{
ret
=
dev
->
drv
[
d
rvidx
]
->
interface
->
writebuf_skb
(
drvidx
,
chan
,
ack
,
skb
);
ret
=
dev
->
drv
[
d
i
]
->
interface
->
writebuf_skb
(
di
,
ch
,
1
,
skb
);
}
}
if
(
ret
>
0
)
{
dev
->
obytes
[
idx
]
+=
ret
;
if
(
dev
->
v110
[
idx
]
)
{
atomic_inc
(
&
dev
->
v110use
[
idx
]
);
dev
->
v110
[
idx
]
->
skbuser
++
;
atomic_dec
(
&
dev
->
v110use
[
idx
]
);
slot
[
sl
].
obytes
+=
ret
;
if
(
slot
[
sl
].
iv110
.
v110
)
{
atomic_inc
(
&
slot
[
sl
].
iv110
.
v110use
);
slot
[
sl
].
iv110
.
v110
->
skbuser
++
;
atomic_dec
(
&
slot
[
sl
].
iv110
.
v110use
);
/* For V.110 return unencoded data length */
ret
=
v110_ret
;
/* if the complete frame was send we free the skb;
...
...
@@ -1916,7 +1860,7 @@ isdn_writebuf_skb_stub(int drvidx, int chan, int ack, struct sk_buff *skb)
dev_kfree_skb
(
skb
);
}
}
else
if
(
dev
->
v110
[
idx
]
)
if
(
slot
[
sl
].
iv110
.
v110
)
dev_kfree_skb
(
nskb
);
return
ret
;
}
...
...
@@ -1997,9 +1941,9 @@ isdn_add_channels(driver *d, int drvidx, int n, int adding)
cli
();
for
(
j
=
d
->
channels
;
j
<
m
;
j
++
)
for
(
k
=
0
;
k
<
ISDN_MAX_CHANNELS
;
k
++
)
if
(
dev
->
chanmap
[
k
]
<
0
)
{
dev
->
chanmap
[
k
]
=
j
;
dev
->
drvmap
[
k
]
=
drvidx
;
if
(
slot
[
k
].
ch
<
0
)
{
slot
[
k
].
ch
=
j
;
slot
[
k
].
di
=
drvidx
;
isdn_register_devfs
(
k
);
break
;
}
...
...
@@ -2026,7 +1970,7 @@ set_global_features(void)
}
}
#if
def CONFIG_ISDN_DIVERSION
#if
defined(CONFIG_ISDN_DIVERSION) || defined(CONFIG_ISDN_DIVERSION_MODULE)
static
char
*
map_drvname
(
int
di
)
{
...
...
@@ -2075,7 +2019,7 @@ int DIVERT_REG_NAME(isdn_divert_if *i_div)
EXPORT_SYMBOL
(
DIVERT_REG_NAME
);
#endif
/* CONFIG_ISDN_DIVERSION */
#endif
EXPORT_SYMBOL
(
register_isdn
);
...
...
@@ -2140,6 +2084,186 @@ register_isdn(isdn_if * i)
return
1
;
}
int
isdn_slot_driver
(
int
sl
)
{
BUG_ON
(
sl
<
0
);
return
slot
[
sl
].
di
;
}
int
isdn_slot_channel
(
int
sl
)
{
BUG_ON
(
sl
<
0
);
return
slot
[
sl
].
ch
;
}
int
isdn_slot_hdrlen
(
int
sl
)
{
int
di
=
isdn_slot_driver
(
sl
);
return
dev
->
drv
[
di
]
->
interface
->
hl_hdrlen
;
}
char
*
isdn_slot_map_eaz2msn
(
int
sl
,
char
*
msn
)
{
int
di
=
isdn_slot_driver
(
sl
);
return
isdn_map_eaz2msn
(
msn
,
di
);
}
int
isdn_slot_command
(
int
sl
,
int
cmd
,
isdn_ctrl
*
ctrl
)
{
ctrl
->
command
=
cmd
;
ctrl
->
driver
=
isdn_slot_driver
(
sl
);
switch
(
cmd
)
{
case
ISDN_CMD_SETL2
:
case
ISDN_CMD_SETL3
:
case
ISDN_CMD_PROT_IO
:
ctrl
->
arg
&=
~
0xff
;
ctrl
->
arg
|=
isdn_slot_channel
(
sl
);
break
;
default:
ctrl
->
arg
=
isdn_slot_channel
(
sl
);
break
;
}
return
isdn_command
(
ctrl
);
}
int
isdn_slot_dial
(
int
sl
,
struct
dial_info
*
dial
)
{
isdn_ctrl
cmd
;
int
retval
;
char
*
msn
=
isdn_slot_map_eaz2msn
(
sl
,
dial
->
msn
);
/* check for DOV */
if
(
dial
->
si1
==
7
&&
tolower
(
dial
->
phone
[
0
])
==
'v'
)
{
/* DOV call */
dial
->
si1
=
1
;
dial
->
phone
++
;
/* skip v/V */
}
strcpy
(
isdn_slot_num
(
sl
),
dial
->
phone
);
isdn_slot_set_usage
(
sl
,
isdn_slot_usage
(
sl
)
|
ISDN_USAGE_OUTGOING
);
retval
=
isdn_slot_command
(
sl
,
ISDN_CMD_CLREAZ
,
&
cmd
);
if
(
retval
)
return
retval
;
strcpy
(
cmd
.
parm
.
num
,
msn
);
retval
=
isdn_slot_command
(
sl
,
ISDN_CMD_SETEAZ
,
&
cmd
);
cmd
.
arg
=
dial
->
l2_proto
<<
8
;
cmd
.
parm
.
fax
=
dial
->
fax
;
retval
=
isdn_slot_command
(
sl
,
ISDN_CMD_SETL2
,
&
cmd
);
if
(
retval
)
return
retval
;
cmd
.
arg
=
dial
->
l3_proto
<<
8
;
retval
=
isdn_slot_command
(
sl
,
ISDN_CMD_SETL3
,
&
cmd
);
if
(
retval
)
return
retval
;
cmd
.
parm
.
setup
.
si1
=
dial
->
si1
;
cmd
.
parm
.
setup
.
si2
=
dial
->
si2
;
strcpy
(
cmd
.
parm
.
setup
.
eazmsn
,
msn
);
strcpy
(
cmd
.
parm
.
setup
.
phone
,
dial
->
phone
);
printk
(
KERN_INFO
"ISDN: slot %d: Dialing %s -> %s (SI %d/%d) (B %d/%d)
\n
"
,
sl
,
cmd
.
parm
.
setup
.
eazmsn
,
cmd
.
parm
.
setup
.
phone
,
cmd
.
parm
.
setup
.
si1
,
cmd
.
parm
.
setup
.
si2
,
dial
->
l2_proto
,
dial
->
l3_proto
);
return
isdn_slot_command
(
sl
,
ISDN_CMD_DIAL
,
&
cmd
);
}
void
isdn_slot_all_eaz
(
int
sl
)
{
isdn_ctrl
cmd
;
cmd
.
parm
.
num
[
0
]
=
'\0'
;
isdn_slot_command
(
sl
,
ISDN_CMD_SETEAZ
,
&
cmd
);
}
int
isdn_slot_usage
(
int
sl
)
{
BUG_ON
(
sl
<
0
);
return
slot
[
sl
].
usage
;
}
void
isdn_slot_set_usage
(
int
sl
,
int
usage
)
{
BUG_ON
(
sl
<
0
);
slot
[
sl
].
usage
=
usage
;
isdn_info_update
();
}
int
isdn_slot_m_idx
(
int
sl
)
{
BUG_ON
(
sl
<
0
);
return
slot
[
sl
].
m_idx
;
}
void
isdn_slot_set_m_idx
(
int
sl
,
int
midx
)
{
BUG_ON
(
sl
<
0
);
slot
[
sl
].
m_idx
=
midx
;
}
char
*
isdn_slot_num
(
int
sl
)
{
BUG_ON
(
sl
<
0
);
return
slot
[
sl
].
num
;
}
void
isdn_slot_set_rx_netdev
(
int
sl
,
isdn_net_dev
*
nd
)
{
BUG_ON
(
sl
<
0
);
slot
[
sl
].
rx_netdev
=
nd
;
}
isdn_net_dev
*
isdn_slot_rx_netdev
(
int
sl
)
{
BUG_ON
(
sl
<
0
);
return
slot
[
sl
].
rx_netdev
;
}
void
isdn_slot_set_st_netdev
(
int
sl
,
isdn_net_dev
*
nd
)
{
BUG_ON
(
sl
<
0
);
slot
[
sl
].
st_netdev
=
nd
;
}
isdn_net_dev
*
isdn_slot_st_netdev
(
int
sl
)
{
BUG_ON
(
sl
<
0
);
return
slot
[
sl
].
st_netdev
;
}
/*
*****************************************************************************
* And now the modules code.
...
...
@@ -2247,53 +2371,43 @@ static void isdn_cleanup_devfs(void)
static
int
__init
isdn_init
(
void
)
{
int
i
;
int
retval
;
char
tmprev
[
50
];
if
(
!
(
dev
=
(
isdn_dev
*
)
vmalloc
(
sizeof
(
isdn_dev
))))
{
printk
(
KERN_WARNING
"isdn: Could not allocate device-struct.
\n
"
);
return
-
EIO
;
dev
=
vmalloc
(
sizeof
(
*
dev
));
if
(
!
dev
)
{
retval
=
-
ENOMEM
;
goto
err
;
}
memset
(
(
char
*
)
dev
,
0
,
sizeof
(
isdn_
dev
));
memset
(
dev
,
0
,
sizeof
(
*
dev
));
init_timer
(
&
dev
->
timer
);
dev
->
timer
.
function
=
isdn_timer_funct
;
init_MUTEX
(
&
dev
->
sem
);
init_waitqueue_head
(
&
dev
->
info_waitq
);
for
(
i
=
0
;
i
<
ISDN_MAX_CHANNELS
;
i
++
)
{
dev
->
drvmap
[
i
]
=
-
1
;
dev
->
chanmap
[
i
]
=
-
1
;
dev
->
m_idx
[
i
]
=
-
1
;
strcpy
(
dev
->
num
[
i
]
,
"???"
);
slot
[
i
].
di
=
-
1
;
slot
[
i
].
ch
=
-
1
;
slot
[
i
].
m_idx
=
-
1
;
strcpy
(
isdn_slot_num
(
i
)
,
"???"
);
init_waitqueue_head
(
&
dev
->
mdm
.
info
[
i
].
open_wait
);
init_waitqueue_head
(
&
dev
->
mdm
.
info
[
i
].
close_wait
);
}
if
(
register_chrdev
(
ISDN_MAJOR
,
"isdn"
,
&
isdn_fops
))
{
retval
=
register_chrdev
(
ISDN_MAJOR
,
"isdn"
,
&
isdn_fops
);
if
(
retval
)
{
printk
(
KERN_WARNING
"isdn: Could not register control devices
\n
"
);
vfree
(
dev
);
return
-
EIO
;
goto
err_vfree
;
}
isdn_init_devfs
();
if
((
i
=
isdn_tty_modem_init
())
<
0
)
{
retval
=
isdn_tty_init
();
if
(
retval
<
0
)
{
printk
(
KERN_WARNING
"isdn: Could not register tty devices
\n
"
);
if
(
i
==
-
3
)
tty_unregister_driver
(
&
dev
->
mdm
.
cua_modem
);
if
(
i
<=
-
2
)
tty_unregister_driver
(
&
dev
->
mdm
.
tty_modem
);
vfree
(
dev
);
isdn_cleanup_devfs
();
unregister_chrdev
(
ISDN_MAJOR
,
"isdn"
);
return
-
EIO
;
goto
err_cleanup_devfs
;
}
#ifdef CONFIG_ISDN_PPP
if
(
isdn_ppp_init
()
<
0
)
{
retval
=
isdn_ppp_init
();
if
(
retval
<
0
)
{
printk
(
KERN_WARNING
"isdn: Could not create PPP-device-structs
\n
"
);
tty_unregister_driver
(
&
dev
->
mdm
.
tty_modem
);
tty_unregister_driver
(
&
dev
->
mdm
.
cua_modem
);
for
(
i
=
0
;
i
<
ISDN_MAX_CHANNELS
;
i
++
)
kfree
(
dev
->
mdm
.
info
[
i
].
xmit_buf
-
4
);
isdn_cleanup_devfs
();
unregister_chrdev
(
ISDN_MAJOR
,
"isdn"
);
vfree
(
dev
);
return
-
EIO
;
goto
err_tty_modem
;
}
#endif
/* CONFIG_ISDN_PPP */
...
...
@@ -2317,6 +2431,16 @@ static int __init isdn_init(void)
#endif
isdn_info_update
();
return
0
;
err_tty_modem:
isdn_tty_exit
();
err_cleanup_devfs:
isdn_cleanup_devfs
();
unregister_chrdev
(
ISDN_MAJOR
,
"isdn"
);
err_vfree:
vfree
(
dev
);
err:
return
retval
;
}
/*
...
...
@@ -2325,46 +2449,24 @@ static int __init isdn_init(void)
static
void
__exit
isdn_exit
(
void
)
{
unsigned
long
flags
;
int
i
;
#ifdef CONFIG_ISDN_PPP
isdn_ppp_cleanup
();
#endif
save_flags
(
flags
);
cli
();
if
(
isdn_net_rmall
()
<
0
)
{
printk
(
KERN_WARNING
"isdn: net-device busy, remove cancelled
\n
"
);
restore_flags
(
flags
);
return
;
}
if
(
tty_unregister_driver
(
&
dev
->
mdm
.
tty_modem
))
{
printk
(
KERN_WARNING
"isdn: ttyI-device busy, remove cancelled
\n
"
);
restore_flags
(
flags
);
return
;
}
if
(
tty_unregister_driver
(
&
dev
->
mdm
.
cua_modem
))
{
printk
(
KERN_WARNING
"isdn: cui-device busy, remove cancelled
\n
"
);
restore_flags
(
flags
);
return
;
}
for
(
i
=
0
;
i
<
ISDN_MAX_CHANNELS
;
i
++
)
{
isdn_tty_cleanup_xmit
(
&
dev
->
mdm
.
info
[
i
]);
kfree
(
dev
->
mdm
.
info
[
i
].
xmit_buf
-
4
);
#ifdef CONFIG_ISDN_TTY_FAX
kfree
(
dev
->
mdm
.
info
[
i
].
fax
);
#endif
}
if
(
unregister_chrdev
(
ISDN_MAJOR
,
"isdn"
)
!=
0
)
{
printk
(
KERN_WARNING
"isdn: controldevice busy, remove cancelled
\n
"
);
restore_flags
(
flags
);
}
else
{
isdn_cleanup_devfs
();
del_timer
(
&
dev
->
timer
);
restore_flags
(
flags
);
/* call vfree with interrupts enabled, else it will hang */
vfree
(
dev
);
printk
(
KERN_NOTICE
"ISDN-subsystem unloaded
\n
"
);
}
if
(
isdn_net_rmall
()
<
0
)
BUG
();
isdn_tty_exit
();
if
(
unregister_chrdev
(
ISDN_MAJOR
,
"isdn"
))
BUG
();
isdn_cleanup_devfs
();
del_timer
(
&
dev
->
timer
);
restore_flags
(
flags
);
/* call vfree with interrupts enabled, else it will hang */
vfree
(
dev
);
}
module_init
(
isdn_init
);
...
...
drivers/isdn/i4l/isdn_common.h
View file @
b14ebcfc
...
...
@@ -23,6 +23,32 @@
#undef ISDN_DEBUG_NET_DUMP
#undef ISDN_DEBUG_NET_DIAL
#undef ISDN_DEBUG_NET_ICALL
#undef ISDN_DEBUG_STATCALLB
#undef ISDN_DEBUG_COMMAND
#ifdef ISDN_DEBUG_NET_DIAL
#define dbg_net_dial(arg...) printk(KERN_DEBUG arg)
#else
#define dbg_net_dial(arg...) do {} while (0)
#endif
#ifdef ISDN_DEBUG_NET_ICALL
#define dbg_net_icall(arg...) printk(KERN_DEBUG arg)
#else
#define dbg_net_icall(arg...) do {} while (0)
#endif
#ifdef ISDN_DEBUG_STATCALLB
#define dbg_statcallb(arg...) printk(KERN_DEBUG arg)
#else
#define dbg_statcallb(arg...) do {} while (0)
#endif
#define isdn_BUG() \
do { printk(KERN_WARNING "ISDN Bug at %s:%d\n", __FILE__, __LINE__); \
} while(0)
#define HERE printk("%s:%d (%s)\n", __FILE__, __LINE__, __FUNCTION__)
/* Prototypes */
extern
void
isdn_MOD_INC_USE_COUNT
(
void
);
...
...
@@ -30,20 +56,50 @@ extern void isdn_MOD_DEC_USE_COUNT(void);
extern
void
isdn_lock_drivers
(
void
);
extern
void
isdn_unlock_drivers
(
void
);
extern
void
isdn_free_channel
(
int
di
,
int
ch
,
int
usage
);
extern
void
isdn_all_eaz
(
int
di
,
int
ch
);
extern
int
isdn_command
(
isdn_ctrl
*
);
extern
int
isdn_dc2minor
(
int
di
,
int
ch
);
extern
void
isdn_info_update
(
void
);
extern
char
*
isdn_map_eaz2msn
(
char
*
msn
,
int
di
);
extern
void
isdn_timer_ctrl
(
int
tf
,
int
onoff
);
extern
void
isdn_unexclusive_channel
(
int
di
,
int
ch
);
extern
int
isdn_getnum
(
char
**
);
extern
int
isdn_readbchan
(
int
,
int
,
u_char
*
,
u_char
*
,
int
,
wait_queue_head_t
*
);
extern
int
isdn_get_free_channel
(
int
,
int
,
int
,
int
,
int
,
char
*
);
extern
int
isdn_writebuf_skb_stub
(
int
,
int
,
int
,
struct
sk_buff
*
);
extern
int
register_isdn
(
isdn_if
*
i
);
extern
int
isdn_msncmp
(
const
char
*
,
const
char
*
);
extern
int
isdn_add_channels
(
driver
*
,
int
,
int
,
int
);
#if defined(ISDN_DEBUG_NET_DUMP) || defined(ISDN_DEBUG_MODEM_DUMP)
extern
void
isdn_dumppkt
(
char
*
,
u_char
*
,
int
,
int
);
#else
static
inline
void
isdn_dumppkt
(
char
*
s
,
u_char
*
d
,
int
l
,
int
m
)
{
}
#endif
struct
dial_info
{
int
l2_proto
;
int
l3_proto
;
struct
T30_s
*
fax
;
unsigned
char
si1
;
unsigned
char
si2
;
unsigned
char
*
msn
;
unsigned
char
*
phone
;
};
extern
struct
list_head
isdn_net_devs
;
extern
int
isdn_get_free_slot
(
int
,
int
,
int
,
int
,
int
,
char
*
);
extern
void
isdn_slot_free
(
int
slot
,
int
usage
);
extern
void
isdn_slot_all_eaz
(
int
slot
);
extern
int
isdn_slot_command
(
int
slot
,
int
cmd
,
isdn_ctrl
*
);
extern
int
isdn_slot_dial
(
int
slot
,
struct
dial_info
*
dial
);
extern
char
*
isdn_slot_map_eaz2msn
(
int
slot
,
char
*
msn
);
extern
int
isdn_slot_write
(
int
slot
,
struct
sk_buff
*
);
extern
int
isdn_slot_readbchan
(
int
slot
,
u_char
*
,
u_char
*
,
int
);
extern
int
isdn_slot_hdrlen
(
int
slot
);
extern
int
isdn_slot_driver
(
int
slot
);
extern
int
isdn_slot_channel
(
int
slot
);
extern
int
isdn_slot_usage
(
int
slot
);
extern
void
isdn_slot_set_usage
(
int
slot
,
int
usage
);
extern
char
*
isdn_slot_num
(
int
slot
);
extern
int
isdn_slot_m_idx
(
int
slot
);
extern
void
isdn_slot_set_m_idx
(
int
slot
,
int
midx
);
extern
void
isdn_slot_set_rx_netdev
(
int
sl
,
isdn_net_dev
*
nd
);
extern
void
isdn_slot_set_st_netdev
(
int
sl
,
isdn_net_dev
*
nd
);
extern
isdn_net_dev
*
isdn_slot_rx_netdev
(
int
sl
);
extern
isdn_net_dev
*
isdn_slot_st_netdev
(
int
sl
);
drivers/isdn/i4l/isdn_net.c
View file @
b14ebcfc
...
...
@@ -38,6 +38,27 @@
#include "isdn_concap.h"
#endif
enum
{
ST_NULL
,
ST_OUT_WAIT_DCONN
,
ST_OUT_WAIT_BCONN
,
ST_IN_WAIT_DCONN
,
ST_IN_WAIT_BCONN
,
ST_ACTIVE
,
ST_WAIT_BEFORE_CB
,
};
/* keep clear of ISDN_CMD_* and ISDN_STAT_* */
enum
{
EV_NET_DIAL
=
0x200
,
EV_NET_TIMER_IN_DCONN
=
0x201
,
EV_NET_TIMER_IN_BCONN
=
0x202
,
EV_NET_TIMER_OUT_DCONN
=
0x203
,
EV_NET_TIMER_OUT_BCONN
=
0x204
,
EV_NET_TIMER_CB
=
0x205
,
};
LIST_HEAD
(
isdn_net_devs
);
/* Linked list of isdn_net_dev's */
/*
* Outline of new tbusy handling:
...
...
@@ -72,7 +93,7 @@
*/
static
__inline__
int
isdn_net_device_started
(
isdn_net_dev
*
n
)
{
isdn_net_local
*
lp
=
n
->
local
;
isdn_net_local
*
lp
=
&
n
->
local
;
struct
net_device
*
dev
;
if
(
lp
->
master
)
...
...
@@ -179,10 +200,13 @@ static __inline__ void isdn_net_zero_frame_cnt(isdn_net_local *lp)
int
isdn_net_force_dial_lp
(
isdn_net_local
*
);
static
int
isdn_net_start_xmit
(
struct
sk_buff
*
,
struct
net_device
*
);
static
int
do_dialout
(
isdn_net_local
*
lp
);
static
void
isdn_net_ciscohdlck_connected
(
isdn_net_local
*
lp
);
static
void
isdn_net_ciscohdlck_disconnected
(
isdn_net_local
*
lp
);
static
int
isdn_net_handle_event
(
isdn_net_local
*
lp
,
int
pr
,
void
*
arg
);
char
*
isdn_net_revision
=
"$Revision: 1.140.6.11 $"
;
/*
...
...
@@ -280,10 +304,9 @@ isdn_net_bind_channel(isdn_net_local * lp, int idx)
save_flags
(
flags
);
cli
();
lp
->
flags
|=
ISDN_NET_CONNECTED
;
lp
->
isdn_device
=
dev
->
drvmap
[
idx
];
lp
->
isdn_channel
=
dev
->
chanmap
[
idx
];
dev
->
rx_netdev
[
idx
]
=
lp
->
netdev
;
dev
->
st_netdev
[
idx
]
=
lp
->
netdev
;
lp
->
isdn_slot
=
idx
;
isdn_slot_set_rx_netdev
(
lp
->
isdn_slot
,
lp
->
netdev
);
isdn_slot_set_st_netdev
(
lp
->
isdn_slot
,
lp
->
netdev
);
restore_flags
(
flags
);
}
...
...
@@ -306,13 +329,14 @@ isdn_net_unbind_channel(isdn_net_local * lp)
*/
qdisc_reset
(
lp
->
netdev
->
dev
.
qdisc
);
}
lp
->
dialstate
=
0
;
dev
->
rx_netdev
[
isdn_dc2minor
(
lp
->
isdn_device
,
lp
->
isdn_channel
)]
=
NULL
;
dev
->
st_netdev
[
isdn_dc2minor
(
lp
->
isdn_device
,
lp
->
isdn_channel
)]
=
NULL
;
isdn_free_channel
(
lp
->
isdn_device
,
lp
->
isdn_channel
,
ISDN_USAGE_NET
);
lp
->
dialstate
=
ST_NULL
;
if
(
lp
->
isdn_slot
>=
0
)
{
isdn_slot_set_rx_netdev
(
lp
->
isdn_slot
,
NULL
);
isdn_slot_set_st_netdev
(
lp
->
isdn_slot
,
NULL
);
isdn_slot_free
(
lp
->
isdn_slot
,
ISDN_USAGE_NET
);
}
lp
->
flags
&=
~
ISDN_NET_CONNECTED
;
lp
->
isdn_device
=
-
1
;
lp
->
isdn_channel
=
-
1
;
lp
->
isdn_slot
=
-
1
;
restore_flags
(
flags
);
}
...
...
@@ -335,12 +359,13 @@ unsigned long last_jiffies = -HZ;
void
isdn_net_autohup
()
{
isdn_net_dev
*
p
=
dev
->
netdev
;
struct
list_head
*
l
;
int
anymore
;
anymore
=
0
;
while
(
p
)
{
isdn_net_local
*
l
=
p
->
local
;
list_for_each
(
l
,
&
isdn_net_devs
)
{
isdn_net_dev
*
p
=
list_entry
(
l
,
isdn_net_dev
,
global_list
);
isdn_net_local
*
l
=
&
p
->
local
;
if
(
jiffies
==
last_jiffies
)
l
->
cps
=
l
->
transcount
;
else
...
...
@@ -348,9 +373,10 @@ isdn_net_autohup()
l
->
transcount
=
0
;
if
(
dev
->
net_verbose
>
3
)
printk
(
KERN_DEBUG
"%s: %d bogocps
\n
"
,
l
->
name
,
l
->
cps
);
if
((
l
->
flags
&
ISDN_NET_CONNECTED
)
&&
(
!
l
->
dialstate
))
{
if
((
l
->
flags
&
ISDN_NET_CONNECTED
)
&&
(
l
->
dialstate
==
ST_ACTIVE
))
{
anymore
=
1
;
l
->
huptimer
++
;
printk
(
"huptimer %d, onhtime %d, chargetime %d, chargeint %d
\n
"
,
l
->
huptimer
,
l
->
onhtime
,
l
->
chargetime
,
l
->
chargeint
);
/*
* if there is some dialmode where timeout-hangup
* should _not_ be done, check for that here
...
...
@@ -363,8 +389,10 @@ isdn_net_autohup()
while
(
time_after
(
jiffies
,
l
->
chargetime
+
l
->
chargeint
))
l
->
chargetime
+=
l
->
chargeint
;
if
(
time_after
(
jiffies
,
l
->
chargetime
+
l
->
chargeint
-
2
*
HZ
))
if
(
l
->
outgoing
||
l
->
hupflags
&
ISDN_INHUP
)
if
(
l
->
outgoing
||
l
->
hupflags
&
ISDN_INHUP
)
{
HERE
;
isdn_net_hangup
(
&
p
->
dev
);
}
}
else
if
(
l
->
outgoing
)
{
if
(
l
->
hupflags
&
ISDN_CHARGEHUP
)
{
if
(
l
->
hupflags
&
ISDN_WAITCHARGE
)
{
...
...
@@ -378,8 +406,10 @@ isdn_net_autohup()
isdn_net_hangup
(
&
p
->
dev
);
}
}
}
else
if
(
l
->
hupflags
&
ISDN_INHUP
)
}
else
if
(
l
->
hupflags
&
ISDN_INHUP
)
{
HERE
;
isdn_net_hangup
(
&
p
->
dev
);
}
}
if
(
dev
->
global_flags
&
ISDN_GLOBAL_STOPPED
||
(
ISDN_NET_DIALMODE
(
*
l
)
==
ISDN_NET_DM_OFF
))
{
...
...
@@ -387,7 +417,6 @@ isdn_net_autohup()
break
;
}
}
p
=
(
isdn_net_dev
*
)
p
->
next
;
}
last_jiffies
=
jiffies
;
isdn_timer_ctrl
(
ISDN_TIMER_NETHANGUP
,
anymore
);
...
...
@@ -398,6 +427,47 @@ static void isdn_net_lp_disconnected(isdn_net_local *lp)
isdn_net_rm_from_bundle
(
lp
);
}
static
void
isdn_net_connected
(
isdn_net_local
*
lp
)
{
#ifdef CONFIG_ISDN_X25
struct
concap_proto
*
cprot
=
lp
->
netdev
->
cprot
;
struct
concap_proto_ops
*
pops
=
cprot
?
cprot
->
pops
:
0
;
#endif
lp
->
dialstate
=
ST_ACTIVE
;
isdn_timer_ctrl
(
ISDN_TIMER_NETHANGUP
,
1
);
if
(
lp
->
p_encap
==
ISDN_NET_ENCAP_CISCOHDLCK
)
isdn_net_ciscohdlck_connected
(
lp
);
if
(
lp
->
p_encap
!=
ISDN_NET_ENCAP_SYNCPPP
)
{
if
(
lp
->
master
)
{
/* is lp a slave? */
isdn_net_dev
*
nd
=
((
isdn_net_local
*
)
lp
->
master
->
priv
)
->
netdev
;
isdn_net_add_to_bundle
(
nd
,
lp
);
}
}
printk
(
KERN_INFO
"isdn_net: %s connected
\n
"
,
lp
->
name
);
/* If first Chargeinfo comes before B-Channel connect,
* we correct the timestamp here.
*/
lp
->
chargetime
=
jiffies
;
/* reset dial-timeout */
lp
->
dialstarted
=
0
;
lp
->
dialwait_timer
=
0
;
#ifdef CONFIG_ISDN_PPP
if
(
lp
->
p_encap
==
ISDN_NET_ENCAP_SYNCPPP
)
isdn_ppp_wakeup_daemon
(
lp
);
#endif
#ifdef CONFIG_ISDN_X25
/* try if there are generic concap receiver routines */
if
(
pops
)
if
(
pops
->
connect_ind
)
pops
->
connect_ind
(
cprot
);
#endif
/* CONFIG_ISDN_X25 */
/* ppp needs to do negotiations first */
if
(
lp
->
p_encap
!=
ISDN_NET_ENCAP_SYNCPPP
)
isdn_net_device_wake_queue
(
lp
);
}
/*
* Handle status-messages from ISDN-interfacecard.
* This function is called from within the main-status-dispatcher
...
...
@@ -407,443 +477,343 @@ static void isdn_net_lp_disconnected(isdn_net_local *lp)
int
isdn_net_stat_callback
(
int
idx
,
isdn_ctrl
*
c
)
{
isdn_net_dev
*
p
=
dev
->
st_netdev
[
idx
];
isdn_net_dev
*
p
=
isdn_slot_st_netdev
(
idx
);
isdn_net_local
*
lp
;
int
cmd
=
c
->
command
;
if
(
p
)
{
isdn_net_local
*
lp
=
p
->
local
;
#ifdef CONFIG_ISDN_X25
struct
concap_proto
*
cprot
=
lp
->
netdev
->
cprot
;
struct
concap_proto_ops
*
pops
=
cprot
?
cprot
->
pops
:
0
;
#endif
switch
(
cmd
)
{
case
ISDN_STAT_BSENT
:
/* A packet has successfully been sent out */
if
((
lp
->
flags
&
ISDN_NET_CONNECTED
)
&&
(
!
lp
->
dialstate
))
{
isdn_net_dec_frame_cnt
(
lp
);
lp
->
stats
.
tx_packets
++
;
lp
->
stats
.
tx_bytes
+=
c
->
parm
.
length
;
}
return
1
;
case
ISDN_STAT_DCONN
:
/* D-Channel is up */
switch
(
lp
->
dialstate
)
{
case
4
:
case
7
:
case
8
:
lp
->
dialstate
++
;
return
1
;
case
12
:
lp
->
dialstate
=
5
;
return
1
;
}
break
;
case
ISDN_STAT_DHUP
:
/* Either D-Channel-hangup or error during dialout */
#ifdef CONFIG_ISDN_X25
/* If we are not connencted then dialing had
failed. If there are generic encap protocol
receiver routines signal the closure of
the link*/
if
(
!
(
lp
->
flags
&
ISDN_NET_CONNECTED
)
&&
pops
&&
pops
->
disconn_ind
)
pops
->
disconn_ind
(
cprot
);
#endif
/* CONFIG_ISDN_X25 */
if
((
!
lp
->
dialstate
)
&&
(
lp
->
flags
&
ISDN_NET_CONNECTED
))
{
if
(
lp
->
p_encap
==
ISDN_NET_ENCAP_CISCOHDLCK
)
isdn_net_ciscohdlck_disconnected
(
lp
);
#ifdef CONFIG_ISDN_PPP
if
(
lp
->
p_encap
==
ISDN_NET_ENCAP_SYNCPPP
)
isdn_ppp_free
(
lp
);
#endif
isdn_net_lp_disconnected
(
lp
);
isdn_all_eaz
(
lp
->
isdn_device
,
lp
->
isdn_channel
);
printk
(
KERN_INFO
"%s: remote hangup
\n
"
,
lp
->
name
);
printk
(
KERN_INFO
"%s: Chargesum is %d
\n
"
,
lp
->
name
,
lp
->
charge
);
isdn_net_unbind_channel
(
lp
);
return
1
;
}
break
;
#ifdef CONFIG_ISDN_X25
case
ISDN_STAT_BHUP
:
/* B-Channel-hangup */
/* try if there are generic encap protocol
receiver routines and signal the closure of
the link */
if
(
pops
&&
pops
->
disconn_ind
){
pops
->
disconn_ind
(
cprot
);
return
1
;
}
break
;
#endif
/* CONFIG_ISDN_X25 */
case
ISDN_STAT_BCONN
:
/* B-Channel is up */
isdn_net_zero_frame_cnt
(
lp
);
switch
(
lp
->
dialstate
)
{
case
5
:
case
6
:
case
7
:
case
8
:
case
9
:
case
10
:
case
12
:
if
(
lp
->
dialstate
<=
6
)
{
dev
->
usage
[
idx
]
|=
ISDN_USAGE_OUTGOING
;
isdn_info_update
();
}
else
dev
->
rx_netdev
[
idx
]
=
p
;
lp
->
dialstate
=
0
;
isdn_timer_ctrl
(
ISDN_TIMER_NETHANGUP
,
1
);
if
(
lp
->
p_encap
==
ISDN_NET_ENCAP_CISCOHDLCK
)
isdn_net_ciscohdlck_connected
(
lp
);
if
(
lp
->
p_encap
!=
ISDN_NET_ENCAP_SYNCPPP
)
{
if
(
lp
->
master
)
{
/* is lp a slave? */
isdn_net_dev
*
nd
=
((
isdn_net_local
*
)
lp
->
master
->
priv
)
->
netdev
;
isdn_net_add_to_bundle
(
nd
,
lp
);
}
}
printk
(
KERN_INFO
"isdn_net: %s connected
\n
"
,
lp
->
name
);
/* If first Chargeinfo comes before B-Channel connect,
* we correct the timestamp here.
*/
lp
->
chargetime
=
jiffies
;
/* reset dial-timeout */
lp
->
dialstarted
=
0
;
lp
->
dialwait_timer
=
0
;
if
(
!
p
)
{
HERE
;
return
0
;
}
lp
=
&
p
->
local
;
#ifdef CONFIG_ISDN_PPP
if
(
lp
->
p_encap
==
ISDN_NET_ENCAP_SYNCPPP
)
isdn_ppp_wakeup_daemon
(
lp
);
#endif
#ifdef CONFIG_ISDN_X25
/* try if there are generic concap receiver routines */
if
(
pops
)
if
(
pops
->
connect_ind
)
pops
->
connect_ind
(
cprot
);
#endif
/* CONFIG_ISDN_X25 */
/* ppp needs to do negotiations first */
if
(
lp
->
p_encap
!=
ISDN_NET_ENCAP_SYNCPPP
)
isdn_net_device_wake_queue
(
lp
);
return
1
;
}
break
;
case
ISDN_STAT_NODCH
:
/* No D-Channel avail. */
if
(
lp
->
dialstate
==
4
)
{
lp
->
dialstate
--
;
return
1
;
}
break
;
case
ISDN_STAT_CINF
:
/* Charge-info from TelCo. Calculate interval between
* charge-infos and set timestamp for last info for
* usage by isdn_net_autohup()
*/
lp
->
charge
++
;
if
(
lp
->
hupflags
&
ISDN_HAVECHARGE
)
{
lp
->
hupflags
&=
~
ISDN_WAITCHARGE
;
lp
->
chargeint
=
jiffies
-
lp
->
chargetime
-
(
2
*
HZ
);
}
if
(
lp
->
hupflags
&
ISDN_WAITCHARGE
)
lp
->
hupflags
|=
ISDN_HAVECHARGE
;
lp
->
chargetime
=
jiffies
;
printk
(
KERN_DEBUG
"isdn_net: Got CINF chargetime of %s now %lu
\n
"
,
lp
->
name
,
lp
->
chargetime
);
return
1
;
}
return
isdn_net_handle_event
(
lp
,
cmd
,
c
);
}
static
void
isdn_net_dial_timer
(
unsigned
long
data
)
{
isdn_net_local
*
lp
=
(
isdn_net_local
*
)
data
;
if
(
!
lp
)
{
isdn_BUG
();
return
;
}
return
0
;
printk
(
"%s: %s %#x
\n
"
,
__FUNCTION__
,
lp
->
name
,
lp
->
dial_event
);
isdn_net_handle_event
(
lp
,
lp
->
dial_event
,
NULL
);
}
/*
* Perform dialout for net-interfaces and timeout-handling for
* D-Channel-up and B-Channel-up Messages.
* This function is initially called from within isdn_net_start_xmit() or
* or isdn_net_find_icall() after initializing the dialstate for an
* interface. If further calls are needed, the function schedules itself
* for a timer-callback via isdn_timer_function().
* The dialstate is also affected by incoming status-messages from
* the ISDN-Channel which are handled in isdn_net_stat_callback() above.
/* Initiate dialout. Set phone-number-pointer to first number
* of interface.
*/
void
i
sdn_net_dial
(
void
)
static
int
i
nit_dialout
(
isdn_net_local
*
lp
)
{
isdn_net_dev
*
p
=
dev
->
netdev
;
int
anymore
=
0
;
int
i
;
unsigned
long
flags
;
isdn_ctrl
cmd
;
u_char
*
phone_number
;
while
(
p
)
{
isdn_net_local
*
lp
=
p
->
local
;
#ifdef ISDN_DEBUG_NET_DIAL
if
(
lp
->
dialstate
)
printk
(
KERN_DEBUG
"%s: dialstate=%d
\n
"
,
lp
->
name
,
lp
->
dialstate
);
#endif
switch
(
lp
->
dialstate
)
{
case
0
:
/* Nothing to do for this interface */
break
;
case
1
:
/* Initiate dialout. Set phone-number-pointer to first number
* of interface.
*/
save_flags
(
flags
);
cli
();
lp
->
dial
=
lp
->
phone
[
1
];
restore_flags
(
flags
);
if
(
!
lp
->
dial
)
{
printk
(
KERN_WARNING
"%s: phone number deleted?
\n
"
,
lp
->
name
);
isdn_net_hangup
(
&
p
->
dev
);
break
;
}
anymore
=
1
;
if
(
lp
->
dialtimeout
>
0
)
if
(
lp
->
dialstarted
==
0
||
time_after
(
jiffies
,
lp
->
dialstarted
+
lp
->
dialtimeout
+
lp
->
dialwait
))
{
lp
->
dialstarted
=
jiffies
;
lp
->
dialwait_timer
=
0
;
}
save_flags
(
flags
);
cli
();
lp
->
dial
=
lp
->
phone
[
1
];
restore_flags
(
flags
);
lp
->
dialstate
++
;
/* Fall through */
case
2
:
/* Prepare dialing. Clear EAZ, then set EAZ. */
cmd
.
driver
=
lp
->
isdn_device
;
cmd
.
arg
=
lp
->
isdn_channel
;
cmd
.
command
=
ISDN_CMD_CLREAZ
;
isdn_command
(
&
cmd
);
sprintf
(
cmd
.
parm
.
num
,
"%s"
,
isdn_map_eaz2msn
(
lp
->
msn
,
cmd
.
driver
));
cmd
.
command
=
ISDN_CMD_SETEAZ
;
isdn_command
(
&
cmd
);
lp
->
dialretry
=
0
;
anymore
=
1
;
lp
->
dialstate
++
;
/* Fall through */
case
3
:
/* Setup interface, dial current phone-number, switch to next number.
* If list of phone-numbers is exhausted, increment
* retry-counter.
*/
if
(
dev
->
global_flags
&
ISDN_GLOBAL_STOPPED
||
(
ISDN_NET_DIALMODE
(
*
lp
)
==
ISDN_NET_DM_OFF
))
{
char
*
s
;
if
(
dev
->
global_flags
&
ISDN_GLOBAL_STOPPED
)
s
=
"dial suppressed: isdn system stopped"
;
else
s
=
"dial suppressed: dialmode `off'"
;
isdn_net_unreachable
(
&
p
->
dev
,
0
,
s
);
isdn_net_hangup
(
&
p
->
dev
);
break
;
}
cmd
.
driver
=
lp
->
isdn_device
;
cmd
.
command
=
ISDN_CMD_SETL2
;
cmd
.
arg
=
lp
->
isdn_channel
+
(
lp
->
l2_proto
<<
8
);
isdn_command
(
&
cmd
);
cmd
.
driver
=
lp
->
isdn_device
;
cmd
.
command
=
ISDN_CMD_SETL3
;
cmd
.
arg
=
lp
->
isdn_channel
+
(
lp
->
l3_proto
<<
8
);
isdn_command
(
&
cmd
);
cmd
.
driver
=
lp
->
isdn_device
;
cmd
.
arg
=
lp
->
isdn_channel
;
save_flags
(
flags
);
cli
();
if
(
!
lp
->
dial
)
{
restore_flags
(
flags
);
printk
(
KERN_WARNING
"%s: phone number deleted?
\n
"
,
lp
->
name
);
isdn_net_hangup
(
&
p
->
dev
);
break
;
}
if
(
!
strncmp
(
lp
->
dial
->
num
,
"LEASED"
,
strlen
(
"LEASED"
)))
{
restore_flags
(
flags
);
lp
->
dialstate
=
4
;
printk
(
KERN_INFO
"%s: Open leased line ...
\n
"
,
lp
->
name
);
}
else
{
if
(
lp
->
dialtimeout
>
0
)
if
(
time_after
(
jiffies
,
lp
->
dialstarted
+
lp
->
dialtimeout
))
{
restore_flags
(
flags
);
lp
->
dialwait_timer
=
jiffies
+
lp
->
dialwait
;
lp
->
dialstarted
=
0
;
isdn_net_unreachable
(
&
p
->
dev
,
0
,
"dial: timed out"
);
isdn_net_hangup
(
&
p
->
dev
);
break
;
}
if
(
!
lp
->
dial
)
{
printk
(
KERN_WARNING
"%s: phone number deleted?
\n
"
,
lp
->
name
);
isdn_net_hangup
(
&
lp
->
netdev
->
dev
);
return
0
;
}
if
(
lp
->
dialtimeout
>
0
&&
(
lp
->
dialstarted
==
0
||
time_after
(
jiffies
,
lp
->
dialstarted
+
lp
->
dialtimeout
+
lp
->
dialwait
)))
{
lp
->
dialstarted
=
jiffies
;
lp
->
dialwait_timer
=
0
;
}
lp
->
dialretry
=
0
;
return
do_dialout
(
lp
);
}
cmd
.
driver
=
lp
->
isdn_device
;
cmd
.
command
=
ISDN_CMD_DIAL
;
cmd
.
parm
.
setup
.
si2
=
0
;
/* check for DOV */
phone_number
=
lp
->
dial
->
num
;
if
((
*
phone_number
==
'v'
)
||
(
*
phone_number
==
'V'
))
{
/* DOV call */
cmd
.
parm
.
setup
.
si1
=
1
;
}
else
{
/* DATA call */
cmd
.
parm
.
setup
.
si1
=
7
;
}
/* Setup interface, dial current phone-number, switch to next number.
* If list of phone-numbers is exhausted, increment
* retry-counter.
*/
static
int
do_dialout
(
isdn_net_local
*
lp
)
{
unsigned
long
flags
;
strcpy
(
cmd
.
parm
.
setup
.
phone
,
phone_number
);
/*
* Switch to next number or back to start if at end of list.
*/
if
(
!
(
lp
->
dial
=
(
isdn_net_phone
*
)
lp
->
dial
->
next
))
{
lp
->
dial
=
lp
->
phone
[
1
];
lp
->
dialretry
++
;
if
(
dev
->
global_flags
&
ISDN_GLOBAL_STOPPED
||
(
ISDN_NET_DIALMODE
(
*
lp
)
==
ISDN_NET_DM_OFF
))
{
char
*
s
;
if
(
dev
->
global_flags
&
ISDN_GLOBAL_STOPPED
)
s
=
"dial suppressed: isdn system stopped"
;
else
s
=
"dial suppressed: dialmode `off'"
;
isdn_net_unreachable
(
&
lp
->
netdev
->
dev
,
0
,
s
);
isdn_net_hangup
(
&
lp
->
netdev
->
dev
);
return
0
;
}
if
(
lp
->
dialretry
>
lp
->
dialmax
)
{
restore_flags
(
flags
);
if
(
lp
->
dialtimeout
==
0
)
{
lp
->
dialwait_timer
=
jiffies
+
lp
->
dialwait
;
lp
->
dialstarted
=
0
;
isdn_net_unreachable
(
&
p
->
dev
,
0
,
"dial: tried all numbers dialmax times"
);
}
isdn_net_hangup
(
&
p
->
dev
);
break
;
}
}
restore_flags
(
flags
);
sprintf
(
cmd
.
parm
.
setup
.
eazmsn
,
"%s"
,
isdn_map_eaz2msn
(
lp
->
msn
,
cmd
.
driver
));
i
=
isdn_dc2minor
(
lp
->
isdn_device
,
lp
->
isdn_channel
);
if
(
i
>=
0
)
{
strcpy
(
dev
->
num
[
i
],
cmd
.
parm
.
setup
.
phone
);
dev
->
usage
[
i
]
|=
ISDN_USAGE_OUTGOING
;
isdn_info_update
();
}
printk
(
KERN_INFO
"%s: dialing %d %s... %s
\n
"
,
lp
->
name
,
lp
->
dialretry
,
cmd
.
parm
.
setup
.
phone
,
(
cmd
.
parm
.
setup
.
si1
==
1
)
?
"DOV"
:
""
);
lp
->
dtimer
=
0
;
#ifdef ISDN_DEBUG_NET_DIAL
printk
(
KERN_DEBUG
"dial: d=%d c=%d
\n
"
,
lp
->
isdn_device
,
lp
->
isdn_channel
);
#endif
isdn_command
(
&
cmd
);
}
lp
->
huptimer
=
0
;
lp
->
outgoing
=
1
;
if
(
lp
->
chargeint
)
{
lp
->
hupflags
|=
ISDN_HAVECHARGE
;
lp
->
hupflags
&=
~
ISDN_WAITCHARGE
;
}
else
{
lp
->
hupflags
|=
ISDN_WAITCHARGE
;
lp
->
hupflags
&=
~
ISDN_HAVECHARGE
;
save_flags
(
flags
);
cli
();
if
(
!
lp
->
dial
)
{
restore_flags
(
flags
);
printk
(
KERN_WARNING
"%s: phone number deleted?
\n
"
,
lp
->
name
);
isdn_net_hangup
(
&
lp
->
netdev
->
dev
);
return
0
;
}
if
(
!
strncmp
(
lp
->
dial
->
num
,
"LEASED"
,
strlen
(
"LEASED"
)))
{
restore_flags
(
flags
);
lp
->
dialstate
=
ST_OUT_WAIT_DCONN
;
printk
(
KERN_INFO
"%s: Open leased line ...
\n
"
,
lp
->
name
);
return
1
;
}
else
{
struct
dial_info
dial
=
{
.
l2_proto
=
lp
->
l2_proto
,
.
l3_proto
=
lp
->
l3_proto
,
.
si1
=
7
,
.
si2
=
0
,
.
msn
=
lp
->
msn
,
.
phone
=
lp
->
dial
->
num
,
};
if
(
lp
->
dialtimeout
>
0
)
{
if
(
time_after
(
jiffies
,
lp
->
dialstarted
+
lp
->
dialtimeout
))
{
restore_flags
(
flags
);
lp
->
dialwait_timer
=
jiffies
+
lp
->
dialwait
;
lp
->
dialstarted
=
0
;
isdn_net_unreachable
(
&
lp
->
netdev
->
dev
,
0
,
"dial: timed out"
);
isdn_net_hangup
(
&
lp
->
netdev
->
dev
);
return
0
;
}
}
/*
* Switch to next number or back to start if at end of list.
*/
if
(
!
(
lp
->
dial
=
(
isdn_net_phone
*
)
lp
->
dial
->
next
))
{
lp
->
dial
=
lp
->
phone
[
1
];
lp
->
dialretry
++
;
if
(
lp
->
dialretry
>
lp
->
dialmax
)
{
restore_flags
(
flags
);
if
(
lp
->
dialtimeout
==
0
)
{
lp
->
dialwait_timer
=
jiffies
+
lp
->
dialwait
;
lp
->
dialstarted
=
0
;
isdn_net_unreachable
(
&
lp
->
netdev
->
dev
,
0
,
"dial: tried all numbers dialmax times"
);
}
anymore
=
1
;
lp
->
dialstate
=
(
lp
->
cbdelay
&&
(
lp
->
flags
&
ISDN_NET_CBOUT
))
?
12
:
4
;
break
;
case
4
:
/* Wait for D-Channel-connect.
* If timeout, switch back to state 3.
* Dialmax-handling moved to state 3.
*/
if
(
lp
->
dtimer
++
>
ISDN_TIMER_DTIMEOUT10
)
lp
->
dialstate
=
3
;
anymore
=
1
;
break
;
case
5
:
/* Got D-Channel-Connect, send B-Channel-request */
cmd
.
driver
=
lp
->
isdn_device
;
cmd
.
arg
=
lp
->
isdn_channel
;
cmd
.
command
=
ISDN_CMD_ACCEPTB
;
anymore
=
1
;
lp
->
dtimer
=
0
;
lp
->
dialstate
++
;
isdn_command
(
&
cmd
);
break
;
case
6
:
/* Wait for B- or D-Channel-connect. If timeout,
* switch back to state 3.
*/
#ifdef ISDN_DEBUG_NET_DIAL
printk
(
KERN_DEBUG
"dialtimer2: %d
\n
"
,
lp
->
dtimer
);
#endif
if
(
lp
->
dtimer
++
>
ISDN_TIMER_DTIMEOUT10
)
lp
->
dialstate
=
3
;
anymore
=
1
;
break
;
case
7
:
/* Got incoming Call, setup L2 and L3 protocols,
* then wait for D-Channel-connect
*/
#ifdef ISDN_DEBUG_NET_DIAL
printk
(
KERN_DEBUG
"dialtimer4: %d
\n
"
,
lp
->
dtimer
);
isdn_net_hangup
(
&
lp
->
netdev
->
dev
);
return
0
;
}
}
restore_flags
(
flags
);
isdn_slot_dial
(
lp
->
isdn_slot
,
&
dial
);
}
lp
->
huptimer
=
0
;
lp
->
outgoing
=
1
;
if
(
lp
->
chargeint
)
{
lp
->
hupflags
|=
ISDN_HAVECHARGE
;
lp
->
hupflags
&=
~
ISDN_WAITCHARGE
;
}
else
{
lp
->
hupflags
|=
ISDN_WAITCHARGE
;
lp
->
hupflags
&=
~
ISDN_HAVECHARGE
;
}
if
(
lp
->
cbdelay
&&
(
lp
->
flags
&
ISDN_NET_CBOUT
))
{
lp
->
dial_timer
.
expires
=
jiffies
+
lp
->
cbdelay
;
lp
->
dial_event
=
EV_NET_TIMER_CB
;
}
else
{
lp
->
dial_timer
.
expires
=
jiffies
+
10
*
HZ
;
lp
->
dial_event
=
EV_NET_TIMER_OUT_DCONN
;
}
lp
->
dialstate
=
ST_OUT_WAIT_DCONN
;
add_timer
(
&
lp
->
dial_timer
);
return
1
;
}
/* For EV_NET_DIAL, returns 1 if timer callback is needed
* For ISDN_STAT_*, returns 1 if event was for us
*/
static
int
isdn_net_handle_event
(
isdn_net_local
*
lp
,
int
pr
,
void
*
arg
)
{
#ifdef CONFIG_ISDN_X25
struct
concap_proto
*
cprot
=
lp
->
netdev
->
cprot
;
struct
concap_proto_ops
*
pops
=
cprot
?
cprot
->
pops
:
0
;
#endif
cmd
.
driver
=
lp
->
isdn_device
;
cmd
.
command
=
ISDN_CMD_SETL2
;
cmd
.
arg
=
lp
->
isdn_channel
+
(
lp
->
l2_proto
<<
8
);
isdn_command
(
&
cmd
);
cmd
.
driver
=
lp
->
isdn_device
;
cmd
.
command
=
ISDN_CMD_SETL3
;
cmd
.
arg
=
lp
->
isdn_channel
+
(
lp
->
l3_proto
<<
8
);
isdn_command
(
&
cmd
);
if
(
lp
->
dtimer
++
>
ISDN_TIMER_DTIMEOUT15
)
isdn_net_hangup
(
&
p
->
dev
);
else
{
anymore
=
1
;
lp
->
dialstate
++
;
}
break
;
case
9
:
/* Got incoming D-Channel-Connect, send B-Channel-request */
cmd
.
driver
=
lp
->
isdn_device
;
cmd
.
arg
=
lp
->
isdn_channel
;
cmd
.
command
=
ISDN_CMD_ACCEPTB
;
isdn_command
(
&
cmd
);
anymore
=
1
;
lp
->
dtimer
=
0
;
lp
->
dialstate
++
;
break
;
case
8
:
case
10
:
/* Wait for B- or D-channel-connect */
#ifdef ISDN_DEBUG_NET_DIAL
printk
(
KERN_DEBUG
"dialtimer4: %d
\n
"
,
lp
->
dtimer
);
isdn_net_dev
*
p
=
lp
->
netdev
;
isdn_ctrl
*
c
=
arg
;
isdn_ctrl
cmd
;
dbg_net_dial
(
"%s: dialstate=%d pr=%#x
\n
"
,
lp
->
name
,
lp
->
dialstate
,
pr
);
switch
(
lp
->
dialstate
)
{
case
ST_ACTIVE
:
switch
(
pr
)
{
case
ISDN_STAT_BSENT
:
/* A packet has successfully been sent out */
if
(
lp
->
flags
&
ISDN_NET_CONNECTED
)
{
isdn_net_dec_frame_cnt
(
lp
);
lp
->
stats
.
tx_packets
++
;
lp
->
stats
.
tx_bytes
+=
c
->
parm
.
length
;
return
1
;
}
break
;
case
ISDN_STAT_DHUP
:
/* Either D-Channel-hangup or error during dialout */
#ifdef CONFIG_ISDN_X25 // FIXME handle != ST_0?
/* If we are not connencted then dialing had
failed. If there are generic encap protocol
receiver routines signal the closure of
the link*/
if
(
!
(
lp
->
flags
&
ISDN_NET_CONNECTED
)
&&
pops
&&
pops
->
disconn_ind
)
pops
->
disconn_ind
(
cprot
);
#endif
/* CONFIG_ISDN_X25 */
if
(
lp
->
flags
&
ISDN_NET_CONNECTED
)
{
if
(
lp
->
p_encap
==
ISDN_NET_ENCAP_CISCOHDLCK
)
isdn_net_ciscohdlck_disconnected
(
lp
);
#ifdef CONFIG_ISDN_PPP
if
(
lp
->
p_encap
==
ISDN_NET_ENCAP_SYNCPPP
)
isdn_ppp_free
(
lp
);
#endif
if
(
lp
->
dtimer
++
>
ISDN_TIMER_DTIMEOUT10
)
isdn_net_hangup
(
&
p
->
dev
);
else
anymore
=
1
;
break
;
case
11
:
/* Callback Delay */
if
(
lp
->
dtimer
++
>
lp
->
cbdelay
)
lp
->
dialstate
=
1
;
anymore
=
1
;
break
;
case
12
:
/* Remote does callback. Hangup after cbdelay, then wait for incoming
* call (in state 4).
*/
if
(
lp
->
dtimer
++
>
lp
->
cbdelay
)
{
printk
(
KERN_INFO
"%s: hangup waiting for callback ...
\n
"
,
lp
->
name
);
lp
->
dtimer
=
0
;
lp
->
dialstate
=
4
;
cmd
.
driver
=
lp
->
isdn_device
;
cmd
.
command
=
ISDN_CMD_HANGUP
;
cmd
.
arg
=
lp
->
isdn_channel
;
isdn_command
(
&
cmd
);
isdn_all_eaz
(
lp
->
isdn_device
,
lp
->
isdn_channel
);
}
anymore
=
1
;
break
;
default:
printk
(
KERN_WARNING
"isdn_net: Illegal dialstate %d for device %s
\n
"
,
lp
->
dialstate
,
lp
->
name
);
isdn_net_lp_disconnected
(
lp
);
isdn_slot_all_eaz
(
lp
->
isdn_slot
);
printk
(
KERN_INFO
"%s: remote hangup
\n
"
,
lp
->
name
);
printk
(
KERN_INFO
"%s: Chargesum is %d
\n
"
,
lp
->
name
,
lp
->
charge
);
isdn_net_unbind_channel
(
lp
);
return
1
;
}
break
;
#ifdef CONFIG_ISDN_X25 // FIXME handle != ST_0?
case
ISDN_STAT_BHUP
:
/* B-Channel-hangup */
/* try if there are generic encap protocol
receiver routines and signal the closure of
the link */
if
(
pops
&&
pops
->
disconn_ind
){
pops
->
disconn_ind
(
cprot
);
return
1
;
}
break
;
#endif
/* CONFIG_ISDN_X25 */
case
ISDN_STAT_CINF
:
/* Charge-info from TelCo. Calculate interval between
* charge-infos and set timestamp for last info for
* usage by isdn_net_autohup()
*/
lp
->
charge
++
;
if
(
lp
->
hupflags
&
ISDN_HAVECHARGE
)
{
lp
->
hupflags
&=
~
ISDN_WAITCHARGE
;
lp
->
chargeint
=
jiffies
-
lp
->
chargetime
-
(
2
*
HZ
);
}
if
(
lp
->
hupflags
&
ISDN_WAITCHARGE
)
lp
->
hupflags
|=
ISDN_HAVECHARGE
;
lp
->
chargetime
=
jiffies
;
printk
(
KERN_DEBUG
"isdn_net: Got CINF chargetime of %s now %lu
\n
"
,
lp
->
name
,
lp
->
chargetime
);
return
1
;
}
break
;
case
ST_OUT_WAIT_DCONN
:
switch
(
pr
)
{
case
EV_NET_TIMER_OUT_DCONN
:
/* try again */
do_dialout
(
lp
);
return
1
;
case
EV_NET_TIMER_CB
:
/* Remote does callback. Hangup after cbdelay,
* then wait for incoming call */
printk
(
KERN_INFO
"%s: hangup waiting for callback ...
\n
"
,
lp
->
name
);
isdn_net_hangup
(
&
lp
->
netdev
->
dev
);
return
1
;
case
ISDN_STAT_DCONN
:
/* Got D-Channel-Connect, send B-Channel-request */
del_timer
(
&
lp
->
dial_timer
);
lp
->
dialstate
=
ST_OUT_WAIT_BCONN
;
isdn_slot_command
(
lp
->
isdn_slot
,
ISDN_CMD_ACCEPTB
,
&
cmd
);
lp
->
dial_timer
.
expires
=
jiffies
+
10
*
HZ
;
lp
->
dial_event
=
EV_NET_TIMER_OUT_BCONN
;
add_timer
(
&
lp
->
dial_timer
);
return
1
;
case
ISDN_STAT_DHUP
:
del_timer
(
&
lp
->
dial_timer
);
isdn_slot_all_eaz
(
lp
->
isdn_slot
);
printk
(
KERN_INFO
"%s: remote hangup
\n
"
,
lp
->
name
);
isdn_net_unbind_channel
(
lp
);
return
1
;
}
break
;
case
ST_OUT_WAIT_BCONN
:
switch
(
pr
)
{
case
EV_NET_TIMER_OUT_BCONN
:
/* try again */
do_dialout
(
lp
);
return
1
;
case
ISDN_STAT_BCONN
:
del_timer
(
&
lp
->
dial_timer
);
isdn_slot_set_usage
(
lp
->
isdn_slot
,
isdn_slot_usage
(
lp
->
isdn_slot
)
|
ISDN_USAGE_OUTGOING
);
isdn_net_connected
(
lp
);
return
1
;
case
ISDN_STAT_DHUP
:
del_timer
(
&
lp
->
dial_timer
);
isdn_slot_all_eaz
(
lp
->
isdn_slot
);
printk
(
KERN_INFO
"%s: remote hangup
\n
"
,
lp
->
name
);
isdn_net_unbind_channel
(
lp
);
return
1
;
}
break
;
case
ST_IN_WAIT_DCONN
:
switch
(
pr
)
{
case
EV_NET_TIMER_IN_DCONN
:
isdn_net_hangup
(
&
p
->
dev
);
return
1
;
case
ISDN_STAT_DCONN
:
del_timer
(
&
lp
->
dial_timer
);
lp
->
dialstate
=
ST_IN_WAIT_BCONN
;
isdn_slot_command
(
lp
->
isdn_slot
,
ISDN_CMD_ACCEPTB
,
&
cmd
);
lp
->
dial_timer
.
expires
=
jiffies
+
10
*
HZ
;
lp
->
dial_event
=
EV_NET_TIMER_IN_BCONN
;
add_timer
(
&
lp
->
dial_timer
);
return
1
;
case
ISDN_STAT_DHUP
:
del_timer
(
&
lp
->
dial_timer
);
isdn_slot_all_eaz
(
lp
->
isdn_slot
);
printk
(
KERN_INFO
"%s: remote hangup
\n
"
,
lp
->
name
);
isdn_net_unbind_channel
(
lp
);
return
1
;
}
break
;
case
ST_IN_WAIT_BCONN
:
switch
(
pr
)
{
case
EV_NET_TIMER_IN_BCONN
:
isdn_net_hangup
(
&
p
->
dev
);
break
;
case
ISDN_STAT_BCONN
:
del_timer
(
&
lp
->
dial_timer
);
isdn_slot_set_rx_netdev
(
lp
->
isdn_slot
,
p
);
isdn_net_connected
(
lp
);
return
1
;
case
ISDN_STAT_DHUP
:
del_timer
(
&
lp
->
dial_timer
);
isdn_slot_all_eaz
(
lp
->
isdn_slot
);
printk
(
KERN_INFO
"%s: remote hangup
\n
"
,
lp
->
name
);
isdn_net_unbind_channel
(
lp
);
return
1
;
}
p
=
(
isdn_net_dev
*
)
p
->
next
;
break
;
case
ST_WAIT_BEFORE_CB
:
switch
(
pr
)
{
case
EV_NET_TIMER_CB
:
/* Callback Delay */
init_dialout
(
lp
);
return
1
;
}
break
;
default:
isdn_BUG
();
break
;
}
isdn_timer_ctrl
(
ISDN_TIMER_NETDIAL
,
anymore
);
printk
(
"NOT HANDLED?
\n
"
);
return
0
;
}
/*
...
...
@@ -883,12 +853,9 @@ isdn_net_hangup(struct net_device *d)
pops
->
disconn_ind
(
cprot
);
#endif
/* CONFIG_ISDN_X25 */
cmd
.
driver
=
lp
->
isdn_device
;
cmd
.
command
=
ISDN_CMD_HANGUP
;
cmd
.
arg
=
lp
->
isdn_channel
;
isdn_command
(
&
cmd
);
isdn_slot_command
(
lp
->
isdn_slot
,
ISDN_CMD_HANGUP
,
&
cmd
);
printk
(
KERN_INFO
"%s: Chargesum is %d
\n
"
,
lp
->
name
,
lp
->
charge
);
isdn_
all_eaz
(
lp
->
isdn_device
,
lp
->
isdn_channel
);
isdn_
slot_all_eaz
(
lp
->
isdn_slot
);
}
isdn_net_unbind_channel
(
lp
);
}
...
...
@@ -1041,15 +1008,15 @@ void isdn_net_writebuf_skb(isdn_net_local *lp, struct sk_buff *skb)
/* before obtaining the lock the caller should have checked that
the lp isn't busy */
if
(
isdn_net_lp_busy
(
lp
))
{
printk
(
"isdn BUG at %s:%d!
\n
"
,
__FILE__
,
__LINE__
);
isdn_BUG
(
);
goto
error
;
}
if
(
!
(
lp
->
flags
&
ISDN_NET_CONNECTED
))
{
printk
(
"isdn BUG at %s:%d!
\n
"
,
__FILE__
,
__LINE__
);
isdn_BUG
(
);
goto
error
;
}
ret
=
isdn_
writebuf_skb_stub
(
lp
->
isdn_device
,
lp
->
isdn_channel
,
1
,
skb
);
ret
=
isdn_
slot_write
(
lp
->
isdn_slot
,
skb
);
if
(
ret
!=
len
)
{
/* we should never get here */
printk
(
KERN_WARNING
"%s: HL driver queue full
\n
"
,
lp
->
name
);
...
...
@@ -1137,7 +1104,7 @@ isdn_net_xmit(struct net_device *ndev, struct sk_buff *skb)
lp
->
sqfull
=
0
;
}
/* this is a hack to allow auto-hangup for slaves on moderate loads */
nd
->
queue
=
nd
->
local
;
nd
->
queue
=
&
nd
->
local
;
}
return
retv
;
...
...
@@ -1165,7 +1132,7 @@ void isdn_net_tx_timeout(struct net_device * ndev)
isdn_net_local
*
lp
=
(
isdn_net_local
*
)
ndev
->
priv
;
printk
(
KERN_WARNING
"isdn_tx_timeout dev %s dialstate %d
\n
"
,
ndev
->
name
,
lp
->
dialstate
);
if
(
!
lp
->
dialstate
){
if
(
lp
->
dialstate
==
ST_ACTIVE
){
lp
->
stats
.
tx_errors
++
;
/*
* There is a certain probability that this currently
...
...
@@ -1220,14 +1187,8 @@ isdn_net_start_xmit(struct sk_buff *skb, struct net_device *ndev)
#endif
/* auto-dialing xmit function */
{
#ifdef ISDN_DEBUG_NET_DUMP
u_char
*
buf
;
#endif
isdn_net_adjust_hdr
(
skb
,
ndev
);
#ifdef ISDN_DEBUG_NET_DUMP
buf
=
skb
->
data
;
isdn_dumppkt
(
"S:"
,
buf
,
skb
->
len
,
40
);
#endif
isdn_dumppkt
(
"S:"
,
skb
->
data
,
skb
->
len
,
40
);
if
(
!
(
lp
->
flags
&
ISDN_NET_CONNECTED
))
{
int
chi
;
...
...
@@ -1257,7 +1218,7 @@ isdn_net_start_xmit(struct sk_buff *skb, struct net_device *ndev)
}
/* Grab a free ISDN-Channel */
if
(((
chi
=
isdn_get_free_
channel
(
isdn_get_free_
slot
(
ISDN_USAGE_NET
,
lp
->
l2_proto
,
lp
->
l3_proto
,
...
...
@@ -1266,7 +1227,7 @@ isdn_net_start_xmit(struct sk_buff *skb, struct net_device *ndev)
lp
->
msn
)
)
<
0
)
&&
((
chi
=
isdn_get_free_
channel
(
isdn_get_free_
slot
(
ISDN_USAGE_NET
,
lp
->
l2_proto
,
lp
->
l3_proto
,
...
...
@@ -1283,7 +1244,6 @@ isdn_net_start_xmit(struct sk_buff *skb, struct net_device *ndev)
/* Log packet, which triggered dialing */
if
(
dev
->
net_verbose
)
isdn_net_log_skb
(
skb
,
lp
);
lp
->
dialstate
=
1
;
/* Connect interface with channel */
isdn_net_bind_channel
(
lp
,
chi
);
#ifdef CONFIG_ISDN_PPP
...
...
@@ -1296,14 +1256,14 @@ isdn_net_start_xmit(struct sk_buff *skb, struct net_device *ndev)
return
0
;
/* STN (skb to nirvana) ;) */
}
restore_flags
(
flags
);
i
sdn_net_dial
();
/* Initiate dialing */
i
nit_dialout
(
lp
);
netif_stop_queue
(
ndev
);
return
1
;
/* let upper layer requeue skb packet */
}
#endif
/* Initiate dialing */
restore_flags
(
flags
);
i
sdn_net_dial
(
);
i
nit_dialout
(
lp
);
isdn_net_device_stop_queue
(
lp
);
return
1
;
}
else
{
...
...
@@ -1315,7 +1275,7 @@ isdn_net_start_xmit(struct sk_buff *skb, struct net_device *ndev)
}
else
{
/* Device is connected to an ISDN channel */
ndev
->
trans_start
=
jiffies
;
if
(
!
lp
->
dialstate
)
{
if
(
lp
->
dialstate
==
ST_ACTIVE
)
{
/* ISDN connection is established, try sending */
int
ret
;
ret
=
(
isdn_net_xmit
(
ndev
,
skb
));
...
...
@@ -1433,7 +1393,7 @@ isdn_net_type_trans(struct sk_buff *skb, struct net_device *dev)
static
struct
sk_buff
*
isdn_net_ciscohdlck_alloc_skb
(
isdn_net_local
*
lp
,
int
len
)
{
unsigned
short
hl
=
dev
->
drv
[
lp
->
isdn_device
]
->
interface
->
hl_hdrlen
;
unsigned
short
hl
=
isdn_slot_hdrlen
(
lp
->
isdn_slot
)
;
struct
sk_buff
*
skb
;
skb
=
alloc_skb
(
hl
+
len
,
GFP_ATOMIC
);
...
...
@@ -1523,8 +1483,8 @@ isdn_net_ciscohdlck_slarp_send_keepalive(unsigned long data)
unsigned
long
last_cisco_myseq
=
lp
->
cisco_myseq
;
int
myseq_diff
=
0
;
if
(
!
(
lp
->
flags
&
ISDN_NET_CONNECTED
)
||
lp
->
dialstate
)
{
printk
(
"isdn BUG at %s:%d!
\n
"
,
__FILE__
,
__LINE__
);
if
(
!
(
lp
->
flags
&
ISDN_NET_CONNECTED
)
||
lp
->
dialstate
!=
ST_ACTIVE
)
{
isdn_BUG
(
);
return
;
}
lp
->
cisco_myseq
++
;
...
...
@@ -1814,9 +1774,7 @@ isdn_net_receive(struct net_device *ndev, struct sk_buff *skb)
skb
->
dev
=
ndev
;
skb
->
pkt_type
=
PACKET_HOST
;
skb
->
mac
.
raw
=
skb
->
data
;
#ifdef ISDN_DEBUG_NET_DUMP
isdn_dumppkt
(
"R:"
,
skb
->
data
,
skb
->
len
,
40
);
#endif
switch
(
lp
->
p_encap
)
{
case
ISDN_NET_ENCAP_ETHER
:
/* Ethernet over ISDN */
...
...
@@ -1893,12 +1851,12 @@ isdn_net_receive(struct net_device *ndev, struct sk_buff *skb)
int
isdn_net_rcv_skb
(
int
idx
,
struct
sk_buff
*
skb
)
{
isdn_net_dev
*
p
=
dev
->
rx_netdev
[
idx
]
;
isdn_net_dev
*
p
=
isdn_slot_rx_netdev
(
idx
)
;
if
(
p
)
{
isdn_net_local
*
lp
=
p
->
local
;
isdn_net_local
*
lp
=
&
p
->
local
;
if
((
lp
->
flags
&
ISDN_NET_CONNECTED
)
&&
(
!
lp
->
dialstate
))
{
(
lp
->
dialstate
==
ST_ACTIVE
))
{
isdn_net_receive
(
&
p
->
dev
,
skb
);
return
1
;
}
...
...
@@ -2093,40 +2051,34 @@ isdn_net_init(struct net_device *ndev)
static
void
isdn_net_swapbind
(
int
drvidx
)
{
isdn_net_dev
*
p
;
struct
list_head
*
l
;
#ifdef ISDN_DEBUG_NET_ICALL
printk
(
KERN_DEBUG
"n_fi: swapping ch of %d
\n
"
,
drvidx
);
#endif
p
=
dev
->
netdev
;
while
(
p
)
{
if
(
p
->
local
->
pre_device
==
drvidx
)
switch
(
p
->
local
->
pre_channel
)
{
case
0
:
p
->
local
->
pre_channel
=
1
;
break
;
case
1
:
p
->
local
->
pre_channel
=
0
;
break
;
}
p
=
(
isdn_net_dev
*
)
p
->
next
;
dbg_net_icall
(
"n_fi: swapping ch of %d
\n
"
,
drvidx
);
list_for_each
(
l
,
&
isdn_net_devs
)
{
isdn_net_dev
*
p
=
list_entry
(
l
,
isdn_net_dev
,
global_list
);
if
(
p
->
local
.
pre_device
!=
drvidx
)
continue
;
switch
(
p
->
local
.
pre_channel
)
{
case
0
:
p
->
local
.
pre_channel
=
1
;
break
;
case
1
:
p
->
local
.
pre_channel
=
0
;
break
;
}
}
}
static
void
isdn_net_swap_usage
(
int
i1
,
int
i2
)
{
int
u1
=
dev
->
usage
[
i1
]
&
ISDN_USAGE_EXCLUSIVE
;
int
u2
=
dev
->
usage
[
i2
]
&
ISDN_USAGE_EXCLUSIVE
;
int
u1
=
isdn_slot_usage
(
i1
)
;
int
u2
=
isdn_slot_usage
(
i2
)
;
#ifdef ISDN_DEBUG_NET_ICALL
printk
(
KERN_DEBUG
"n_fi: usage of %d and %d
\n
"
,
i1
,
i2
);
#endif
dev
->
usage
[
i1
]
&=
~
ISDN_USAGE_EXCLUSIVE
;
dev
->
usage
[
i1
]
|=
u2
;
dev
->
usage
[
i2
]
&=
~
ISDN_USAGE_EXCLUSIVE
;
dev
->
usage
[
i2
]
|=
u1
;
isdn_info_update
();
dbg_net_icall
(
"n_fi: usage of %d and %d
\n
"
,
i1
,
i2
);
isdn_slot_set_usage
(
i1
,
(
u1
&
~
ISDN_USAGE_EXCLUSIVE
)
|
(
u2
&
ISDN_USAGE_EXCLUSIVE
));
isdn_slot_set_usage
(
i2
,
(
u2
&
~
ISDN_USAGE_EXCLUSIVE
)
|
(
u1
&
ISDN_USAGE_EXCLUSIVE
));
}
/*
...
...
@@ -2155,12 +2107,14 @@ isdn_net_find_icall(int di, int ch, int idx, setup_parm *setup)
int
wret
;
int
swapped
;
int
sidx
=
0
;
isdn_net_dev
*
p
;
struct
list_head
*
l
;
isdn_net_phone
*
n
;
ulong
flags
;
char
nr
[
32
];
char
*
my_eaz
;
isdn_ctrl
cmd
;
int
slot
=
isdn_dc2minor
(
di
,
ch
);
/* Search name in netdev-chain */
save_flags
(
flags
);
cli
();
...
...
@@ -2188,16 +2142,15 @@ isdn_net_find_icall(int di, int ch, int idx, setup_parm *setup)
return
0
;
}
n
=
(
isdn_net_phone
*
)
0
;
p
=
dev
->
netdev
;
n
=
(
isdn_net_phone
*
)
0
;
ematch
=
wret
=
swapped
=
0
;
#ifdef ISDN_DEBUG_NET_ICALL
printk
(
KERN_DEBUG
"n_fi: di=%d ch=%d idx=%d usg=%d
\n
"
,
di
,
ch
,
idx
,
dev
->
usage
[
idx
]);
#endif
while
(
p
)
{
dbg_net_icall
(
"n_fi: di=%d ch=%d idx=%d usg=%d
\n
"
,
di
,
ch
,
idx
,
isdn_slot_usage
(
idx
));
list_for_each
(
l
,
&
isdn_net_devs
)
{
int
matchret
;
isdn_net_local
*
lp
=
p
->
local
;
isdn_net_dev
*
p
=
list_entry
(
l
,
isdn_net_dev
,
global_list
);
isdn_net_local
*
lp
=
&
p
->
local
;
/* If last check has triggered as binding-swap, revert it */
switch
(
swapped
)
{
...
...
@@ -2210,7 +2163,7 @@ p = dev->netdev;
}
swapped
=
0
;
/* check acceptable call types for DOV */
my_eaz
=
isdn_
map_eaz2msn
(
lp
->
msn
,
di
);
my_eaz
=
isdn_
slot_map_eaz2msn
(
slot
,
lp
->
msn
);
if
(
si1
==
1
)
{
/* it's a DOV call, check if we allow it */
if
(
*
my_eaz
==
'v'
||
*
my_eaz
==
'V'
||
*
my_eaz
==
'b'
||
*
my_eaz
==
'B'
)
...
...
@@ -2231,22 +2184,18 @@ p = dev->netdev;
/* Remember if more numbers eventually can match */
if
(
matchret
>
wret
)
wret
=
matchret
;
#ifdef ISDN_DEBUG_NET_ICALL
printk
(
KERN_DEBUG
"n_fi: if='%s', l.msn=%s, l.flags=%d, l.dstate=%d
\n
"
,
dbg_net_icall
(
"n_fi: if='%s', l.msn=%s, l.flags=%d, l.dstate=%d
\n
"
,
lp
->
name
,
lp
->
msn
,
lp
->
flags
,
lp
->
dialstate
);
#endif
if
((
!
matchret
)
&&
/* EAZ is matching */
(((
!
(
lp
->
flags
&
ISDN_NET_CONNECTED
))
&&
/* but not connected */
(
USG_NONE
(
dev
->
usage
[
idx
]
)))
||
/* and ch. unused or */
((((
lp
->
dialstate
==
4
)
||
(
lp
->
dialstate
==
12
))
&&
/* if dialing */
(
USG_NONE
(
isdn_slot_usage
(
idx
)
)))
||
/* and ch. unused or */
((((
lp
->
dialstate
==
ST_OUT_WAIT_DCONN
)
||
(
lp
->
dialstate
==
ST_OUT_WAIT_DCONN
))
&&
/* if dialing */
(
!
(
lp
->
flags
&
ISDN_NET_CALLBACK
)))
/* but no callback */
)))
{
#ifdef ISDN_DEBUG_NET_ICALL
printk
(
KERN_DEBUG
"n_fi: match1, pdev=%d pch=%d
\n
"
,
dbg_net_icall
(
"n_fi: match1, pdev=%d pch=%d
\n
"
,
lp
->
pre_device
,
lp
->
pre_channel
);
#endif
if
(
dev
->
usage
[
idx
]
&
ISDN_USAGE_EXCLUSIVE
)
{
if
(
isdn_slot_usage
(
idx
)
&
ISDN_USAGE_EXCLUSIVE
)
{
if
((
lp
->
pre_channel
!=
ch
)
||
(
lp
->
pre_device
!=
di
))
{
/* Here we got a problem:
...
...
@@ -2260,16 +2209,12 @@ p = dev->netdev;
*/
if
(
ch
==
0
)
{
sidx
=
isdn_dc2minor
(
di
,
1
);
#ifdef ISDN_DEBUG_NET_ICALL
printk
(
KERN_DEBUG
"n_fi: ch is 0
\n
"
);
#endif
if
(
USG_NONE
(
dev
->
usage
[
sidx
]))
{
dbg_net_icall
(
"n_fi: ch is 0
\n
"
);
if
(
USG_NONE
(
isdn_slot_usage
(
sidx
)))
{
/* Second Channel is free, now see if it is bound
* exclusive too. */
if
(
dev
->
usage
[
sidx
]
&
ISDN_USAGE_EXCLUSIVE
)
{
#ifdef ISDN_DEBUG_NET_ICALL
printk
(
KERN_DEBUG
"n_fi: 2nd channel is down and bound
\n
"
);
#endif
if
(
isdn_slot_usage
(
sidx
)
&
ISDN_USAGE_EXCLUSIVE
)
{
dbg_net_icall
(
"n_fi: 2nd channel is down and bound
\n
"
);
/* Yes, swap bindings only, if the original
* binding is bound to channel 1 of this driver */
if
((
lp
->
pre_device
==
di
)
&&
...
...
@@ -2278,43 +2223,31 @@ p = dev->netdev;
swapped
=
1
;
}
else
{
/* ... else iterate next device */
p
=
(
isdn_net_dev
*
)
p
->
next
;
continue
;
}
}
else
{
#ifdef ISDN_DEBUG_NET_ICALL
printk
(
KERN_DEBUG
"n_fi: 2nd channel is down and unbound
\n
"
);
#endif
dbg_net_icall
(
"n_fi: 2nd channel is down and unbound
\n
"
);
/* No, swap always and swap excl-usage also */
isdn_net_swap_usage
(
idx
,
sidx
);
isdn_net_swapbind
(
di
);
swapped
=
2
;
}
/* Now check for exclusive binding again */
#ifdef ISDN_DEBUG_NET_ICALL
printk
(
KERN_DEBUG
"n_fi: final check
\n
"
);
#endif
if
((
dev
->
usage
[
idx
]
&
ISDN_USAGE_EXCLUSIVE
)
&&
dbg_net_icall
(
"n_fi: final check
\n
"
);
if
((
isdn_slot_usage
(
idx
)
&
ISDN_USAGE_EXCLUSIVE
)
&&
((
lp
->
pre_channel
!=
ch
)
||
(
lp
->
pre_device
!=
di
)))
{
#ifdef ISDN_DEBUG_NET_ICALL
printk
(
KERN_DEBUG
"n_fi: final check failed
\n
"
);
#endif
p
=
(
isdn_net_dev
*
)
p
->
next
;
dbg_net_icall
(
"n_fi: final check failed
\n
"
);
continue
;
}
}
}
else
{
/* We are already on the second channel, so nothing to do */
#ifdef ISDN_DEBUG_NET_ICALL
printk
(
KERN_DEBUG
"n_fi: already on 2nd channel
\n
"
);
#endif
dbg_net_icall
(
"n_fi: already on 2nd channel
\n
"
);
}
}
}
#ifdef ISDN_DEBUG_NET_ICALL
printk
(
KERN_DEBUG
"n_fi: match2
\n
"
);
#endif
dbg_net_icall
(
"n_fi: match2
\n
"
);
n
=
lp
->
phone
[
0
];
if
(
lp
->
flags
&
ISDN_NET_SECURE
)
{
while
(
n
)
{
...
...
@@ -2324,9 +2257,7 @@ p = dev->netdev;
}
}
if
(
n
||
(
!
(
lp
->
flags
&
ISDN_NET_SECURE
)))
{
#ifdef ISDN_DEBUG_NET_ICALL
printk
(
KERN_DEBUG
"n_fi: match3
\n
"
);
#endif
dbg_net_icall
(
"n_fi: match3
\n
"
);
/* matching interface found */
/*
...
...
@@ -2370,7 +2301,6 @@ p = dev->netdev;
/* Found parent, if it's offline iterate next device */
printk
(
KERN_DEBUG
"mlpf: %d
\n
"
,
mlp
->
flags
&
ISDN_NET_CONNECTED
);
if
(
!
(
mlp
->
flags
&
ISDN_NET_CONNECTED
))
{
p
=
(
isdn_net_dev
*
)
p
->
next
;
continue
;
}
}
...
...
@@ -2392,7 +2322,7 @@ p = dev->netdev;
if
(
lp
->
phone
[
1
])
{
/* Grab a free ISDN-Channel */
if
((
chi
=
isdn_get_free_
channel
(
isdn_get_free_
slot
(
ISDN_USAGE_NET
,
lp
->
l2_proto
,
lp
->
l3_proto
,
...
...
@@ -2406,8 +2336,11 @@ p = dev->netdev;
return
0
;
}
/* Setup dialstate. */
lp
->
dtimer
=
0
;
lp
->
dialstate
=
11
;
lp
->
dial_timer
.
expires
=
jiffies
+
lp
->
cbdelay
;
lp
->
dial_event
=
EV_NET_TIMER_CB
;
add_timer
(
&
lp
->
dial_timer
);
lp
->
dialstate
=
ST_WAIT_BEFORE_CB
;
/* Connect interface with channel */
isdn_net_bind_channel
(
lp
,
chi
);
#ifdef CONFIG_ISDN_PPP
...
...
@@ -2430,30 +2363,39 @@ p = dev->netdev;
eaz
);
/* if this interface is dialing, it does it probably on a different
device, so free this device */
if
(
(
lp
->
dialstate
==
4
)
||
(
lp
->
dialstate
==
12
)
)
{
if
(
lp
->
dialstate
==
ST_OUT_WAIT_DCONN
)
{
#ifdef CONFIG_ISDN_PPP
if
(
lp
->
p_encap
==
ISDN_NET_ENCAP_SYNCPPP
)
isdn_ppp_free
(
lp
);
#endif
isdn_net_lp_disconnected
(
lp
);
isdn_
free_channel
(
lp
->
isdn_device
,
lp
->
isdn_channel
,
isdn_
slot_free
(
lp
->
isdn_slot
,
ISDN_USAGE_NET
);
}
dev
->
usage
[
idx
]
&=
ISDN_USAGE_EXCLUSIVE
;
dev
->
usage
[
idx
]
|=
ISDN_USAGE_NET
;
strcpy
(
dev
->
num
[
idx
],
nr
);
isdn_info_update
();
dev
->
st_netdev
[
idx
]
=
lp
->
netdev
;
lp
->
isdn_device
=
di
;
lp
->
isdn_channel
=
ch
;
strcpy
(
isdn_slot_num
(
idx
),
nr
);
isdn_slot_set_usage
(
idx
,
(
isdn_slot_usage
(
idx
)
&
ISDN_USAGE_EXCLUSIVE
)
|
ISDN_USAGE_NET
);
isdn_slot_set_st_netdev
(
idx
,
lp
->
netdev
);
lp
->
isdn_slot
=
slot
;
lp
->
ppp_slot
=
-
1
;
lp
->
flags
|=
ISDN_NET_CONNECTED
;
lp
->
dialstate
=
7
;
lp
->
dtimer
=
0
;
lp
->
outgoing
=
0
;
lp
->
huptimer
=
0
;
lp
->
hupflags
|=
ISDN_WAITCHARGE
;
lp
->
hupflags
&=
~
ISDN_HAVECHARGE
;
/* Got incoming Call, setup L2 and L3 protocols,
* then wait for D-Channel-connect
*/
cmd
.
arg
=
lp
->
l2_proto
<<
8
;
isdn_slot_command
(
lp
->
isdn_slot
,
ISDN_CMD_SETL2
,
&
cmd
);
cmd
.
arg
=
lp
->
l3_proto
<<
8
;
isdn_slot_command
(
lp
->
isdn_slot
,
ISDN_CMD_SETL3
,
&
cmd
);
lp
->
dial_timer
.
expires
=
jiffies
+
15
*
HZ
;
lp
->
dial_event
=
EV_NET_TIMER_IN_DCONN
;
add_timer
(
&
lp
->
dial_timer
);
lp
->
dialstate
=
ST_IN_WAIT_DCONN
;
#ifdef CONFIG_ISDN_PPP
if
(
lp
->
p_encap
==
ISDN_NET_ENCAP_SYNCPPP
)
if
(
isdn_ppp_bind
(
lp
)
<
0
)
{
...
...
@@ -2467,11 +2409,10 @@ p = dev->netdev;
}
}
}
p
=
(
isdn_net_dev
*
)
p
->
next
;
}
/* If none of configured EAZ/MSN matched and not verbose, be silent */
if
(
!
ematch
||
dev
->
net_verbose
)
printk
(
KERN_INFO
"isdn_net: call from %s -> %d %s ignored
\n
"
,
nr
,
di
,
eaz
);
printk
(
KERN_INFO
"isdn_net: call from %s -> %d %s ignored
\n
"
,
nr
,
slot
,
eaz
);
restore_flags
(
flags
);
return
(
wret
==
2
)
?
5
:
0
;
}
...
...
@@ -2482,14 +2423,14 @@ p = dev->netdev;
isdn_net_dev
*
isdn_net_findif
(
char
*
name
)
{
isdn_net_dev
*
p
=
dev
->
netdev
;
struct
list_head
*
l
;
while
(
p
)
{
if
(
!
strcmp
(
p
->
local
->
name
,
name
))
list_for_each
(
l
,
&
isdn_net_devs
)
{
isdn_net_dev
*
p
=
list_entry
(
l
,
isdn_net_dev
,
global_list
);
if
(
!
strcmp
(
p
->
local
.
name
,
name
))
return
p
;
p
=
(
isdn_net_dev
*
)
p
->
next
;
}
return
(
isdn_net_dev
*
)
NULL
;
return
NULL
;
}
/*
...
...
@@ -2500,7 +2441,7 @@ isdn_net_findif(char *name)
int
isdn_net_force_dial_lp
(
isdn_net_local
*
lp
)
{
if
((
!
(
lp
->
flags
&
ISDN_NET_CONNECTED
))
&&
!
lp
->
dialstate
)
{
if
((
!
(
lp
->
flags
&
ISDN_NET_CONNECTED
))
&&
lp
->
dialstate
==
ST_NULL
)
{
int
chi
;
if
(
lp
->
phone
[
1
])
{
ulong
flags
;
...
...
@@ -2509,7 +2450,7 @@ isdn_net_force_dial_lp(isdn_net_local * lp)
/* Grab a free ISDN-Channel */
if
((
chi
=
isdn_get_free_
channel
(
isdn_get_free_
slot
(
ISDN_USAGE_NET
,
lp
->
l2_proto
,
lp
->
l3_proto
,
...
...
@@ -2521,7 +2462,6 @@ isdn_net_force_dial_lp(isdn_net_local * lp)
restore_flags
(
flags
);
return
-
EAGAIN
;
}
lp
->
dialstate
=
1
;
/* Connect interface with channel */
isdn_net_bind_channel
(
lp
,
chi
);
#ifdef CONFIG_ISDN_PPP
...
...
@@ -2534,7 +2474,7 @@ isdn_net_force_dial_lp(isdn_net_local * lp)
#endif
/* Initiate dialing */
restore_flags
(
flags
);
i
sdn_net_dial
(
);
i
nit_dialout
(
lp
);
return
0
;
}
else
return
-
EINVAL
;
...
...
@@ -2567,47 +2507,39 @@ isdn_net_force_dial(char *name)
if
(
!
p
)
return
-
ENODEV
;
return
(
isdn_net_force_dial_lp
(
p
->
local
));
return
(
isdn_net_force_dial_lp
(
&
p
->
local
));
}
/*
* Allocate a new network-interface and initialize its data structures.
*/
char
*
int
isdn_net_new
(
char
*
name
,
struct
net_device
*
master
)
{
int
retval
;
isdn_net_dev
*
netdev
;
/* Avoid creating an existing interface */
if
(
isdn_net_findif
(
name
))
{
printk
(
KERN_WARNING
"isdn_net: interface %s already exists
\n
"
,
name
);
return
NULL
;
return
-
EEXIST
;
}
if
(
!
(
netdev
=
(
isdn_net_dev
*
)
kmalloc
(
sizeof
(
isdn_net_dev
),
GFP_KERNEL
)))
{
if
(
!
(
netdev
=
kmalloc
(
sizeof
(
isdn_net_dev
),
GFP_KERNEL
)))
{
printk
(
KERN_WARNING
"isdn_net: Could not allocate net-device
\n
"
);
return
NULL
;
return
-
ENOMEM
;
}
memset
(
netdev
,
0
,
sizeof
(
isdn_net_dev
));
if
(
!
(
netdev
->
local
=
(
isdn_net_local
*
)
kmalloc
(
sizeof
(
isdn_net_local
),
GFP_KERNEL
)))
{
printk
(
KERN_WARNING
"isdn_net: Could not allocate device locals
\n
"
);
kfree
(
netdev
);
return
NULL
;
}
memset
(
netdev
->
local
,
0
,
sizeof
(
isdn_net_local
));
if
(
name
==
NULL
)
strcpy
(
netdev
->
local
->
name
,
" "
);
else
strcpy
(
netdev
->
local
->
name
,
name
);
strcpy
(
netdev
->
dev
.
name
,
netdev
->
local
->
name
);
netdev
->
dev
.
priv
=
netdev
->
local
;
strcpy
(
netdev
->
local
.
name
,
name
);
strcpy
(
netdev
->
dev
.
name
,
name
);
netdev
->
dev
.
priv
=
&
netdev
->
local
;
netdev
->
dev
.
init
=
isdn_net_init
;
netdev
->
local
->
p_encap
=
ISDN_NET_ENCAP_RAWIP
;
netdev
->
local
.
p_encap
=
ISDN_NET_ENCAP_RAWIP
;
if
(
master
)
{
/* Device shall be a slave */
struct
net_device
*
p
=
(((
isdn_net_local
*
)
master
->
priv
)
->
slave
);
struct
net_device
*
q
=
master
;
netdev
->
local
->
master
=
master
;
netdev
->
local
.
master
=
master
;
/* Put device at end of slave-chain */
while
(
p
)
{
q
=
p
;
...
...
@@ -2621,81 +2553,80 @@ isdn_net_new(char *name, struct net_device *master)
*/
netdev
->
dev
.
tx_timeout
=
isdn_net_tx_timeout
;
netdev
->
dev
.
watchdog_timeo
=
ISDN_NET_TX_TIMEOUT
;
if
(
register_netdev
(
&
netdev
->
dev
)
!=
0
)
{
retval
=
register_netdev
(
&
netdev
->
dev
);
if
(
retval
)
{
printk
(
KERN_WARNING
"isdn_net: Could not register net-device
\n
"
);
kfree
(
netdev
->
local
);
kfree
(
netdev
);
return
NULL
;
return
retval
;
}
}
netdev
->
local
->
magic
=
ISDN_NET_MAGIC
;
netdev
->
local
.
magic
=
ISDN_NET_MAGIC
;
netdev
->
queue
=
netdev
->
local
;
netdev
->
queue
=
&
netdev
->
local
;
spin_lock_init
(
&
netdev
->
queue_lock
);
netdev
->
local
->
last
=
netdev
->
local
;
netdev
->
local
->
netdev
=
netdev
;
netdev
->
local
->
next
=
netdev
->
local
;
netdev
->
local
->
tqueue
.
sync
=
0
;
netdev
->
local
->
tqueue
.
routine
=
isdn_net_softint
;
netdev
->
local
->
tqueue
.
data
=
netdev
->
local
;
spin_lock_init
(
&
netdev
->
local
->
xmit_lock
);
netdev
->
local
->
isdn_device
=
-
1
;
netdev
->
local
->
isdn_channel
=
-
1
;
netdev
->
local
->
pre_device
=
-
1
;
netdev
->
local
->
pre_channel
=
-
1
;
netdev
->
local
->
exclusive
=
-
1
;
netdev
->
local
->
ppp_slot
=
-
1
;
netdev
->
local
->
pppbind
=
-
1
;
skb_queue_head_init
(
&
netdev
->
local
->
super_tx_queue
);
netdev
->
local
->
l2_proto
=
ISDN_PROTO_L2_X75I
;
netdev
->
local
->
l3_proto
=
ISDN_PROTO_L3_TRANS
;
netdev
->
local
->
triggercps
=
6000
;
netdev
->
local
->
slavedelay
=
10
*
HZ
;
netdev
->
local
->
hupflags
=
ISDN_INHUP
;
/* Do hangup even on incoming calls */
netdev
->
local
->
onhtime
=
10
;
/* Default hangup-time for saving costs
netdev
->
local
.
last
=
&
netdev
->
local
;
netdev
->
local
.
netdev
=
netdev
;
netdev
->
local
.
next
=
&
netdev
->
local
;
netdev
->
local
.
tqueue
.
sync
=
0
;
netdev
->
local
.
tqueue
.
routine
=
isdn_net_softint
;
netdev
->
local
.
tqueue
.
data
=
&
netdev
->
local
;
spin_lock_init
(
&
netdev
->
local
.
xmit_lock
);
netdev
->
local
.
isdn_slot
=
-
1
;
netdev
->
local
.
pre_device
=
-
1
;
netdev
->
local
.
pre_channel
=
-
1
;
netdev
->
local
.
exclusive
=
-
1
;
netdev
->
local
.
ppp_slot
=
-
1
;
netdev
->
local
.
pppbind
=
-
1
;
skb_queue_head_init
(
&
netdev
->
local
.
super_tx_queue
);
netdev
->
local
.
l2_proto
=
ISDN_PROTO_L2_X75I
;
netdev
->
local
.
l3_proto
=
ISDN_PROTO_L3_TRANS
;
netdev
->
local
.
triggercps
=
6000
;
netdev
->
local
.
slavedelay
=
10
*
HZ
;
netdev
->
local
.
hupflags
=
ISDN_INHUP
;
/* Do hangup even on incoming calls */
netdev
->
local
.
onhtime
=
10
;
/* Default hangup-time for saving costs
of those who forget configuring this */
netdev
->
local
->
dialmax
=
1
;
netdev
->
local
->
flags
=
ISDN_NET_CBHUP
|
ISDN_NET_DM_MANUAL
;
/* Hangup before Callback, manual dial */
netdev
->
local
->
cbdelay
=
25
;
/* Wait 5 secs before Callback */
netdev
->
local
->
dialtimeout
=
-
1
;
/* Infinite Dial-Timeout */
netdev
->
local
->
dialwait
=
5
*
HZ
;
/* Wait 5 sec. after failed dial */
netdev
->
local
->
dialstarted
=
0
;
/* Jiffies of last dial-start */
netdev
->
local
->
dialwait_timer
=
0
;
/* Jiffies of earliest next dial-start */
netdev
->
local
.
dialmax
=
1
;
netdev
->
local
.
flags
=
ISDN_NET_CBHUP
|
ISDN_NET_DM_MANUAL
;
/* Hangup before Callback, manual dial */
netdev
->
local
.
cbdelay
=
5
*
HZ
;
/* Wait 5 secs before Callback */
netdev
->
local
.
dialtimeout
=
-
1
;
/* Infinite Dial-Timeout */
netdev
->
local
.
dialwait
=
5
*
HZ
;
/* Wait 5 sec. after failed dial */
netdev
->
local
.
dialstarted
=
0
;
/* Jiffies of last dial-start */
netdev
->
local
.
dialwait_timer
=
0
;
/* Jiffies of earliest next dial-start */
init_timer
(
&
netdev
->
local
.
dial_timer
);
netdev
->
local
.
dial_timer
.
data
=
(
unsigned
long
)
&
netdev
->
local
;
netdev
->
local
.
dial_timer
.
function
=
isdn_net_dial_timer
;
/* Put into to netdev-chain */
netdev
->
next
=
(
void
*
)
dev
->
netdev
;
dev
->
netdev
=
netdev
;
return
netdev
->
dev
.
name
;
list_add
(
&
netdev
->
global_list
,
&
isdn_net_devs
);
return
0
;
}
char
*
int
isdn_net_newslave
(
char
*
parm
)
{
char
*
p
=
strchr
(
parm
,
','
);
isdn_net_dev
*
n
;
char
newname
[
10
];
isdn_net_dev
*
m
;
if
(
p
)
{
/* Slave-Name MUST not be empty */
if
(
!
strlen
(
p
+
1
))
return
NULL
;
strcpy
(
newname
,
p
+
1
);
*
p
=
0
;
/* Master must already exist */
if
(
!
(
n
=
isdn_net_findif
(
parm
)))
return
NULL
;
/* Master must be a real interface, not a slave */
if
(
n
->
local
->
master
)
return
NULL
;
/* Master must not be started yet */
if
(
isdn_net_device_started
(
n
))
return
NULL
;
return
(
isdn_net_new
(
newname
,
&
(
n
->
dev
)));
}
return
NULL
;
/* Slave-Name MUST not be empty */
if
(
!
p
||
!
p
[
1
])
return
-
EINVAL
;
*
p
=
0
;
/* Master must already exist */
if
(
!
(
m
=
isdn_net_findif
(
parm
)))
return
-
ESRCH
;
/* Master must be a real interface, not a slave */
if
(
m
->
local
.
master
)
return
-
ENXIO
;
/* Master must not be started yet */
if
(
isdn_net_device_started
(
m
))
return
-
EBUSY
;
return
isdn_net_new
(
p
+
1
,
&
m
->
dev
);
}
/*
...
...
@@ -2717,7 +2648,7 @@ isdn_net_setcfg(isdn_net_ioctl_cfg * cfg)
ulong
flags
;
#endif
if
(
p
)
{
isdn_net_local
*
lp
=
p
->
local
;
isdn_net_local
*
lp
=
&
p
->
local
;
/* See if any registered driver supports the features we want */
features
=
((
1
<<
cfg
->
l2_proto
)
<<
ISDN_FEATURE_L2_SHIFT
)
|
...
...
@@ -2777,7 +2708,7 @@ isdn_net_setcfg(isdn_net_ioctl_cfg * cfg)
case
ISDN_NET_ENCAP_X25IFACE
:
#ifndef CONFIG_ISDN_X25
printk
(
KERN_WARNING
"%s: isdn-x25 support not configured
\n
"
,
p
->
local
->
name
);
p
->
local
.
name
);
return
-
EINVAL
;
#else
p
->
dev
.
type
=
ARPHRD_X25
;
/* change ARP type */
...
...
@@ -2793,7 +2724,7 @@ isdn_net_setcfg(isdn_net_ioctl_cfg * cfg)
break
;
printk
(
KERN_WARNING
"%s: encapsulation protocol %d not supported
\n
"
,
p
->
local
->
name
,
cfg
->
p_encap
);
p
->
local
.
name
,
cfg
->
p_encap
);
return
-
EINVAL
;
}
if
(
strlen
(
cfg
->
drvid
))
{
...
...
@@ -2830,7 +2761,7 @@ isdn_net_setcfg(isdn_net_ioctl_cfg * cfg)
/* If binding is exclusive, try to grab the channel */
save_flags
(
flags
);
if
((
i
=
isdn_get_free_
channel
(
ISDN_USAGE_NET
,
if
((
i
=
isdn_get_free_
slot
(
ISDN_USAGE_NET
,
lp
->
l2_proto
,
lp
->
l3_proto
,
drvidx
,
chidx
,
lp
->
msn
))
<
0
)
{
/* Grab failed, because desired channel is in use */
...
...
@@ -2839,8 +2770,7 @@ isdn_net_setcfg(isdn_net_ioctl_cfg * cfg)
return
-
EBUSY
;
}
/* All went ok, so update isdninfo */
dev
->
usage
[
i
]
=
ISDN_USAGE_EXCLUSIVE
;
isdn_info_update
();
isdn_slot_set_usage
(
i
,
ISDN_USAGE_EXCLUSIVE
);
restore_flags
(
flags
);
lp
->
exclusive
=
i
;
}
else
{
...
...
@@ -2860,7 +2790,7 @@ isdn_net_setcfg(isdn_net_ioctl_cfg * cfg)
lp
->
charge
=
cfg
->
charge
;
lp
->
l2_proto
=
cfg
->
l2_proto
;
lp
->
l3_proto
=
cfg
->
l3_proto
;
lp
->
cbdelay
=
cfg
->
cbdelay
;
lp
->
cbdelay
=
cfg
->
cbdelay
*
HZ
/
5
;
lp
->
dialmax
=
cfg
->
dialmax
;
lp
->
triggercps
=
cfg
->
triggercps
;
lp
->
slavedelay
=
cfg
->
slavedelay
*
HZ
;
...
...
@@ -2944,7 +2874,7 @@ isdn_net_getcfg(isdn_net_ioctl_cfg * cfg)
isdn_net_dev
*
p
=
isdn_net_findif
(
cfg
->
name
);
if
(
p
)
{
isdn_net_local
*
lp
=
p
->
local
;
isdn_net_local
*
lp
=
&
p
->
local
;
strcpy
(
cfg
->
eaz
,
lp
->
msn
);
cfg
->
exclusive
=
lp
->
exclusive
;
...
...
@@ -2968,7 +2898,7 @@ isdn_net_getcfg(isdn_net_ioctl_cfg * cfg)
cfg
->
dialmode
=
lp
->
flags
&
ISDN_NET_DIALMODE_MASK
;
cfg
->
chargehup
=
(
lp
->
hupflags
&
4
)
?
1
:
0
;
cfg
->
ihup
=
(
lp
->
hupflags
&
8
)
?
1
:
0
;
cfg
->
cbdelay
=
lp
->
cbdelay
;
cfg
->
cbdelay
=
lp
->
cbdelay
*
5
/
HZ
;
cfg
->
dialmax
=
lp
->
dialmax
;
cfg
->
triggercps
=
lp
->
triggercps
;
cfg
->
slavedelay
=
lp
->
slavedelay
/
HZ
;
...
...
@@ -3003,8 +2933,8 @@ isdn_net_addphone(isdn_net_ioctl_phone * phone)
if
(
!
(
n
=
(
isdn_net_phone
*
)
kmalloc
(
sizeof
(
isdn_net_phone
),
GFP_KERNEL
)))
return
-
ENOMEM
;
strcpy
(
n
->
num
,
phone
->
phone
);
n
->
next
=
p
->
local
->
phone
[
phone
->
outgoing
&
1
];
p
->
local
->
phone
[
phone
->
outgoing
&
1
]
=
n
;
n
->
next
=
p
->
local
.
phone
[
phone
->
outgoing
&
1
];
p
->
local
.
phone
[
phone
->
outgoing
&
1
]
=
n
;
return
0
;
}
return
-
ENODEV
;
...
...
@@ -3026,7 +2956,7 @@ isdn_net_getphones(isdn_net_ioctl_phone * phone, char *phones)
if
(
!
p
)
return
-
ENODEV
;
inout
&=
1
;
for
(
n
=
p
->
local
->
phone
[
inout
];
n
;
n
=
n
->
next
)
{
for
(
n
=
p
->
local
.
phone
[
inout
];
n
;
n
=
n
->
next
)
{
if
(
more
)
{
put_user
(
' '
,
phones
++
);
count
++
;
...
...
@@ -3051,7 +2981,7 @@ int
isdn_net_getpeer
(
isdn_net_ioctl_phone
*
phone
,
isdn_net_ioctl_phone
*
peer
)
{
isdn_net_dev
*
p
=
isdn_net_findif
(
phone
->
name
);
int
ch
,
dv
,
idx
;
int
idx
;
if
(
!
p
)
return
-
ENODEV
;
/*
...
...
@@ -3060,15 +2990,12 @@ isdn_net_getpeer(isdn_net_ioctl_phone *phone, isdn_net_ioctl_phone *peer)
* in (partially) wrong number copied to user. This race
* currently ignored.
*/
ch
=
p
->
local
->
isdn_channel
;
dv
=
p
->
local
->
isdn_device
;
if
(
ch
<
0
&&
dv
<
0
)
return
-
ENOTCONN
;
idx
=
isdn_dc2minor
(
dv
,
ch
);
if
(
idx
<
0
)
return
-
ENODEV
;
idx
=
p
->
local
.
isdn_slot
;
if
(
idx
<
0
)
return
-
ENOTCONN
;
/* for pre-bound channels, we need this extra check */
if
(
strncmp
(
dev
->
num
[
idx
]
,
"???"
,
3
)
==
0
)
return
-
ENOTCONN
;
strncpy
(
phone
->
phone
,
dev
->
num
[
idx
]
,
ISDN_MSNLEN
);
phone
->
outgoing
=
USG_OUTGOING
(
dev
->
usage
[
idx
]
);
if
(
strncmp
(
isdn_slot_num
(
idx
)
,
"???"
,
3
)
==
0
)
return
-
ENOTCONN
;
strncpy
(
phone
->
phone
,
isdn_slot_num
(
idx
)
,
ISDN_MSNLEN
);
phone
->
outgoing
=
USG_OUTGOING
(
isdn_slot_usage
(
idx
)
);
if
(
copy_to_user
(
peer
,
phone
,
sizeof
(
*
peer
))
)
return
-
EFAULT
;
return
0
;
}
...
...
@@ -3087,16 +3014,16 @@ isdn_net_delphone(isdn_net_ioctl_phone * phone)
if
(
p
)
{
save_flags
(
flags
);
cli
();
n
=
p
->
local
->
phone
[
inout
];
n
=
p
->
local
.
phone
[
inout
];
m
=
NULL
;
while
(
n
)
{
if
(
!
strcmp
(
n
->
num
,
phone
->
phone
))
{
if
(
p
->
local
->
dial
==
n
)
p
->
local
->
dial
=
n
->
next
;
if
(
p
->
local
.
dial
==
n
)
p
->
local
.
dial
=
n
->
next
;
if
(
m
)
m
->
next
=
n
->
next
;
else
p
->
local
->
phone
[
inout
]
=
n
->
next
;
p
->
local
.
phone
[
inout
]
=
n
->
next
;
kfree
(
n
);
restore_flags
(
flags
);
return
0
;
...
...
@@ -3124,15 +3051,15 @@ isdn_net_rmallphone(isdn_net_dev * p)
save_flags
(
flags
);
cli
();
for
(
i
=
0
;
i
<
2
;
i
++
)
{
n
=
p
->
local
->
phone
[
i
];
n
=
p
->
local
.
phone
[
i
];
while
(
n
)
{
m
=
n
->
next
;
kfree
(
n
);
n
=
m
;
}
p
->
local
->
phone
[
i
]
=
NULL
;
p
->
local
.
phone
[
i
]
=
NULL
;
}
p
->
local
->
dial
=
NULL
;
p
->
local
.
dial
=
NULL
;
restore_flags
(
flags
);
return
0
;
}
...
...
@@ -3147,9 +3074,9 @@ isdn_net_force_hangup(char *name)
struct
net_device
*
q
;
if
(
p
)
{
if
(
p
->
local
->
isdn_device
<
0
)
if
(
p
->
local
.
isdn_slot
<
0
)
return
1
;
q
=
p
->
local
->
slave
;
q
=
p
->
local
.
slave
;
/* If this interface has slaves, do a hangup for them also. */
while
(
q
)
{
isdn_net_hangup
(
q
);
...
...
@@ -3165,7 +3092,7 @@ isdn_net_force_hangup(char *name)
* Helper-function for isdn_net_rm: Do the real work.
*/
static
int
isdn_net_realrm
(
isdn_net_dev
*
p
,
isdn_net_dev
*
q
)
isdn_net_realrm
(
isdn_net_dev
*
p
)
{
unsigned
long
flags
;
...
...
@@ -3182,42 +3109,37 @@ isdn_net_realrm(isdn_net_dev * p, isdn_net_dev * q)
/* Free all phone-entries */
isdn_net_rmallphone
(
p
);
/* If interface is bound exclusive, free channel-usage */
if
(
p
->
local
->
exclusive
!=
-
1
)
isdn_unexclusive_channel
(
p
->
local
->
pre_device
,
p
->
local
->
pre_channel
);
if
(
p
->
local
->
master
)
{
if
(
p
->
local
.
exclusive
!=
-
1
)
isdn_unexclusive_channel
(
p
->
local
.
pre_device
,
p
->
local
.
pre_channel
);
if
(
p
->
local
.
master
)
{
/* It's a slave-device, so update master's slave-pointer if necessary */
if
(((
isdn_net_local
*
)
(
p
->
local
->
master
->
priv
))
->
slave
==
&
p
->
dev
)
((
isdn_net_local
*
)
(
p
->
local
->
master
->
priv
))
->
slave
=
p
->
local
->
slave
;
if
(((
isdn_net_local
*
)
(
p
->
local
.
master
->
priv
))
->
slave
==
&
p
->
dev
)
((
isdn_net_local
*
)
(
p
->
local
.
master
->
priv
))
->
slave
=
p
->
local
.
slave
;
}
else
{
/* Unregister only if it's a master-device */
p
->
dev
.
hard_header_cache
=
p
->
local
->
org_hhc
;
p
->
dev
.
header_cache_update
=
p
->
local
->
org_hcu
;
p
->
dev
.
hard_header_cache
=
p
->
local
.
org_hhc
;
p
->
dev
.
header_cache_update
=
p
->
local
.
org_hcu
;
unregister_netdev
(
&
p
->
dev
);
}
/* Unlink device from chain */
if
(
q
)
q
->
next
=
p
->
next
;
else
dev
->
netdev
=
p
->
next
;
if
(
p
->
local
->
slave
)
{
list_del
(
&
p
->
global_list
);
if
(
p
->
local
.
slave
)
{
/* If this interface has a slave, remove it also */
char
*
slavename
=
((
isdn_net_local
*
)
(
p
->
local
->
slave
->
priv
))
->
name
;
isdn_net_dev
*
n
=
dev
->
netdev
;
q
=
NULL
;
while
(
n
)
{
if
(
!
strcmp
(
n
->
local
->
name
,
slavename
))
{
isdn_net_realrm
(
n
,
q
);
char
*
slavename
=
((
isdn_net_local
*
)
(
p
->
local
.
slave
->
priv
))
->
name
;
struct
list_head
*
l
;
list_for_each
(
l
,
&
isdn_net_devs
)
{
isdn_net_dev
*
n
=
list_entry
(
l
,
isdn_net_dev
,
global_list
);
if
(
!
strcmp
(
n
->
local
.
name
,
slavename
))
{
isdn_net_realrm
(
n
);
break
;
}
q
=
n
;
n
=
(
isdn_net_dev
*
)
n
->
next
;
}
}
/* If no more net-devices remain, disable auto-hangup timer */
if
(
dev
->
netdev
==
NULL
)
if
(
list_empty
(
&
isdn_net_devs
)
)
isdn_timer_ctrl
(
ISDN_TIMER_NETHANGUP
,
0
);
restore_flags
(
flags
);
kfree
(
p
->
local
);
kfree
(
p
);
return
0
;
...
...
@@ -3229,21 +3151,14 @@ isdn_net_realrm(isdn_net_dev * p, isdn_net_dev * q)
int
isdn_net_rm
(
char
*
name
)
{
isdn_net_dev
*
p
;
isdn_net_dev
*
q
;
struct
list_head
*
l
;
/* Search name in netdev-chain */
p
=
dev
->
netdev
;
q
=
NULL
;
while
(
p
)
{
if
(
!
strcmp
(
p
->
local
->
name
,
name
))
return
(
isdn_net_realrm
(
p
,
q
));
q
=
p
;
p
=
(
isdn_net_dev
*
)
p
->
next
;
list_for_each
(
l
,
&
isdn_net_devs
)
{
isdn_net_dev
*
p
=
list_entry
(
l
,
isdn_net_dev
,
global_list
);
if
(
!
strcmp
(
p
->
local
.
name
,
name
))
return
isdn_net_realrm
(
p
);
}
/* If no more net-devices remain, disable auto-hangup timer */
if
(
dev
->
netdev
==
NULL
)
isdn_timer_ctrl
(
ISDN_TIMER_NETHANGUP
,
0
);
return
-
ENODEV
;
}
...
...
@@ -3259,16 +3174,17 @@ isdn_net_rmall(void)
/* Walk through netdev-chain */
save_flags
(
flags
);
cli
();
while
(
dev
->
netdev
)
{
if
(
!
dev
->
netdev
->
local
->
master
)
{
/* Remove master-devices only, slaves get removed with their master */
if
((
ret
=
isdn_net_realrm
(
dev
->
netdev
,
NULL
)))
{
while
(
!
list_empty
(
&
isdn_net_devs
))
{
isdn_net_dev
*
p
=
list_entry
(
isdn_net_devs
.
next
,
isdn_net_dev
,
global_list
);
/* Remove master-devices only, slaves get removed with their master */
if
(
!
p
->
local
.
master
)
{
if
((
ret
=
isdn_net_realrm
(
p
)))
{
restore_flags
(
flags
);
return
ret
;
}
}
}
dev
->
netdev
=
NULL
;
restore_flags
(
flags
);
return
0
;
}
drivers/isdn/i4l/isdn_net.h
View file @
b14ebcfc
...
...
@@ -31,8 +31,8 @@
#define CISCO_SLARP_REPLY 1
#define CISCO_SLARP_KEEPALIVE 2
extern
char
*
isdn_net_new
(
char
*
,
struct
net_device
*
);
extern
char
*
isdn_net_newslave
(
char
*
);
extern
int
isdn_net_new
(
char
*
,
struct
net_device
*
);
extern
int
isdn_net_newslave
(
char
*
);
extern
int
isdn_net_rm
(
char
*
);
extern
int
isdn_net_rmall
(
void
);
extern
int
isdn_net_stat_callback
(
int
,
isdn_ctrl
*
);
...
...
@@ -44,7 +44,6 @@ extern int isdn_net_getpeer(isdn_net_ioctl_phone *, isdn_net_ioctl_phone *);
extern
int
isdn_net_delphone
(
isdn_net_ioctl_phone
*
);
extern
int
isdn_net_find_icall
(
int
,
int
,
int
,
setup_parm
*
);
extern
void
isdn_net_hangup
(
struct
net_device
*
);
extern
void
isdn_net_dial
(
void
);
extern
void
isdn_net_autohup
(
void
);
extern
int
isdn_net_force_hangup
(
char
*
);
extern
int
isdn_net_force_dial
(
char
*
);
...
...
@@ -131,7 +130,7 @@ static __inline__ void isdn_net_rm_from_bundle(isdn_net_local *lp)
if
(
master_lp
->
netdev
->
queue
==
lp
)
{
master_lp
->
netdev
->
queue
=
lp
->
next
;
if
(
lp
->
next
==
lp
)
{
/* last in queue */
master_lp
->
netdev
->
queue
=
master_lp
->
netdev
->
local
;
master_lp
->
netdev
->
queue
=
&
master_lp
->
netdev
->
local
;
}
}
lp
->
next
=
lp
->
last
=
lp
;
/* (re)set own pointers */
...
...
drivers/isdn/i4l/isdn_ppp.c
View file @
b14ebcfc
...
...
@@ -165,14 +165,15 @@ isdn_ppp_bind(isdn_net_local * lp)
save_flags
(
flags
);
cli
();
if
(
lp
->
pppbind
<
0
)
{
/* device bounded to ippp device ? */
isdn_net_dev
*
net_dev
=
dev
->
netdev
;
struct
list_head
*
l
;
char
exclusive
[
ISDN_MAX_CHANNELS
];
/* exclusive flags */
memset
(
exclusive
,
0
,
ISDN_MAX_CHANNELS
);
while
(
net_dev
)
{
/* step through net devices to find exclusive minors */
isdn_net_local
*
lp
=
net_dev
->
local
;
/* step through net devices to find exclusive minors */
list_for_each
(
l
,
&
isdn_net_devs
)
{
isdn_net_dev
*
p
=
list_entry
(
l
,
isdn_net_dev
,
global_list
);
isdn_net_local
*
lp
=
&
p
->
local
;
if
(
lp
->
pppbind
>=
0
)
exclusive
[
lp
->
pppbind
]
=
1
;
net_dev
=
net_dev
->
next
;
}
/*
* search a free device / slot
...
...
@@ -804,11 +805,11 @@ isdn_ppp_write(struct file *file, const char *buf, size_t count, loff_t *off)
if
(
proto
!=
PPP_LCP
)
lp
->
huptimer
=
0
;
if
(
lp
->
isdn_
device
<
0
||
lp
->
isdn_channel
<
0
)
{
if
(
lp
->
isdn_
slot
<
0
)
{
retval
=
0
;
goto
out
;
}
if
((
dev
->
drv
[
lp
->
isdn_device
]
->
flags
&
DRV_FLAG_RUNNING
)
&&
if
((
dev
->
drv
[
isdn_slot_driver
(
lp
->
isdn_slot
)
]
->
flags
&
DRV_FLAG_RUNNING
)
&&
lp
->
dialstate
==
0
&&
(
lp
->
flags
&
ISDN_NET_CONNECTED
))
{
unsigned
short
hl
;
...
...
@@ -818,7 +819,7 @@ isdn_ppp_write(struct file *file, const char *buf, size_t count, loff_t *off)
* sk_buff. old call to dev_alloc_skb only reserved
* 16 bytes, now we are looking what the driver want
*/
hl
=
dev
->
drv
[
lp
->
isdn_device
]
->
interface
->
hl_hdrlen
;
hl
=
isdn_slot_hdrlen
(
lp
->
isdn_slot
)
;
skb
=
alloc_skb
(
hl
+
count
,
GFP_ATOMIC
);
if
(
!
skb
)
{
printk
(
KERN_WARNING
"isdn_ppp_write: out of memory!
\n
"
);
...
...
@@ -974,7 +975,7 @@ void isdn_ppp_receive(isdn_net_dev * net_dev, isdn_net_local * lp, struct sk_buf
int
slot
;
int
proto
;
if
(
net_dev
->
local
->
master
)
if
(
net_dev
->
local
.
master
)
BUG
();
// we're called with the master device always
slot
=
lp
->
ppp_slot
;
...
...
@@ -1077,12 +1078,12 @@ isdn_ppp_push_higher(isdn_net_dev * net_dev, isdn_net_local * lp, struct sk_buff
case
PPP_VJC_UNCOMP
:
if
(
is
->
debug
&
0x20
)
printk
(
KERN_DEBUG
"isdn_ppp: VJC_UNCOMP
\n
"
);
if
(
net_dev
->
local
->
ppp_slot
<
0
)
{
if
(
net_dev
->
local
.
ppp_slot
<
0
)
{
printk
(
KERN_ERR
__FUNCTION__
": net_dev->local->ppp_slot(%d) out of range
\n
"
,
net_dev
->
local
->
ppp_slot
);
net_dev
->
local
.
ppp_slot
);
goto
drop_packet
;
}
if
(
slhc_remember
(
ippp_table
[
net_dev
->
local
->
ppp_slot
]
->
slcomp
,
skb
->
data
,
skb
->
len
)
<=
0
)
{
if
(
slhc_remember
(
ippp_table
[
net_dev
->
local
.
ppp_slot
]
->
slcomp
,
skb
->
data
,
skb
->
len
)
<=
0
)
{
printk
(
KERN_WARNING
"isdn_ppp: received illegal VJC_UNCOMP frame!
\n
"
);
goto
drop_packet
;
}
...
...
@@ -1103,12 +1104,12 @@ isdn_ppp_push_higher(isdn_net_dev * net_dev, isdn_net_local * lp, struct sk_buff
}
skb_put
(
skb
,
skb_old
->
len
+
128
);
memcpy
(
skb
->
data
,
skb_old
->
data
,
skb_old
->
len
);
if
(
net_dev
->
local
->
ppp_slot
<
0
)
{
if
(
net_dev
->
local
.
ppp_slot
<
0
)
{
printk
(
KERN_ERR
__FUNCTION__
": net_dev->local->ppp_slot(%d) out of range
\n
"
,
net_dev
->
local
->
ppp_slot
);
net_dev
->
local
.
ppp_slot
);
goto
drop_packet
;
}
pkt_len
=
slhc_uncompress
(
ippp_table
[
net_dev
->
local
->
ppp_slot
]
->
slcomp
,
pkt_len
=
slhc_uncompress
(
ippp_table
[
net_dev
->
local
.
ppp_slot
]
->
slcomp
,
skb
->
data
,
skb_old
->
len
);
kfree_skb
(
skb_old
);
if
(
pkt_len
<
0
)
...
...
@@ -1144,7 +1145,7 @@ isdn_ppp_push_higher(isdn_net_dev * net_dev, isdn_net_local * lp, struct sk_buff
return
;
drop_packet:
net_dev
->
local
->
stats
.
rx_dropped
++
;
net_dev
->
local
.
stats
.
rx_dropped
++
;
kfree_skb
(
skb
);
}
...
...
@@ -1263,7 +1264,7 @@ isdn_ppp_xmit(struct sk_buff *skb, struct net_device *netdev)
* sk_buff. old call to dev_alloc_skb only reserved
* 16 bytes, now we are looking what the driver want.
*/
hl
=
dev
->
drv
[
lp
->
isdn_device
]
->
interface
->
hl_hdrlen
+
IPPP_MAX_HEADER
;
hl
=
isdn_slot_hdrlen
(
lp
->
isdn_slot
)
+
IPPP_MAX_HEADER
;
;
/*
* Note: hl might still be insufficient because the method
* above does not account for a possibible MPPP slave channel
...
...
@@ -1976,7 +1977,7 @@ isdn_ppp_dial_slave(char *name)
if
(
!
(
ndev
=
isdn_net_findif
(
name
)))
return
1
;
lp
=
ndev
->
local
;
lp
=
&
ndev
->
local
;
if
(
!
(
lp
->
flags
&
ISDN_NET_CONNECTED
))
return
5
;
...
...
@@ -2007,7 +2008,7 @@ isdn_ppp_hangup_slave(char *name)
if
(
!
(
ndev
=
isdn_net_findif
(
name
)))
return
1
;
lp
=
ndev
->
local
;
lp
=
&
ndev
->
local
;
if
(
!
(
lp
->
flags
&
ISDN_NET_CONNECTED
))
return
5
;
...
...
@@ -2094,7 +2095,7 @@ static void isdn_ppp_ccp_xmit_reset(struct ippp_struct *is, int proto,
isdn_net_local
*
lp
=
is
->
lp
;
/* Alloc large enough skb */
hl
=
dev
->
drv
[
lp
->
isdn_device
]
->
interface
->
hl_hdrlen
;
hl
=
isdn_slot_hdrlen
(
lp
->
isdn_slot
)
;
skb
=
alloc_skb
(
len
+
hl
+
16
,
GFP_ATOMIC
);
if
(
!
skb
)
{
printk
(
KERN_WARNING
...
...
drivers/isdn/i4l/isdn_tty.c
View file @
b14ebcfc
...
...
@@ -128,7 +128,7 @@ isdn_tty_readmodem(void)
modem_info
*
info
;
for
(
i
=
0
;
i
<
ISDN_MAX_CHANNELS
;
i
++
)
{
if
((
midx
=
dev
->
m_idx
[
i
]
)
>=
0
)
{
if
((
midx
=
isdn_slot_m_idx
(
i
)
)
>=
0
)
{
info
=
&
dev
->
mdm
.
info
[
midx
];
if
(
info
->
online
)
{
r
=
0
;
...
...
@@ -143,9 +143,9 @@ isdn_tty_readmodem(void)
if
(
c
>
0
)
{
save_flags
(
flags
);
cli
();
r
=
isdn_
readbchan
(
info
->
isdn_driver
,
info
->
isdn_channel
,
r
=
isdn_
slot_readbchan
(
info
->
isdn_slot
,
tty
->
flip
.
char_buf_ptr
,
tty
->
flip
.
flag_buf_ptr
,
c
,
0
);
tty
->
flip
.
flag_buf_ptr
,
c
);
/* CISCO AsyncPPP Hack */
if
(
!
(
info
->
emu
.
mdmreg
[
REG_CPPP
]
&
BIT_CPPP
))
memset
(
tty
->
flip
.
flag_buf_ptr
,
0
,
r
);
...
...
@@ -182,7 +182,7 @@ isdn_tty_rcv_skb(int i, int di, int channel, struct sk_buff *skb)
#endif
modem_info
*
info
;
if
((
midx
=
dev
->
m_idx
[
i
]
)
<
0
)
{
if
((
midx
=
isdn_slot_m_idx
(
i
)
)
<
0
)
{
/* if midx is invalid, packet is not for tty */
return
0
;
}
...
...
@@ -315,8 +315,7 @@ isdn_tty_tint(modem_info * info)
if
(
!
skb
)
return
;
len
=
skb
->
len
;
if
((
slen
=
isdn_writebuf_skb_stub
(
info
->
isdn_driver
,
info
->
isdn_channel
,
1
,
skb
))
==
len
)
{
if
((
slen
=
isdn_slot_write
(
info
->
isdn_slot
,
skb
))
==
len
)
{
struct
tty_struct
*
tty
=
info
->
tty
;
info
->
send_outstanding
++
;
info
->
msr
&=
~
UART_MSR_CTS
;
...
...
@@ -479,11 +478,11 @@ isdn_tty_senddown(modem_info * info)
atomic_inc
(
&
info
->
xmit_lock
);
if
(
!
(
atomic_dec_and_test
(
&
info
->
xmit_lock
)))
return
;
if
(
info
->
isdn_
driver
<
0
)
{
if
(
info
->
isdn_
slot
<
0
)
{
info
->
xmit_count
=
0
;
return
;
}
skb_res
=
dev
->
drv
[
info
->
isdn_driver
]
->
interface
->
hl_hdrlen
+
4
;
skb_res
=
isdn_slot_hdrlen
(
info
->
isdn_slot
)
;
#ifdef CONFIG_ISDN_AUDIO
if
(
info
->
vonline
&
2
)
audio_len
=
buflen
*
voice_cf
[
info
->
emu
.
vpar
[
3
]];
...
...
@@ -627,7 +626,6 @@ isdn_tty_dial(char *n, modem_info * info, atemu * m)
int
usg
=
ISDN_USAGE_MODEM
;
int
si
=
7
;
int
l2
=
m
->
mdmreg
[
REG_L2PROT
];
isdn_ctrl
cmd
;
ulong
flags
;
int
i
;
int
j
;
...
...
@@ -652,56 +650,34 @@ isdn_tty_dial(char *n, modem_info * info, atemu * m)
m
->
mdmreg
[
REG_SI1I
]
=
si2bit
[
si
];
save_flags
(
flags
);
cli
();
i
=
isdn_get_free_
channel
(
usg
,
l2
,
m
->
mdmreg
[
REG_L3PROT
],
-
1
,
-
1
,
m
->
msn
);
i
=
isdn_get_free_
slot
(
usg
,
l2
,
m
->
mdmreg
[
REG_L3PROT
],
-
1
,
-
1
,
m
->
msn
);
if
(
i
<
0
)
{
restore_flags
(
flags
);
isdn_tty_modem_result
(
RESULT_NO_DIALTONE
,
info
);
}
else
{
info
->
isdn_driver
=
dev
->
drvmap
[
i
];
info
->
isdn_channel
=
dev
->
chanmap
[
i
];
info
->
drv_index
=
i
;
dev
->
m_idx
[
i
]
=
info
->
line
;
dev
->
usage
[
i
]
|=
ISDN_USAGE_OUTGOING
;
struct
dial_info
dial
=
{
.
l2_proto
=
l2
,
.
l3_proto
=
m
->
mdmreg
[
REG_L3PROT
],
.
si1
=
si
,
.
si2
=
m
->
mdmreg
[
REG_SI2
],
.
msn
=
m
->
msn
,
.
phone
=
n
,
};
info
->
isdn_slot
=
i
;
isdn_slot_set_m_idx
(
i
,
info
->
line
);
info
->
last_dir
=
1
;
info
->
last_l2
=
l2
;
strcpy
(
info
->
last_num
,
n
);
isdn_info_update
();
restore_flags
(
flags
);
cmd
.
driver
=
info
->
isdn_driver
;
cmd
.
arg
=
info
->
isdn_channel
;
cmd
.
command
=
ISDN_CMD_CLREAZ
;
isdn_command
(
&
cmd
);
strcpy
(
cmd
.
parm
.
num
,
isdn_map_eaz2msn
(
m
->
msn
,
info
->
isdn_driver
));
cmd
.
driver
=
info
->
isdn_driver
;
cmd
.
command
=
ISDN_CMD_SETEAZ
;
isdn_command
(
&
cmd
);
cmd
.
driver
=
info
->
isdn_driver
;
cmd
.
command
=
ISDN_CMD_SETL2
;
info
->
last_l2
=
l2
;
cmd
.
arg
=
info
->
isdn_channel
+
(
l2
<<
8
);
isdn_command
(
&
cmd
);
cmd
.
driver
=
info
->
isdn_driver
;
cmd
.
command
=
ISDN_CMD_SETL3
;
cmd
.
arg
=
info
->
isdn_channel
+
(
m
->
mdmreg
[
REG_L3PROT
]
<<
8
);
#ifdef CONFIG_ISDN_TTY_FAX
if
(
l2
==
ISDN_PROTO_L2_FAX
)
{
cmd
.
parm
.
fax
=
info
->
fax
;
dial
.
fax
=
info
->
fax
;
info
->
fax
->
direction
=
ISDN_TTY_FAX_CONN_OUT
;
}
#endif
isdn_command
(
&
cmd
);
cmd
.
driver
=
info
->
isdn_driver
;
cmd
.
arg
=
info
->
isdn_channel
;
sprintf
(
cmd
.
parm
.
setup
.
phone
,
"%s"
,
n
);
sprintf
(
cmd
.
parm
.
setup
.
eazmsn
,
"%s"
,
isdn_map_eaz2msn
(
m
->
msn
,
info
->
isdn_driver
));
cmd
.
parm
.
setup
.
si1
=
si
;
cmd
.
parm
.
setup
.
si2
=
m
->
mdmreg
[
REG_SI2
];
cmd
.
command
=
ISDN_CMD_DIAL
;
info
->
dialing
=
1
;
info
->
emu
.
carrierwait
=
0
;
strcpy
(
dev
->
num
[
i
],
n
);
isdn_info_update
();
isdn_command
(
&
cmd
);
isdn_slot_dial
(
info
->
isdn_slot
,
&
dial
);
isdn_timer_ctrl
(
ISDN_TIMER_CARRIER
,
1
);
}
}
...
...
@@ -714,19 +690,15 @@ void
isdn_tty_modem_hup
(
modem_info
*
info
,
int
local
)
{
isdn_ctrl
cmd
;
int
di
,
ch
;
int
slot
;
if
(
!
info
)
return
;
di
=
info
->
isdn_driver
;
ch
=
info
->
isdn_channel
;
if
(
di
<
0
||
ch
<
0
)
slot
=
info
->
isdn_slot
;
if
(
slot
<
0
)
return
;
info
->
isdn_driver
=
-
1
;
info
->
isdn_channel
=
-
1
;
#ifdef ISDN_DEBUG_MODEM_HUP
printk
(
KERN_DEBUG
"Mhup ttyI%d
\n
"
,
info
->
line
);
#endif
...
...
@@ -768,21 +740,14 @@ isdn_tty_modem_hup(modem_info * info, int local)
info
->
msr
&=
~
(
UART_MSR_DCD
|
UART_MSR_RI
);
info
->
lsr
|=
UART_LSR_TEMT
;
if
(
local
)
{
cmd
.
driver
=
di
;
cmd
.
command
=
ISDN_CMD_HANGUP
;
cmd
.
arg
=
ch
;
isdn_command
(
&
cmd
);
}
if
(
local
)
isdn_slot_command
(
slot
,
ISDN_CMD_HANGUP
,
&
cmd
);
isdn_
all_eaz
(
di
,
ch
);
isdn_
slot_all_eaz
(
slot
);
info
->
emu
.
mdmreg
[
REG_RINGCNT
]
=
0
;
isdn_free_channel
(
di
,
ch
,
0
);
if
(
info
->
drv_index
>=
0
)
{
dev
->
m_idx
[
info
->
drv_index
]
=
-
1
;
info
->
drv_index
=
-
1
;
}
isdn_slot_free
(
slot
,
0
);
isdn_slot_set_m_idx
(
slot
,
-
1
);
info
->
isdn_slot
=
-
1
;
}
/*
...
...
@@ -812,11 +777,11 @@ isdn_tty_suspend(char *id, modem_info * info, atemu * m)
printk
(
KERN_DEBUG
"Msusp ttyI%d
\n
"
,
info
->
line
);
#endif
l
=
strlen
(
id
);
if
((
info
->
isdn_
driver
>=
0
))
{
if
((
info
->
isdn_
slot
>=
0
))
{
cmd
.
parm
.
cmsg
.
Length
=
l
+
18
;
cmd
.
parm
.
cmsg
.
Command
=
CAPI_FACILITY
;
cmd
.
parm
.
cmsg
.
Subcommand
=
CAPI_REQ
;
cmd
.
parm
.
cmsg
.
adr
.
Controller
=
i
nfo
->
isdn_driver
+
1
;
cmd
.
parm
.
cmsg
.
adr
.
Controller
=
i
sdn_slot_driver
(
info
->
isdn_slot
)
+
1
;
cmd
.
parm
.
cmsg
.
para
[
0
]
=
3
;
/* 16 bit 0x0003 suplementary service */
cmd
.
parm
.
cmsg
.
para
[
1
]
=
0
;
cmd
.
parm
.
cmsg
.
para
[
2
]
=
l
+
3
;
...
...
@@ -824,10 +789,7 @@ isdn_tty_suspend(char *id, modem_info * info, atemu * m)
cmd
.
parm
.
cmsg
.
para
[
4
]
=
0
;
cmd
.
parm
.
cmsg
.
para
[
5
]
=
l
;
strncpy
(
&
cmd
.
parm
.
cmsg
.
para
[
6
],
id
,
l
);
cmd
.
command
=
CAPI_PUT_MESSAGE
;
cmd
.
driver
=
info
->
isdn_driver
;
cmd
.
arg
=
info
->
isdn_channel
;
isdn_command
(
&
cmd
);
isdn_slot_command
(
info
->
isdn_slot
,
CAPI_PUT_MESSAGE
,
&
cmd
);
}
}
...
...
@@ -871,43 +833,26 @@ isdn_tty_resume(char *id, modem_info * info, atemu * m)
m
->
mdmreg
[
REG_SI1I
]
=
si2bit
[
si
];
save_flags
(
flags
);
cli
();
i
=
isdn_get_free_
channel
(
usg
,
l2
,
m
->
mdmreg
[
REG_L3PROT
],
-
1
,
-
1
,
m
->
msn
);
i
=
isdn_get_free_
slot
(
usg
,
l2
,
m
->
mdmreg
[
REG_L3PROT
],
-
1
,
-
1
,
m
->
msn
);
if
(
i
<
0
)
{
restore_flags
(
flags
);
isdn_tty_modem_result
(
RESULT_NO_DIALTONE
,
info
);
}
else
{
info
->
isdn_driver
=
dev
->
drvmap
[
i
];
info
->
isdn_channel
=
dev
->
chanmap
[
i
];
info
->
drv_index
=
i
;
dev
->
m_idx
[
i
]
=
info
->
line
;
dev
->
usage
[
i
]
|=
ISDN_USAGE_OUTGOING
;
info
->
isdn_slot
=
i
;
isdn_slot_set_m_idx
(
i
,
info
->
line
);
isdn_slot_set_usage
(
i
,
isdn_slot_usage
(
i
)
|
ISDN_USAGE_OUTGOING
);
info
->
last_dir
=
1
;
// strcpy(info->last_num, n);
isdn_info_update
();
restore_flags
(
flags
);
cmd
.
driver
=
info
->
isdn_driver
;
cmd
.
arg
=
info
->
isdn_channel
;
cmd
.
command
=
ISDN_CMD_CLREAZ
;
isdn_command
(
&
cmd
);
strcpy
(
cmd
.
parm
.
num
,
isdn_map_eaz2msn
(
m
->
msn
,
info
->
isdn_driver
));
cmd
.
driver
=
info
->
isdn_driver
;
cmd
.
command
=
ISDN_CMD_SETEAZ
;
isdn_command
(
&
cmd
);
cmd
.
driver
=
info
->
isdn_driver
;
cmd
.
command
=
ISDN_CMD_SETL2
;
info
->
last_l2
=
l2
;
cmd
.
arg
=
info
->
isdn_channel
+
(
l2
<<
8
);
isdn_command
(
&
cmd
);
cmd
.
driver
=
info
->
isdn_driver
;
cmd
.
command
=
ISDN_CMD_SETL3
;
cmd
.
arg
=
info
->
isdn_channel
+
(
m
->
mdmreg
[
REG_L3PROT
]
<<
8
);
isdn_command
(
&
cmd
);
cmd
.
driver
=
info
->
isdn_driver
;
cmd
.
arg
=
info
->
isdn_channel
;
cmd
.
arg
=
l2
<<
8
;
isdn_slot_command
(
info
->
isdn_slot
,
ISDN_CMD_SETL2
,
&
cmd
);
cmd
.
arg
=
m
->
mdmreg
[
REG_L3PROT
]
<<
8
;
isdn_slot_command
(
info
->
isdn_slot
,
ISDN_CMD_SETL3
,
&
cmd
);
cmd
.
parm
.
cmsg
.
Length
=
l
+
18
;
cmd
.
parm
.
cmsg
.
Command
=
CAPI_FACILITY
;
cmd
.
parm
.
cmsg
.
Subcommand
=
CAPI_REQ
;
cmd
.
parm
.
cmsg
.
adr
.
Controller
=
i
nfo
->
isdn_driver
+
1
;
cmd
.
parm
.
cmsg
.
adr
.
Controller
=
i
sdn_slot_driver
(
info
->
isdn_slot
)
+
1
;
cmd
.
parm
.
cmsg
.
para
[
0
]
=
3
;
/* 16 bit 0x0003 suplementary service */
cmd
.
parm
.
cmsg
.
para
[
1
]
=
0
;
cmd
.
parm
.
cmsg
.
para
[
2
]
=
l
+
3
;
...
...
@@ -915,11 +860,10 @@ isdn_tty_resume(char *id, modem_info * info, atemu * m)
cmd
.
parm
.
cmsg
.
para
[
4
]
=
0
;
cmd
.
parm
.
cmsg
.
para
[
5
]
=
l
;
strncpy
(
&
cmd
.
parm
.
cmsg
.
para
[
6
],
id
,
l
);
cmd
.
command
=
CAPI_PUT_MESSAGE
;
info
->
dialing
=
1
;
// strcpy(dev->num[i], n);
isdn_info_update
();
isdn_
command
(
&
cmd
);
isdn_
slot_command
(
info
->
isdn_slot
,
CAPI_PUT_MESSAGE
,
&
cmd
);
isdn_timer_ctrl
(
ISDN_TIMER_CARRIER
,
1
);
}
}
...
...
@@ -965,51 +909,33 @@ isdn_tty_send_msg(modem_info * info, atemu * m, char *msg)
m
->
mdmreg
[
REG_SI1I
]
=
si2bit
[
si
];
save_flags
(
flags
);
cli
();
i
=
isdn_get_free_
channel
(
usg
,
l2
,
m
->
mdmreg
[
REG_L3PROT
],
-
1
,
-
1
,
m
->
msn
);
i
=
isdn_get_free_
slot
(
usg
,
l2
,
m
->
mdmreg
[
REG_L3PROT
],
-
1
,
-
1
,
m
->
msn
);
if
(
i
<
0
)
{
restore_flags
(
flags
);
isdn_tty_modem_result
(
RESULT_NO_DIALTONE
,
info
);
}
else
{
info
->
isdn_driver
=
dev
->
drvmap
[
i
];
info
->
isdn_channel
=
dev
->
chanmap
[
i
];
info
->
drv_index
=
i
;
dev
->
m_idx
[
i
]
=
info
->
line
;
dev
->
usage
[
i
]
|=
ISDN_USAGE_OUTGOING
;
info
->
isdn_slot
=
i
;
isdn_slot_set_m_idx
(
i
,
info
->
line
);
isdn_slot_set_usage
(
i
,
isdn_slot_usage
(
i
)
|
ISDN_USAGE_OUTGOING
);
info
->
last_dir
=
1
;
isdn_info_update
();
restore_flags
(
flags
);
cmd
.
driver
=
info
->
isdn_driver
;
cmd
.
arg
=
info
->
isdn_channel
;
cmd
.
command
=
ISDN_CMD_CLREAZ
;
isdn_command
(
&
cmd
);
strcpy
(
cmd
.
parm
.
num
,
isdn_map_eaz2msn
(
m
->
msn
,
info
->
isdn_driver
));
cmd
.
driver
=
info
->
isdn_driver
;
cmd
.
command
=
ISDN_CMD_SETEAZ
;
isdn_command
(
&
cmd
);
cmd
.
driver
=
info
->
isdn_driver
;
cmd
.
command
=
ISDN_CMD_SETL2
;
info
->
last_l2
=
l2
;
cmd
.
arg
=
info
->
isdn_channel
+
(
l2
<<
8
);
isdn_command
(
&
cmd
);
cmd
.
driver
=
info
->
isdn_driver
;
cmd
.
command
=
ISDN_CMD_SETL3
;
cmd
.
arg
=
info
->
isdn_channel
+
(
m
->
mdmreg
[
REG_L3PROT
]
<<
8
);
isdn_command
(
&
cmd
);
cmd
.
driver
=
info
->
isdn_driver
;
cmd
.
arg
=
info
->
isdn_channel
;
cmd
.
arg
=
l2
<<
8
;
isdn_slot_command
(
info
->
isdn_slot
,
ISDN_CMD_SETL2
,
&
cmd
);
cmd
.
arg
=
m
->
mdmreg
[
REG_L3PROT
]
<<
8
;
isdn_slot_command
(
info
->
isdn_slot
,
ISDN_CMD_SETL3
,
&
cmd
);
cmd
.
parm
.
cmsg
.
Length
=
l
+
14
;
cmd
.
parm
.
cmsg
.
Command
=
CAPI_MANUFACTURER
;
cmd
.
parm
.
cmsg
.
Subcommand
=
CAPI_REQ
;
cmd
.
parm
.
cmsg
.
adr
.
Controller
=
i
nfo
->
isdn_driver
+
1
;
cmd
.
parm
.
cmsg
.
adr
.
Controller
=
i
sdn_slot_driver
(
info
->
isdn_slot
)
+
1
;
cmd
.
parm
.
cmsg
.
para
[
0
]
=
l
+
1
;
strncpy
(
&
cmd
.
parm
.
cmsg
.
para
[
1
],
msg
,
l
);
cmd
.
parm
.
cmsg
.
para
[
l
+
1
]
=
0xd
;
cmd
.
command
=
CAPI_PUT_MESSAGE
;
/* info->dialing = 1;
strcpy(dev->num[i], n);
isdn_info_update();
*/
isdn_
command
(
&
cmd
);
isdn_
slot_command
(
info
->
isdn_slot
,
CAPI_PUT_MESSAGE
,
&
cmd
);
}
}
...
...
@@ -1173,6 +1099,7 @@ isdn_tty_write(struct tty_struct *tty, int from_user, const u_char * buf, int co
{
int
c
;
int
total
=
0
;
int
di
;
modem_info
*
info
=
(
modem_info
*
)
tty
->
driver_data
;
atemu
*
m
=
&
info
->
emu
;
...
...
@@ -1186,8 +1113,9 @@ isdn_tty_write(struct tty_struct *tty, int from_user, const u_char * buf, int co
c
=
count
;
if
(
c
>
info
->
xmit_size
-
info
->
xmit_count
)
c
=
info
->
xmit_size
-
info
->
xmit_count
;
if
(
info
->
isdn_driver
>=
0
&&
c
>
dev
->
drv
[
info
->
isdn_driver
]
->
maxbufsize
)
c
=
dev
->
drv
[
info
->
isdn_driver
]
->
maxbufsize
;
di
=
isdn_slot_driver
(
info
->
isdn_slot
);
if
(
di
>=
0
&&
c
>
dev
->
drv
[
di
]
->
maxbufsize
)
c
=
dev
->
drv
[
di
]
->
maxbufsize
;
if
(
c
<=
0
)
break
;
if
((
info
->
online
>
1
)
...
...
@@ -1247,12 +1175,9 @@ isdn_tty_write(struct tty_struct *tty, int from_user, const u_char * buf, int co
if
(
info
->
vonline
&
4
)
{
/* ETX seen */
isdn_ctrl
c
;
c
.
command
=
ISDN_CMD_FAXCMD
;
c
.
driver
=
info
->
isdn_driver
;
c
.
arg
=
info
->
isdn_channel
;
c
.
parm
.
aux
.
cmd
=
ISDN_FAX_CLASS1_CTRL
;
c
.
parm
.
aux
.
subcmd
=
ETX
;
isdn_
command
(
&
c
);
isdn_
slot_command
(
info
->
isdn_slot
,
ISDN_CMD_FAXCMD
,
&
c
);
}
info
->
vonline
=
0
;
#ifdef ISDN_DEBUG_MODEM_VOICE
...
...
@@ -2015,10 +1940,10 @@ modem_write_profile(atemu * m)
}
int
isdn_tty_
modem_
init
(
void
)
isdn_tty_init
(
void
)
{
modem
*
m
;
int
i
;
int
i
,
retval
;
modem_info
*
info
;
m
=
&
dev
->
mdm
;
...
...
@@ -2063,13 +1988,15 @@ isdn_tty_modem_init(void)
m
->
tty_modem
.
minor_start
=
0
;
m
->
cua_modem
.
subtype
=
ISDN_SERIAL_TYPE_CALLOUT
;
if
(
tty_register_driver
(
&
m
->
tty_modem
))
{
retval
=
tty_register_driver
(
&
m
->
tty_modem
);
if
(
retval
)
{
printk
(
KERN_WARNING
"isdn_tty: Couldn't register modem-device
\n
"
);
return
-
1
;
goto
err
;
}
if
(
tty_register_driver
(
&
m
->
cua_modem
))
{
retval
=
tty_register_driver
(
&
m
->
cua_modem
);
if
(
retval
)
{
printk
(
KERN_WARNING
"isdn_tty: Couldn't register modem-callout-device
\n
"
);
return
-
2
;
goto
err_unregister_tty
;
}
for
(
i
=
0
;
i
<
ISDN_MAX_CHANNELS
;
i
++
)
{
info
=
&
m
->
info
[
i
];
...
...
@@ -2098,24 +2025,58 @@ isdn_tty_modem_init(void)
info
->
normal_termios
=
m
->
tty_modem
.
init_termios
;
init_waitqueue_head
(
&
info
->
open_wait
);
init_waitqueue_head
(
&
info
->
close_wait
);
info
->
isdn_driver
=
-
1
;
info
->
isdn_channel
=
-
1
;
info
->
drv_index
=
-
1
;
info
->
isdn_slot
=
-
1
;
info
->
xmit_size
=
ISDN_SERIAL_XMIT_SIZE
;
skb_queue_head_init
(
&
info
->
xmit_queue
);
#ifdef CONFIG_ISDN_AUDIO
skb_queue_head_init
(
&
info
->
dtmf_queue
);
#endif
if
(
!
(
info
->
xmit_buf
=
kmalloc
(
ISDN_SERIAL_XMIT_MAX
+
5
,
GFP_KERNEL
)))
{
info
->
xmit_buf
=
kmalloc
(
ISDN_SERIAL_XMIT_MAX
+
5
,
GFP_KERNEL
);
if
(
!
info
->
xmit_buf
)
{
printk
(
KERN_ERR
"Could not allocate modem xmit-buffer
\n
"
);
return
-
3
;
#ifdef CONFIG_ISDN_TTY_FAX
kfree
(
info
->
fax
);
#endif
goto
err_unregister_cua
;
}
/* Make room for T.70 header */
info
->
xmit_buf
+=
4
;
}
return
0
;
err_unregister_cua:
for
(
i
--
;
i
>=
0
;
i
--
)
{
info
=
&
m
->
info
[
i
];
#ifdef CONFIG_ISDN_TTY_FAX
kfree
(
info
->
fax
);
#endif
kfree
(
info
->
xmit_buf
-
4
);
}
tty_unregister_driver
(
&
dev
->
mdm
.
cua_modem
);
err_unregister_tty:
tty_unregister_driver
(
&
dev
->
mdm
.
tty_modem
);
err:
return
retval
;
}
void
isdn_tty_exit
(
void
)
{
modem
*
m
=
&
dev
->
mdm
;
modem_info
*
info
;
int
i
;
for
(
i
=
0
;
i
<
ISDN_MAX_CHANNELS
;
i
++
)
{
info
=
&
m
->
info
[
i
];
isdn_tty_cleanup_xmit
(
info
);
#ifdef CONFIG_ISDN_TTY_FAX
kfree
(
info
->
fax
);
#endif
kfree
(
info
->
xmit_buf
-
4
);
}
tty_unregister_driver
(
&
dev
->
mdm
.
cua_modem
);
tty_unregister_driver
(
&
dev
->
mdm
.
tty_modem
);
}
/*
* isdn_tty_match_icall(char *MSN, atemu *tty_emulator, int dev_idx)
...
...
@@ -2227,26 +2188,21 @@ isdn_tty_find_icall(int di, int ch, setup_parm *setup)
#ifndef FIX_FILE_TRANSFER
(
info
->
flags
&
ISDN_ASYNC_NORMAL_ACTIVE
)
&&
#endif
(
info
->
isdn_driver
==
-
1
)
&&
(
info
->
isdn_channel
==
-
1
)
&&
(
USG_NONE
(
dev
->
usage
[
idx
])))
{
(
info
->
isdn_slot
==
-
1
)
&&
(
USG_NONE
(
isdn_slot_usage
(
idx
))))
{
int
matchret
;
if
((
matchret
=
isdn_tty_match_icall
(
eaz
,
&
info
->
emu
,
di
))
>
wret
)
wret
=
matchret
;
if
(
!
matchret
)
{
/* EAZ is matching */
info
->
isdn_driver
=
di
;
info
->
isdn_channel
=
ch
;
info
->
drv_index
=
idx
;
dev
->
m_idx
[
idx
]
=
info
->
line
;
dev
->
usage
[
idx
]
&=
ISDN_USAGE_EXCLUSIVE
;
dev
->
usage
[
idx
]
|=
isdn_calc_usage
(
si1
,
info
->
emu
.
mdmreg
[
REG_L2PROT
]);
strcpy
(
dev
->
num
[
idx
],
nr
);
info
->
isdn_slot
=
idx
;
isdn_slot_set_m_idx
(
idx
,
info
->
line
);
strcpy
(
isdn_slot_num
(
idx
),
nr
);
strcpy
(
info
->
emu
.
cpn
,
eaz
);
info
->
emu
.
mdmreg
[
REG_SI1I
]
=
si2bit
[
si1
];
info
->
emu
.
mdmreg
[
REG_PLAN
]
=
setup
->
plan
;
info
->
emu
.
mdmreg
[
REG_SCREEN
]
=
setup
->
screen
;
isdn_
info_update
(
);
isdn_
slot_set_usage
(
idx
,
(
isdn_slot_usage
(
idx
)
&
ISDN_USAGE_EXCLUSIVE
)
|
isdn_calc_usage
(
si1
,
info
->
emu
.
mdmreg
[
REG_L2PROT
])
);
restore_flags
(
flags
);
printk
(
KERN_INFO
"isdn_tty: call from %s, -> RING on ttyI%d
\n
"
,
nr
,
info
->
line
);
...
...
@@ -2276,7 +2232,7 @@ isdn_tty_stat_callback(int i, isdn_ctrl *c)
if
(
i
<
0
)
return
0
;
if
((
mi
=
dev
->
m_idx
[
i
]
)
>=
0
)
{
if
((
mi
=
isdn_slot_m_idx
(
i
)
)
>=
0
)
{
info
=
&
dev
->
mdm
.
info
[
mi
];
switch
(
c
->
command
)
{
case
ISDN_STAT_CINF
:
...
...
@@ -2290,8 +2246,7 @@ isdn_tty_stat_callback(int i, isdn_ctrl *c)
#ifdef ISDN_TTY_STAT_DEBUG
printk
(
KERN_DEBUG
"tty_STAT_BSENT ttyI%d
\n
"
,
info
->
line
);
#endif
if
((
info
->
isdn_driver
==
c
->
driver
)
&&
(
info
->
isdn_channel
==
c
->
arg
))
{
if
((
info
->
isdn_slot
==
isdn_dc2minor
(
c
->
driver
,
c
->
arg
)))
{
info
->
msr
|=
UART_MSR_CTS
;
if
(
info
->
send_outstanding
)
if
(
!
(
--
info
->
send_outstanding
))
...
...
@@ -2375,14 +2330,14 @@ isdn_tty_stat_callback(int i, isdn_ctrl *c)
info
->
last_dir
=
0
;
info
->
dialing
=
0
;
info
->
rcvsched
=
1
;
if
(
USG_MODEM
(
dev
->
usage
[
i
]
))
{
if
(
USG_MODEM
(
isdn_slot_usage
(
i
)
))
{
if
(
info
->
emu
.
mdmreg
[
REG_L2PROT
]
==
ISDN_PROTO_L2_MODEM
)
{
strcpy
(
info
->
emu
.
connmsg
,
c
->
parm
.
num
);
isdn_tty_modem_result
(
RESULT_CONNECT
,
info
);
}
else
isdn_tty_modem_result
(
RESULT_CONNECT64000
,
info
);
}
if
(
USG_VOICE
(
dev
->
usage
[
i
]
))
if
(
USG_VOICE
(
isdn_slot_usage
(
i
)
))
isdn_tty_modem_result
(
RESULT_VCON
,
info
);
return
1
;
}
...
...
@@ -2421,7 +2376,7 @@ isdn_tty_stat_callback(int i, isdn_ctrl *c)
#endif
for
(
i
=
0
;
i
<
ISDN_MAX_CHANNELS
;
i
++
)
{
info
=
&
dev
->
mdm
.
info
[
i
];
if
(
i
nfo
->
isdn_driver
==
c
->
driver
)
{
if
(
i
sdn_slot_driver
(
info
->
isdn_slot
)
==
c
->
driver
)
{
if
(
info
->
online
)
isdn_tty_modem_hup
(
info
,
1
);
}
...
...
@@ -2473,6 +2428,7 @@ isdn_tty_at_cout(char *msg, modem_info * info)
ulong
flags
;
struct
sk_buff
*
skb
=
0
;
char
*
sp
=
0
;
int
di
,
ch
;
if
(
!
msg
)
{
printk
(
KERN_WARNING
"isdn_tty: Null-Message in isdn_tty_at_cout
\n
"
);
...
...
@@ -2488,8 +2444,9 @@ isdn_tty_at_cout(char *msg, modem_info * info)
/* use queue instead of direct flip, if online and */
/* data is in queue or flip buffer is full */
di
=
isdn_slot_driver
(
info
->
isdn_slot
);
ch
=
isdn_slot_channel
(
info
->
isdn_slot
);
if
((
info
->
online
)
&&
(((
tty
->
flip
.
count
+
strlen
(
msg
))
>=
TTY_FLIPBUF_SIZE
)
||
(
!
skb_queue_empty
(
&
dev
->
drv
[
info
->
isdn_driver
]
->
rpqueue
[
info
->
isdn_channel
]))))
{
(
!
skb_queue_empty
(
&
dev
->
drv
[
di
]
->
rpqueue
[
ch
]))))
{
skb
=
alloc_skb
(
strlen
(
msg
)
#ifdef CONFIG_ISDN_AUDIO
+
sizeof
(
isdn_audio_skb
)
...
...
@@ -2532,8 +2489,8 @@ isdn_tty_at_cout(char *msg, modem_info * info)
}
}
if
(
skb
)
{
__skb_queue_tail
(
&
dev
->
drv
[
info
->
isdn_driver
]
->
rpqueue
[
info
->
isdn_channel
],
skb
);
dev
->
drv
[
info
->
isdn_driver
]
->
rcvcount
[
info
->
isdn_channel
]
+=
skb
->
len
;
__skb_queue_tail
(
&
dev
->
drv
[
di
]
->
rpqueue
[
ch
],
skb
);
dev
->
drv
[
di
]
->
rcvcount
[
ch
]
+=
skb
->
len
;
restore_flags
(
flags
);
/* Schedule dequeuing */
if
((
dev
->
modempoll
)
&&
(
info
->
rcvsched
))
...
...
@@ -2551,7 +2508,7 @@ isdn_tty_at_cout(char *msg, modem_info * info)
static
void
isdn_tty_on_hook
(
modem_info
*
info
)
{
if
(
info
->
isdn_
channel
>=
0
)
{
if
(
info
->
isdn_
slot
>=
0
)
{
#ifdef ISDN_DEBUG_MODEM_HUP
printk
(
KERN_DEBUG
"Mhup in isdn_tty_on_hook
\n
"
);
#endif
...
...
@@ -2711,7 +2668,7 @@ isdn_tty_modem_result(int code, modem_info * info)
/* print CID, _before_ _every_ ring */
if
(
!
(
m
->
mdmreg
[
REG_CIDONCE
]
&
BIT_CIDONCE
))
{
isdn_tty_at_cout
(
"
\r\n
CALLER NUMBER: "
,
info
);
isdn_tty_at_cout
(
dev
->
num
[
info
->
drv_index
]
,
info
);
isdn_tty_at_cout
(
isdn_slot_num
(
info
->
isdn_slot
)
,
info
);
if
(
m
->
mdmreg
[
REG_CDN
]
&
BIT_CDN
)
{
isdn_tty_at_cout
(
"
\r\n
CALLED NUMBER: "
,
info
);
isdn_tty_at_cout
(
info
->
emu
.
cpn
,
info
);
...
...
@@ -2740,7 +2697,7 @@ isdn_tty_modem_result(int code, modem_info * info)
(
m
->
mdmreg
[
REG_RINGCNT
]
==
1
))
{
isdn_tty_at_cout
(
"
\r\n
"
,
info
);
isdn_tty_at_cout
(
"CALLER NUMBER: "
,
info
);
isdn_tty_at_cout
(
dev
->
num
[
info
->
drv_index
]
,
info
);
isdn_tty_at_cout
(
isdn_slot_num
(
info
->
isdn_slot
)
,
info
);
if
(
m
->
mdmreg
[
REG_CDN
]
&
BIT_CDN
)
{
isdn_tty_at_cout
(
"
\r\n
CALLED NUMBER: "
,
info
);
isdn_tty_at_cout
(
info
->
emu
.
cpn
,
info
);
...
...
@@ -3252,7 +3209,7 @@ isdn_tty_cmd_ATA(modem_info * info)
if
(
info
->
msr
&
UART_MSR_RI
)
{
/* Accept incoming call */
info
->
last_dir
=
0
;
strcpy
(
info
->
last_num
,
dev
->
num
[
info
->
drv_index
]
);
strcpy
(
info
->
last_num
,
isdn_slot_num
(
info
->
isdn_slot
)
);
m
->
mdmreg
[
REG_RINGCNT
]
=
0
;
info
->
msr
&=
~
UART_MSR_RI
;
l2
=
m
->
mdmreg
[
REG_L2PROT
];
...
...
@@ -3266,27 +3223,20 @@ isdn_tty_cmd_ATA(modem_info * info)
l2
=
ISDN_PROTO_L2_X75I
;
}
#endif
cmd
.
driver
=
info
->
isdn_driver
;
cmd
.
command
=
ISDN_CMD_SETL2
;
cmd
.
arg
=
info
->
isdn_channel
+
(
l2
<<
8
);
cmd
.
arg
=
l2
<<
8
;
info
->
last_l2
=
l2
;
isdn_command
(
&
cmd
);
cmd
.
driver
=
info
->
isdn_driver
;
cmd
.
command
=
ISDN_CMD_SETL3
;
cmd
.
arg
=
info
->
isdn_channel
+
(
m
->
mdmreg
[
REG_L3PROT
]
<<
8
);
isdn_slot_command
(
info
->
isdn_slot
,
ISDN_CMD_SETL2
,
&
cmd
);
cmd
.
arg
=
m
->
mdmreg
[
REG_L3PROT
]
<<
8
;
#ifdef CONFIG_ISDN_TTY_FAX
if
(
l2
==
ISDN_PROTO_L2_FAX
)
{
cmd
.
parm
.
fax
=
info
->
fax
;
info
->
fax
->
direction
=
ISDN_TTY_FAX_CONN_IN
;
}
#endif
isdn_command
(
&
cmd
);
cmd
.
driver
=
info
->
isdn_driver
;
cmd
.
arg
=
info
->
isdn_channel
;
cmd
.
command
=
ISDN_CMD_ACCEPTD
;
isdn_slot_command
(
info
->
isdn_slot
,
ISDN_CMD_SETL3
,
&
cmd
);
info
->
dialing
=
16
;
info
->
emu
.
carrierwait
=
0
;
isdn_
command
(
&
cmd
);
isdn_
slot_command
(
info
->
isdn_slot
,
ISDN_CMD_ACCEPTD
,
&
cmd
);
isdn_timer_ctrl
(
ISDN_TIMER_CARRIER
,
1
);
}
else
isdn_tty_modem_result
(
RESULT_NO_ANSWER
,
info
);
...
...
@@ -3642,12 +3592,10 @@ isdn_tty_cmd_PLUSV(char **p, modem_info * info)
PARSE_ERROR1
;
m
->
vpar
[
4
]
=
par1
;
m
->
vpar
[
5
]
=
par2
;
cmd
.
driver
=
info
->
isdn_driver
;
cmd
.
command
=
ISDN_CMD_AUDIO
;
cmd
.
arg
=
info
->
isdn_channel
+
(
ISDN_AUDIO_SETDD
<<
8
);
cmd
.
arg
=
ISDN_AUDIO_SETDD
<<
8
;
cmd
.
parm
.
num
[
0
]
=
par1
;
cmd
.
parm
.
num
[
1
]
=
par2
;
isdn_
command
(
&
cmd
);
isdn_
slot_command
(
info
->
isdn_slot
,
ISDN_CMD_AUDIO
,
&
cmd
);
break
;
}
else
if
(
*
p
[
0
]
==
'?'
)
{
...
...
@@ -3973,8 +3921,8 @@ isdn_tty_modem_escape(void)
int
midx
;
for
(
i
=
0
;
i
<
ISDN_MAX_CHANNELS
;
i
++
)
if
(
USG_MODEM
(
dev
->
usage
[
i
]
))
if
((
midx
=
dev
->
m_idx
[
i
]
)
>=
0
)
{
if
(
USG_MODEM
(
isdn_slot_usage
(
i
)
))
if
((
midx
=
isdn_slot_m_idx
(
i
)
)
>=
0
)
{
modem_info
*
info
=
&
dev
->
mdm
.
info
[
midx
];
if
(
info
->
online
)
{
ton
=
1
;
...
...
drivers/isdn/i4l/isdn_tty.h
View file @
b14ebcfc
...
...
@@ -105,7 +105,7 @@ extern void isdn_tty_modem_escape(void);
extern
void
isdn_tty_modem_ring
(
void
);
extern
void
isdn_tty_carrier_timeout
(
void
);
extern
void
isdn_tty_modem_xmit
(
void
);
extern
int
isdn_tty_
modem_
init
(
void
);
extern
int
isdn_tty_init
(
void
);
extern
void
isdn_tty_readmodem
(
void
);
extern
int
isdn_tty_find_icall
(
int
,
int
,
setup_parm
*
);
extern
void
isdn_tty_cleanup_xmit
(
modem_info
*
);
...
...
@@ -119,3 +119,6 @@ extern int isdn_tty_cmd_PLUSF_FAX(char **, modem_info *);
extern
int
isdn_tty_fax_command
(
modem_info
*
,
isdn_ctrl
*
);
extern
void
isdn_tty_fax_bitorder
(
modem_info
*
,
struct
sk_buff
*
);
#endif
extern
int
isdn_tty_init
(
void
);
extern
void
isdn_tty_exit
(
void
);
drivers/isdn/i4l/isdn_ttyfax.c
View file @
b14ebcfc
...
...
@@ -74,7 +74,7 @@ isdn_tty_fax_modem_result(int code, modem_info * info)
case
2
:
/* +FCON */
/* Append CPN, if enabled */
if
((
m
->
mdmreg
[
REG_CPNFCON
]
&
BIT_CPNFCON
)
&&
(
!
(
dev
->
usage
[
info
->
isdn_channel
]
&
ISDN_USAGE_OUTGOING
)))
{
(
!
(
isdn_slot_usage
(
info
->
isdn_slot
)
&
ISDN_USAGE_OUTGOING
)))
{
sprintf
(
rs
,
"/%s"
,
m
->
cpn
);
isdn_tty_at_cout
(
rs
,
info
);
}
...
...
@@ -360,12 +360,11 @@ isdn_tty_cmd_FCLASS1(char **p, modem_info * info)
default:
PARSE_ERROR1
;
}
c
.
command
=
ISDN_CMD_FAXCMD
;
#ifdef ISDN_TTY_FAX_CMD_DEBUG
printk
(
KERN_DEBUG
"isdn_tty_cmd_FCLASS1 %d/%d/%d)
\n
"
,
c
.
parm
.
aux
.
cmd
,
c
.
parm
.
aux
.
subcmd
,
c
.
parm
.
aux
.
para
[
0
]);
#endif
if
(
info
->
isdn_
driver
<
0
)
{
if
(
info
->
isdn_
slot
<
0
)
{
save_flags
(
flags
);
cli
();
if
((
c
.
parm
.
aux
.
subcmd
==
AT_EQ_VALUE
)
||
...
...
@@ -374,32 +373,21 @@ isdn_tty_cmd_FCLASS1(char **p, modem_info * info)
PARSE_ERROR1
;
}
/* get a temporary connection to the first free fax driver */
i
=
isdn_get_free_
channel
(
ISDN_USAGE_FAX
,
ISDN_PROTO_L2_FAX
,
ISDN_PROTO_L3_FCLASS1
,
-
1
,
-
1
,
"00"
);
i
=
isdn_get_free_
slot
(
ISDN_USAGE_FAX
,
ISDN_PROTO_L2_FAX
,
ISDN_PROTO_L3_FCLASS1
,
-
1
,
-
1
,
"00"
);
if
(
i
<
0
)
{
restore_flags
(
flags
);
PARSE_ERROR1
;
}
info
->
isdn_driver
=
dev
->
drvmap
[
i
];
info
->
isdn_channel
=
dev
->
chanmap
[
i
];
info
->
drv_index
=
i
;
dev
->
m_idx
[
i
]
=
info
->
line
;
c
.
driver
=
info
->
isdn_driver
;
c
.
arg
=
info
->
isdn_channel
;
isdn_command
(
&
c
);
isdn_free_channel
(
info
->
isdn_driver
,
info
->
isdn_channel
,
ISDN_USAGE_FAX
);
info
->
isdn_driver
=
-
1
;
info
->
isdn_channel
=
-
1
;
if
(
info
->
drv_index
>=
0
)
{
dev
->
m_idx
[
info
->
drv_index
]
=
-
1
;
info
->
drv_index
=
-
1
;
}
info
->
isdn_slot
=
i
;
isdn_slot_set_m_idx
(
i
,
info
->
line
);
isdn_slot_command
(
info
->
isdn_slot
,
ISDN_CMD_FAXCMD
,
&
c
);
isdn_slot_free
(
info
->
isdn_slot
,
ISDN_USAGE_FAX
);
isdn_slot_set_m_idx
(
i
,
-
1
);
info
->
isdn_slot
=
-
1
;
restore_flags
(
flags
);
}
else
{
c
.
driver
=
info
->
isdn_driver
;
c
.
arg
=
info
->
isdn_channel
;
isdn_command
(
&
c
);
isdn_slot_command
(
info
->
isdn_slot
,
ISDN_CMD_FAXCMD
,
&
c
);
}
return
1
;
}
...
...
@@ -800,10 +788,7 @@ isdn_tty_cmd_FCLASS2(char **p, modem_info * info)
printk
(
KERN_DEBUG
"isdn_tty: Fax FDR
\n
"
);
#endif
f
->
code
=
ISDN_TTY_FAX_DR
;
cmd
.
driver
=
info
->
isdn_driver
;
cmd
.
arg
=
info
->
isdn_channel
;
cmd
.
command
=
ISDN_CMD_FAXCMD
;
isdn_command
(
&
cmd
);
isdn_slot_command
(
info
->
isdn_slot
,
ISDN_CMD_FAXCMD
,
&
cmd
);
if
(
f
->
phase
==
ISDN_FAX_PHASE_B
)
{
f
->
phase
=
ISDN_FAX_PHASE_C
;
}
else
if
(
f
->
phase
==
ISDN_FAX_PHASE_D
)
{
...
...
@@ -855,10 +840,7 @@ isdn_tty_cmd_FCLASS2(char **p, modem_info * info)
#endif
if
((
f
->
phase
==
ISDN_FAX_PHASE_B
)
||
(
f
->
phase
==
ISDN_FAX_PHASE_D
))
{
f
->
code
=
ISDN_TTY_FAX_DT
;
cmd
.
driver
=
info
->
isdn_driver
;
cmd
.
arg
=
info
->
isdn_channel
;
cmd
.
command
=
ISDN_CMD_FAXCMD
;
isdn_command
(
&
cmd
);
isdn_slot_command
(
info
->
isdn_slot
,
ISDN_CMD_FAXCMD
,
&
cmd
);
if
(
f
->
phase
==
ISDN_FAX_PHASE_D
)
{
f
->
phase
=
ISDN_FAX_PHASE_C
;
isdn_tty_fax_modem_result
(
7
,
info
);
/* CONNECT */
...
...
@@ -913,10 +895,7 @@ isdn_tty_cmd_FCLASS2(char **p, modem_info * info)
PARSE_ERROR1
;
f
->
fet
=
par
;
f
->
code
=
ISDN_TTY_FAX_ET
;
cmd
.
driver
=
info
->
isdn_driver
;
cmd
.
arg
=
info
->
isdn_channel
;
cmd
.
command
=
ISDN_CMD_FAXCMD
;
isdn_command
(
&
cmd
);
isdn_slot_command
(
info
->
isdn_slot
,
ISDN_CMD_FAXCMD
,
&
cmd
);
#ifdef ISDN_TTY_FAX_STAT_DEBUG
printk
(
KERN_DEBUG
"isdn_tty: Fax FET=%d
\n
"
,
par
);
#endif
...
...
drivers/isdn/i4l/isdn_v110.c
View file @
b14ebcfc
...
...
@@ -515,14 +515,12 @@ isdn_v110_encode(isdn_v110_stream * v, struct sk_buff *skb)
}
int
isdn_v110_stat_callback
(
int
idx
,
isdn_ctrl
*
c
)
isdn_v110_stat_callback
(
struct
isdn_v110
*
iv110
,
isdn_ctrl
*
c
)
{
isdn_v110_stream
*
v
=
NULL
;
int
i
;
int
ret
;
if
(
idx
<
0
)
return
0
;
switch
(
c
->
command
)
{
case
ISDN_STAT_BSENT
:
/* Keep the send-queue of the driver filled
...
...
@@ -531,9 +529,9 @@ isdn_v110_stat_callback(int idx, isdn_ctrl * c)
* send down an Idle-Frame (or an Sync-Frame, if
* v->SyncInit != 0).
*/
if
(
!
(
v
=
dev
->
v110
[
idx
]
))
if
(
!
(
v
=
iv110
->
v110
))
return
0
;
atomic_inc
(
&
dev
->
v110use
[
idx
]
);
atomic_inc
(
&
iv110
->
v110use
);
if
(
v
->
skbidle
>
0
)
{
v
->
skbidle
--
;
ret
=
1
;
...
...
@@ -560,38 +558,38 @@ isdn_v110_stat_callback(int idx, isdn_ctrl * c)
}
else
break
;
}
atomic_dec
(
&
dev
->
v110use
[
idx
]
);
atomic_dec
(
&
iv110
->
v110use
);
return
ret
;
case
ISDN_STAT_DHUP
:
case
ISDN_STAT_BHUP
:
while
(
1
)
{
atomic_inc
(
&
dev
->
v110use
[
idx
]
);
if
(
atomic_dec_and_test
(
&
dev
->
v110use
[
idx
]
))
{
isdn_v110_close
(
dev
->
v110
[
idx
]
);
dev
->
v110
[
idx
]
=
NULL
;
atomic_inc
(
&
iv110
->
v110use
);
if
(
atomic_dec_and_test
(
&
iv110
->
v110use
))
{
isdn_v110_close
(
iv110
->
v110
);
iv110
->
v110
=
NULL
;
break
;
}
sti
();
}
break
;
case
ISDN_STAT_BCONN
:
if
(
dev
->
v110emu
[
idx
]
&&
(
dev
->
v110
[
idx
]
==
NULL
))
{
if
(
iv110
->
v110emu
&&
(
iv110
->
v110
==
NULL
))
{
int
hdrlen
=
dev
->
drv
[
c
->
driver
]
->
interface
->
hl_hdrlen
;
int
maxsize
=
dev
->
drv
[
c
->
driver
]
->
interface
->
maxbufsize
;
atomic_inc
(
&
dev
->
v110use
[
idx
]
);
switch
(
dev
->
v110emu
[
idx
]
)
{
atomic_inc
(
&
iv110
->
v110use
);
switch
(
iv110
->
v110emu
)
{
case
ISDN_PROTO_L2_V11096
:
dev
->
v110
[
idx
]
=
isdn_v110_open
(
V110_9600
,
hdrlen
,
maxsize
);
iv110
->
v110
=
isdn_v110_open
(
V110_9600
,
hdrlen
,
maxsize
);
break
;
case
ISDN_PROTO_L2_V11019
:
dev
->
v110
[
idx
]
=
isdn_v110_open
(
V110_19200
,
hdrlen
,
maxsize
);
iv110
->
v110
=
isdn_v110_open
(
V110_19200
,
hdrlen
,
maxsize
);
break
;
case
ISDN_PROTO_L2_V11038
:
dev
->
v110
[
idx
]
=
isdn_v110_open
(
V110_38400
,
hdrlen
,
maxsize
);
iv110
->
v110
=
isdn_v110_open
(
V110_38400
,
hdrlen
,
maxsize
);
break
;
default:
;
}
if
((
v
=
dev
->
v110
[
idx
]
))
{
if
((
v
=
iv110
->
v110
))
{
while
(
v
->
SyncInit
)
{
struct
sk_buff
*
skb
=
isdn_v110_sync
(
v
);
if
(
dev
->
drv
[
c
->
driver
]
->
interface
->
writebuf_skb
(
c
->
driver
,
c
->
arg
,
1
,
skb
)
<=
0
)
{
...
...
@@ -603,8 +601,8 @@ isdn_v110_stat_callback(int idx, isdn_ctrl * c)
v
->
skbidle
++
;
}
}
else
printk
(
KERN_WARNING
"isdn_v110: Couldn't open stream
for chan %d
\n
"
,
idx
);
atomic_dec
(
&
dev
->
v110use
[
idx
]
);
printk
(
KERN_WARNING
"isdn_v110: Couldn't open stream
\n
"
);
atomic_dec
(
&
iv110
->
v110use
);
}
break
;
default:
...
...
drivers/isdn/i4l/isdn_v110.h
View file @
b14ebcfc
...
...
@@ -9,8 +9,14 @@
*
*/
#ifndef _isdn_v110_h_
#define _isdn_v110_h_
#ifndef ISDN_V110_H
#define ISDN_V110_H
struct
isdn_v110
{
int
v110emu
;
/* V.110 emulator-mode 0=none */
atomic_t
v110use
;
/* Usage-Semaphore for stream */
isdn_v110_stream
*
v110
;
/* V.110 private data */
};
/*
* isdn_v110_encode will take raw data and encode it using V.110
...
...
@@ -23,7 +29,7 @@ extern struct sk_buff *isdn_v110_encode(isdn_v110_stream *, struct sk_buff *);
*/
extern
struct
sk_buff
*
isdn_v110_decode
(
isdn_v110_stream
*
,
struct
sk_buff
*
);
extern
int
isdn_v110_stat_callback
(
int
,
isdn_ctrl
*
);
extern
int
isdn_v110_stat_callback
(
struct
isdn_v110
*
v110
,
isdn_ctrl
*
);
extern
void
isdn_v110_close
(
isdn_v110_stream
*
v
);
#endif
drivers/isdn/isdnloop/isdnloop.c
View file @
b14ebcfc
...
...
@@ -757,6 +757,10 @@ isdnloop_vstphone(isdnloop_card * card, char *phone, int caller)
int
i
;
static
char
nphone
[
30
];
if
(
!
card
)
{
printk
(
"BUG!!!
\n
"
);
return
""
;
}
switch
(
card
->
ptype
)
{
case
ISDN_PTYPE_EURO
:
if
(
caller
)
{
...
...
@@ -775,7 +779,7 @@ isdnloop_vstphone(isdnloop_card * card, char *phone, int caller)
return
(
&
phone
[
strlen
(
phone
)
-
1
]);
break
;
}
return
(
"
\0
"
)
;
return
""
;
}
/*
...
...
@@ -882,7 +886,7 @@ isdnloop_parse_cmd(isdnloop_card * card)
isdnloop_vstphone
(
card
,
cmd
.
parm
.
setup
.
eazmsn
,
1
),
cmd
.
parm
.
setup
.
si1
,
cmd
.
parm
.
setup
.
si2
,
isdnloop_vstphone
(
card
->
rcard
[
ch
],
isdnloop_vstphone
(
card
->
rcard
[
ch
-
1
],
cmd
.
parm
.
setup
.
phone
,
0
));
isdnloop_fake
(
card
->
rcard
[
ch
-
1
],
buf
,
card
->
rch
[
ch
-
1
]
+
1
);
/* Fall through */
...
...
fs/ntfs/ChangeLog
View file @
b14ebcfc
...
...
@@ -2,6 +2,36 @@ ToDo:
- Find and fix bugs.
- Enable NFS exporting of NTFS.
2.0.24 - Cleanups.
- Treat BUG_ON() as ASSERT() not VERIFY(), i.e. do not use side effects
inside BUG_ON(). (Adam J. Richter)
- Split logical OR expressions inside BUG_ON() into individual BUG_ON()
calls for improved debugging. (Adam J. Richter)
- Add errors flag to the ntfs volume state, accessed via
NVol{,Set,Clear}Errors(vol).
- Do not allow read-write remounts of read-only volumes with errors.
- Clarify comment for ntfs file operation sendfile which was added by
Christoph Hellwig a while ago (just using generic_file_sendfile())
to say that ntfs ->sendfile is only used for the case where the
source data is on the ntfs partition and the destination is
somewhere else, i.e. nothing we need to concern ourselves with.
- Add generic_file_write() as our ntfs file write operation.
2.0.23 - Major bug fixes (races, deadlocks, non-i386 architectures).
- Massive internal locking changes to mft record locking. Fixes lock
recursion and replaces the mrec_lock read/write semaphore with a
mutex. Also removes the now superfluous mft_count. This fixes several
race conditions and deadlocks, especially in the future write code.
- Fix ntfs over loopback for compressed files by adding an
optimization barrier. (gcc was screwing up otherwise ?)
- Miscellaneous cleanups all over the code and a fix or two in error
handling code paths.
Thanks go to Christoph Hellwig for pointing out the following two:
- Remove now unused function fs/ntfs/malloc.h::vmalloc_nofs().
- Fix ntfs_free() for ia64 and parisc by checking for VMALLOC_END, too.
2.0.22 - Cleanups, mainly to ntfs_readdir(), and use C99 initializers.
- Change fs/ntfs/dir.c::ntfs_reddir() to only read/write ->f_pos once
...
...
fs/ntfs/Makefile
View file @
b14ebcfc
...
...
@@ -5,7 +5,7 @@ obj-$(CONFIG_NTFS_FS) += ntfs.o
ntfs-objs
:=
aops.o attrib.o compress.o debug.o dir.o file.o inode.o mft.o
\
mst.o namei.o super.o sysctl.o time.o unistr.o upcase.o
EXTRA_CFLAGS
=
-DNTFS_VERSION
=
\"
2.0.2
2
\"
EXTRA_CFLAGS
=
-DNTFS_VERSION
=
\"
2.0.2
4
\"
ifeq
($(CONFIG_NTFS_DEBUG),y)
EXTRA_CFLAGS
+=
-DDEBUG
...
...
fs/ntfs/aops.c
View file @
b14ebcfc
...
...
@@ -106,8 +106,6 @@ static void ntfs_end_buffer_async_read(struct buffer_head *bh, int uptodate)
if
(
!
NInoMstProtected
(
ni
))
{
if
(
likely
(
page_uptodate
&&
!
PageError
(
page
)))
SetPageUptodate
(
page
);
unlock_page
(
page
);
return
;
}
else
{
char
*
addr
;
unsigned
int
i
,
recs
,
nr_err
;
...
...
@@ -332,6 +330,8 @@ static int ntfs_read_block(struct page *page)
* for it to be read in before we can do the copy.
*
* Return 0 on success and -errno on error.
*
* WARNING: Do not make this function static! It is used by mft.c!
*/
int
ntfs_readpage
(
struct
file
*
file
,
struct
page
*
page
)
{
...
...
@@ -372,8 +372,8 @@ int ntfs_readpage(struct file *file, struct page *page)
else
base_ni
=
ni
->
_INE
(
base_ntfs_ino
);
/* Map, pin and lock the mft record
for reading
. */
mrec
=
map_mft_record
(
READ
,
base_ni
);
/* Map, pin and lock the mft record. */
mrec
=
map_mft_record
(
base_ni
);
if
(
unlikely
(
IS_ERR
(
mrec
)))
{
err
=
PTR_ERR
(
mrec
);
goto
err_out
;
...
...
@@ -416,7 +416,7 @@ int ntfs_readpage(struct file *file, struct page *page)
put_unm_err_out:
put_attr_search_ctx
(
ctx
);
unm_err_out:
unmap_mft_record
(
READ
,
base_ni
);
unmap_mft_record
(
base_ni
);
err_out:
unlock_page
(
page
);
return
err
;
...
...
fs/ntfs/attrib.c
View file @
b14ebcfc
...
...
@@ -110,7 +110,8 @@ static inline run_list_element *ntfs_rl_realloc(run_list_element *rl,
static
inline
BOOL
ntfs_are_rl_mergeable
(
run_list_element
*
dst
,
run_list_element
*
src
)
{
BUG_ON
(
!
dst
||
!
src
);
BUG_ON
(
!
dst
);
BUG_ON
(
!
src
);
if
((
dst
->
lcn
<
0
)
||
(
src
->
lcn
<
0
))
/* Are we merging holes? */
return
FALSE
;
...
...
@@ -192,7 +193,8 @@ static inline run_list_element *ntfs_rl_append(run_list_element *dst,
BOOL
right
;
int
magic
;
BUG_ON
(
!
dst
||
!
src
);
BUG_ON
(
!
dst
);
BUG_ON
(
!
src
);
/* First, check if the right hand end needs merging. */
right
=
ntfs_are_rl_mergeable
(
src
+
ssize
-
1
,
dst
+
loc
+
1
);
...
...
@@ -258,7 +260,8 @@ static inline run_list_element *ntfs_rl_insert(run_list_element *dst,
BOOL
hole
=
FALSE
;
/* Following a hole */
int
magic
;
BUG_ON
(
!
dst
||
!
src
);
BUG_ON
(
!
dst
);
BUG_ON
(
!
src
);
/* disc => Discontinuity between the end of @dst and the start of @src.
* This means we might need to insert a hole.
...
...
@@ -362,7 +365,8 @@ static inline run_list_element *ntfs_rl_replace(run_list_element *dst,
BOOL
right
;
int
magic
;
BUG_ON
(
!
dst
||
!
src
);
BUG_ON
(
!
dst
);
BUG_ON
(
!
src
);
/* First, merge the left and right ends, if necessary. */
right
=
ntfs_are_rl_mergeable
(
src
+
ssize
-
1
,
dst
+
loc
+
1
);
...
...
@@ -423,7 +427,8 @@ static inline run_list_element *ntfs_rl_replace(run_list_element *dst,
static
inline
run_list_element
*
ntfs_rl_split
(
run_list_element
*
dst
,
int
dsize
,
run_list_element
*
src
,
int
ssize
,
int
loc
)
{
BUG_ON
(
!
dst
||
!
src
);
BUG_ON
(
!
dst
);
BUG_ON
(
!
src
);
/* Space required: @dst size + @src size + one new hole. */
dst
=
ntfs_rl_realloc
(
dst
,
dsize
,
dsize
+
ssize
+
1
);
...
...
@@ -948,7 +953,7 @@ int map_run_list(ntfs_inode *ni, VCN vcn)
else
base_ni
=
ni
->
_INE
(
base_ntfs_ino
);
mrec
=
map_mft_record
(
READ
,
base_ni
);
mrec
=
map_mft_record
(
base_ni
);
if
(
IS_ERR
(
mrec
))
return
PTR_ERR
(
mrec
);
ctx
=
get_attr_search_ctx
(
base_ni
,
mrec
);
...
...
@@ -979,7 +984,7 @@ int map_run_list(ntfs_inode *ni, VCN vcn)
put_attr_search_ctx
(
ctx
);
err_out:
unmap_mft_record
(
READ
,
base_ni
);
unmap_mft_record
(
base_ni
);
return
err
;
}
...
...
@@ -1671,7 +1676,7 @@ void reinit_attr_search_ctx(attr_search_context *ctx)
return
;
}
/* Attribute list. */
if
(
ctx
->
ntfs_ino
!=
ctx
->
base_ntfs_ino
)
unmap_mft_record
(
READ
,
ctx
->
ntfs_ino
);
unmap_mft_record
(
ctx
->
ntfs_ino
);
init_attr_search_ctx
(
ctx
,
ctx
->
base_ntfs_ino
,
ctx
->
base_mrec
);
return
;
}
...
...
@@ -1704,7 +1709,7 @@ attr_search_context *get_attr_search_ctx(ntfs_inode *ni, MFT_RECORD *mrec)
void
put_attr_search_ctx
(
attr_search_context
*
ctx
)
{
if
(
ctx
->
base_ntfs_ino
&&
ctx
->
ntfs_ino
!=
ctx
->
base_ntfs_ino
)
unmap_mft_record
(
READ
,
ctx
->
ntfs_ino
);
unmap_mft_record
(
ctx
->
ntfs_ino
);
kmem_cache_free
(
ntfs_attr_ctx_cache
,
ctx
);
return
;
}
...
...
fs/ntfs/compress.c
View file @
b14ebcfc
...
...
@@ -467,7 +467,8 @@ int ntfs_read_compressed_block(struct page *page)
* Bad things happen if we get here for anything that is not an
* unnamed $DATA attribute.
*/
BUG_ON
(
ni
->
type
!=
AT_DATA
||
ni
->
name_len
);
BUG_ON
(
ni
->
type
!=
AT_DATA
);
BUG_ON
(
ni
->
name_len
);
pages
=
kmalloc
(
nr_pages
*
sizeof
(
struct
page
*
),
GFP_NOFS
);
...
...
@@ -608,8 +609,27 @@ int ntfs_read_compressed_block(struct page *page)
if
(
buffer_uptodate
(
tbh
))
continue
;
wait_on_buffer
(
tbh
);
if
(
unlikely
(
!
buffer_uptodate
(
tbh
)))
goto
read_err
;
/*
* We need an optimization barrier here, otherwise we start
* hitting the below fixup code when accessing a loopback
* mounted ntfs partition. This indicates either there is a
* race condition in the loop driver or, more likely, gcc
* overoptimises the code without the barrier and it doesn't
* do the Right Thing(TM).
*/
barrier
();
if
(
unlikely
(
!
buffer_uptodate
(
tbh
)))
{
ntfs_warning
(
vol
->
sb
,
"Buffer is unlocked but not "
"uptodate! Unplugging the disk queue "
"and rescheduling."
);
get_bh
(
tbh
);
blk_run_queues
();
schedule
();
put_bh
(
tbh
);
if
(
unlikely
(
!
buffer_uptodate
(
tbh
)))
goto
read_err
;
ntfs_warning
(
vol
->
sb
,
"Buffer is now uptodate. Good."
);
}
}
/*
...
...
fs/ntfs/dir.c
View file @
b14ebcfc
...
...
@@ -76,7 +76,7 @@ MFT_REF ntfs_lookup_inode_by_name(ntfs_inode *dir_ni, const uchar_t *uname,
u8
*
index_end
;
u64
mref
;
attr_search_context
*
ctx
;
int
err
=
0
,
rc
;
int
err
,
rc
;
VCN
vcn
,
old_vcn
;
struct
address_space
*
ia_mapping
;
struct
page
*
page
;
...
...
@@ -84,23 +84,24 @@ MFT_REF ntfs_lookup_inode_by_name(ntfs_inode *dir_ni, const uchar_t *uname,
ntfs_name
*
name
=
NULL
;
/* Get hold of the mft record for the directory. */
m
=
map_mft_record
(
READ
,
dir_ni
);
if
(
IS_ERR
(
m
))
goto
map_err_out
;
m
=
map_mft_record
(
dir_ni
);
if
(
unlikely
(
IS_ERR
(
m
)))
{
ntfs_error
(
sb
,
"map_mft_record() failed with error code %ld."
,
-
PTR_ERR
(
m
));
return
ERR_MREF
(
PTR_ERR
(
m
));
}
ctx
=
get_attr_search_ctx
(
dir_ni
,
m
);
if
(
!
ctx
)
{
if
(
unlikely
(
!
ctx
)
)
{
err
=
-
ENOMEM
;
goto
unm_
err_out
;
goto
err_out
;
}
/* Find the index root attribute in the mft record. */
if
(
!
lookup_attr
(
AT_INDEX_ROOT
,
I30
,
4
,
CASE_SENSITIVE
,
0
,
NULL
,
0
,
ctx
))
{
ntfs_error
(
sb
,
"Index root attribute missing in directory "
"inode 0x%lx."
,
dir_ni
->
mft_no
);
err
=
-
EIO
;
goto
put_unm_
err_out
;
goto
err_out
;
}
/* Get to the index root value (it's been verified in read_inode). */
ir
=
(
INDEX_ROOT
*
)((
u8
*
)
ctx
->
attr
+
...
...
@@ -154,7 +155,7 @@ MFT_REF ntfs_lookup_inode_by_name(ntfs_inode *dir_ni, const uchar_t *uname,
GFP_NOFS
);
if
(
!
name
)
{
err
=
-
ENOMEM
;
goto
put_unm_
err_out
;
goto
err_out
;
}
}
name
->
mref
=
le64_to_cpu
(
...
...
@@ -169,7 +170,7 @@ MFT_REF ntfs_lookup_inode_by_name(ntfs_inode *dir_ni, const uchar_t *uname,
}
mref
=
le64_to_cpu
(
ie
->
_IIF
(
indexed_file
));
put_attr_search_ctx
(
ctx
);
unmap_mft_record
(
READ
,
dir_ni
);
unmap_mft_record
(
dir_ni
);
return
mref
;
}
/*
...
...
@@ -208,7 +209,7 @@ MFT_REF ntfs_lookup_inode_by_name(ntfs_inode *dir_ni, const uchar_t *uname,
name
=
kmalloc
(
name_size
,
GFP_NOFS
);
if
(
!
name
)
{
err
=
-
ENOMEM
;
goto
put_unm_
err_out
;
goto
err_out
;
}
name
->
mref
=
le64_to_cpu
(
ie
->
_IIF
(
indexed_file
));
name
->
type
=
type
;
...
...
@@ -267,12 +268,12 @@ MFT_REF ntfs_lookup_inode_by_name(ntfs_inode *dir_ni, const uchar_t *uname,
if
(
!
(
ie
->
_IEH
(
flags
)
&
INDEX_ENTRY_NODE
))
{
if
(
name
)
{
put_attr_search_ctx
(
ctx
);
unmap_mft_record
(
READ
,
dir_ni
);
unmap_mft_record
(
dir_ni
);
return
name
->
mref
;
}
ntfs_debug
(
"Entry not found."
);
err
=
-
ENOENT
;
goto
put_unm_
err_out
;
goto
err_out
;
}
/* Child node present, descend into it. */
/* Consistency check: Verify that an index allocation exists. */
if
(
!
NInoIndexAllocPresent
(
dir_ni
))
{
...
...
@@ -280,11 +281,19 @@ MFT_REF ntfs_lookup_inode_by_name(ntfs_inode *dir_ni, const uchar_t *uname,
"requires one. Directory inode 0x%lx is "
"corrupt or driver bug."
,
dir_ni
->
mft_no
);
err
=
-
EIO
;
goto
put_unm_
err_out
;
goto
err_out
;
}
/* Get the starting vcn of the index_block holding the child node. */
vcn
=
sle64_to_cpup
((
u8
*
)
ie
+
le16_to_cpu
(
ie
->
_IEH
(
length
))
-
8
);
ia_mapping
=
VFS_I
(
dir_ni
)
->
i_mapping
;
/*
* We are done with the index root and the mft record. Release them,
* otherwise we deadlock with ntfs_map_page().
*/
put_attr_search_ctx
(
ctx
);
unmap_mft_record
(
dir_ni
);
m
=
NULL
;
ctx
=
NULL
;
descend_into_child_node:
/*
* Convert vcn to index into the index allocation attribute in units
...
...
@@ -296,7 +305,8 @@ MFT_REF ntfs_lookup_inode_by_name(ntfs_inode *dir_ni, const uchar_t *uname,
if
(
IS_ERR
(
page
))
{
ntfs_error
(
sb
,
"Failed to map directory index page, error %ld."
,
-
PTR_ERR
(
page
));
goto
put_unm_err_out
;
err
=
PTR_ERR
(
page
);
goto
err_out
;
}
kaddr
=
(
u8
*
)
page_address
(
page
);
fast_descend_into_child_node:
...
...
@@ -308,7 +318,7 @@ MFT_REF ntfs_lookup_inode_by_name(ntfs_inode *dir_ni, const uchar_t *uname,
ntfs_error
(
sb
,
"Out of bounds check failed. Corrupt directory "
"inode 0x%lx or driver bug."
,
dir_ni
->
mft_no
);
err
=
-
EIO
;
goto
unm_
unm_
err_out
;
goto
unm_err_out
;
}
if
(
sle64_to_cpu
(
ia
->
index_block_vcn
)
!=
vcn
)
{
ntfs_error
(
sb
,
"Actual VCN (0x%Lx) of index buffer is "
...
...
@@ -318,7 +328,7 @@ MFT_REF ntfs_lookup_inode_by_name(ntfs_inode *dir_ni, const uchar_t *uname,
(
long
long
)
sle64_to_cpu
(
ia
->
index_block_vcn
),
(
long
long
)
vcn
,
dir_ni
->
mft_no
);
err
=
-
EIO
;
goto
unm_
unm_
err_out
;
goto
unm_err_out
;
}
if
(
le32_to_cpu
(
ia
->
index
.
allocated_size
)
+
0x18
!=
dir_ni
->
_IDM
(
index_block_size
))
{
...
...
@@ -330,7 +340,7 @@ MFT_REF ntfs_lookup_inode_by_name(ntfs_inode *dir_ni, const uchar_t *uname,
le32_to_cpu
(
ia
->
index
.
allocated_size
)
+
0x18
,
dir_ni
->
_IDM
(
index_block_size
));
err
=
-
EIO
;
goto
unm_
unm_
err_out
;
goto
unm_err_out
;
}
index_end
=
(
u8
*
)
ia
+
dir_ni
->
_IDM
(
index_block_size
);
if
(
index_end
>
kaddr
+
PAGE_CACHE_SIZE
)
{
...
...
@@ -339,7 +349,7 @@ MFT_REF ntfs_lookup_inode_by_name(ntfs_inode *dir_ni, const uchar_t *uname,
"Cannot access! This is probably a bug in the "
"driver."
,
(
long
long
)
vcn
,
dir_ni
->
mft_no
);
err
=
-
EIO
;
goto
unm_
unm_
err_out
;
goto
unm_err_out
;
}
index_end
=
(
u8
*
)
&
ia
->
index
+
le32_to_cpu
(
ia
->
index
.
index_length
);
if
(
index_end
>
(
u8
*
)
ia
+
dir_ni
->
_IDM
(
index_block_size
))
{
...
...
@@ -347,7 +357,7 @@ MFT_REF ntfs_lookup_inode_by_name(ntfs_inode *dir_ni, const uchar_t *uname,
"inode 0x%lx exceeds maximum size."
,
(
long
long
)
vcn
,
dir_ni
->
mft_no
);
err
=
-
EIO
;
goto
unm_
unm_
err_out
;
goto
unm_err_out
;
}
/* The first index entry. */
ie
=
(
INDEX_ENTRY
*
)((
u8
*
)
&
ia
->
index
+
...
...
@@ -367,7 +377,7 @@ MFT_REF ntfs_lookup_inode_by_name(ntfs_inode *dir_ni, const uchar_t *uname,
"directory inode 0x%lx."
,
dir_ni
->
mft_no
);
err
=
-
EIO
;
goto
unm_
unm_
err_out
;
goto
unm_err_out
;
}
/*
* The last entry cannot contain a name. It can however contain
...
...
@@ -403,7 +413,7 @@ MFT_REF ntfs_lookup_inode_by_name(ntfs_inode *dir_ni, const uchar_t *uname,
GFP_NOFS
);
if
(
!
name
)
{
err
=
-
ENOMEM
;
goto
unm_
unm_
err_out
;
goto
unm_err_out
;
}
}
name
->
mref
=
le64_to_cpu
(
...
...
@@ -418,8 +428,6 @@ MFT_REF ntfs_lookup_inode_by_name(ntfs_inode *dir_ni, const uchar_t *uname,
}
mref
=
le64_to_cpu
(
ie
->
_IIF
(
indexed_file
));
ntfs_unmap_page
(
page
);
put_attr_search_ctx
(
ctx
);
unmap_mft_record
(
READ
,
dir_ni
);
return
mref
;
}
/*
...
...
@@ -459,7 +467,7 @@ MFT_REF ntfs_lookup_inode_by_name(ntfs_inode *dir_ni, const uchar_t *uname,
name
=
kmalloc
(
name_size
,
GFP_NOFS
);
if
(
!
name
)
{
err
=
-
ENOMEM
;
goto
put_
unm_err_out
;
goto
unm_err_out
;
}
name
->
mref
=
le64_to_cpu
(
ie
->
_IIF
(
indexed_file
));
name
->
type
=
type
;
...
...
@@ -519,7 +527,7 @@ MFT_REF ntfs_lookup_inode_by_name(ntfs_inode *dir_ni, const uchar_t *uname,
"a leaf node in directory inode 0x%lx."
,
dir_ni
->
mft_no
);
err
=
-
EIO
;
goto
unm_
unm_
err_out
;
goto
unm_err_out
;
}
/* Child node present, descend into it. */
old_vcn
=
vcn
;
...
...
@@ -539,7 +547,7 @@ MFT_REF ntfs_lookup_inode_by_name(ntfs_inode *dir_ni, const uchar_t *uname,
ntfs_error
(
sb
,
"Negative child node vcn in directory inode "
"0x%lx."
,
dir_ni
->
mft_no
);
err
=
-
EIO
;
goto
unm_
unm_
err_out
;
goto
unm_err_out
;
}
/*
* No child node present, return -ENOENT, unless we have got a matching
...
...
@@ -548,31 +556,26 @@ MFT_REF ntfs_lookup_inode_by_name(ntfs_inode *dir_ni, const uchar_t *uname,
*/
if
(
name
)
{
ntfs_unmap_page
(
page
);
put_attr_search_ctx
(
ctx
);
unmap_mft_record
(
READ
,
dir_ni
);
return
name
->
mref
;
}
ntfs_debug
(
"Entry not found."
);
err
=
-
ENOENT
;
unm_unm_err_out:
ntfs_unmap_page
(
page
);
put_unm_err_out:
put_attr_search_ctx
(
ctx
);
unm_err_out:
unmap_mft_record
(
READ
,
dir_ni
);
ntfs_unmap_page
(
page
);
err_out:
if
(
ctx
)
put_attr_search_ctx
(
ctx
);
if
(
m
)
unmap_mft_record
(
dir_ni
);
if
(
name
)
{
kfree
(
name
);
*
res
=
NULL
;
}
return
ERR_MREF
(
err
);
map_err_out:
ntfs_error
(
sb
,
"map_mft_record(READ) failed with error code %ld."
,
-
PTR_ERR
(
m
));
return
ERR_MREF
(
PTR_ERR
(
m
));
dir_err_out:
ntfs_error
(
sb
,
"Corrupt directory. Aborting lookup."
);
err
=
-
EIO
;
goto
put_unm_
err_out
;
goto
err_out
;
}
#if 0
...
...
@@ -614,7 +617,7 @@ u64 ntfs_lookup_inode_by_name(ntfs_inode *dir_ni, const uchar_t *uname,
u8 *index_end;
u64 mref;
attr_search_context *ctx;
int err
= 0
, rc;
int err, rc;
IGNORE_CASE_BOOL ic;
VCN vcn, old_vcn;
struct address_space *ia_mapping;
...
...
@@ -622,23 +625,24 @@ u64 ntfs_lookup_inode_by_name(ntfs_inode *dir_ni, const uchar_t *uname,
u8 *kaddr;
/* Get hold of the mft record for the directory. */
m = map_mft_record(READ, dir_ni);
if (IS_ERR(m))
goto map_err_out;
m = map_mft_record(dir_ni);
if (IS_ERR(m)) {
ntfs_error(sb, "map_mft_record() failed with error code %ld.",
-PTR_ERR(m));
return ERR_MREF(PTR_ERR(m));
}
ctx = get_attr_search_ctx(dir_ni, m);
if (!ctx) {
err = -ENOMEM;
goto
unm_
err_out;
goto err_out;
}
/* Find the index root attribute in the mft record. */
if (!lookup_attr(AT_INDEX_ROOT, I30, 4, CASE_SENSITIVE, 0, NULL, 0,
ctx)) {
ntfs_error(sb, "Index root attribute missing in directory "
"inode 0x%lx.", dir_ni->mft_no);
err = -EIO;
goto
put_unm_
err_out;
goto err_out;
}
/* Get to the index root value (it's been verified in read_inode). */
ir = (INDEX_ROOT*)((u8*)ctx->attr +
...
...
@@ -689,7 +693,7 @@ u64 ntfs_lookup_inode_by_name(ntfs_inode *dir_ni, const uchar_t *uname,
found_it:
mref = le64_to_cpu(ie->_IIF(indexed_file));
put_attr_search_ctx(ctx);
unmap_mft_record(
READ,
dir_ni);
unmap_mft_record(dir_ni);
return mref;
}
/*
...
...
@@ -737,7 +741,7 @@ u64 ntfs_lookup_inode_by_name(ntfs_inode *dir_ni, const uchar_t *uname,
if (!(ie->_IEH(flags) & INDEX_ENTRY_NODE)) {
/* No child node, return -ENOENT. */
err = -ENOENT;
goto
put_unm_
err_out;
goto err_out;
} /* Child node present, descend into it. */
/* Consistency check: Verify that an index allocation exists. */
if (!NInoIndexAllocPresent(dir_ni)) {
...
...
@@ -745,11 +749,19 @@ u64 ntfs_lookup_inode_by_name(ntfs_inode *dir_ni, const uchar_t *uname,
"requires one. Directory inode 0x%lx is "
"corrupt or driver bug.", dir_ni->mft_no);
err = -EIO;
goto
put_unm_
err_out;
goto err_out;
}
/* Get the starting vcn of the index_block holding the child node. */
vcn = sle64_to_cpup((u8*)ie + le16_to_cpu(ie->_IEH(length)) - 8);
ia_mapping = VFS_I(dir_ni)->i_mapping;
/*
* We are done with the index root and the mft record. Release them,
* otherwise we deadlock with ntfs_map_page().
*/
put_attr_search_ctx(ctx);
unmap_mft_record(dir_ni);
m = NULL;
ctx = NULL;
descend_into_child_node:
/*
* Convert vcn to index into the index allocation attribute in units
...
...
@@ -761,7 +773,8 @@ u64 ntfs_lookup_inode_by_name(ntfs_inode *dir_ni, const uchar_t *uname,
if (IS_ERR(page)) {
ntfs_error(sb, "Failed to map directory index page, error %ld.",
-PTR_ERR(page));
goto put_unm_err_out;
err = PTR_ERR(page);
goto err_out;
}
kaddr = (u8*)page_address(page);
fast_descend_into_child_node:
...
...
@@ -773,7 +786,7 @@ u64 ntfs_lookup_inode_by_name(ntfs_inode *dir_ni, const uchar_t *uname,
ntfs_error(sb, "Out of bounds check failed. Corrupt directory "
"inode 0x%lx or driver bug.", dir_ni->mft_no);
err = -EIO;
goto unm_
unm_
err_out;
goto unm_err_out;
}
if (sle64_to_cpu(ia->index_block_vcn) != vcn) {
ntfs_error(sb, "Actual VCN (0x%Lx) of index buffer is "
...
...
@@ -783,7 +796,7 @@ u64 ntfs_lookup_inode_by_name(ntfs_inode *dir_ni, const uchar_t *uname,
(long long)sle64_to_cpu(ia->index_block_vcn),
(long long)vcn, dir_ni->mft_no);
err = -EIO;
goto unm_
unm_
err_out;
goto unm_err_out;
}
if (le32_to_cpu(ia->index.allocated_size) + 0x18 !=
dir_ni->_IDM(index_block_size)) {
...
...
@@ -795,7 +808,7 @@ u64 ntfs_lookup_inode_by_name(ntfs_inode *dir_ni, const uchar_t *uname,
le32_to_cpu(ia->index.allocated_size) + 0x18,
dir_ni->_IDM(index_block_size));
err = -EIO;
goto unm_
unm_
err_out;
goto unm_err_out;
}
index_end = (u8*)ia + dir_ni->_IDM(index_block_size);
if (index_end > kaddr + PAGE_CACHE_SIZE) {
...
...
@@ -804,7 +817,7 @@ u64 ntfs_lookup_inode_by_name(ntfs_inode *dir_ni, const uchar_t *uname,
"Cannot access! This is probably a bug in the "
"driver.", (long long)vcn, dir_ni->mft_no);
err = -EIO;
goto unm_
unm_
err_out;
goto unm_err_out;
}
index_end = (u8*)&ia->index + le32_to_cpu(ia->index.index_length);
if (index_end > (u8*)ia + dir_ni->_IDM(index_block_size)) {
...
...
@@ -812,7 +825,7 @@ u64 ntfs_lookup_inode_by_name(ntfs_inode *dir_ni, const uchar_t *uname,
"inode 0x%lx exceeds maximum size.",
(long long)vcn, dir_ni->mft_no);
err = -EIO;
goto unm_
unm_
err_out;
goto unm_err_out;
}
/* The first index entry. */
ie = (INDEX_ENTRY*)((u8*)&ia->index +
...
...
@@ -832,7 +845,7 @@ u64 ntfs_lookup_inode_by_name(ntfs_inode *dir_ni, const uchar_t *uname,
"directory inode 0x%lx.",
dir_ni->mft_no);
err = -EIO;
goto unm_
unm_
err_out;
goto unm_err_out;
}
/*
* The last entry cannot contain a name. It can however contain
...
...
@@ -865,8 +878,6 @@ u64 ntfs_lookup_inode_by_name(ntfs_inode *dir_ni, const uchar_t *uname,
found_it2:
mref = le64_to_cpu(ie->_IIF(indexed_file));
ntfs_unmap_page(page);
put_attr_search_ctx(ctx);
unmap_mft_record(READ, dir_ni);
return mref;
}
/*
...
...
@@ -917,7 +928,7 @@ u64 ntfs_lookup_inode_by_name(ntfs_inode *dir_ni, const uchar_t *uname,
"a leaf node in directory inode 0x%lx.",
dir_ni->mft_no);
err = -EIO;
goto unm_
unm_
err_out;
goto unm_err_out;
}
/* Child node present, descend into it. */
old_vcn = vcn;
...
...
@@ -937,26 +948,23 @@ u64 ntfs_lookup_inode_by_name(ntfs_inode *dir_ni, const uchar_t *uname,
ntfs_error(sb, "Negative child node vcn in directory inode "
"0x%lx.", dir_ni->mft_no);
err = -EIO;
goto unm_
unm_
err_out;
goto unm_err_out;
}
/* No child node, return -ENOENT. */
ntfs_debug("Entry not found.");
err = -ENOENT;
unm_unm_err_out:
ntfs_unmap_page(page);
put_unm_err_out:
put_attr_search_ctx(ctx);
unm_err_out:
unmap_mft_record(READ, dir_ni);
ntfs_unmap_page(page);
err_out:
if (ctx)
put_attr_search_ctx(ctx);
if (m)
unmap_mft_record(dir_ni);
return ERR_MREF(err);
map_err_out:
ntfs_error(sb, "map_mft_record(READ) failed with error code %ld.",
-PTR_ERR(m));
return ERR_MREF(PTR_ERR(m));
dir_err_out:
ntfs_error(sb, "Corrupt directory. Aborting lookup.");
err = -EIO;
goto
put_unm_
err_out;
goto err_out;
}
#endif
...
...
@@ -1095,22 +1103,8 @@ static int ntfs_readdir(struct file *filp, void *dirent, filldir_t filldir)
goto
done
;
fpos
++
;
}
/* Get hold of the mft record for the directory. */
m
=
map_mft_record
(
READ
,
ndir
);
if
(
unlikely
(
IS_ERR
(
m
)))
{
err
=
PTR_ERR
(
m
);
m
=
NULL
;
ctx
=
NULL
;
goto
err_out
;
}
ctx
=
get_attr_search_ctx
(
ndir
,
m
);
if
(
unlikely
(
!
ctx
))
{
err
=
-
ENOMEM
;
goto
err_out
;
}
m
=
NULL
;
ctx
=
NULL
;
/*
* Allocate a buffer to store the current name being processed
* converted to format determined by current NLS.
...
...
@@ -1124,6 +1118,18 @@ static int ntfs_readdir(struct file *filp, void *dirent, filldir_t filldir)
/* Are we jumping straight into the index allocation attribute? */
if
(
fpos
>=
vol
->
mft_record_size
)
goto
skip_index_root
;
/* Get hold of the mft record for the directory. */
m
=
map_mft_record
(
ndir
);
if
(
unlikely
(
IS_ERR
(
m
)))
{
err
=
PTR_ERR
(
m
);
m
=
NULL
;
goto
err_out
;
}
ctx
=
get_attr_search_ctx
(
ndir
,
m
);
if
(
unlikely
(
!
ctx
))
{
err
=
-
ENOMEM
;
goto
err_out
;
}
/* Get the offset into the index root attribute. */
ir_pos
=
(
s64
)
fpos
;
/* Find the index root attribute in the mft record. */
...
...
@@ -1162,9 +1168,21 @@ static int ntfs_readdir(struct file *filp, void *dirent, filldir_t filldir)
/* Submit the name to the filldir callback. */
rc
=
ntfs_filldir
(
vol
,
&
fpos
,
ndir
,
INDEX_TYPE_ROOT
,
ir
,
ie
,
name
,
dirent
,
filldir
);
if
(
rc
)
if
(
rc
)
{
put_attr_search_ctx
(
ctx
);
unmap_mft_record
(
ndir
);
goto
abort
;
}
}
/*
* We are done with the index root and the mft record for that matter.
* We need to release it, otherwise we deadlock on ntfs_attr_iget()
* and/or ntfs_read_page().
*/
put_attr_search_ctx
(
ctx
);
unmap_mft_record
(
ndir
);
m
=
NULL
;
ctx
=
NULL
;
/* If there is no index allocation attribute we are finished. */
if
(
!
NInoIndexAllocPresent
(
ndir
))
goto
EOD
;
...
...
@@ -1197,7 +1215,7 @@ static int ntfs_readdir(struct file *filp, void *dirent, filldir_t filldir)
}
/* Get the starting bit position in the current bitmap page. */
cur_bmp_pos
=
bmp_pos
&
((
PAGE_CACHE_SIZE
*
8
)
-
1
);
bmp_pos
&=
~
((
PAGE_CACHE_SIZE
*
8
)
-
1
);
bmp_pos
&=
~
(
u64
)(
(
PAGE_CACHE_SIZE
*
8
)
-
1
);
get_next_bmp_page:
ntfs_debug
(
"Reading bitmap with page index 0x%Lx, bit ofs 0x%Lx"
,
(
long
long
)
bmp_pos
>>
(
3
+
PAGE_CACHE_SHIFT
),
...
...
@@ -1343,8 +1361,6 @@ static int ntfs_readdir(struct file *filp, void *dirent, filldir_t filldir)
/* We are finished, set fpos to EOD. */
fpos
=
vdir
->
i_size
+
vol
->
mft_record_size
;
abort:
put_attr_search_ctx
(
ctx
);
unmap_mft_record
(
READ
,
ndir
);
kfree
(
name
);
done:
#ifdef DEBUG
...
...
@@ -1366,7 +1382,7 @@ static int ntfs_readdir(struct file *filp, void *dirent, filldir_t filldir)
if
(
ctx
)
put_attr_search_ctx
(
ctx
);
if
(
m
)
unmap_mft_record
(
READ
,
ndir
);
unmap_mft_record
(
ndir
);
if
(
!
err
)
err
=
-
EIO
;
ntfs_debug
(
"Failed. Returning error code %i."
,
-
err
);
...
...
fs/ntfs/file.c
View file @
b14ebcfc
...
...
@@ -51,8 +51,15 @@ static int ntfs_file_open(struct inode *vi, struct file *filp)
struct
file_operations
ntfs_file_ops
=
{
.
llseek
=
generic_file_llseek
,
/* Seek inside file. */
.
read
=
generic_file_read
,
/* Read from file. */
#ifdef NTFS_RW
.
write
=
generic_file_write
,
/* Write to a file. */
#endif
.
mmap
=
generic_file_mmap
,
/* Mmap file. */
.
sendfile
=
generic_file_sendfile
,
/* Zero-copy data send. */
.
sendfile
=
generic_file_sendfile
,
/* Zero-copy data send with the
data source being on the
ntfs partition. We don't
need to care about the data
destination. */
.
open
=
ntfs_file_open
,
/* Open file. */
};
...
...
fs/ntfs/inode.c
View file @
b14ebcfc
...
...
@@ -278,7 +278,9 @@ void ntfs_destroy_big_inode(struct inode *inode)
ntfs_inode
*
ni
=
NTFS_I
(
inode
);
ntfs_debug
(
"Entering."
);
BUG_ON
(
atomic_read
(
&
ni
->
mft_count
)
||
!
atomic_dec_and_test
(
&
ni
->
count
));
BUG_ON
(
ni
->
page
);
if
(
!
atomic_dec_and_test
(
&
ni
->
count
))
BUG
();
kmem_cache_free
(
ntfs_big_inode_cache
,
NTFS_I
(
inode
));
}
...
...
@@ -299,7 +301,9 @@ static inline ntfs_inode *ntfs_alloc_extent_inode(void)
void
ntfs_destroy_extent_inode
(
ntfs_inode
*
ni
)
{
ntfs_debug
(
"Entering."
);
BUG_ON
(
atomic_read
(
&
ni
->
mft_count
)
||
!
atomic_dec_and_test
(
&
ni
->
count
));
BUG_ON
(
ni
->
page
);
if
(
!
atomic_dec_and_test
(
&
ni
->
count
))
BUG
();
kmem_cache_free
(
ntfs_inode_cache
,
ni
);
}
...
...
@@ -323,8 +327,7 @@ static void __ntfs_init_inode(struct super_block *sb, ntfs_inode *ni)
atomic_set
(
&
ni
->
count
,
1
);
ni
->
vol
=
NTFS_SB
(
sb
);
init_run_list
(
&
ni
->
run_list
);
init_rwsem
(
&
ni
->
mrec_lock
);
atomic_set
(
&
ni
->
mft_count
,
0
);
init_MUTEX
(
&
ni
->
mrec_lock
);
ni
->
page
=
NULL
;
ni
->
page_ofs
=
0
;
ni
->
attr_list_size
=
0
;
...
...
@@ -504,7 +507,7 @@ static int ntfs_read_locked_inode(struct inode *vi)
ntfs_init_big_inode
(
vi
);
ni
=
NTFS_I
(
vi
);
m
=
map_mft_record
(
READ
,
ni
);
m
=
map_mft_record
(
ni
);
if
(
IS_ERR
(
m
))
{
err
=
PTR_ERR
(
m
);
goto
err_out
;
...
...
@@ -790,6 +793,11 @@ static int ntfs_read_locked_inode(struct inode *vi)
/* No index allocation. */
vi
->
i_size
=
ni
->
initialized_size
=
ni
->
allocated_size
=
0
;
/* We are done with the mft record, so we release it. */
put_attr_search_ctx
(
ctx
);
unmap_mft_record
(
ni
);
m
=
NULL
;
ctx
=
NULL
;
goto
skip_large_dir_stuff
;
}
/* LARGE_INDEX: Index allocation present. Setup state. */
NInoSetIndexAllocPresent
(
ni
);
...
...
@@ -834,7 +842,14 @@ static int ntfs_read_locked_inode(struct inode *vi)
ctx
->
attr
->
_ANR
(
initialized_size
));
ni
->
allocated_size
=
sle64_to_cpu
(
ctx
->
attr
->
_ANR
(
allocated_size
));
/*
* We are done with the mft record, so we release it. Otherwise
*
*/
put_attr_search_ctx
(
ctx
);
unmap_mft_record
(
ni
);
m
=
NULL
;
ctx
=
NULL
;
/* Get the index bitmap attribute inode. */
bvi
=
ntfs_attr_iget
(
vi
,
AT_BITMAP
,
I30
,
4
);
if
(
unlikely
(
IS_ERR
(
bvi
)))
{
...
...
@@ -858,7 +873,6 @@ static int ntfs_read_locked_inode(struct inode *vi)
bvi
->
i_size
<<
3
,
vi
->
i_size
);
goto
unm_err_out
;
}
skip_large_dir_stuff:
/* Everyone gets read and scan permissions. */
vi
->
i_mode
|=
S_IRUGO
|
S_IXUGO
;
...
...
@@ -998,6 +1012,11 @@ static int ntfs_read_locked_inode(struct inode *vi)
le32_to_cpu
(
ctx
->
attr
->
_ARA
(
value_length
));
}
no_data_attr_special_case:
/* We are done with the mft record, so we release it. */
put_attr_search_ctx
(
ctx
);
unmap_mft_record
(
ni
);
m
=
NULL
;
ctx
=
NULL
;
/* Everyone gets all permissions. */
vi
->
i_mode
|=
S_IRWXUGO
;
/* If read-only, noone gets write permissions. */
...
...
@@ -1026,9 +1045,6 @@ static int ntfs_read_locked_inode(struct inode *vi)
else
vi
->
i_blocks
=
ni
->
_ICF
(
compressed_size
)
>>
9
;
put_attr_search_ctx
(
ctx
);
unmap_mft_record
(
READ
,
ni
);
ntfs_debug
(
"Done."
);
return
0
;
...
...
@@ -1037,7 +1053,8 @@ static int ntfs_read_locked_inode(struct inode *vi)
err
=
-
EIO
;
if
(
ctx
)
put_attr_search_ctx
(
ctx
);
unmap_mft_record
(
READ
,
ni
);
if
(
m
)
unmap_mft_record
(
ni
);
err_out:
ntfs_error
(
vi
->
i_sb
,
"Failed with error code %i. Marking inode 0x%lx "
"as bad."
,
-
err
,
vi
->
i_ino
);
...
...
@@ -1091,7 +1108,7 @@ static int ntfs_read_locked_attr_inode(struct inode *base_vi, struct inode *vi)
/* Set inode type to zero but preserve permissions. */
vi
->
i_mode
=
base_vi
->
i_mode
&
~
S_IFMT
;
m
=
map_mft_record
(
READ
,
base_ni
);
m
=
map_mft_record
(
base_ni
);
if
(
IS_ERR
(
m
))
{
err
=
PTR_ERR
(
m
);
goto
err_out
;
...
...
@@ -1265,7 +1282,7 @@ static int ntfs_read_locked_attr_inode(struct inode *base_vi, struct inode *vi)
ni
->
nr_extents
=
-
1
;
put_attr_search_ctx
(
ctx
);
unmap_mft_record
(
READ
,
base_ni
);
unmap_mft_record
(
base_ni
);
ntfs_debug
(
"Done."
);
return
0
;
...
...
@@ -1275,7 +1292,7 @@ static int ntfs_read_locked_attr_inode(struct inode *base_vi, struct inode *vi)
err
=
-
EIO
;
if
(
ctx
)
put_attr_search_ctx
(
ctx
);
unmap_mft_record
(
READ
,
base_ni
);
unmap_mft_record
(
base_ni
);
err_out:
ntfs_error
(
vi
->
i_sb
,
"Failed with error code %i while reading "
"attribute inode (mft_no 0x%lx, type 0x%x, name_len "
...
...
@@ -1398,7 +1415,7 @@ void ntfs_read_inode_mount(struct inode *vi)
/* Need this to sanity check attribute list references to $MFT. */
ni
->
seq_no
=
le16_to_cpu
(
m
->
sequence_number
);
/* Provides readpage() and sync_page() for map_mft_record(
READ
). */
/* Provides readpage() and sync_page() for map_mft_record(). */
vi
->
i_mapping
->
a_ops
=
&
ntfs_mft_aops
;
ctx
=
get_attr_search_ctx
(
ni
,
m
);
...
...
@@ -1795,8 +1812,8 @@ void __ntfs_clear_inode(ntfs_inode *ni)
}
}
/* Synchronize with ntfs_commit_inode(). */
down
_write
(
&
ni
->
mrec_lock
);
up
_write
(
&
ni
->
mrec_lock
);
down
(
&
ni
->
mrec_lock
);
up
(
&
ni
->
mrec_lock
);
if
(
NInoDirty
(
ni
))
{
ntfs_error
(
ni
->
vol
->
sb
,
"Failed to commit dirty inode "
"asynchronously."
);
...
...
fs/ntfs/inode.h
View file @
b14ebcfc
...
...
@@ -72,9 +72,8 @@ struct _ntfs_inode {
* The following fields are only valid for real inodes and extent
* inodes.
*/
struct
rw_semaphore
mrec_lock
;
/* Lock for serializing access to the
struct
semaphore
mrec_lock
;
/* Lock for serializing access to the
mft record belonging to this inode. */
atomic_t
mft_count
;
/* Mapping reference count for book keeping. */
struct
page
*
page
;
/* The page containing the mft record of the
inode. This should only be touched by the
(un)map_mft_record*() functions. */
...
...
fs/ntfs/malloc.h
View file @
b14ebcfc
...
...
@@ -25,20 +25,6 @@
#include <linux/vmalloc.h>
#include <linux/slab.h>
/**
* vmalloc_nofs - allocate any pages but don't allow calls into fs layer
* @size: number of bytes to allocate
*
* Allocate any pages but don't allow calls into fs layer. Return allocated
* memory or NULL if insufficient memory.
*/
static
inline
void
*
vmalloc_nofs
(
unsigned
long
size
)
{
if
(
likely
(
size
>>
PAGE_SHIFT
<
num_physpages
))
return
__vmalloc
(
size
,
GFP_NOFS
|
__GFP_HIGHMEM
,
PAGE_KERNEL
);
return
NULL
;
}
/**
* ntfs_malloc_nofs - allocate memory in multiples of pages
* @size number of bytes to allocate
...
...
@@ -66,7 +52,8 @@ static inline void *ntfs_malloc_nofs(unsigned long size)
static
inline
void
ntfs_free
(
void
*
addr
)
{
if
(
likely
((
unsigned
long
)
addr
<
VMALLOC_START
))
{
if
(
likely
(((
unsigned
long
)
addr
<
VMALLOC_START
)
||
((
unsigned
long
)
addr
>=
VMALLOC_END
)))
{
return
kfree
(
addr
);
/* return free_page((unsigned long)addr); */
}
...
...
fs/ntfs/mft.c
View file @
b14ebcfc
...
...
@@ -2,7 +2,7 @@
* mft.c - NTFS kernel mft record operations. Part of the Linux-NTFS project.
*
* Copyright (c) 2001,2002 Anton Altaparmakov.
* Copyright (
C
) 2002 Richard Russon.
* Copyright (
c
) 2002 Richard Russon.
*
* This program/include file is free software; you can redistribute it and/or
* modify it under the terms of the GNU General Public License as published
...
...
@@ -85,13 +85,15 @@ int format_mft_record(ntfs_inode *ni, MFT_RECORD *mft_rec)
if
(
mft_rec
)
m
=
mft_rec
;
else
{
m
=
map_mft_record
(
WRITE
,
ni
);
m
=
map_mft_record
(
ni
);
if
(
IS_ERR
(
m
))
return
PTR_ERR
(
m
);
}
__format_mft_record
(
m
,
ni
->
vol
->
mft_record_size
,
ni
->
mft_no
);
if
(
!
mft_rec
)
unmap_mft_record
(
WRITE
,
ni
);
if
(
!
mft_rec
)
{
// FIXME: Need to set the mft record dirty!
unmap_mft_record
(
ni
);
}
return
0
;
}
...
...
@@ -132,7 +134,7 @@ static inline MFT_RECORD *map_mft_record_page(ntfs_inode *ni)
struct
page
*
page
;
unsigned
long
index
,
ofs
,
end_index
;
BUG_ON
(
atomic_read
(
&
ni
->
mft_count
)
||
ni
->
page
);
BUG_ON
(
ni
->
page
);
/*
* The index into the page cache and the offset within the page cache
* page of the wanted mft record. FIXME: We need to check for
...
...
@@ -146,70 +148,36 @@ static inline MFT_RECORD *map_mft_record_page(ntfs_inode *ni)
end_index
=
mft_vi
->
i_size
>>
PAGE_CACHE_SHIFT
;
/* If the wanted index is out of bounds the mft record doesn't exist. */
if
(
index
>=
end_index
)
{
if
(
unlikely
(
index
>=
end_index
)
)
{
if
(
index
>
end_index
||
(
mft_vi
->
i_size
&
~
PAGE_CACHE_MASK
)
<
ofs
+
vol
->
mft_record_size
)
{
page
=
ERR_PTR
(
-
ENOENT
);
goto
up_
err_out
;
goto
err_out
;
}
}
/* Read, map, and pin the page. */
page
=
ntfs_map_page
(
mft_vi
->
i_mapping
,
index
);
if
(
!
IS_ERR
(
page
))
{
/* Pin the mft record mapping in the ntfs_inode. */
atomic_inc
(
&
ni
->
mft_count
);
/* Setup the references in the ntfs_inode. */
if
(
likely
(
!
IS_ERR
(
page
)))
{
ni
->
page
=
page
;
ni
->
page_ofs
=
ofs
;
return
page_address
(
page
)
+
ofs
;
}
up_err_out:
/* Just in case... */
err_out:
ni
->
page
=
NULL
;
ni
->
page_ofs
=
0
;
ntfs_error
(
vol
->
sb
,
"Failed with error code %lu."
,
-
PTR_ERR
(
page
));
return
(
void
*
)
page
;
}
/**
* unmap_mft_record_page - unmap the page in which a specific mft record resides
* @ni: ntfs inode whose mft record page to unmap
*
* This unmaps the page in which the mft record of the ntfs inode @ni is
* situated and returns. This is a NOOP if highmem is not configured.
*
* The unmap happens via ntfs_unmap_page() which in turn decrements the use
* count on the page thus releasing it from the pinned state.
*
* We do not actually unmap the page from memory of course, as that will be
* done by the page cache code itself when memory pressure increases or
* whatever.
*/
static
inline
void
unmap_mft_record_page
(
ntfs_inode
*
ni
)
{
BUG_ON
(
atomic_read
(
&
ni
->
mft_count
)
||
!
ni
->
page
);
// TODO: If dirty, blah...
ntfs_unmap_page
(
ni
->
page
);
ni
->
page
=
NULL
;
ni
->
page_ofs
=
0
;
return
;
}
/**
* map_mft_record - map, pin and lock an mft record
* @rw: map for read (rw = READ) or write (rw = WRITE)
* @ni: ntfs inode whose MFT record to map
*
* First, take the mrec_lock semaphore for reading or writing, depending on
* the value or @rw. We might now be sleeping, while waiting for the semaphore
* if it was already locked by someone else.
* First, take the mrec_lock semaphore. We might now be sleeping, while waiting
* for the semaphore if it was already locked by someone else.
*
* Then increment the map reference count and return the mft. If this is the
* first invocation, the page of the record is first mapped using
* map_mft_record_page().
* The page of the record is first mapped using map_mft_record_page() before
* being returned to the caller.
*
* This in turn uses ntfs_map_page() to get the page containing the wanted mft
* record (it in turn calls read_cache_page() which reads it in from disk if
...
...
@@ -234,11 +202,11 @@ static inline void unmap_mft_record_page(ntfs_inode *ni)
* locking problem then is them locking the page while we are accessing it.
*
* So that code will end up having to own the mrec_lock of all mft
* records/inodes present in the page before I/O can proceed.
Grr. In that
*
case we wouldn't need need to bother with PG_locked and PG_uptodate as
*
nobody will be accessing anything without owning the mrec_lock semaphore.
*
But we do need to use them because of the read_cache_page() invokation and
*
the code becomes
so much simpler this way that it is well worth it.
* records/inodes present in the page before I/O can proceed.
In that case we
*
wouldn't need to bother with PG_locked and PG_uptodate as nobody will be
*
accessing anything without owning the mrec_lock semaphore. But we do need
*
to use them because of the read_cache_page() invokation and the code becomes
* so much simpler this way that it is well worth it.
*
* The mft record is now ours and we return a pointer to it. You need to check
* the returned pointer with IS_ERR() and if that is true, PTR_ERR() will return
...
...
@@ -251,89 +219,75 @@ static inline void unmap_mft_record_page(ntfs_inode *ni)
* A: No, the inode ones mean we want to change the mft record, not we want to
* write it out.
*/
MFT_RECORD
*
map_mft_record
(
const
int
rw
,
ntfs_inode
*
ni
)
MFT_RECORD
*
map_mft_record
(
ntfs_inode
*
ni
)
{
MFT_RECORD
*
m
;
ntfs_debug
(
"Entering for mft_no 0x%lx, mapping for %s."
,
ni
->
mft_no
,
rw
==
READ
?
"READ"
:
"WRITE"
);
ntfs_debug
(
"Entering for mft_no 0x%lx."
,
ni
->
mft_no
);
/* Make sure the ntfs inode doesn't go away. */
atomic_inc
(
&
ni
->
count
);
/* Serialize access to this mft record. */
if
(
rw
==
READ
)
down_read
(
&
ni
->
mrec_lock
);
else
down_write
(
&
ni
->
mrec_lock
);
/* If already mapped, bump reference count and return the mft record. */
if
(
atomic_read
(
&
ni
->
mft_count
))
{
BUG_ON
(
!
ni
->
page
);
atomic_inc
(
&
ni
->
mft_count
);
return
page_address
(
ni
->
page
)
+
ni
->
page_ofs
;
}
down
(
&
ni
->
mrec_lock
);
/* Wasn't mapped. Map it now and return it if all was ok. */
m
=
map_mft_record_page
(
ni
);
if
(
!
IS_ERR
(
m
))
if
(
likely
(
!
IS_ERR
(
m
)
))
return
m
;
/* Mapping failed. Release the mft record lock. */
if
(
rw
==
READ
)
up_read
(
&
ni
->
mrec_lock
);
else
up_write
(
&
ni
->
mrec_lock
);
ntfs_error
(
ni
->
vol
->
sb
,
"Failed with error code %lu."
,
-
PTR_ERR
(
m
));
/* Release the ntfs inode and return the error code. */
up
(
&
ni
->
mrec_lock
);
atomic_dec
(
&
ni
->
count
);
ntfs_error
(
ni
->
vol
->
sb
,
"Failed with error code %lu."
,
-
PTR_ERR
(
m
));
return
m
;
}
/**
* unmap_mft_record - release a mapped mft record
* @rw: unmap from read (@rw = READ) or write (@rw = WRITE)
* @ni: ntfs inode whose MFT record to unmap
*
* First, decrement the mapping count and when it reaches zero unmap the mft
* record.
* unmap_mft_record_page - unmap the page in which a specific mft record resides
* @ni: ntfs inode whose mft record page to unmap
*
* Second, release the mrec_lock semaphore.
* This unmaps the page in which the mft record of the ntfs inode @ni is
* situated and returns. This is a NOOP if highmem is not configured.
*
* The mft record is now released for others to get hold of.
* The unmap happens via ntfs_unmap_page() which in turn decrements the use
* count on the page thus releasing it from the pinned state.
*
* Finally, release the ntfs inode by decreasing the ntfs inode reference count.
* We do not actually unmap the page from memory of course, as that will be
* done by the page cache code itself when memory pressure increases or
* whatever.
*/
static
inline
void
unmap_mft_record_page
(
ntfs_inode
*
ni
)
{
BUG_ON
(
!
ni
->
page
);
// TODO: If dirty, blah...
ntfs_unmap_page
(
ni
->
page
);
ni
->
page
=
NULL
;
ni
->
page_ofs
=
0
;
return
;
}
/**
* unmap_mft_record - release a mapped mft record
* @ni: ntfs inode whose MFT record to unmap
*
* NOTE: If caller had the mft record mapped for write and has modified it, it
* is imperative to set the mft record dirty BEFORE calling unmap_mft_record().
* We release the page mapping and the mrec_lock mutex which unmaps the mft
* record and releases it for others to get hold of. We also release the ntfs
* inode by decrementing the ntfs inode reference count.
*
* NOTE:
This has to be done both for 'normal' mft records, and for extent
mft
* record
s
.
* NOTE:
If caller has modified the mft record, it is imperative to set the
mft
* record
dirty BEFORE calling unmap_mft_record()
.
*/
void
unmap_mft_record
(
const
int
rw
,
ntfs_inode
*
ni
)
void
unmap_mft_record
(
ntfs_inode
*
ni
)
{
struct
page
*
page
=
ni
->
page
;
BUG_ON
(
!
atomic_read
(
&
ni
->
mft_count
)
||
!
page
);
ntfs_debug
(
"Entering for mft_no 0x%lx, unmapping from %s."
,
ni
->
mft_no
,
rw
==
READ
?
"READ"
:
"WRITE"
);
BUG_ON
(
!
page
);
/* Only release the actual page mapping if this is the last one. */
if
(
atomic_dec_and_test
(
&
ni
->
mft_count
))
unmap_mft_record_page
(
ni
);
ntfs_debug
(
"Entering for mft_no 0x%lx."
,
ni
->
mft_no
);
/* Release the semaphore. */
if
(
rw
==
READ
)
up_read
(
&
ni
->
mrec_lock
);
else
up_write
(
&
ni
->
mrec_lock
);
/* Release the ntfs inode. */
unmap_mft_record_page
(
ni
);
up
(
&
ni
->
mrec_lock
);
atomic_dec
(
&
ni
->
count
);
/*
* If pure ntfs_inode, i.e. no vfs inode attached, we leave it to
* ntfs_clear_extent_inode() in the extent inode case, and to the
...
...
@@ -355,11 +309,6 @@ void unmap_mft_record(const int rw, ntfs_inode *ni)
*
* On successful return, @ntfs_ino contains a pointer to the ntfs_inode
* structure of the mapped extent inode.
*
* Note, we always map for READ. We consider this lock as irrelevant because
* the base inode will be write locked in all cases when we want to write to
* an extent inode which already gurantees that there is no-one else accessing
* the extent inode.
*/
MFT_RECORD
*
map_extent_mft_record
(
ntfs_inode
*
base_ni
,
MFT_REF
mref
,
ntfs_inode
**
ntfs_ino
)
...
...
@@ -393,21 +342,21 @@ MFT_RECORD *map_extent_mft_record(ntfs_inode *base_ni, MFT_REF mref,
break
;
}
}
if
(
ni
)
{
if
(
likely
(
ni
!=
NULL
)
)
{
up
(
&
base_ni
->
extent_lock
);
atomic_dec
(
&
base_ni
->
count
);
/* We found the record; just have to map and return it. */
m
=
map_mft_record
(
READ
,
ni
);
/*
Map mft record increments
this on success. */
m
=
map_mft_record
(
ni
);
/*
map_mft_record() has incremented
this on success. */
atomic_dec
(
&
ni
->
count
);
if
(
!
IS_ERR
(
m
))
{
if
(
likely
(
!
IS_ERR
(
m
)
))
{
/* Verify the sequence number. */
if
(
l
e16_to_cpu
(
m
->
sequence_number
)
==
seq_no
)
{
if
(
l
ikely
(
le16_to_cpu
(
m
->
sequence_number
)
==
seq_no
)
)
{
ntfs_debug
(
"Done 1."
);
*
ntfs_ino
=
ni
;
return
m
;
}
unmap_mft_record
(
READ
,
ni
);
unmap_mft_record
(
ni
);
ntfs_error
(
base_ni
->
vol
->
sb
,
"Found stale extent mft "
"reference! Corrupt file system. "
"Run chkdsk."
);
...
...
@@ -420,7 +369,7 @@ MFT_RECORD *map_extent_mft_record(ntfs_inode *base_ni, MFT_REF mref,
}
/* Record wasn't there. Get a new ntfs inode and initialize it. */
ni
=
ntfs_new_extent_inode
(
base_ni
->
vol
->
sb
,
mft_no
);
if
(
!
ni
)
{
if
(
unlikely
(
!
ni
)
)
{
up
(
&
base_ni
->
extent_lock
);
atomic_dec
(
&
base_ni
->
count
);
return
ERR_PTR
(
-
ENOMEM
);
...
...
@@ -430,15 +379,15 @@ MFT_RECORD *map_extent_mft_record(ntfs_inode *base_ni, MFT_REF mref,
ni
->
nr_extents
=
-
1
;
ni
->
_INE
(
base_ntfs_ino
)
=
base_ni
;
/* Now map the record. */
m
=
map_mft_record
(
READ
,
ni
);
if
(
IS_ERR
(
m
))
{
m
=
map_mft_record
(
ni
);
if
(
unlikely
(
IS_ERR
(
m
)
))
{
up
(
&
base_ni
->
extent_lock
);
atomic_dec
(
&
base_ni
->
count
);
ntfs_clear_extent_inode
(
ni
);
goto
map_err_out
;
}
/* Verify the sequence number. */
if
(
le16_to_cpu
(
m
->
sequence_number
)
!=
seq_no
)
{
if
(
unlikely
(
le16_to_cpu
(
m
->
sequence_number
)
!=
seq_no
)
)
{
ntfs_error
(
base_ni
->
vol
->
sb
,
"Found stale extent mft "
"reference! Corrupt file system. Run chkdsk."
);
destroy_ni
=
TRUE
;
...
...
@@ -451,7 +400,7 @@ MFT_RECORD *map_extent_mft_record(ntfs_inode *base_ni, MFT_REF mref,
int
new_size
=
(
base_ni
->
nr_extents
+
4
)
*
sizeof
(
ntfs_inode
*
);
tmp
=
(
ntfs_inode
**
)
kmalloc
(
new_size
,
GFP_NOFS
);
if
(
!
tmp
)
{
if
(
unlikely
(
!
tmp
)
)
{
ntfs_error
(
base_ni
->
vol
->
sb
,
"Failed to allocate "
"internal buffer."
);
destroy_ni
=
TRUE
;
...
...
@@ -472,7 +421,7 @@ MFT_RECORD *map_extent_mft_record(ntfs_inode *base_ni, MFT_REF mref,
*
ntfs_ino
=
ni
;
return
m
;
unm_err_out:
unmap_mft_record
(
READ
,
ni
);
unmap_mft_record
(
ni
);
up
(
&
base_ni
->
extent_lock
);
atomic_dec
(
&
base_ni
->
count
);
/*
...
...
fs/ntfs/mft.h
View file @
b14ebcfc
...
...
@@ -31,15 +31,15 @@ extern int format_mft_record(ntfs_inode *ni, MFT_RECORD *m);
//extern int format_mft_record2(struct super_block *vfs_sb,
// const unsigned long inum, MFT_RECORD *m);
extern
MFT_RECORD
*
map_mft_record
(
const
int
rw
,
ntfs_inode
*
ni
);
extern
void
unmap_mft_record
(
const
int
rw
,
ntfs_inode
*
ni
);
extern
MFT_RECORD
*
map_mft_record
(
ntfs_inode
*
ni
);
extern
void
unmap_mft_record
(
ntfs_inode
*
ni
);
extern
MFT_RECORD
*
map_extent_mft_record
(
ntfs_inode
*
base_ni
,
MFT_REF
mref
,
ntfs_inode
**
ntfs_ino
);
static
inline
void
unmap_extent_mft_record
(
ntfs_inode
*
ni
)
{
unmap_mft_record
(
READ
,
ni
);
unmap_mft_record
(
ni
);
return
;
}
...
...
fs/ntfs/namei.c
View file @
b14ebcfc
...
...
@@ -162,6 +162,7 @@ static struct dentry *ntfs_lookup(struct inode *dir_ino, struct dentry *dent)
handle_name:
{
struct
dentry
*
real_dent
;
MFT_RECORD
*
m
;
attr_search_context
*
ctx
;
ntfs_inode
*
ni
=
NTFS_I
(
dent_inode
);
int
err
;
...
...
@@ -175,22 +176,23 @@ static struct dentry *ntfs_lookup(struct inode *dir_ino, struct dentry *dent)
name
->
len
*
3
+
1
);
kfree
(
name
);
}
else
/* if (name->type == FILE_NAME_DOS) */
{
/* Case 3. */
MFT_RECORD
*
m
;
FILE_NAME_ATTR
*
fn
;
kfree
(
name
);
/* Find the WIN32 name corresponding to the matched DOS name. */
ni
=
NTFS_I
(
dent_inode
);
m
=
map_mft_record
(
READ
,
ni
);
m
=
map_mft_record
(
ni
);
if
(
IS_ERR
(
m
))
{
err
=
PTR_ERR
(
m
);
goto
name_err_out
;
m
=
NULL
;
ctx
=
NULL
;
goto
err_out
;
}
ctx
=
get_attr_search_ctx
(
ni
,
m
);
if
(
!
ctx
)
{
err
=
-
ENOMEM
;
goto
unm_
err_out
;
goto
err_out
;
}
do
{
ATTR_RECORD
*
a
;
...
...
@@ -202,21 +204,21 @@ static struct dentry *ntfs_lookup(struct inode *dir_ino, struct dentry *dent)
"namespace counterpart to DOS "
"file name. Run chkdsk."
);
err
=
-
EIO
;
goto
put_unm_
err_out
;
goto
err_out
;
}
/* Consistency checks. */
a
=
ctx
->
attr
;
if
(
a
->
non_resident
||
a
->
flags
)
goto
eio_
put_unm_
err_out
;
goto
eio_err_out
;
val_len
=
le32_to_cpu
(
a
->
_ARA
(
value_length
));
if
(
le16_to_cpu
(
a
->
_ARA
(
value_offset
))
+
val_len
>
le32_to_cpu
(
a
->
length
))
goto
eio_
put_unm_
err_out
;
goto
eio_err_out
;
fn
=
(
FILE_NAME_ATTR
*
)((
u8
*
)
ctx
->
attr
+
le16_to_cpu
(
ctx
->
attr
->
_ARA
(
value_offset
)));
if
((
u32
)(
fn
->
file_name_length
*
sizeof
(
uchar_t
)
+
sizeof
(
FILE_NAME_ATTR
))
>
val_len
)
goto
eio_
put_unm_
err_out
;
goto
eio_err_out
;
}
while
(
fn
->
file_name_type
!=
FILE_NAME_WIN32
);
/* Convert the found WIN32 name to current NLS code page. */
...
...
@@ -226,13 +228,15 @@ static struct dentry *ntfs_lookup(struct inode *dir_ino, struct dentry *dent)
fn
->
file_name_length
*
3
+
1
);
put_attr_search_ctx
(
ctx
);
unmap_mft_record
(
READ
,
ni
);
unmap_mft_record
(
ni
);
}
m
=
NULL
;
ctx
=
NULL
;
/* Check if a conversion error occured. */
if
((
signed
)
nls_name
.
len
<
0
)
{
err
=
(
signed
)
nls_name
.
len
;
goto
name_
err_out
;
goto
err_out
;
}
nls_name
.
hash
=
full_name_hash
(
nls_name
.
name
,
nls_name
.
len
);
...
...
@@ -248,7 +252,7 @@ static struct dentry *ntfs_lookup(struct inode *dir_ino, struct dentry *dent)
kfree
(
nls_name
.
name
);
if
(
!
real_dent
)
{
err
=
-
ENOMEM
;
goto
name_
err_out
;
goto
err_out
;
}
d_add
(
real_dent
,
dent_inode
);
return
real_dent
;
...
...
@@ -269,14 +273,14 @@ static struct dentry *ntfs_lookup(struct inode *dir_ino, struct dentry *dent)
d_instantiate
(
real_dent
,
dent_inode
);
return
real_dent
;
eio_
put_unm_
err_out:
eio_err_out:
ntfs_error
(
vol
->
sb
,
"Illegal file name attribute. Run chkdsk."
);
err
=
-
EIO
;
put_unm_
err_out:
put_attr_search_ctx
(
ctx
);
unm_err_out:
unmap_mft_record
(
READ
,
ni
);
name_err_out:
err_out:
if
(
ctx
)
put_attr_search_ctx
(
ctx
);
if
(
m
)
unmap_mft_record
(
ni
);
iput
(
dent_inode
);
return
ERR_PTR
(
err
);
}
...
...
fs/ntfs/super.c
View file @
b14ebcfc
...
...
@@ -307,6 +307,23 @@ static int ntfs_remount(struct super_block *sb, int *flags, char *opt)
ntfs_debug
(
"Entering with remount options string: %s"
,
opt
);
#ifndef NTFS_RW
/* For read-only compiled driver, enforce all read-only flags. */
*
flags
|=
MS_RDONLY
|
MS_NOATIME
|
MS_NODIRATIME
;
#else
/*
* For the read-write compiled driver, if we are remounting read-write,
* make sure there aren't any volume errors.
*/
if
((
sb
->
s_flags
&
MS_RDONLY
)
&&
!
(
*
flags
&
MS_RDONLY
))
{
if
(
NVolErrors
(
vol
))
{
ntfs_error
(
sb
,
"Volume has errors and is read-only."
"Cannot remount read-write."
);
return
-
EROFS
;
}
}
#endif
// FIXME/TODO: If left like this we will have problems with rw->ro and
// ro->rw, as well as with sync->async and vice versa remounts.
// Note: The VFS already checks that there are no pending deletes and
...
...
@@ -324,10 +341,6 @@ static int ntfs_remount(struct super_block *sb, int *flags, char *opt)
if
(
!
parse_options
(
vol
,
opt
))
return
-
EINVAL
;
#ifndef NTFS_RW
*
flags
|=
MS_RDONLY
|
MS_NOATIME
|
MS_NODIRATIME
;
#endif
return
0
;
}
...
...
@@ -852,7 +865,7 @@ static BOOL load_system_files(ntfs_volume *vol)
ntfs_error
(
sb
,
"Failed to load $Volume."
);
goto
iput_lcnbmp_err_out
;
}
m
=
map_mft_record
(
READ
,
NTFS_I
(
vol
->
vol_ino
));
m
=
map_mft_record
(
NTFS_I
(
vol
->
vol_ino
));
if
(
IS_ERR
(
m
))
{
iput_volume_failed:
iput
(
vol
->
vol_ino
);
...
...
@@ -867,7 +880,7 @@ static BOOL load_system_files(ntfs_volume *vol)
err_put_vol:
put_attr_search_ctx
(
ctx
);
get_ctx_vol_failed:
unmap_mft_record
(
READ
,
NTFS_I
(
vol
->
vol_ino
));
unmap_mft_record
(
NTFS_I
(
vol
->
vol_ino
));
goto
iput_volume_failed
;
}
vi
=
(
VOLUME_INFORMATION
*
)((
char
*
)
ctx
->
attr
+
...
...
@@ -882,7 +895,7 @@ static BOOL load_system_files(ntfs_volume *vol)
vol
->
major_ver
=
vi
->
major_ver
;
vol
->
minor_ver
=
vi
->
minor_ver
;
put_attr_search_ctx
(
ctx
);
unmap_mft_record
(
READ
,
NTFS_I
(
vol
->
vol_ino
));
unmap_mft_record
(
NTFS_I
(
vol
->
vol_ino
));
printk
(
KERN_INFO
"NTFS volume version %i.%i.
\n
"
,
vol
->
major_ver
,
vol
->
minor_ver
);
/*
...
...
fs/ntfs/volume.h
View file @
b14ebcfc
...
...
@@ -101,6 +101,7 @@ typedef struct {
* Defined bits for the flags field in the ntfs_volume structure.
*/
typedef
enum
{
NV_Errors
,
/* 1: Volume has errors, prevent remount rw. */
NV_ShowSystemFiles
,
/* 1: Return system files in ntfs_readdir(). */
NV_CaseSensitive
,
/* 1: Treat file names as case sensitive and
create filenames in the POSIX namespace.
...
...
@@ -127,6 +128,7 @@ static inline void NVolClear##flag(ntfs_volume *vol) \
}
/* Emit the ntfs volume bitops functions. */
NVOL_FNS
(
Errors
)
NVOL_FNS
(
ShowSystemFiles
)
NVOL_FNS
(
CaseSensitive
)
...
...
include/linux/isdn.h
View file @
b14ebcfc
...
...
@@ -245,18 +245,12 @@ typedef struct {
#define ISDN_TIMER_MODEMPLUS 2
#define ISDN_TIMER_MODEMRING 4
#define ISDN_TIMER_MODEMXMIT 8
#define ISDN_TIMER_NETDIAL 16
#define ISDN_TIMER_NETHANGUP 32
#define ISDN_TIMER_CARRIER 256
/* Wait for Carrier */
#define ISDN_TIMER_FAST (ISDN_TIMER_MODEMREAD | ISDN_TIMER_MODEMPLUS | \
ISDN_TIMER_MODEMXMIT)
#define ISDN_TIMER_SLOW (ISDN_TIMER_MODEMRING | ISDN_TIMER_NETHANGUP | \
ISDN_TIMER_NETDIAL | ISDN_TIMER_CARRIER)
/* Timeout-Values for isdn_net_dial() */
#define ISDN_TIMER_DTIMEOUT10 (10*HZ/(ISDN_TIMER_02SEC*(ISDN_TIMER_RES+1)))
#define ISDN_TIMER_DTIMEOUT15 (15*HZ/(ISDN_TIMER_02SEC*(ISDN_TIMER_RES+1)))
#define ISDN_TIMER_DTIMEOUT60 (60*HZ/(ISDN_TIMER_02SEC*(ISDN_TIMER_RES+1)))
ISDN_TIMER_CARRIER)
/* GLOBAL_FLAGS */
#define ISDN_GLOBAL_STOPPED 1
...
...
@@ -291,9 +285,10 @@ typedef struct {
typedef
struct
isdn_net_local_s
{
ulong
magic
;
char
name
[
10
];
/* Name of device */
struct
timer_list
dial_timer
;
/* dial timeout */
int
dial_event
;
/* event in case of timer expiry */
struct
net_device_stats
stats
;
/* Ethernet Statistics */
int
isdn_device
;
/* Index to isdn-device */
int
isdn_channel
;
/* Index to isdn-channel */
int
isdn_slot
;
/* Index to isdn device/channel */
int
ppp_slot
;
/* PPPD device slot number */
int
pre_device
;
/* Preselected isdn-device */
int
pre_channel
;
/* Preselected isdn-channel */
...
...
@@ -302,7 +297,6 @@ typedef struct isdn_net_local_s {
int
dialretry
;
/* Counter for Dialout-retries */
int
dialmax
;
/* Max. Number of Dial-retries */
int
cbdelay
;
/* Delay before Callback starts */
int
dtimer
;
/* Timeout-counter for dialing */
char
msn
[
ISDN_MSNLEN
];
/* MSNs/EAZs for this interface */
u_char
cbhup
;
/* Flag: Reject Call before Callback*/
u_char
dialstate
;
/* State for dialing */
...
...
@@ -387,12 +381,12 @@ typedef struct isdn_net_local_s {
/* the interface itself */
typedef
struct
isdn_net_dev_s
{
isdn_net_local
*
local
;
isdn_net_local
local
;
isdn_net_local
*
queue
;
/* circular list of all bundled
channels, which are currently
online */
spinlock_t
queue_lock
;
/* lock to protect queue */
void
*
next
;
/* Pointer to next isdn-interface
*/
struct
list_head
global_list
;
/* global list of all isdn_net_devs
*/
struct
net_device
dev
;
/* interface to upper levels */
#ifdef CONFIG_ISDN_PPP
ippp_bundle
*
pb
;
/* pointer to the common bundle structure
...
...
@@ -480,9 +474,7 @@ typedef struct modem_info {
/* 2 = B-Channel is up, deliver d.*/
int
dialing
;
/* Dial in progress or ATA */
int
rcvsched
;
/* Receive needs schedule */
int
isdn_driver
;
/* Index to isdn-driver */
int
isdn_channel
;
/* Index to isdn-channel */
int
drv_index
;
/* Index to dev->usage */
int
isdn_slot
;
/* Index to isdn-driver/channel */
int
ncarrier
;
/* Flag: schedule NO CARRIER */
unsigned
char
last_cause
[
8
];
/* Last cause message */
unsigned
char
last_num
[
ISDN_MSNLEN
];
...
...
@@ -608,24 +600,10 @@ typedef struct isdn_devt {
infostruct
*
infochain
;
/* List of open info-devs. */
wait_queue_head_t
info_waitq
;
/* Wait-Queue for isdninfo */
struct
timer_list
timer
;
/* Misc.-function Timer */
int
chanmap
[
ISDN_MAX_CHANNELS
];
/* Map minor->device-channel */
int
drvmap
[
ISDN_MAX_CHANNELS
];
/* Map minor->driver-index */
int
usage
[
ISDN_MAX_CHANNELS
];
/* Used by tty/ip/voice */
char
num
[
ISDN_MAX_CHANNELS
][
ISDN_MSNLEN
];
/* Remote number of active ch.*/
int
m_idx
[
ISDN_MAX_CHANNELS
];
/* Index for mdm.... */
driver
*
drv
[
ISDN_MAX_DRIVERS
];
/* Array of drivers */
isdn_net_dev
*
netdev
;
/* Linked list of net-if's */
char
drvid
[
ISDN_MAX_DRIVERS
][
20
];
/* Driver-ID */
struct
task_struct
*
profd
;
/* For iprofd */
modem
mdm
;
/* tty-driver-data */
isdn_net_dev
*
rx_netdev
[
ISDN_MAX_CHANNELS
];
/* rx netdev-pointers */
isdn_net_dev
*
st_netdev
[
ISDN_MAX_CHANNELS
];
/* stat netdev-pointers */
ulong
ibytes
[
ISDN_MAX_CHANNELS
];
/* Statistics incoming bytes */
ulong
obytes
[
ISDN_MAX_CHANNELS
];
/* Statistics outgoing bytes */
int
v110emu
[
ISDN_MAX_CHANNELS
];
/* V.110 emulator-mode 0=none */
atomic_t
v110use
[
ISDN_MAX_CHANNELS
];
/* Usage-Semaphore for stream */
isdn_v110_stream
*
v110
[
ISDN_MAX_CHANNELS
];
/* V.110 private data */
struct
semaphore
sem
;
/* serialize list access*/
unsigned
long
global_features
;
#ifdef CONFIG_DEVFS_FS
...
...
include/linux/isdnif.h
View file @
b14ebcfc
...
...
@@ -418,9 +418,7 @@ typedef struct {
char
display
[
85
];
/* display message data */
isdn_cmd_stat
isdn_io
;
/* ISDN IO-parameter/result */
aux_s
aux
;
/* for modem commands/indications */
#ifdef CONFIG_ISDN_TTY_FAX
T30_s
*
fax
;
/* Pointer to ttys fax struct */
#endif
ulong
userdata
;
/* User Data */
}
parm
;
}
isdn_ctrl
;
...
...
mm/mmap.c
View file @
b14ebcfc
...
...
@@ -422,6 +422,7 @@ unsigned long do_mmap_pgoff(struct file * file, unsigned long addr,
{
struct
mm_struct
*
mm
=
current
->
mm
;
struct
vm_area_struct
*
vma
,
*
prev
;
struct
inode
*
inode
=
NULL
;
unsigned
int
vm_flags
;
int
correct_wcount
=
0
;
int
error
;
...
...
@@ -469,17 +470,18 @@ unsigned long do_mmap_pgoff(struct file * file, unsigned long addr,
}
if
(
file
)
{
inode
=
file
->
f_dentry
->
d_inode
;
switch
(
flags
&
MAP_TYPE
)
{
case
MAP_SHARED
:
if
((
prot
&
PROT_WRITE
)
&&
!
(
file
->
f_mode
&
FMODE_WRITE
))
return
-
EACCES
;
/* Make sure we don't allow writing to an append-only file.. */
if
(
IS_APPEND
(
file
->
f_dentry
->
d_
inode
)
&&
(
file
->
f_mode
&
FMODE_WRITE
))
if
(
IS_APPEND
(
inode
)
&&
(
file
->
f_mode
&
FMODE_WRITE
))
return
-
EACCES
;
/* make sure there are no mandatory locks on the file. */
if
(
locks_verify_locked
(
file
->
f_dentry
->
d_
inode
))
if
(
locks_verify_locked
(
inode
))
return
-
EAGAIN
;
vm_flags
|=
VM_SHARED
|
VM_MAYSHARE
;
...
...
@@ -603,7 +605,7 @@ unsigned long do_mmap_pgoff(struct file * file, unsigned long addr,
vma_link
(
mm
,
vma
,
prev
,
rb_link
,
rb_parent
);
if
(
correct_wcount
)
atomic_inc
(
&
file
->
f_dentry
->
d_
inode
->
i_writecount
);
atomic_inc
(
&
inode
->
i_writecount
);
out:
mm
->
total_vm
+=
len
>>
PAGE_SHIFT
;
...
...
@@ -615,7 +617,7 @@ unsigned long do_mmap_pgoff(struct file * file, unsigned long addr,
unmap_and_free_vma:
if
(
correct_wcount
)
atomic_inc
(
&
file
->
f_dentry
->
d_
inode
->
i_writecount
);
atomic_inc
(
&
inode
->
i_writecount
);
vma
->
vm_file
=
NULL
;
fput
(
file
);
...
...
@@ -755,38 +757,41 @@ struct vm_area_struct * find_vma_prev(struct mm_struct * mm, unsigned long addr,
return
prev
?
prev
->
vm_next
:
vma
;
}
#ifdef ARCH_STACK_GROWSUP
/*
* vma is the first one with address < vma->vm_end,
* and even address < vma->vm_start. Have to extend vma.
* vma is the first one with address > vma->vm_end. Have to extend vma.
*/
int
expand_stack
(
struct
vm_area_struct
*
vma
,
unsigned
long
address
)
{
unsigned
long
grow
;
if
(
!
(
vma
->
vm_flags
&
VM_GROWSUP
))
return
-
EFAULT
;
/*
* vma->vm_start/vm_end cannot change under us because the caller
* is required to hold the mmap_sem in
write
mode. We need to get
* is required to hold the mmap_sem in
read
mode. We need to get
* the spinlock only before relocating the vma range ourself.
*/
address
+=
4
+
PAGE_SIZE
-
1
;
address
&=
PAGE_MASK
;
spin_lock
(
&
vma
->
vm_mm
->
page_table_lock
);
grow
=
(
vma
->
vm_start
-
address
)
>>
PAGE_SHIFT
;
grow
=
(
address
-
vma
->
vm_end
)
>>
PAGE_SHIFT
;
/* Overcommit.. */
if
(
!
vm_enough_memory
(
grow
))
{
if
(
!
vm_enough_memory
(
grow
))
{
spin_unlock
(
&
vma
->
vm_mm
->
page_table_lock
);
return
-
ENOMEM
;
}
if
(
vma
->
vm_end
-
address
>
current
->
rlim
[
RLIMIT_STACK
].
rlim_cur
||
if
(
address
-
vma
->
vm_start
>
current
->
rlim
[
RLIMIT_STACK
].
rlim_cur
||
((
vma
->
vm_mm
->
total_vm
+
grow
)
<<
PAGE_SHIFT
)
>
current
->
rlim
[
RLIMIT_AS
].
rlim_cur
)
{
spin_unlock
(
&
vma
->
vm_mm
->
page_table_lock
);
vm_unacct_memory
(
grow
);
return
-
ENOMEM
;
}
vma
->
vm_start
=
address
;
vma
->
vm_pgoff
-=
grow
;
vma
->
vm_end
=
address
;
vma
->
vm_mm
->
total_vm
+=
grow
;
if
(
vma
->
vm_flags
&
VM_LOCKED
)
vma
->
vm_mm
->
locked_vm
+=
grow
;
...
...
@@ -794,7 +799,6 @@ int expand_stack(struct vm_area_struct * vma, unsigned long address)
return
0
;
}
#ifdef ARCH_STACK_GROWSUP
struct
vm_area_struct
*
find_extend_vma
(
struct
mm_struct
*
mm
,
unsigned
long
addr
)
{
struct
vm_area_struct
*
vma
,
*
prev
;
...
...
@@ -811,6 +815,44 @@ struct vm_area_struct * find_extend_vma(struct mm_struct * mm, unsigned long add
return
prev
;
}
#else
/*
* vma is the first one with address < vma->vm_start. Have to extend vma.
*/
int
expand_stack
(
struct
vm_area_struct
*
vma
,
unsigned
long
address
)
{
unsigned
long
grow
;
/*
* vma->vm_start/vm_end cannot change under us because the caller
* is required to hold the mmap_sem in read mode. We need to get
* the spinlock only before relocating the vma range ourself.
*/
address
&=
PAGE_MASK
;
spin_lock
(
&
vma
->
vm_mm
->
page_table_lock
);
grow
=
(
vma
->
vm_start
-
address
)
>>
PAGE_SHIFT
;
/* Overcommit.. */
if
(
!
vm_enough_memory
(
grow
))
{
spin_unlock
(
&
vma
->
vm_mm
->
page_table_lock
);
return
-
ENOMEM
;
}
if
(
vma
->
vm_end
-
address
>
current
->
rlim
[
RLIMIT_STACK
].
rlim_cur
||
((
vma
->
vm_mm
->
total_vm
+
grow
)
<<
PAGE_SHIFT
)
>
current
->
rlim
[
RLIMIT_AS
].
rlim_cur
)
{
spin_unlock
(
&
vma
->
vm_mm
->
page_table_lock
);
vm_unacct_memory
(
grow
);
return
-
ENOMEM
;
}
vma
->
vm_start
=
address
;
vma
->
vm_pgoff
-=
grow
;
vma
->
vm_mm
->
total_vm
+=
grow
;
if
(
vma
->
vm_flags
&
VM_LOCKED
)
vma
->
vm_mm
->
locked_vm
+=
grow
;
spin_unlock
(
&
vma
->
vm_mm
->
page_table_lock
);
return
0
;
}
struct
vm_area_struct
*
find_extend_vma
(
struct
mm_struct
*
mm
,
unsigned
long
addr
)
{
struct
vm_area_struct
*
vma
;
...
...
Write
Preview
Markdown
is supported
0%
Try again
or
attach a new file
Attach a file
Cancel
You are about to add
0
people
to the discussion. Proceed with caution.
Finish editing this message first!
Cancel
Please
register
or
sign in
to comment