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