Skip to content
Projects
Groups
Snippets
Help
Loading...
Help
Support
Keyboard shortcuts
?
Submit feedback
Contribute to GitLab
Sign in / Register
Toggle navigation
L
linux
Project overview
Project overview
Details
Activity
Releases
Repository
Repository
Files
Commits
Branches
Tags
Contributors
Graph
Compare
Issues
0
Issues
0
List
Boards
Labels
Milestones
Merge Requests
0
Merge Requests
0
Analytics
Analytics
Repository
Value Stream
Wiki
Wiki
Snippets
Snippets
Members
Members
Collapse sidebar
Close sidebar
Activity
Graph
Create a new issue
Commits
Issue Boards
Open sidebar
Kirill Smelkov
linux
Commits
b168ffdf
Commit
b168ffdf
authored
Nov 23, 2007
by
Linus Torvalds
Browse files
Options
Browse Files
Download
Email Patches
Plain Diff
Import 0.99.14v
parent
bfeedc98
Changes
37
Hide whitespace changes
Inline
Side-by-side
Showing
37 changed files
with
1167 additions
and
939 deletions
+1167
-939
Makefile
Makefile
+1
-1
drivers/FPU-emu/errors.c
drivers/FPU-emu/errors.c
+8
-6
drivers/FPU-emu/fpu_emu.h
drivers/FPU-emu/fpu_emu.h
+3
-3
drivers/FPU-emu/fpu_entry.c
drivers/FPU-emu/fpu_entry.c
+6
-1
drivers/FPU-emu/fpu_system.h
drivers/FPU-emu/fpu_system.h
+19
-1
drivers/FPU-emu/get_address.c
drivers/FPU-emu/get_address.c
+19
-13
drivers/FPU-emu/load_store.c
drivers/FPU-emu/load_store.c
+4
-3
drivers/FPU-emu/poly_sin.c
drivers/FPU-emu/poly_sin.c
+5
-5
drivers/FPU-emu/reg_ld_str.c
drivers/FPU-emu/reg_ld_str.c
+71
-56
drivers/FPU-emu/version.h
drivers/FPU-emu/version.h
+1
-1
drivers/char/atixlmouse.c
drivers/char/atixlmouse.c
+0
-1
drivers/char/busmouse.c
drivers/char/busmouse.c
+0
-1
drivers/char/console.c
drivers/char/console.c
+2
-1
drivers/char/keyboard.c
drivers/char/keyboard.c
+29
-10
drivers/char/msbusmouse.c
drivers/char/msbusmouse.c
+0
-1
drivers/char/pty.c
drivers/char/pty.c
+31
-23
drivers/char/serial.c
drivers/char/serial.c
+7
-9
drivers/char/tty_io.c
drivers/char/tty_io.c
+503
-402
drivers/char/tty_ioctl.c
drivers/char/tty_ioctl.c
+218
-241
drivers/net/8390.c
drivers/net/8390.c
+0
-1
drivers/net/lance.c
drivers/net/lance.c
+8
-1
drivers/net/slip.c
drivers/net/slip.c
+0
-2
fs/open.c
fs/open.c
+4
-0
include/linux/kernel.h
include/linux/kernel.h
+0
-5
include/linux/mm.h
include/linux/mm.h
+18
-1
include/linux/sched.h
include/linux/sched.h
+15
-15
include/linux/termios.h
include/linux/termios.h
+1
-0
include/linux/tty.h
include/linux/tty.h
+81
-45
kernel/fork.c
kernel/fork.c
+2
-1
kernel/ksyms.S
kernel/ksyms.S
+1
-1
kernel/sys.c
kernel/sys.c
+1
-2
mm/memory.c
mm/memory.c
+1
-10
net/inet/ip.c
net/inet/ip.c
+2
-1
net/inet/skbuff.c
net/inet/skbuff.c
+35
-0
net/inet/skbuff.h
net/inet/skbuff.h
+3
-1
net/inet/tcp.c
net/inet/tcp.c
+68
-73
net/socket.c
net/socket.c
+0
-1
No files found.
Makefile
View file @
b168ffdf
VERSION
=
0.99
VERSION
=
0.99
PATCHLEVEL
=
14
PATCHLEVEL
=
14
ALPHA
=
u
ALPHA
=
v
all
:
Version zImage
all
:
Version zImage
...
...
drivers/FPU-emu/errors.c
View file @
b168ffdf
...
@@ -38,7 +38,8 @@ void Un_impl(void)
...
@@ -38,7 +38,8 @@ void Un_impl(void)
{
{
unsigned
char
byte1
,
FPU_modrm
;
unsigned
char
byte1
,
FPU_modrm
;
RE_ENTRANT_CHECK_OFF
RE_ENTRANT_CHECK_OFF
;
/* No need to verify_area(), we have previously fetched these bytes. */
byte1
=
get_fs_byte
((
unsigned
char
*
)
FPU_ORIG_EIP
);
byte1
=
get_fs_byte
((
unsigned
char
*
)
FPU_ORIG_EIP
);
FPU_modrm
=
get_fs_byte
(
1
+
(
unsigned
char
*
)
FPU_ORIG_EIP
);
FPU_modrm
=
get_fs_byte
(
1
+
(
unsigned
char
*
)
FPU_ORIG_EIP
);
...
@@ -49,7 +50,7 @@ void Un_impl(void)
...
@@ -49,7 +50,7 @@ void Un_impl(void)
printk
(
"%02x (%02x+%d)
\n
"
,
FPU_modrm
,
FPU_modrm
&
0xf8
,
FPU_modrm
&
7
);
printk
(
"%02x (%02x+%d)
\n
"
,
FPU_modrm
,
FPU_modrm
&
0xf8
,
FPU_modrm
&
7
);
else
else
printk
(
"/%d
\n
"
,
(
FPU_modrm
>>
3
)
&
7
);
printk
(
"/%d
\n
"
,
(
FPU_modrm
>>
3
)
&
7
);
RE_ENTRANT_CHECK_ON
RE_ENTRANT_CHECK_ON
;
EXCEPTION
(
EX_Invalid
);
EXCEPTION
(
EX_Invalid
);
...
@@ -65,7 +66,8 @@ void emu_printall()
...
@@ -65,7 +66,8 @@ void emu_printall()
"DeNorm"
,
"Inf"
,
"NaN"
,
"Empty"
};
"DeNorm"
,
"Inf"
,
"NaN"
,
"Empty"
};
unsigned
char
byte1
,
FPU_modrm
;
unsigned
char
byte1
,
FPU_modrm
;
RE_ENTRANT_CHECK_OFF
RE_ENTRANT_CHECK_OFF
;
/* No need to verify_area(), we have previously fetched these bytes. */
byte1
=
get_fs_byte
((
unsigned
char
*
)
FPU_ORIG_EIP
);
byte1
=
get_fs_byte
((
unsigned
char
*
)
FPU_ORIG_EIP
);
FPU_modrm
=
get_fs_byte
(
1
+
(
unsigned
char
*
)
FPU_ORIG_EIP
);
FPU_modrm
=
get_fs_byte
(
1
+
(
unsigned
char
*
)
FPU_ORIG_EIP
);
partial_status
=
status_word
();
partial_status
=
status_word
();
...
@@ -154,7 +156,7 @@ printk(" CW: ic=%d rc=%ld%ld pc=%ld%ld iem=%d ef=%d%d%d%d%d%d\n",
...
@@ -154,7 +156,7 @@ printk(" CW: ic=%d rc=%ld%ld pc=%ld%ld iem=%d ef=%d%d%d%d%d%d\n",
(
long
)(
FPU_loaded_data
.
sigl
&
0xFFFF
),
(
long
)(
FPU_loaded_data
.
sigl
&
0xFFFF
),
FPU_loaded_data
.
exp
-
EXP_BIAS
+
1
);
FPU_loaded_data
.
exp
-
EXP_BIAS
+
1
);
printk
(
"%s
\n
"
,
tag_desc
[(
int
)
(
unsigned
)
FPU_loaded_data
.
tag
]);
printk
(
"%s
\n
"
,
tag_desc
[(
int
)
(
unsigned
)
FPU_loaded_data
.
tag
]);
RE_ENTRANT_CHECK_ON
RE_ENTRANT_CHECK_ON
;
}
}
...
@@ -261,7 +263,7 @@ void exception(int n)
...
@@ -261,7 +263,7 @@ void exception(int n)
}
}
}
}
RE_ENTRANT_CHECK_OFF
RE_ENTRANT_CHECK_OFF
;
if
(
(
~
control_word
&
n
&
CW_Exceptions
)
||
(
n
==
EX_INTERNAL
)
)
if
(
(
~
control_word
&
n
&
CW_Exceptions
)
||
(
n
==
EX_INTERNAL
)
)
{
{
#ifdef PRINT_MESSAGES
#ifdef PRINT_MESSAGES
...
@@ -303,7 +305,7 @@ void exception(int n)
...
@@ -303,7 +305,7 @@ void exception(int n)
*/
*/
/* regs[0].tag |= TW_FPU_Interrupt; */
/* regs[0].tag |= TW_FPU_Interrupt; */
}
}
RE_ENTRANT_CHECK_ON
RE_ENTRANT_CHECK_ON
;
#ifdef __DEBUG__
#ifdef __DEBUG__
math_abort
(
FPU_info
,
SIGFPE
);
math_abort
(
FPU_info
,
SIGFPE
);
...
...
drivers/FPU-emu/fpu_emu.h
View file @
b168ffdf
/*---------------------------------------------------------------------------+
/*---------------------------------------------------------------------------+
| fpu_emu.h |
| fpu_emu.h |
| |
| |
| Copyright (C) 1992,1993
|
| Copyright (C) 1992,1993
,1994
|
| W. Metzenthen, 22 Parker St, Ormond, Vic 3163, |
| W. Metzenthen, 22 Parker St, Ormond, Vic 3163, |
| Australia. E-mail billm@vaxc.cc.monash.edu.au |
| Australia. E-mail billm@vaxc.cc.monash.edu.au |
| |
| |
...
@@ -62,8 +62,8 @@
...
@@ -62,8 +62,8 @@
#ifdef PARANOID
#ifdef PARANOID
extern
char
emulating
;
extern
char
emulating
;
# define RE_ENTRANT_CHECK_OFF emulating = 0
;
# define RE_ENTRANT_CHECK_OFF emulating = 0
# define RE_ENTRANT_CHECK_ON emulating = 1
;
# define RE_ENTRANT_CHECK_ON emulating = 1
#else
#else
# define RE_ENTRANT_CHECK_OFF
# define RE_ENTRANT_CHECK_OFF
# define RE_ENTRANT_CHECK_ON
# define RE_ENTRANT_CHECK_ON
...
...
drivers/FPU-emu/fpu_entry.c
View file @
b168ffdf
...
@@ -209,6 +209,7 @@ asmlinkage void math_emulate(long arg)
...
@@ -209,6 +209,7 @@ asmlinkage void math_emulate(long arg)
do_another_FPU_instruction:
do_another_FPU_instruction:
RE_ENTRANT_CHECK_OFF
;
RE_ENTRANT_CHECK_OFF
;
FPU_code_verify_area
(
1
);
code
=
get_fs_word
((
unsigned
short
*
)
FPU_EIP
);
code
=
get_fs_word
((
unsigned
short
*
)
FPU_EIP
);
RE_ENTRANT_CHECK_ON
;
RE_ENTRANT_CHECK_ON
;
...
@@ -301,6 +302,7 @@ asmlinkage void math_emulate(long arg)
...
@@ -301,6 +302,7 @@ asmlinkage void math_emulate(long arg)
{
{
FPU_EIP
++
;
FPU_EIP
++
;
RE_ENTRANT_CHECK_OFF
;
RE_ENTRANT_CHECK_OFF
;
FPU_code_verify_area
(
1
);
code
=
get_fs_word
((
unsigned
short
*
)
FPU_EIP
);
code
=
get_fs_word
((
unsigned
short
*
)
FPU_EIP
);
RE_ENTRANT_CHECK_ON
;
RE_ENTRANT_CHECK_ON
;
}
}
...
@@ -560,6 +562,7 @@ asmlinkage void math_emulate(long arg)
...
@@ -560,6 +562,7 @@ asmlinkage void math_emulate(long arg)
unsigned
char
next
;
unsigned
char
next
;
RE_ENTRANT_CHECK_OFF
;
RE_ENTRANT_CHECK_OFF
;
FPU_code_verify_area
(
1
);
next
=
get_fs_byte
((
unsigned
char
*
)
FPU_EIP
);
next
=
get_fs_byte
((
unsigned
char
*
)
FPU_EIP
);
RE_ENTRANT_CHECK_ON
;
RE_ENTRANT_CHECK_ON
;
if
(
valid_prefix
(
next
)
)
if
(
valid_prefix
(
next
)
)
...
@@ -591,8 +594,10 @@ static int valid_prefix(unsigned char byte)
...
@@ -591,8 +594,10 @@ static int valid_prefix(unsigned char byte)
case
PREFIX_GS
:
case
PREFIX_GS
:
case
OP_SIZE_PREFIX
:
/* Used often by gcc, but has no effect. */
case
OP_SIZE_PREFIX
:
/* Used often by gcc, but has no effect. */
FPU_EIP
++
;
RE_ENTRANT_CHECK_OFF
;
RE_ENTRANT_CHECK_OFF
;
byte
=
get_fs_byte
((
unsigned
char
*
)
(
++
FPU_EIP
));
FPU_code_verify_area
(
1
);
byte
=
get_fs_byte
((
unsigned
char
*
)
(
FPU_EIP
));
RE_ENTRANT_CHECK_ON
;
RE_ENTRANT_CHECK_ON
;
break
;
break
;
case
FWAIT_OPCODE
:
case
FWAIT_OPCODE
:
...
...
drivers/FPU-emu/fpu_system.h
View file @
b168ffdf
/*---------------------------------------------------------------------------+
/*---------------------------------------------------------------------------+
| fpu_system.h |
| fpu_system.h |
| |
| |
| Copyright (C) 1992 W. Metzenthen, 22 Parker St, Ormond, Vic 3163, |
| Copyright (C) 1992,1994 |
| W. Metzenthen, 22 Parker St, Ormond, Vic 3163, |
| Australia. E-mail billm@vaxc.cc.monash.edu.au |
| Australia. E-mail billm@vaxc.cc.monash.edu.au |
| |
| |
+---------------------------------------------------------------------------*/
+---------------------------------------------------------------------------*/
...
@@ -41,6 +42,23 @@
...
@@ -41,6 +42,23 @@
#define data_operand_offset (I387.soft.foo)
#define data_operand_offset (I387.soft.foo)
#define operand_selector (I387.soft.fos)
#define operand_selector (I387.soft.fos)
#define FPU_verify_area(x,y,z) if ( verify_area(x,y,z) ) \
math_abort(FPU_info,SIGSEGV)
#undef FPU_IGNORE_CODE_SEGV
#ifdef FPU_IGNORE_CODE_SEGV
/* verify_area() is very expensive, and causes the emulator to run
about 20% slower if applied to the code. Anyway, errors due to bad
code addresses should be much rarer than errors due to bad data
addresses. */
#define FPU_code_verify_area(z)
#else
/* A simpler test than verify_area() can probably be done for
FPU_code_verify_area() because the only possible error is to step
past the upper boundary of a legal code area. */
#define FPU_code_verify_area(z) FPU_verify_area(VERIFY_READ,(void *)FPU_EIP,z)
#endif
/* ######## temporary and ugly ;-) */
/* ######## temporary and ugly ;-) */
#define FPU_data_address ((void *)(I387.soft.twd))
#define FPU_data_address ((void *)(I387.soft.twd))
...
...
drivers/FPU-emu/get_address.c
View file @
b168ffdf
...
@@ -3,7 +3,7 @@
...
@@ -3,7 +3,7 @@
| |
| |
| Get the effective address from an FPU instruction. |
| Get the effective address from an FPU instruction. |
| |
| |
| Copyright (C) 1992,1993
|
| Copyright (C) 1992,1993
,1994
|
| W. Metzenthen, 22 Parker St, Ormond, Vic 3163, |
| W. Metzenthen, 22 Parker St, Ormond, Vic 3163, |
| Australia. E-mail billm@vaxc.cc.monash.edu.au |
| Australia. E-mail billm@vaxc.cc.monash.edu.au |
| |
| |
...
@@ -46,9 +46,10 @@ static void *sib(int mod)
...
@@ -46,9 +46,10 @@ static void *sib(int mod)
unsigned
char
ss
,
index
,
base
;
unsigned
char
ss
,
index
,
base
;
long
offset
;
long
offset
;
RE_ENTRANT_CHECK_OFF
RE_ENTRANT_CHECK_OFF
;
FPU_code_verify_area
(
1
);
base
=
get_fs_byte
((
char
*
)
FPU_EIP
);
/* The SIB byte */
base
=
get_fs_byte
((
char
*
)
FPU_EIP
);
/* The SIB byte */
RE_ENTRANT_CHECK_ON
RE_ENTRANT_CHECK_ON
;
FPU_EIP
++
;
FPU_EIP
++
;
ss
=
base
>>
6
;
ss
=
base
>>
6
;
index
=
(
base
>>
3
)
&
7
;
index
=
(
base
>>
3
)
&
7
;
...
@@ -74,17 +75,19 @@ static void *sib(int mod)
...
@@ -74,17 +75,19 @@ static void *sib(int mod)
if
(
mod
==
1
)
if
(
mod
==
1
)
{
{
/* 8 bit signed displacement */
/* 8 bit signed displacement */
RE_ENTRANT_CHECK_OFF
RE_ENTRANT_CHECK_OFF
;
FPU_code_verify_area
(
1
);
offset
+=
(
signed
char
)
get_fs_byte
((
char
*
)
FPU_EIP
);
offset
+=
(
signed
char
)
get_fs_byte
((
char
*
)
FPU_EIP
);
RE_ENTRANT_CHECK_ON
RE_ENTRANT_CHECK_ON
;
FPU_EIP
++
;
FPU_EIP
++
;
}
}
else
if
(
mod
==
2
||
base
==
5
)
/* The second condition also has mod==0 */
else
if
(
mod
==
2
||
base
==
5
)
/* The second condition also has mod==0 */
{
{
/* 32 bit displacment */
/* 32 bit displacment */
RE_ENTRANT_CHECK_OFF
RE_ENTRANT_CHECK_OFF
;
FPU_code_verify_area
(
4
);
offset
+=
(
signed
)
get_fs_long
((
unsigned
long
*
)
FPU_EIP
);
offset
+=
(
signed
)
get_fs_long
((
unsigned
long
*
)
FPU_EIP
);
RE_ENTRANT_CHECK_ON
RE_ENTRANT_CHECK_ON
;
FPU_EIP
+=
4
;
FPU_EIP
+=
4
;
}
}
...
@@ -135,9 +138,10 @@ void get_address(unsigned char FPU_modrm)
...
@@ -135,9 +138,10 @@ void get_address(unsigned char FPU_modrm)
if
(
FPU_rm
==
5
)
if
(
FPU_rm
==
5
)
{
{
/* Special case: disp32 */
/* Special case: disp32 */
RE_ENTRANT_CHECK_OFF
RE_ENTRANT_CHECK_OFF
;
FPU_code_verify_area
(
4
);
offset
=
get_fs_long
((
unsigned
long
*
)
FPU_EIP
);
offset
=
get_fs_long
((
unsigned
long
*
)
FPU_EIP
);
RE_ENTRANT_CHECK_ON
RE_ENTRANT_CHECK_ON
;
FPU_EIP
+=
4
;
FPU_EIP
+=
4
;
FPU_data_address
=
(
void
*
)
offset
;
FPU_data_address
=
(
void
*
)
offset
;
return
;
return
;
...
@@ -150,16 +154,18 @@ void get_address(unsigned char FPU_modrm)
...
@@ -150,16 +154,18 @@ void get_address(unsigned char FPU_modrm)
}
}
case
1
:
case
1
:
/* 8 bit signed displacement */
/* 8 bit signed displacement */
RE_ENTRANT_CHECK_OFF
RE_ENTRANT_CHECK_OFF
;
FPU_code_verify_area
(
1
);
offset
=
(
signed
char
)
get_fs_byte
((
char
*
)
FPU_EIP
);
offset
=
(
signed
char
)
get_fs_byte
((
char
*
)
FPU_EIP
);
RE_ENTRANT_CHECK_ON
RE_ENTRANT_CHECK_ON
;
FPU_EIP
++
;
FPU_EIP
++
;
break
;
break
;
case
2
:
case
2
:
/* 32 bit displacement */
/* 32 bit displacement */
RE_ENTRANT_CHECK_OFF
RE_ENTRANT_CHECK_OFF
;
FPU_code_verify_area
(
4
);
offset
=
(
signed
)
get_fs_long
((
unsigned
long
*
)
FPU_EIP
);
offset
=
(
signed
)
get_fs_long
((
unsigned
long
*
)
FPU_EIP
);
RE_ENTRANT_CHECK_ON
RE_ENTRANT_CHECK_ON
;
FPU_EIP
+=
4
;
FPU_EIP
+=
4
;
break
;
break
;
case
3
:
case
3
:
...
...
drivers/FPU-emu/load_store.c
View file @
b168ffdf
...
@@ -4,7 +4,7 @@
...
@@ -4,7 +4,7 @@
| This file contains most of the code to interpret the FPU instructions |
| This file contains most of the code to interpret the FPU instructions |
| which load and store from user memory. |
| which load and store from user memory. |
| |
| |
| Copyright (C) 1992,1993
|
| Copyright (C) 1992,1993
,1994
|
| W. Metzenthen, 22 Parker St, Ormond, Vic 3163, |
| W. Metzenthen, 22 Parker St, Ormond, Vic 3163, |
| Australia. E-mail billm@vaxc.cc.monash.edu.au |
| Australia. E-mail billm@vaxc.cc.monash.edu.au |
| |
| |
...
@@ -168,6 +168,7 @@ switch ( type )
...
@@ -168,6 +168,7 @@ switch ( type )
break
;
break
;
case
024
:
/* fldcw */
case
024
:
/* fldcw */
RE_ENTRANT_CHECK_OFF
;
RE_ENTRANT_CHECK_OFF
;
FPU_verify_area
(
VERIFY_READ
,
FPU_data_address
,
2
);
control_word
=
get_fs_word
((
unsigned
short
*
)
FPU_data_address
);
control_word
=
get_fs_word
((
unsigned
short
*
)
FPU_data_address
);
RE_ENTRANT_CHECK_ON
;
RE_ENTRANT_CHECK_ON
;
if
(
partial_status
&
~
control_word
&
CW_Exceptions
)
if
(
partial_status
&
~
control_word
&
CW_Exceptions
)
...
@@ -206,7 +207,7 @@ switch ( type )
...
@@ -206,7 +207,7 @@ switch ( type )
break
;
break
;
case
034
:
/* fstcw m16int */
case
034
:
/* fstcw m16int */
RE_ENTRANT_CHECK_OFF
;
RE_ENTRANT_CHECK_OFF
;
verify_area
(
VERIFY_WRITE
,
FPU_data_address
,
2
);
FPU_
verify_area
(
VERIFY_WRITE
,
FPU_data_address
,
2
);
put_fs_word
(
control_word
,
(
short
*
)
FPU_data_address
);
put_fs_word
(
control_word
,
(
short
*
)
FPU_data_address
);
RE_ENTRANT_CHECK_ON
;
RE_ENTRANT_CHECK_ON
;
NO_NET_DATA_EFFECT
;
NO_NET_DATA_EFFECT
;
...
@@ -220,7 +221,7 @@ switch ( type )
...
@@ -220,7 +221,7 @@ switch ( type )
break
;
break
;
case
036
:
/* fstsw m2byte */
case
036
:
/* fstsw m2byte */
RE_ENTRANT_CHECK_OFF
;
RE_ENTRANT_CHECK_OFF
;
verify_area
(
VERIFY_WRITE
,
FPU_data_address
,
2
);
FPU_
verify_area
(
VERIFY_WRITE
,
FPU_data_address
,
2
);
put_fs_word
(
status_word
(),(
short
*
)
FPU_data_address
);
put_fs_word
(
status_word
(),(
short
*
)
FPU_data_address
);
RE_ENTRANT_CHECK_ON
;
RE_ENTRANT_CHECK_ON
;
NO_NET_DATA_EFFECT
;
NO_NET_DATA_EFFECT
;
...
...
drivers/FPU-emu/poly_sin.c
View file @
b168ffdf
...
@@ -3,7 +3,7 @@
...
@@ -3,7 +3,7 @@
| |
| |
| Computation of an approximation of the sin function by a polynomial |
| Computation of an approximation of the sin function by a polynomial |
| |
| |
| Copyright (C) 1992,1993
|
| Copyright (C) 1992,1993
,1994
|
| W. Metzenthen, 22 Parker St, Ormond, Vic 3163, |
| W. Metzenthen, 22 Parker St, Ormond, Vic 3163, |
| Australia. E-mail billm@vaxc.cc.monash.edu.au |
| Australia. E-mail billm@vaxc.cc.monash.edu.au |
| |
| |
...
@@ -128,20 +128,20 @@ void poly_sine(FPU_REG const *arg, FPU_REG *result)
...
@@ -128,20 +128,20 @@ void poly_sine(FPU_REG const *arg, FPU_REG *result)
)
)
{
{
#ifdef DEBUGGING
#ifdef DEBUGGING
RE_ENTRANT_CHECK_OFF
RE_ENTRANT_CHECK_OFF
;
printk
(
"
\n
EXP=%d, MS=%08x, LS=%08x
\n
"
,
result
->
exp
,
printk
(
"
\n
EXP=%d, MS=%08x, LS=%08x
\n
"
,
result
->
exp
,
result
->
sigh
,
result
->
sigl
);
result
->
sigh
,
result
->
sigl
);
RE_ENTRANT_CHECK_ON
RE_ENTRANT_CHECK_ON
;
#endif DEBUGGING
#endif DEBUGGING
EXCEPTION
(
EX_INTERNAL
|
0x103
);
EXCEPTION
(
EX_INTERNAL
|
0x103
);
}
}
#ifdef DEBUGGING
#ifdef DEBUGGING
RE_ENTRANT_CHECK_OFF
RE_ENTRANT_CHECK_OFF
;
printk
(
"
\n
***CORRECTING ILLEGAL RESULT*** in poly_sin() computation
\n
"
);
printk
(
"
\n
***CORRECTING ILLEGAL RESULT*** in poly_sin() computation
\n
"
);
printk
(
"EXP=%d, MS=%08x, LS=%08x
\n
"
,
result
->
exp
,
printk
(
"EXP=%d, MS=%08x, LS=%08x
\n
"
,
result
->
exp
,
result
->
sigh
,
result
->
sigl
);
result
->
sigh
,
result
->
sigl
);
RE_ENTRANT_CHECK_ON
RE_ENTRANT_CHECK_ON
;
#endif DEBUGGING
#endif DEBUGGING
result
->
sigl
=
0
;
/* Truncate the result to 1.00 */
result
->
sigl
=
0
;
/* Truncate the result to 1.00 */
...
...
drivers/FPU-emu/reg_ld_str.c
View file @
b168ffdf
...
@@ -3,7 +3,7 @@
...
@@ -3,7 +3,7 @@
| |
| |
| All of the functions which transfer data between user memory and FPU_REGs.|
| All of the functions which transfer data between user memory and FPU_REGs.|
| |
| |
| Copyright (C) 1992,1993
|
| Copyright (C) 1992,1993
,1994
|
| W. Metzenthen, 22 Parker St, Ormond, Vic 3163, |
| W. Metzenthen, 22 Parker St, Ormond, Vic 3163, |
| Australia. E-mail billm@vaxc.cc.monash.edu.au |
| Australia. E-mail billm@vaxc.cc.monash.edu.au |
| |
| |
...
@@ -49,13 +49,14 @@ int reg_load_extended(void)
...
@@ -49,13 +49,14 @@ int reg_load_extended(void)
long
double
*
s
=
(
long
double
*
)
FPU_data_address
;
long
double
*
s
=
(
long
double
*
)
FPU_data_address
;
unsigned
long
sigl
,
sigh
,
exp
;
unsigned
long
sigl
,
sigh
,
exp
;
RE_ENTRANT_CHECK_OFF
RE_ENTRANT_CHECK_OFF
;
FPU_verify_area
(
VERIFY_READ
,
s
,
10
);
/* Use temporary variables here because FPU_loaded data is
/* Use temporary variables here because FPU_loaded data is
static and hence re-entrancy problems can arise */
static and hence re-entrancy problems can arise */
sigl
=
get_fs_long
((
unsigned
long
*
)
s
);
sigl
=
get_fs_long
((
unsigned
long
*
)
s
);
sigh
=
get_fs_long
(
1
+
(
unsigned
long
*
)
s
);
sigh
=
get_fs_long
(
1
+
(
unsigned
long
*
)
s
);
exp
=
get_fs_word
(
4
+
(
unsigned
short
*
)
s
);
exp
=
get_fs_word
(
4
+
(
unsigned
short
*
)
s
);
RE_ENTRANT_CHECK_ON
RE_ENTRANT_CHECK_ON
;
FPU_loaded_data
.
tag
=
TW_Valid
;
/* Default */
FPU_loaded_data
.
tag
=
TW_Valid
;
/* Default */
FPU_loaded_data
.
sigl
=
sigl
;
FPU_loaded_data
.
sigl
=
sigl
;
...
@@ -150,10 +151,11 @@ int reg_load_double(void)
...
@@ -150,10 +151,11 @@ int reg_load_double(void)
int
exp
;
int
exp
;
unsigned
m64
,
l64
;
unsigned
m64
,
l64
;
RE_ENTRANT_CHECK_OFF
RE_ENTRANT_CHECK_OFF
;
FPU_verify_area
(
VERIFY_READ
,
dfloat
,
8
);
m64
=
get_fs_long
(
1
+
(
unsigned
long
*
)
dfloat
);
m64
=
get_fs_long
(
1
+
(
unsigned
long
*
)
dfloat
);
l64
=
get_fs_long
((
unsigned
long
*
)
dfloat
);
l64
=
get_fs_long
((
unsigned
long
*
)
dfloat
);
RE_ENTRANT_CHECK_ON
RE_ENTRANT_CHECK_ON
;
if
(
m64
&
0x80000000
)
if
(
m64
&
0x80000000
)
FPU_loaded_data
.
sign
=
SIGN_NEG
;
FPU_loaded_data
.
sign
=
SIGN_NEG
;
...
@@ -227,9 +229,10 @@ int reg_load_single(void)
...
@@ -227,9 +229,10 @@ int reg_load_single(void)
unsigned
m32
;
unsigned
m32
;
int
exp
;
int
exp
;
RE_ENTRANT_CHECK_OFF
RE_ENTRANT_CHECK_OFF
;
FPU_verify_area
(
VERIFY_READ
,
single
,
4
);
m32
=
get_fs_long
((
unsigned
long
*
)
single
);
m32
=
get_fs_long
((
unsigned
long
*
)
single
);
RE_ENTRANT_CHECK_ON
RE_ENTRANT_CHECK_ON
;
if
(
m32
&
0x80000000
)
if
(
m32
&
0x80000000
)
FPU_loaded_data
.
sign
=
SIGN_NEG
;
FPU_loaded_data
.
sign
=
SIGN_NEG
;
...
@@ -295,10 +298,11 @@ void reg_load_int64(void)
...
@@ -295,10 +298,11 @@ void reg_load_int64(void)
int
e
;
int
e
;
long
long
s
;
long
long
s
;
RE_ENTRANT_CHECK_OFF
RE_ENTRANT_CHECK_OFF
;
FPU_verify_area
(
VERIFY_READ
,
_s
,
8
);
((
unsigned
long
*
)
&
s
)[
0
]
=
get_fs_long
((
unsigned
long
*
)
_s
);
((
unsigned
long
*
)
&
s
)[
0
]
=
get_fs_long
((
unsigned
long
*
)
_s
);
((
unsigned
long
*
)
&
s
)[
1
]
=
get_fs_long
(
1
+
(
unsigned
long
*
)
_s
);
((
unsigned
long
*
)
&
s
)[
1
]
=
get_fs_long
(
1
+
(
unsigned
long
*
)
_s
);
RE_ENTRANT_CHECK_ON
RE_ENTRANT_CHECK_ON
;
if
(
s
==
0
)
if
(
s
==
0
)
{
reg_move
(
&
CONST_Z
,
&
FPU_loaded_data
);
return
;
}
{
reg_move
(
&
CONST_Z
,
&
FPU_loaded_data
);
return
;
}
...
@@ -326,9 +330,10 @@ void reg_load_int32(void)
...
@@ -326,9 +330,10 @@ void reg_load_int32(void)
long
s
;
long
s
;
int
e
;
int
e
;
RE_ENTRANT_CHECK_OFF
RE_ENTRANT_CHECK_OFF
;
FPU_verify_area
(
VERIFY_READ
,
_s
,
4
);
s
=
(
long
)
get_fs_long
((
unsigned
long
*
)
_s
);
s
=
(
long
)
get_fs_long
((
unsigned
long
*
)
_s
);
RE_ENTRANT_CHECK_ON
RE_ENTRANT_CHECK_ON
;
if
(
s
==
0
)
if
(
s
==
0
)
{
reg_move
(
&
CONST_Z
,
&
FPU_loaded_data
);
return
;
}
{
reg_move
(
&
CONST_Z
,
&
FPU_loaded_data
);
return
;
}
...
@@ -356,10 +361,11 @@ void reg_load_int16(void)
...
@@ -356,10 +361,11 @@ void reg_load_int16(void)
short
*
_s
=
(
short
*
)
FPU_data_address
;
short
*
_s
=
(
short
*
)
FPU_data_address
;
int
s
,
e
;
int
s
,
e
;
RE_ENTRANT_CHECK_OFF
RE_ENTRANT_CHECK_OFF
;
FPU_verify_area
(
VERIFY_READ
,
_s
,
2
);
/* Cast as short to get the sign extended. */
/* Cast as short to get the sign extended. */
s
=
(
short
)
get_fs_word
((
unsigned
short
*
)
_s
);
s
=
(
short
)
get_fs_word
((
unsigned
short
*
)
_s
);
RE_ENTRANT_CHECK_ON
RE_ENTRANT_CHECK_ON
;
if
(
s
==
0
)
if
(
s
==
0
)
{
reg_move
(
&
CONST_Z
,
&
FPU_loaded_data
);
return
;
}
{
reg_move
(
&
CONST_Z
,
&
FPU_loaded_data
);
return
;
}
...
@@ -390,12 +396,15 @@ void reg_load_bcd(void)
...
@@ -390,12 +396,15 @@ void reg_load_bcd(void)
unsigned
char
bcd
;
unsigned
char
bcd
;
long
long
l
=
0
;
long
long
l
=
0
;
RE_ENTRANT_CHECK_OFF
;
FPU_verify_area
(
VERIFY_READ
,
s
,
10
);
RE_ENTRANT_CHECK_ON
;
for
(
pos
=
8
;
pos
>=
0
;
pos
--
)
for
(
pos
=
8
;
pos
>=
0
;
pos
--
)
{
{
l
*=
10
;
l
*=
10
;
RE_ENTRANT_CHECK_OFF
RE_ENTRANT_CHECK_OFF
;
bcd
=
(
unsigned
char
)
get_fs_byte
((
unsigned
char
*
)
s
+
pos
);
bcd
=
(
unsigned
char
)
get_fs_byte
((
unsigned
char
*
)
s
+
pos
);
RE_ENTRANT_CHECK_ON
RE_ENTRANT_CHECK_ON
;
l
+=
bcd
>>
4
;
l
+=
bcd
>>
4
;
l
*=
10
;
l
*=
10
;
l
+=
bcd
&
0x0f
;
l
+=
bcd
&
0x0f
;
...
@@ -403,11 +412,11 @@ void reg_load_bcd(void)
...
@@ -403,11 +412,11 @@ void reg_load_bcd(void)
/* Finish all access to user memory before putting stuff into
/* Finish all access to user memory before putting stuff into
the static FPU_loaded_data */
the static FPU_loaded_data */
RE_ENTRANT_CHECK_OFF
RE_ENTRANT_CHECK_OFF
;
FPU_loaded_data
.
sign
=
FPU_loaded_data
.
sign
=
((
unsigned
char
)
get_fs_byte
((
unsigned
char
*
)
s
+
9
))
&
0x80
?
((
unsigned
char
)
get_fs_byte
((
unsigned
char
*
)
s
+
9
))
&
0x80
?
SIGN_NEG
:
SIGN_POS
;
SIGN_NEG
:
SIGN_POS
;
RE_ENTRANT_CHECK_ON
RE_ENTRANT_CHECK_ON
;
if
(
l
==
0
)
if
(
l
==
0
)
{
{
...
@@ -438,7 +447,9 @@ int reg_store_extended(void)
...
@@ -438,7 +447,9 @@ int reg_store_extended(void)
if
(
FPU_st0_tag
!=
TW_Empty
)
if
(
FPU_st0_tag
!=
TW_Empty
)
{
{
verify_area
(
VERIFY_WRITE
,
d
,
10
);
RE_ENTRANT_CHECK_OFF
;
FPU_verify_area
(
VERIFY_WRITE
,
d
,
10
);
RE_ENTRANT_CHECK_ON
;
write_to_extended
(
FPU_st0_ptr
,
(
char
*
)
FPU_data_address
);
write_to_extended
(
FPU_st0_ptr
,
(
char
*
)
FPU_data_address
);
return
1
;
return
1
;
}
}
...
@@ -450,7 +461,7 @@ int reg_store_extended(void)
...
@@ -450,7 +461,7 @@ int reg_store_extended(void)
/* The masked response */
/* The masked response */
/* Put out the QNaN indefinite */
/* Put out the QNaN indefinite */
RE_ENTRANT_CHECK_OFF
;
RE_ENTRANT_CHECK_OFF
;
verify_area
(
VERIFY_WRITE
,
d
,
10
);
FPU_
verify_area
(
VERIFY_WRITE
,
d
,
10
);
put_fs_long
(
0
,
(
unsigned
long
*
)
d
);
put_fs_long
(
0
,
(
unsigned
long
*
)
d
);
put_fs_long
(
0xc0000000
,
1
+
(
unsigned
long
*
)
d
);
put_fs_long
(
0xc0000000
,
1
+
(
unsigned
long
*
)
d
);
put_fs_word
(
0xffff
,
4
+
(
short
*
)
d
);
put_fs_word
(
0xffff
,
4
+
(
short
*
)
d
);
...
@@ -635,11 +646,11 @@ int reg_store_double(void)
...
@@ -635,11 +646,11 @@ int reg_store_double(void)
{
{
/* The masked response */
/* The masked response */
/* Put out the QNaN indefinite */
/* Put out the QNaN indefinite */
RE_ENTRANT_CHECK_OFF
RE_ENTRANT_CHECK_OFF
;
verify_area
(
VERIFY_WRITE
,(
void
*
)
dfloat
,
8
);
FPU_
verify_area
(
VERIFY_WRITE
,(
void
*
)
dfloat
,
8
);
put_fs_long
(
0
,
(
unsigned
long
*
)
dfloat
);
put_fs_long
(
0
,
(
unsigned
long
*
)
dfloat
);
put_fs_long
(
0xfff80000
,
1
+
(
unsigned
long
*
)
dfloat
);
put_fs_long
(
0xfff80000
,
1
+
(
unsigned
long
*
)
dfloat
);
RE_ENTRANT_CHECK_ON
RE_ENTRANT_CHECK_ON
;
return
1
;
return
1
;
}
}
else
else
...
@@ -648,11 +659,11 @@ int reg_store_double(void)
...
@@ -648,11 +659,11 @@ int reg_store_double(void)
if
(
FPU_st0_ptr
->
sign
)
if
(
FPU_st0_ptr
->
sign
)
l
[
1
]
|=
0x80000000
;
l
[
1
]
|=
0x80000000
;
RE_ENTRANT_CHECK_OFF
RE_ENTRANT_CHECK_OFF
;
verify_area
(
VERIFY_WRITE
,(
void
*
)
dfloat
,
8
);
FPU_
verify_area
(
VERIFY_WRITE
,(
void
*
)
dfloat
,
8
);
put_fs_long
(
l
[
0
],
(
unsigned
long
*
)
dfloat
);
put_fs_long
(
l
[
0
],
(
unsigned
long
*
)
dfloat
);
put_fs_long
(
l
[
1
],
1
+
(
unsigned
long
*
)
dfloat
);
put_fs_long
(
l
[
1
],
1
+
(
unsigned
long
*
)
dfloat
);
RE_ENTRANT_CHECK_ON
RE_ENTRANT_CHECK_ON
;
return
1
;
return
1
;
}
}
...
@@ -819,10 +830,10 @@ int reg_store_single(void)
...
@@ -819,10 +830,10 @@ int reg_store_single(void)
{
{
/* The masked response */
/* The masked response */
/* Put out the QNaN indefinite */
/* Put out the QNaN indefinite */
RE_ENTRANT_CHECK_OFF
RE_ENTRANT_CHECK_OFF
;
verify_area
(
VERIFY_WRITE
,(
void
*
)
single
,
4
);
FPU_
verify_area
(
VERIFY_WRITE
,(
void
*
)
single
,
4
);
put_fs_long
(
0xffc00000
,
(
unsigned
long
*
)
single
);
put_fs_long
(
0xffc00000
,
(
unsigned
long
*
)
single
);
RE_ENTRANT_CHECK_ON
RE_ENTRANT_CHECK_ON
;
return
1
;
return
1
;
}
}
else
else
...
@@ -838,10 +849,10 @@ int reg_store_single(void)
...
@@ -838,10 +849,10 @@ int reg_store_single(void)
if
(
FPU_st0_ptr
->
sign
)
if
(
FPU_st0_ptr
->
sign
)
templ
|=
0x80000000
;
templ
|=
0x80000000
;
RE_ENTRANT_CHECK_OFF
RE_ENTRANT_CHECK_OFF
;
verify_area
(
VERIFY_WRITE
,(
void
*
)
single
,
4
);
FPU_
verify_area
(
VERIFY_WRITE
,(
void
*
)
single
,
4
);
put_fs_long
(
templ
,(
unsigned
long
*
)
single
);
put_fs_long
(
templ
,(
unsigned
long
*
)
single
);
RE_ENTRANT_CHECK_ON
RE_ENTRANT_CHECK_ON
;
return
1
;
return
1
;
}
}
...
@@ -896,11 +907,11 @@ int reg_store_int64(void)
...
@@ -896,11 +907,11 @@ int reg_store_int64(void)
tll
=
-
tll
;
tll
=
-
tll
;
}
}
RE_ENTRANT_CHECK_OFF
RE_ENTRANT_CHECK_OFF
;
verify_area
(
VERIFY_WRITE
,(
void
*
)
d
,
8
);
FPU_
verify_area
(
VERIFY_WRITE
,(
void
*
)
d
,
8
);
put_fs_long
(((
long
*
)
&
tll
)[
0
],(
unsigned
long
*
)
d
);
put_fs_long
(((
long
*
)
&
tll
)[
0
],(
unsigned
long
*
)
d
);
put_fs_long
(((
long
*
)
&
tll
)[
1
],
1
+
(
unsigned
long
*
)
d
);
put_fs_long
(((
long
*
)
&
tll
)[
1
],
1
+
(
unsigned
long
*
)
d
);
RE_ENTRANT_CHECK_ON
RE_ENTRANT_CHECK_ON
;
return
1
;
return
1
;
}
}
...
@@ -951,10 +962,10 @@ int reg_store_int32(void)
...
@@ -951,10 +962,10 @@ int reg_store_int32(void)
t
.
sigl
=
-
(
long
)
t
.
sigl
;
t
.
sigl
=
-
(
long
)
t
.
sigl
;
}
}
RE_ENTRANT_CHECK_OFF
RE_ENTRANT_CHECK_OFF
;
verify_area
(
VERIFY_WRITE
,
d
,
4
);
FPU_
verify_area
(
VERIFY_WRITE
,
d
,
4
);
put_fs_long
(
t
.
sigl
,
(
unsigned
long
*
)
d
);
put_fs_long
(
t
.
sigl
,
(
unsigned
long
*
)
d
);
RE_ENTRANT_CHECK_ON
RE_ENTRANT_CHECK_ON
;
return
1
;
return
1
;
}
}
...
@@ -1005,10 +1016,10 @@ int reg_store_int16(void)
...
@@ -1005,10 +1016,10 @@ int reg_store_int16(void)
t
.
sigl
=
-
t
.
sigl
;
t
.
sigl
=
-
t
.
sigl
;
}
}
RE_ENTRANT_CHECK_OFF
RE_ENTRANT_CHECK_OFF
;
verify_area
(
VERIFY_WRITE
,
d
,
2
);
FPU_
verify_area
(
VERIFY_WRITE
,
d
,
2
);
put_fs_word
((
short
)
t
.
sigl
,(
short
*
)
d
);
put_fs_word
((
short
)
t
.
sigl
,(
short
*
)
d
);
RE_ENTRANT_CHECK_ON
RE_ENTRANT_CHECK_ON
;
return
1
;
return
1
;
}
}
...
@@ -1045,14 +1056,14 @@ int reg_store_bcd(void)
...
@@ -1045,14 +1056,14 @@ int reg_store_bcd(void)
if
(
control_word
&
CW_Invalid
)
if
(
control_word
&
CW_Invalid
)
{
{
/* Produce the QNaN "indefinite" */
/* Produce the QNaN "indefinite" */
RE_ENTRANT_CHECK_OFF
RE_ENTRANT_CHECK_OFF
;
verify_area
(
VERIFY_WRITE
,
d
,
10
);
FPU_
verify_area
(
VERIFY_WRITE
,
d
,
10
);
for
(
i
=
0
;
i
<
7
;
i
++
)
for
(
i
=
0
;
i
<
7
;
i
++
)
put_fs_byte
(
0
,
(
unsigned
char
*
)
d
+
i
);
/* These bytes "undefined" */
put_fs_byte
(
0
,
(
unsigned
char
*
)
d
+
i
);
/* These bytes "undefined" */
put_fs_byte
(
0xc0
,
(
unsigned
char
*
)
d
+
7
);
/* This byte "undefined" */
put_fs_byte
(
0xc0
,
(
unsigned
char
*
)
d
+
7
);
/* This byte "undefined" */
put_fs_byte
(
0xff
,
(
unsigned
char
*
)
d
+
8
);
put_fs_byte
(
0xff
,
(
unsigned
char
*
)
d
+
8
);
put_fs_byte
(
0xff
,
(
unsigned
char
*
)
d
+
9
);
put_fs_byte
(
0xff
,
(
unsigned
char
*
)
d
+
9
);
RE_ENTRANT_CHECK_ON
RE_ENTRANT_CHECK_ON
;
return
1
;
return
1
;
}
}
else
else
...
@@ -1064,18 +1075,20 @@ int reg_store_bcd(void)
...
@@ -1064,18 +1075,20 @@ int reg_store_bcd(void)
set_precision_flag
(
precision_loss
);
set_precision_flag
(
precision_loss
);
}
}
verify_area
(
VERIFY_WRITE
,
d
,
10
);
RE_ENTRANT_CHECK_OFF
;
FPU_verify_area
(
VERIFY_WRITE
,
d
,
10
);
RE_ENTRANT_CHECK_ON
;
for
(
i
=
0
;
i
<
9
;
i
++
)
for
(
i
=
0
;
i
<
9
;
i
++
)
{
{
b
=
div_small
(
&
ll
,
10
);
b
=
div_small
(
&
ll
,
10
);
b
|=
(
div_small
(
&
ll
,
10
))
<<
4
;
b
|=
(
div_small
(
&
ll
,
10
))
<<
4
;
RE_ENTRANT_CHECK_OFF
RE_ENTRANT_CHECK_OFF
;
put_fs_byte
(
b
,(
unsigned
char
*
)
d
+
i
);
put_fs_byte
(
b
,(
unsigned
char
*
)
d
+
i
);
RE_ENTRANT_CHECK_ON
RE_ENTRANT_CHECK_ON
;
}
}
RE_ENTRANT_CHECK_OFF
RE_ENTRANT_CHECK_OFF
;
put_fs_byte
(
sign
,(
unsigned
char
*
)
d
+
9
);
put_fs_byte
(
sign
,(
unsigned
char
*
)
d
+
9
);
RE_ENTRANT_CHECK_ON
RE_ENTRANT_CHECK_ON
;
return
1
;
return
1
;
}
}
...
@@ -1157,7 +1170,8 @@ char *fldenv(void)
...
@@ -1157,7 +1170,8 @@ char *fldenv(void)
unsigned
char
tag
;
unsigned
char
tag
;
int
i
;
int
i
;
RE_ENTRANT_CHECK_OFF
RE_ENTRANT_CHECK_OFF
;
FPU_verify_area
(
VERIFY_READ
,
s
,
0x1c
);
control_word
=
get_fs_word
((
unsigned
short
*
)
s
);
control_word
=
get_fs_word
((
unsigned
short
*
)
s
);
partial_status
=
get_fs_word
((
unsigned
short
*
)
(
s
+
4
));
partial_status
=
get_fs_word
((
unsigned
short
*
)
(
s
+
4
));
tag_word
=
get_fs_word
((
unsigned
short
*
)
(
s
+
8
));
tag_word
=
get_fs_word
((
unsigned
short
*
)
(
s
+
8
));
...
@@ -1165,7 +1179,7 @@ char *fldenv(void)
...
@@ -1165,7 +1179,7 @@ char *fldenv(void)
cs_selector
=
get_fs_long
((
unsigned
long
*
)
(
s
+
0x10
));
cs_selector
=
get_fs_long
((
unsigned
long
*
)
(
s
+
0x10
));
data_operand_offset
=
get_fs_long
((
unsigned
long
*
)
(
s
+
0x14
));
data_operand_offset
=
get_fs_long
((
unsigned
long
*
)
(
s
+
0x14
));
operand_selector
=
get_fs_long
((
unsigned
long
*
)
(
s
+
0x18
));
operand_selector
=
get_fs_long
((
unsigned
long
*
)
(
s
+
0x18
));
RE_ENTRANT_CHECK_ON
RE_ENTRANT_CHECK_ON
;
top
=
(
partial_status
>>
SW_Top_Shift
)
&
7
;
top
=
(
partial_status
>>
SW_Top_Shift
)
&
7
;
...
@@ -1275,9 +1289,8 @@ char *fstenv(void)
...
@@ -1275,9 +1289,8 @@ char *fstenv(void)
{
{
char
*
d
=
(
char
*
)
FPU_data_address
;
char
*
d
=
(
char
*
)
FPU_data_address
;
verify_area
(
VERIFY_WRITE
,
d
,
28
);
RE_ENTRANT_CHECK_OFF
;
FPU_verify_area
(
VERIFY_WRITE
,
d
,
28
);
RE_ENTRANT_CHECK_OFF
#ifdef PECULIAR_486
#ifdef PECULIAR_486
/* An 80486 sets all the reserved bits to 1. */
/* An 80486 sets all the reserved bits to 1. */
put_fs_long
(
0xffff0040
|
(
control_word
&
~
0xe080
),
(
unsigned
long
*
)
d
);
put_fs_long
(
0xffff0040
|
(
control_word
&
~
0xe080
),
(
unsigned
long
*
)
d
);
...
@@ -1297,7 +1310,7 @@ char *fstenv(void)
...
@@ -1297,7 +1310,7 @@ char *fstenv(void)
#else
#else
put_fs_long
(
operand_selector
,
(
unsigned
long
*
)
(
d
+
0x18
));
put_fs_long
(
operand_selector
,
(
unsigned
long
*
)
(
d
+
0x18
));
#endif PECULIAR_486
#endif PECULIAR_486
RE_ENTRANT_CHECK_ON
RE_ENTRANT_CHECK_ON
;
control_word
|=
CW_Exceptions
;
control_word
|=
CW_Exceptions
;
partial_status
&=
~
(
SW_Summary
|
SW_Backward
);
partial_status
&=
~
(
SW_Summary
|
SW_Backward
);
...
@@ -1312,7 +1325,9 @@ void fsave(void)
...
@@ -1312,7 +1325,9 @@ void fsave(void)
int
i
;
int
i
;
d
=
fstenv
();
d
=
fstenv
();
verify_area
(
VERIFY_WRITE
,
d
,
80
);
RE_ENTRANT_CHECK_OFF
;
FPU_verify_area
(
VERIFY_WRITE
,
d
,
80
);
RE_ENTRANT_CHECK_ON
;
for
(
i
=
0
;
i
<
8
;
i
++
)
for
(
i
=
0
;
i
<
8
;
i
++
)
write_to_extended
(
&
regs
[(
top
+
i
)
&
7
],
d
+
10
*
i
);
write_to_extended
(
&
regs
[(
top
+
i
)
&
7
],
d
+
10
*
i
);
...
@@ -1324,7 +1339,7 @@ void fsave(void)
...
@@ -1324,7 +1339,7 @@ void fsave(void)
/*
/*
A call to this function must be preceeded by a call to
A call to this function must be preceeded by a call to
verify_area() to verify access to the 10 bytes at d
FPU_
verify_area() to verify access to the 10 bytes at d
*/
*/
static
void
write_to_extended
(
FPU_REG
*
rp
,
char
*
d
)
static
void
write_to_extended
(
FPU_REG
*
rp
,
char
*
d
)
{
{
...
...
drivers/FPU-emu/version.h
View file @
b168ffdf
...
@@ -9,5 +9,5 @@
...
@@ -9,5 +9,5 @@
| |
| |
+---------------------------------------------------------------------------*/
+---------------------------------------------------------------------------*/
#define FPU_VERSION "wm-FPU-emu version Beta 1.
7
"
#define FPU_VERSION "wm-FPU-emu version Beta 1.
8
"
drivers/char/atixlmouse.c
View file @
b168ffdf
...
@@ -11,7 +11,6 @@
...
@@ -11,7 +11,6 @@
#include <linux/kernel.h>
#include <linux/kernel.h>
#include <linux/sched.h>
#include <linux/sched.h>
#include <linux/tty.h>
#include <linux/signal.h>
#include <linux/signal.h>
#include <linux/errno.h>
#include <linux/errno.h>
...
...
drivers/char/busmouse.c
View file @
b168ffdf
...
@@ -26,7 +26,6 @@
...
@@ -26,7 +26,6 @@
#include <linux/kernel.h>
#include <linux/kernel.h>
#include <linux/sched.h>
#include <linux/sched.h>
#include <linux/busmouse.h>
#include <linux/busmouse.h>
#include <linux/tty.h>
#include <linux/signal.h>
#include <linux/signal.h>
#include <linux/errno.h>
#include <linux/errno.h>
...
...
drivers/char/console.c
View file @
b168ffdf
...
@@ -967,7 +967,6 @@ void con_write(struct tty_struct * tty)
...
@@ -967,7 +967,6 @@ void con_write(struct tty_struct * tty)
int
c
;
int
c
;
unsigned
int
currcons
;
unsigned
int
currcons
;
wake_up_interruptible
(
&
tty
->
write_q
.
proc_list
);
currcons
=
tty
->
line
-
1
;
currcons
=
tty
->
line
-
1
;
if
(
currcons
>=
NR_CONSOLES
)
{
if
(
currcons
>=
NR_CONSOLES
)
{
printk
(
"con_write: illegal tty (%d)
\n
"
,
currcons
);
printk
(
"con_write: illegal tty (%d)
\n
"
,
currcons
);
...
@@ -1279,6 +1278,8 @@ void con_write(struct tty_struct * tty)
...
@@ -1279,6 +1278,8 @@ void con_write(struct tty_struct * tty)
if
(
vcmode
!=
KD_GRAPHICS
)
if
(
vcmode
!=
KD_GRAPHICS
)
set_cursor
(
currcons
);
set_cursor
(
currcons
);
enable_bh
(
KEYBOARD_BH
);
enable_bh
(
KEYBOARD_BH
);
if
(
LEFT
(
&
tty
->
write_q
)
>
WAKEUP_CHARS
)
wake_up_interruptible
(
&
tty
->
write_q
.
proc_list
);
}
}
void
do_keyboard_interrupt
(
void
)
void
do_keyboard_interrupt
(
void
)
...
...
drivers/char/keyboard.c
View file @
b168ffdf
...
@@ -126,6 +126,8 @@ static unsigned char handle_diacr(unsigned char);
...
@@ -126,6 +126,8 @@ static unsigned char handle_diacr(unsigned char);
/* pt_regs - set by keyboard_interrupt(), used by show_ptregs() */
/* pt_regs - set by keyboard_interrupt(), used by show_ptregs() */
static
struct
pt_regs
*
pt_regs
;
static
struct
pt_regs
*
pt_regs
;
static
int
got_break
=
0
;
static
inline
void
kb_wait
(
void
)
static
inline
void
kb_wait
(
void
)
{
{
int
i
;
int
i
;
...
@@ -343,7 +345,6 @@ static void put_queue(int ch)
...
@@ -343,7 +345,6 @@ static void put_queue(int ch)
if
(
LEFT
(
qp
))
{
if
(
LEFT
(
qp
))
{
qp
->
buf
[
qp
->
head
]
=
ch
;
qp
->
buf
[
qp
->
head
]
=
ch
;
INC
(
qp
->
head
);
INC
(
qp
->
head
);
wake_up_interruptible
(
&
qp
->
proc_list
);
}
}
}
}
...
@@ -364,7 +365,6 @@ static void puts_queue(char *cp)
...
@@ -364,7 +365,6 @@ static void puts_queue(char *cp)
INC
(
qp
->
head
);
INC
(
qp
->
head
);
}
}
}
}
wake_up_interruptible
(
&
qp
->
proc_list
);
}
}
static
void
applkey
(
int
key
,
char
mode
)
static
void
applkey
(
int
key
,
char
mode
)
...
@@ -419,13 +419,13 @@ static void hold(void)
...
@@ -419,13 +419,13 @@ static void hold(void)
{
{
if
(
rep
||
!
tty
)
if
(
rep
||
!
tty
)
return
;
return
;
if
(
vc_kbd_flag
(
kbd
,
VC_SCROLLOCK
))
/* pressing scroll lock 1st time sends ^S, ChN */
/* pressing srcoll lock 2nd time sends ^Q, ChN */
/* pressing scroll lock 2nd time sends ^Q, ChN */
put_queue
(
START_CHAR
(
tty
));
/* now done directly without regard to ISIG -- jlc */
if
(
!
vc_kbd_flag
(
kbd
,
VC_SCROLLOCK
))
stop_tty
(
tty
);
else
else
/* pressing scroll lock 1st time sends ^S, ChN */
start_tty
(
tty
);
put_queue
(
STOP_CHAR
(
tty
));
chg_vc_kbd_flag
(
kbd
,
VC_SCROLLOCK
);
}
}
static
void
num
(
void
)
static
void
num
(
void
)
...
@@ -453,8 +453,7 @@ static void lastcons(void)
...
@@ -453,8 +453,7 @@ static void lastcons(void)
static
void
send_intr
(
void
)
static
void
send_intr
(
void
)
{
{
if
(
tty
)
got_break
=
1
;
put_queue
(
INTR_CHAR
(
tty
));
}
}
static
void
scrll_forw
(
void
)
static
void
scrll_forw
(
void
)
...
@@ -814,6 +813,26 @@ static void kbd_bh(void * unused)
...
@@ -814,6 +813,26 @@ static void kbd_bh(void * unused)
}
}
want_console
=
-
1
;
want_console
=
-
1
;
}
}
if
(
got_break
)
{
if
(
tty
&&
!
I_IGNBRK
(
tty
))
{
if
(
I_BRKINT
(
tty
))
{
flush_input
(
tty
);
flush_output
(
tty
);
if
(
tty
->
pgrp
>
0
)
kill_pg
(
tty
->
pgrp
,
SIGINT
,
1
);
}
else
{
cli
();
if
(
LEFT
(
&
tty
->
read_q
)
>=
2
)
{
set_bit
(
tty
->
read_q
.
head
,
&
tty
->
readq_flags
);
put_queue
(
TTY_BREAK
);
put_queue
(
0
);
}
sti
();
}
}
got_break
=
0
;
}
do_keyboard_interrupt
();
do_keyboard_interrupt
();
cli
();
cli
();
if
((
inb_p
(
0x64
)
&
kbd_read_mask
)
==
0x01
)
if
((
inb_p
(
0x64
)
&
kbd_read_mask
)
==
0x01
)
...
...
drivers/char/msbusmouse.c
View file @
b168ffdf
...
@@ -31,7 +31,6 @@
...
@@ -31,7 +31,6 @@
#include <linux/kernel.h>
#include <linux/kernel.h>
#include <linux/sched.h>
#include <linux/sched.h>
#include <linux/busmouse.h>
#include <linux/busmouse.h>
#include <linux/tty.h>
#include <linux/signal.h>
#include <linux/signal.h>
#include <linux/errno.h>
#include <linux/errno.h>
...
...
drivers/char/pty.c
View file @
b168ffdf
...
@@ -17,17 +17,20 @@
...
@@ -17,17 +17,20 @@
#include <linux/tty.h>
#include <linux/tty.h>
#include <linux/fcntl.h>
#include <linux/fcntl.h>
#include <linux/interrupt.h>
#include <linux/interrupt.h>
#include <linux/string.h>
#include <asm/system.h>
#include <asm/system.h>
#include <asm/bitops.h>
#include <asm/bitops.h>
#define MIN(a,b) ((a) < (b) ? (a) : (b))
static
void
pty_close
(
struct
tty_struct
*
tty
,
struct
file
*
filp
)
static
void
pty_close
(
struct
tty_struct
*
tty
,
struct
file
*
filp
)
{
{
if
(
!
tty
)
if
(
!
tty
)
return
;
return
;
if
(
IS_A_PTY_MASTER
(
tty
->
line
))
{
if
(
IS_A_PTY_MASTER
(
tty
->
line
))
{
if
(
tty
->
count
>
1
)
if
(
tty
->
count
>
1
)
return
;
printk
(
"master pty_close: count = %d!!
\n
"
,
tty
->
count
)
;
}
else
{
}
else
{
if
(
tty
->
count
>
2
)
if
(
tty
->
count
>
2
)
return
;
return
;
...
@@ -40,32 +43,39 @@ static void pty_close(struct tty_struct * tty, struct file * filp)
...
@@ -40,32 +43,39 @@ static void pty_close(struct tty_struct * tty, struct file * filp)
wake_up_interruptible
(
&
tty
->
link
->
secondary
.
proc_list
);
wake_up_interruptible
(
&
tty
->
link
->
secondary
.
proc_list
);
wake_up_interruptible
(
&
tty
->
link
->
read_q
.
proc_list
);
wake_up_interruptible
(
&
tty
->
link
->
read_q
.
proc_list
);
wake_up_interruptible
(
&
tty
->
link
->
write_q
.
proc_list
);
wake_up_interruptible
(
&
tty
->
link
->
write_q
.
proc_list
);
if
(
IS_A_PTY_MASTER
(
tty
->
line
))
{
if
(
IS_A_PTY_MASTER
(
tty
->
line
))
tty_hangup
(
tty
->
link
);
tty_hangup
(
tty
->
link
);
flush_input
(
tty
);
else
{
flush_output
(
tty
);
start_tty
(
tty
);
set_bit
(
TTY_SLAVE_CLOSED
,
&
tty
->
link
->
flags
);
}
}
}
}
static
inline
void
pty_copy
(
struct
tty_struct
*
from
,
struct
tty_struct
*
to
)
static
inline
void
pty_copy
(
struct
tty_struct
*
from
,
struct
tty_struct
*
to
)
{
{
int
c
;
unsigned
long
count
,
n
;
struct
tty_queue
*
fq
,
*
tq
;
while
(
!
from
->
stopped
&&
!
EMPTY
(
&
from
->
write_q
))
{
if
(
from
->
stopped
||
EMPTY
(
&
from
->
write_q
))
if
(
FULL
(
&
to
->
read_q
))
{
return
;
TTY_READ_FLUSH
(
to
);
fq
=
&
from
->
write_q
;
if
(
FULL
(
&
to
->
read_q
))
/* Bypass the read_q if this is a pty master. */
break
;
tq
=
IS_A_PTY_MASTER
(
to
->
line
)
?
&
to
->
secondary
:
&
to
->
read_q
;
continue
;
count
=
MIN
(
CHARS
(
fq
),
LEFT
(
tq
));
}
while
(
count
)
{
c
=
get_tty_queue
(
&
from
->
write_q
);
n
=
MIN
(
MIN
(
TTY_BUF_SIZE
-
fq
->
tail
,
TTY_BUF_SIZE
-
tq
->
head
),
put_tty_queue
(
c
,
&
to
->
read_q
);
count
);
if
(
current
->
signal
&
~
current
->
blocked
)
memcpy
(
&
tq
->
buf
[
tq
->
head
],
&
fq
->
buf
[
fq
->
tail
],
n
);
break
;
count
-=
n
;
fq
->
tail
=
(
fq
->
tail
+
n
)
&
(
TTY_BUF_SIZE
-
1
);
tq
->
head
=
(
tq
->
head
+
n
)
&
(
TTY_BUF_SIZE
-
1
);
}
}
TTY_READ_FLUSH
(
to
);
if
(
IS_A_PTY_MASTER
(
to
->
line
))
if
(
!
FULL
(
&
from
->
write_q
))
wake_up_interruptible
(
&
tq
->
proc_list
);
wake_up_interruptible
(
&
from
->
write_q
.
proc_list
);
else
TTY_READ_FLUSH
(
to
);
if
(
LEFT
(
fq
)
>
WAKEUP_CHARS
)
wake_up_interruptible
(
&
fq
->
proc_list
);
if
(
from
->
write_data_cnt
)
{
if
(
from
->
write_data_cnt
)
{
set_bit
(
from
->
line
,
&
tty_check_write
);
set_bit
(
from
->
line
,
&
tty_check_write
);
mark_bh
(
TTY_BH
);
mark_bh
(
TTY_BH
);
...
@@ -87,10 +97,8 @@ int pty_open(struct tty_struct *tty, struct file * filp)
...
@@ -87,10 +97,8 @@ int pty_open(struct tty_struct *tty, struct file * filp)
{
{
if
(
!
tty
||
!
tty
->
link
)
if
(
!
tty
||
!
tty
->
link
)
return
-
ENODEV
;
return
-
ENODEV
;
if
(
IS_A_PTY_MASTER
(
tty
->
line
))
if
(
IS_A_PTY_SLAVE
(
tty
->
line
))
clear_bit
(
TTY_SLAVE_OPENED
,
&
tty
->
flags
);
clear_bit
(
TTY_SLAVE_CLOSED
,
&
tty
->
link
->
flags
);
else
set_bit
(
TTY_SLAVE_OPENED
,
&
tty
->
link
->
flags
);
tty
->
write
=
tty
->
link
->
write
=
pty_write
;
tty
->
write
=
tty
->
link
->
write
=
pty_write
;
tty
->
close
=
tty
->
link
->
close
=
pty_close
;
tty
->
close
=
tty
->
link
->
close
=
pty_close
;
wake_up_interruptible
(
&
tty
->
read_q
.
proc_list
);
wake_up_interruptible
(
&
tty
->
read_q
.
proc_list
);
...
...
drivers/char/serial.c
View file @
b168ffdf
...
@@ -58,8 +58,6 @@
...
@@ -58,8 +58,6 @@
#undef ISR_HACK
#undef ISR_HACK
#define WAKEUP_CHARS (3*TTY_BUF_SIZE/4)
/*
/*
* rs_event - Bitfield of serial lines that events pending
* rs_event - Bitfield of serial lines that events pending
* to be processed at the next clock tick.
* to be processed at the next clock tick.
...
@@ -418,7 +416,7 @@ static inline int check_modem_status(struct async_struct *info)
...
@@ -418,7 +416,7 @@ static inline int check_modem_status(struct async_struct *info)
status
=
serial_in
(
info
,
UART_MSR
);
status
=
serial_in
(
info
,
UART_MSR
);
if
((
status
&
UART_MSR_DDCD
)
&&
!
C_LOCAL
(
info
->
tty
))
{
if
((
status
&
UART_MSR_DDCD
)
&&
!
C_
C
LOCAL
(
info
->
tty
))
{
#if (defined(SERIAL_DEBUG_OPEN) || defined(SERIAL_DEBUG_INTR))
#if (defined(SERIAL_DEBUG_OPEN) || defined(SERIAL_DEBUG_INTR))
printk
(
"ttys%d CD now %s..."
,
info
->
line
,
printk
(
"ttys%d CD now %s..."
,
info
->
line
,
(
status
&
UART_MSR_DCD
)
?
"on"
:
"off"
);
(
status
&
UART_MSR_DCD
)
?
"on"
:
"off"
);
...
@@ -433,7 +431,7 @@ static inline int check_modem_status(struct async_struct *info)
...
@@ -433,7 +431,7 @@ static inline int check_modem_status(struct async_struct *info)
rs_sched_event
(
info
,
RS_EVENT_HANGUP
);
rs_sched_event
(
info
,
RS_EVENT_HANGUP
);
}
}
}
}
if
(
C_RTSCTS
(
info
->
tty
))
{
if
(
C_
C
RTSCTS
(
info
->
tty
))
{
if
(
info
->
tty
->
hw_stopped
)
{
if
(
info
->
tty
->
hw_stopped
)
{
if
(
status
&
UART_MSR_CTS
)
{
if
(
status
&
UART_MSR_CTS
)
{
#ifdef SERIAL_DEBUG_INTR
#ifdef SERIAL_DEBUG_INTR
...
@@ -562,7 +560,7 @@ static inline void handle_rs_break(struct async_struct *info)
...
@@ -562,7 +560,7 @@ static inline void handle_rs_break(struct async_struct *info)
if
(
info
->
flags
&
ASYNC_SAK
)
if
(
info
->
flags
&
ASYNC_SAK
)
do_SAK
(
info
->
tty
);
do_SAK
(
info
->
tty
);
if
(
I_BRKINT
(
info
->
tty
))
{
if
(
!
I_IGNBRK
(
info
->
tty
)
&&
I_BRKINT
(
info
->
tty
))
{
flush_input
(
info
->
tty
);
flush_input
(
info
->
tty
);
flush_output
(
info
->
tty
);
flush_output
(
info
->
tty
);
if
(
info
->
tty
->
pgrp
>
0
)
if
(
info
->
tty
->
pgrp
>
0
)
...
@@ -1066,7 +1064,7 @@ static void rs_throttle(struct tty_struct * tty, int status)
...
@@ -1066,7 +1064,7 @@ static void rs_throttle(struct tty_struct * tty, int status)
switch
(
status
)
{
switch
(
status
)
{
case
TTY_THROTTLE_RQ_FULL
:
case
TTY_THROTTLE_RQ_FULL
:
info
=
rs_table
+
DEV_TO_SL
(
tty
->
line
);
info
=
rs_table
+
DEV_TO_SL
(
tty
->
line
);
if
(
tty
->
termios
->
c_iflag
&
IXOFF
)
{
if
(
I_IXOFF
(
tty
)
)
{
info
->
x_char
=
STOP_CHAR
(
tty
);
info
->
x_char
=
STOP_CHAR
(
tty
);
}
else
{
}
else
{
mcr
=
serial_inp
(
info
,
UART_MCR
);
mcr
=
serial_inp
(
info
,
UART_MCR
);
...
@@ -1076,7 +1074,7 @@ static void rs_throttle(struct tty_struct * tty, int status)
...
@@ -1076,7 +1074,7 @@ static void rs_throttle(struct tty_struct * tty, int status)
break
;
break
;
case
TTY_THROTTLE_RQ_AVAIL
:
case
TTY_THROTTLE_RQ_AVAIL
:
info
=
rs_table
+
DEV_TO_SL
(
tty
->
line
);
info
=
rs_table
+
DEV_TO_SL
(
tty
->
line
);
if
(
tty
->
termios
->
c_iflag
&
IXOFF
)
{
if
(
I_IXOFF
(
tty
)
)
{
if
(
info
->
x_char
)
if
(
info
->
x_char
)
info
->
x_char
=
0
;
info
->
x_char
=
0
;
else
else
...
@@ -1382,7 +1380,7 @@ static int rs_ioctl(struct tty_struct *tty, struct file * file,
...
@@ -1382,7 +1380,7 @@ static int rs_ioctl(struct tty_struct *tty, struct file * file,
error
=
verify_area
(
VERIFY_WRITE
,
(
void
*
)
arg
,
sizeof
(
long
));
error
=
verify_area
(
VERIFY_WRITE
,
(
void
*
)
arg
,
sizeof
(
long
));
if
(
error
)
if
(
error
)
return
error
;
return
error
;
put_fs_long
(
C_LOCAL
(
tty
)
?
1
:
0
,
put_fs_long
(
C_
C
LOCAL
(
tty
)
?
1
:
0
,
(
unsigned
long
*
)
arg
);
(
unsigned
long
*
)
arg
);
return
0
;
return
0
;
case
TIOCSSOFTCAR
:
case
TIOCSSOFTCAR
:
...
@@ -1591,7 +1589,7 @@ static int block_til_ready(struct tty_struct *tty, struct file * filp,
...
@@ -1591,7 +1589,7 @@ static int block_til_ready(struct tty_struct *tty, struct file * filp,
{
{
struct
wait_queue
wait
=
{
current
,
NULL
};
struct
wait_queue
wait
=
{
current
,
NULL
};
int
retval
;
int
retval
;
int
do_clocal
=
C_LOCAL
(
tty
);
int
do_clocal
=
C_
C
LOCAL
(
tty
);
/*
/*
* If the device is in the middle of being closed, then block
* If the device is in the middle of being closed, then block
...
...
drivers/char/tty_io.c
View file @
b168ffdf
...
@@ -32,6 +32,9 @@
...
@@ -32,6 +32,9 @@
* Added functionality to the OPOST tty handling. No delays, but all
* Added functionality to the OPOST tty handling. No delays, but all
* other bits should be there.
* other bits should be there.
* -- Nick Holloway <alfie@dcs.warwick.ac.uk>, 27th May 1993.
* -- Nick Holloway <alfie@dcs.warwick.ac.uk>, 27th May 1993.
*
* Rewrote canonical mode and added more termios flags.
* -- julian@uhunix.uhcc.hawaii.edu (J. Cowley), 13Jan94
*/
*/
#include <linux/types.h>
#include <linux/types.h>
...
@@ -98,7 +101,7 @@ int tty_register_ldisc(int disc, struct tty_ldisc *new_ldisc)
...
@@ -98,7 +101,7 @@ int tty_register_ldisc(int disc, struct tty_ldisc *new_ldisc)
return
0
;
return
0
;
}
}
void
put_tty_queue
(
char
c
,
struct
tty_queue
*
queue
)
void
put_tty_queue
(
unsigned
char
c
,
struct
tty_queue
*
queue
)
{
{
int
head
;
int
head
;
unsigned
long
flags
;
unsigned
long
flags
;
...
@@ -121,8 +124,8 @@ int get_tty_queue(struct tty_queue * queue)
...
@@ -121,8 +124,8 @@ int get_tty_queue(struct tty_queue * queue)
save_flags
(
flags
);
save_flags
(
flags
);
cli
();
cli
();
if
(
queue
->
tail
!=
queue
->
head
)
{
if
(
queue
->
tail
!=
queue
->
head
)
{
result
=
0xff
&
queue
->
buf
[
queue
->
tail
];
result
=
queue
->
buf
[
queue
->
tail
];
queue
->
tail
=
(
queue
->
tail
+
1
)
&
(
TTY_BUF_SIZE
-
1
);
INC
(
queue
->
tail
);
}
}
restore_flags
(
flags
);
restore_flags
(
flags
);
return
result
;
return
result
;
...
@@ -499,7 +502,220 @@ void wait_for_keypress(void)
...
@@ -499,7 +502,220 @@ void wait_for_keypress(void)
sleep_on
(
&
keypress_wait
);
sleep_on
(
&
keypress_wait
);
}
}
void
copy_to_cooked
(
struct
tty_struct
*
tty
)
void
stop_tty
(
struct
tty_struct
*
tty
)
{
if
(
tty
->
stopped
)
return
;
tty
->
stopped
=
1
;
if
(
tty
->
link
&&
tty
->
link
->
packet
)
{
tty
->
ctrl_status
&=
~
TIOCPKT_START
;
tty
->
ctrl_status
|=
TIOCPKT_STOP
;
wake_up_interruptible
(
&
tty
->
link
->
secondary
.
proc_list
);
}
if
(
tty
->
stop
)
(
tty
->
stop
)(
tty
);
if
(
IS_A_CONSOLE
(
tty
->
line
))
{
set_vc_kbd_flag
(
kbd_table
+
fg_console
,
VC_SCROLLOCK
);
set_leds
();
}
}
void
start_tty
(
struct
tty_struct
*
tty
)
{
if
(
!
tty
->
stopped
)
return
;
tty
->
stopped
=
0
;
if
(
tty
->
link
&&
tty
->
link
->
packet
)
{
tty
->
ctrl_status
&=
~
TIOCPKT_STOP
;
tty
->
ctrl_status
|=
TIOCPKT_START
;
wake_up_interruptible
(
&
tty
->
link
->
secondary
.
proc_list
);
}
if
(
tty
->
start
)
(
tty
->
start
)(
tty
);
if
(
IS_A_CONSOLE
(
tty
->
line
))
{
clr_vc_kbd_flag
(
kbd_table
+
fg_console
,
VC_SCROLLOCK
);
set_leds
();
}
TTY_WRITE_FLUSH
(
tty
);
}
/* Perform OPOST processing. Returns -1 when the write_q becomes full
and the character must be retried. */
static
int
opost
(
unsigned
char
c
,
struct
tty_struct
*
tty
)
{
if
(
FULL
(
&
tty
->
write_q
))
return
-
1
;
if
(
O_OPOST
(
tty
))
{
switch
(
c
)
{
case
'\n'
:
if
(
O_ONLRET
(
tty
))
tty
->
column
=
0
;
if
(
O_ONLCR
(
tty
))
{
if
(
LEFT
(
&
tty
->
write_q
)
<
2
)
return
-
1
;
put_tty_queue
(
'\r'
,
&
tty
->
write_q
);
tty
->
column
=
0
;
}
tty
->
canon_column
=
tty
->
column
;
break
;
case
'\r'
:
if
(
O_ONOCR
(
tty
)
&&
tty
->
column
==
0
)
return
0
;
if
(
O_OCRNL
(
tty
))
{
c
=
'\n'
;
if
(
O_ONLRET
(
tty
))
tty
->
canon_column
=
tty
->
column
=
0
;
break
;
}
tty
->
canon_column
=
tty
->
column
=
0
;
break
;
case
'\t'
:
if
(
O_TABDLY
(
tty
)
==
XTABS
)
{
if
(
LEFT
(
&
tty
->
write_q
)
<
8
)
return
-
1
;
do
put_tty_queue
(
' '
,
&
tty
->
write_q
);
while
(
++
tty
->
column
%
8
);
return
0
;
}
tty
->
column
=
(
tty
->
column
|
7
)
+
1
;
break
;
case
'\b'
:
if
(
tty
->
column
>
0
)
tty
->
column
--
;
break
;
default:
if
(
O_OLCUC
(
tty
))
c
=
toupper
(
c
);
if
(
!
iscntrl
(
c
))
tty
->
column
++
;
break
;
}
}
put_tty_queue
(
c
,
&
tty
->
write_q
);
return
0
;
}
/* Must be called only when L_ECHO(tty) is true. */
static
void
echo_char
(
unsigned
char
c
,
struct
tty_struct
*
tty
)
{
if
(
L_ECHOCTL
(
tty
)
&&
iscntrl
(
c
)
&&
c
!=
'\t'
)
{
opost
(
'^'
,
tty
);
opost
(
c
^
0100
,
tty
);
}
else
opost
(
c
,
tty
);
}
static
void
eraser
(
unsigned
char
c
,
struct
tty_struct
*
tty
)
{
enum
{
ERASE
,
WERASE
,
KILL
}
kill_type
;
int
seen_alnums
;
if
(
tty
->
secondary
.
head
==
tty
->
canon_head
)
{
/* opost('\a', tty); */
/* what do you think? */
return
;
}
if
(
c
==
ERASE_CHAR
(
tty
))
kill_type
=
ERASE
;
else
if
(
c
==
WERASE_CHAR
(
tty
))
kill_type
=
WERASE
;
else
{
if
(
!
L_ECHO
(
tty
))
{
tty
->
secondary
.
head
=
tty
->
canon_head
;
return
;
}
if
(
!
L_ECHOK
(
tty
)
||
!
L_ECHOKE
(
tty
))
{
tty
->
secondary
.
head
=
tty
->
canon_head
;
if
(
tty
->
erasing
)
{
opost
(
'/'
,
tty
);
tty
->
erasing
=
0
;
}
echo_char
(
KILL_CHAR
(
tty
),
tty
);
/* Add a newline if ECHOK is on and ECHOKE is off. */
if
(
L_ECHOK
(
tty
))
opost
(
'\n'
,
tty
);
return
;
}
kill_type
=
KILL
;
}
seen_alnums
=
0
;
while
(
tty
->
secondary
.
head
!=
tty
->
canon_head
)
{
c
=
LAST
(
&
tty
->
secondary
);
if
(
kill_type
==
WERASE
)
{
/* Equivalent to BSD's ALTWERASE. */
if
(
isalnum
(
c
)
||
c
==
'_'
)
seen_alnums
++
;
else
if
(
seen_alnums
)
break
;
}
DEC
(
tty
->
secondary
.
head
);
if
(
L_ECHO
(
tty
))
{
if
(
L_ECHOPRT
(
tty
))
{
if
(
!
tty
->
erasing
)
{
opost
(
'\\'
,
tty
);
tty
->
erasing
=
1
;
}
echo_char
(
c
,
tty
);
}
else
if
(
!
L_ECHOE
(
tty
))
{
echo_char
(
ERASE_CHAR
(
tty
),
tty
);
}
else
if
(
c
==
'\t'
)
{
unsigned
int
col
=
tty
->
canon_column
;
unsigned
long
tail
=
tty
->
canon_head
;
/* Find the column of the last char. */
while
(
tail
!=
tty
->
secondary
.
head
)
{
c
=
tty
->
secondary
.
buf
[
tail
];
if
(
c
==
'\t'
)
col
=
(
col
|
7
)
+
1
;
else
if
(
iscntrl
(
c
))
{
if
(
L_ECHOCTL
(
tty
))
col
+=
2
;
}
else
col
++
;
INC
(
tail
);
}
/* Now backup to that column. */
while
(
tty
->
column
>
col
)
{
/* Can't use opost here. */
put_tty_queue
(
'\b'
,
&
tty
->
write_q
);
tty
->
column
--
;
}
}
else
{
if
(
iscntrl
(
c
)
&&
L_ECHOCTL
(
tty
))
{
opost
(
'\b'
,
tty
);
opost
(
' '
,
tty
);
opost
(
'\b'
,
tty
);
}
if
(
!
iscntrl
(
c
)
||
L_ECHOCTL
(
tty
))
{
opost
(
'\b'
,
tty
);
opost
(
' '
,
tty
);
opost
(
'\b'
,
tty
);
}
}
}
if
(
kill_type
==
ERASE
)
break
;
}
if
(
tty
->
erasing
&&
tty
->
secondary
.
head
==
tty
->
canon_head
)
{
opost
(
'/'
,
tty
);
tty
->
erasing
=
0
;
}
}
static
void
isig
(
int
sig
,
struct
tty_struct
*
tty
)
{
kill_pg
(
tty
->
pgrp
,
sig
,
1
);
if
(
!
L_NOFLSH
(
tty
))
{
flush_input
(
tty
);
flush_output
(
tty
);
}
}
static
void
copy_to_cooked
(
struct
tty_struct
*
tty
)
{
{
int
c
,
special_flag
;
int
c
,
special_flag
;
unsigned
long
flags
;
unsigned
long
flags
;
...
@@ -525,19 +741,18 @@ void copy_to_cooked(struct tty_struct * tty)
...
@@ -525,19 +741,18 @@ void copy_to_cooked(struct tty_struct * tty)
if
(
c
==
0
)
if
(
c
==
0
)
break
;
break
;
save_flags
(
flags
);
cli
();
save_flags
(
flags
);
cli
();
if
(
tty
->
read_q
.
tail
!=
tty
->
read_q
.
head
)
{
if
(
!
EMPTY
(
&
tty
->
read_q
)
)
{
c
=
0xff
&
tty
->
read_q
.
buf
[
tty
->
read_q
.
tail
];
c
=
tty
->
read_q
.
buf
[
tty
->
read_q
.
tail
];
special_flag
=
clear_bit
(
tty
->
read_q
.
tail
,
special_flag
=
clear_bit
(
tty
->
read_q
.
tail
,
&
tty
->
readq_flags
);
&
tty
->
readq_flags
);
tty
->
read_q
.
tail
=
(
tty
->
read_q
.
tail
+
1
)
&
INC
(
tty
->
read_q
.
tail
);
(
TTY_BUF_SIZE
-
1
);
restore_flags
(
flags
);
restore_flags
(
flags
);
}
else
{
}
else
{
restore_flags
(
flags
);
restore_flags
(
flags
);
break
;
break
;
}
}
if
(
special_flag
)
{
if
(
special_flag
)
{
tty
->
char_error
=
c
&
7
;
tty
->
char_error
=
c
;
continue
;
continue
;
}
}
if
(
tty
->
char_error
)
{
if
(
tty
->
char_error
)
{
...
@@ -545,6 +760,9 @@ void copy_to_cooked(struct tty_struct * tty)
...
@@ -545,6 +760,9 @@ void copy_to_cooked(struct tty_struct * tty)
tty
->
char_error
=
0
;
tty
->
char_error
=
0
;
if
(
I_IGNBRK
(
tty
))
if
(
I_IGNBRK
(
tty
))
continue
;
continue
;
/* A break is handled by the lower levels. */
if
(
I_BRKINT
(
tty
))
continue
;
if
(
I_PARMRK
(
tty
))
{
if
(
I_PARMRK
(
tty
))
{
put_tty_queue
(
'\377'
,
&
tty
->
secondary
);
put_tty_queue
(
'\377'
,
&
tty
->
secondary
);
put_tty_queue
(
'\0'
,
&
tty
->
secondary
);
put_tty_queue
(
'\0'
,
&
tty
->
secondary
);
...
@@ -570,157 +788,131 @@ void copy_to_cooked(struct tty_struct * tty)
...
@@ -570,157 +788,131 @@ void copy_to_cooked(struct tty_struct * tty)
put_tty_queue
(
'\0'
,
&
tty
->
secondary
);
put_tty_queue
(
'\0'
,
&
tty
->
secondary
);
continue
;
continue
;
}
}
if
(
I_
STR
P
(
tty
))
if
(
I_
ISTRI
P
(
tty
))
c
&=
0x7f
;
c
&=
0x7f
;
else
if
(
I_PARMRK
(
tty
)
&&
(
c
==
'\377'
))
if
(
!
tty
->
lnext
)
{
put_tty_queue
(
'\377'
,
&
tty
->
secondary
);
if
(
c
==
'\r'
)
{
if
(
c
==
13
)
{
if
(
I_IGNCR
(
tty
))
if
(
I_CRNL
(
tty
))
continue
;
c
=
10
;
if
(
I_ICRNL
(
tty
))
else
if
(
I_NOCR
(
tty
))
c
=
'\n'
;
continue
;
}
else
if
(
c
==
'\n'
&&
I_INLCR
(
tty
))
}
else
if
(
c
==
10
&&
I_NLCR
(
tty
))
c
=
'\r'
;
c
=
13
;
}
if
(
I_
UCLC
(
tty
))
if
(
I_
IUCLC
(
tty
)
&&
L_IEXTEN
(
tty
))
c
=
tolower
(
c
);
c
=
tolower
(
c
);
if
(
c
==
__DISABLED_CHAR
)
if
(
c
==
__DISABLED_CHAR
)
tty
->
lnext
=
1
;
tty
->
lnext
=
1
;
if
(
L_CANON
(
tty
)
&&
!
tty
->
lnext
)
{
if
(
L_ICANON
(
tty
)
&&
!
tty
->
lnext
)
{
if
(
c
==
ERASE_CHAR
(
tty
)
||
c
==
KILL_CHAR
(
tty
)
||
c
==
WERASE_CHAR
(
tty
))
{
if
(
c
==
ERASE_CHAR
(
tty
)
||
c
==
KILL_CHAR
(
tty
)
||
int
seen_alnums
=
(
c
==
WERASE_CHAR
(
tty
)
&&
L_IEXTEN
(
tty
)))
{
(
c
==
WERASE_CHAR
(
tty
))
?
0
:
-
1
;
eraser
(
c
,
tty
);
int
cc
;
continue
;
}
/* deal with killing in the input line */
if
(
c
==
LNEXT_CHAR
(
tty
)
&&
L_IEXTEN
(
tty
))
{
while
(
!
(
EMPTY
(
&
tty
->
secondary
)
||
tty
->
lnext
=
1
;
(
cc
=
LAST
(
&
tty
->
secondary
))
==
10
||
if
(
L_ECHO
(
tty
))
{
((
EOF_CHAR
(
tty
)
!=
__DISABLED_CHAR
)
&&
if
(
tty
->
erasing
)
{
(
cc
==
EOF_CHAR
(
tty
)))))
{
opost
(
'/'
,
tty
);
/* if killing just a word, kill all
tty
->
erasing
=
0
;
non-alnum chars, then all alnum
chars. */
if
(
seen_alnums
>=
0
)
{
if
(
isalnum
(
cc
))
seen_alnums
++
;
else
if
(
seen_alnums
)
break
;
}
}
if
(
L_ECHO
(
tty
))
{
if
(
L_ECHOCTL
(
tty
))
{
int
ct
=
1
;
opost
(
'^'
,
tty
);
if
(
cc
<
32
)
opost
(
'\b'
,
tty
);
ct
=
(
L_ECHOCTL
(
tty
)
?
2
:
0
);
while
(
ct
--
)
{
put_tty_queue
(
'\b'
,
&
tty
->
write_q
);
put_tty_queue
(
' '
,
&
tty
->
write_q
);
put_tty_queue
(
'\b'
,
&
tty
->
write_q
);
}
}
}
DEC
(
tty
->
secondary
.
head
);
if
(
c
==
ERASE_CHAR
(
tty
))
break
;
}
}
continue
;
continue
;
}
}
if
(
c
==
LNEXT_CHAR
(
tty
))
{
if
(
c
==
REPRINT_CHAR
(
tty
)
&&
L_ECHO
(
tty
)
&&
tty
->
lnext
=
1
;
L_IEXTEN
(
tty
))
{
if
(
L_ECHO
(
tty
))
{
unsigned
long
tail
=
tty
->
canon_head
;
put_tty_queue
(
'^'
,
&
tty
->
write_q
);
put_tty_queue
(
'\b'
,
&
tty
->
write_q
);
if
(
tty
->
erasing
)
{
opost
(
'/'
,
tty
);
tty
->
erasing
=
0
;
}
echo_char
(
c
,
tty
);
opost
(
'\n'
,
tty
);
while
(
tail
!=
tty
->
secondary
.
head
)
{
echo_char
(
tty
->
secondary
.
buf
[
tail
],
tty
);
INC
(
tail
);
}
}
continue
;
continue
;
}
}
}
}
if
(
I_IXON
(
tty
)
&&
!
tty
->
lnext
)
{
if
(
I_IXON
(
tty
)
&&
!
tty
->
lnext
)
{
if
(
c
==
STOP_CHAR
(
tty
))
{
if
((
tty
->
stopped
&&
I_IXANY
(
tty
)
&&
L_IEXTEN
(
tty
))
||
tty
->
ctrl_status
&=
~
(
TIOCPKT_START
);
c
==
START_CHAR
(
tty
))
{
tty
->
ctrl_status
|=
TIOCPKT_STOP
;
start_tty
(
tty
);
if
(
tty
->
link
)
wake_up_interruptible
(
&
tty
->
link
->
except_q
);
tty
->
stopped
=
1
;
if
(
tty
->
stop
)
(
tty
->
stop
)(
tty
);
if
(
IS_A_CONSOLE
(
tty
->
line
))
{
set_vc_kbd_flag
(
kbd_table
+
fg_console
,
VC_SCROLLOCK
);
set_leds
();
}
continue
;
continue
;
}
}
if
(((
I_IXANY
(
tty
))
&&
tty
->
stopped
)
||
if
(
c
==
STOP_CHAR
(
tty
))
{
(
c
==
START_CHAR
(
tty
)))
{
stop_tty
(
tty
);
tty
->
ctrl_status
&=
~
(
TIOCPKT_STOP
);
tty
->
ctrl_status
|=
TIOCPKT_START
;
tty
->
stopped
=
0
;
if
(
tty
->
link
)
wake_up_interruptible
(
&
tty
->
link
->
except_q
);
if
(
tty
->
start
)
(
tty
->
start
)(
tty
);
if
(
IS_A_CONSOLE
(
tty
->
line
))
{
clr_vc_kbd_flag
(
kbd_table
+
fg_console
,
VC_SCROLLOCK
);
set_leds
();
}
continue
;
continue
;
}
}
}
}
if
(
L_ISIG
(
tty
)
&&
!
tty
->
lnext
)
{
if
(
L_ISIG
(
tty
)
&&
!
tty
->
lnext
)
{
if
(
c
==
INTR_CHAR
(
tty
))
{
if
(
c
==
INTR_CHAR
(
tty
))
{
kill_pg
(
tty
->
pgrp
,
SIGINT
,
1
);
isig
(
SIGINT
,
tty
);
if
(
!
_L_FLAG
(
tty
,
NOFLSH
))
{
flush_input
(
tty
);
flush_output
(
tty
);
}
continue
;
continue
;
}
}
if
(
c
==
QUIT_CHAR
(
tty
))
{
if
(
c
==
QUIT_CHAR
(
tty
))
{
kill_pg
(
tty
->
pgrp
,
SIGQUIT
,
1
);
isig
(
SIGQUIT
,
tty
);
if
(
!
_L_FLAG
(
tty
,
NOFLSH
))
{
flush_input
(
tty
);
flush_output
(
tty
);
}
continue
;
continue
;
}
}
if
(
c
==
SUSPEND_CHAR
(
tty
))
{
if
(
c
==
SUSP_CHAR
(
tty
))
{
if
(
!
is_orphaned_pgrp
(
tty
->
pgrp
))
{
if
(
!
is_orphaned_pgrp
(
tty
->
pgrp
))
kill_pg
(
tty
->
pgrp
,
SIGTSTP
,
1
);
isig
(
SIGTSTP
,
tty
);
if
(
!
_L_FLAG
(
tty
,
NOFLSH
))
{
flush_input
(
tty
);
flush_output
(
tty
);
}
}
continue
;
continue
;
}
}
}
}
if
(
c
==
10
||
(
EOF_CHAR
(
tty
)
!=
__DISABLED_CHAR
&&
c
==
EOF_CHAR
(
tty
)))
if
(
tty
->
erasing
)
{
tty
->
secondary
.
data
++
;
opost
(
'/'
,
tty
);
if
((
c
==
10
)
&&
(
L_ECHO
(
tty
)
||
(
L_CANON
(
tty
)
&&
L_ECHONL
(
tty
))))
{
tty
->
erasing
=
0
;
put_tty_queue
(
'\n'
,
&
tty
->
write_q
);
}
put_tty_queue
(
'\r'
,
&
tty
->
write_q
);
if
(
c
==
'\n'
&&
!
tty
->
lnext
)
{
if
(
L_ECHO
(
tty
)
||
(
L_ICANON
(
tty
)
&&
L_ECHONL
(
tty
)))
opost
(
'\n'
,
tty
);
}
else
if
(
L_ECHO
(
tty
))
{
}
else
if
(
L_ECHO
(
tty
))
{
if
(
c
<
32
&&
L_ECHOCTL
(
tty
))
{
/* Don't echo the EOF char in canonical mode. Sun
put_tty_queue
(
'^'
,
&
tty
->
write_q
);
handles this differently by echoing the char and
put_tty_queue
(
c
+
'A'
-
1
,
&
tty
->
write_q
);
then backspacing, but that's a hack. */
if
(
EOF_CHAR
(
tty
)
!=
__DISABLED_CHAR
&&
if
(
c
!=
EOF_CHAR
(
tty
)
||
!
L_ICANON
(
tty
)
||
c
==
EOF_CHAR
(
tty
)
&&
!
tty
->
lnext
)
{
tty
->
lnext
)
{
put_tty_queue
(
'\b'
,
&
tty
->
write_q
);
/* Record the column of first canon char. */
put_tty_queue
(
'\b'
,
&
tty
->
write_q
);
if
(
tty
->
canon_head
==
tty
->
secondary
.
head
)
}
tty
->
canon_column
=
tty
->
column
;
}
else
echo_char
(
c
,
tty
);
put_tty_queue
(
c
,
&
tty
->
write_q
);
}
}
}
if
(
I_PARMRK
(
tty
)
&&
c
==
(
unsigned
char
)
'\377'
&&
(
c
!=
EOF_CHAR
(
tty
)
||
!
L_ICANON
(
tty
)
||
tty
->
lnext
))
put_tty_queue
(
c
,
&
tty
->
secondary
);
if
(
L_ICANON
(
tty
)
&&
!
tty
->
lnext
&&
(
c
==
'\n'
||
c
==
EOF_CHAR
(
tty
)
||
c
==
EOL_CHAR
(
tty
)
||
(
c
==
EOL2_CHAR
(
tty
)
&&
L_IEXTEN
(
tty
))))
{
if
(
c
==
EOF_CHAR
(
tty
))
c
=
__DISABLED_CHAR
;
set_bit
(
tty
->
secondary
.
head
,
&
tty
->
secondary_flags
);
put_tty_queue
(
c
,
&
tty
->
secondary
);
tty
->
canon_head
=
tty
->
secondary
.
head
;
tty
->
canon_data
++
;
}
else
put_tty_queue
(
c
,
&
tty
->
secondary
);
tty
->
lnext
=
0
;
tty
->
lnext
=
0
;
put_tty_queue
(
c
,
&
tty
->
secondary
);
}
}
TTY_WRITE_FLUSH
(
tty
);
if
(
!
EMPTY
(
&
tty
->
write_q
))
if
(
!
EMPTY
(
&
tty
->
secondary
))
TTY_WRITE_FLUSH
(
tty
);
if
(
L_ICANON
(
tty
)
?
tty
->
canon_data
:
!
EMPTY
(
&
tty
->
secondary
))
wake_up_interruptible
(
&
tty
->
secondary
.
proc_list
);
wake_up_interruptible
(
&
tty
->
secondary
.
proc_list
);
if
(
tty
->
write_q
.
proc_list
&&
LEFT
(
&
tty
->
write_q
)
>
TTY_BUF_SIZE
/
2
)
wake_up_interruptible
(
&
tty
->
write_q
.
proc_list
);
if
(
tty
->
throttle
&&
(
LEFT
(
&
tty
->
read_q
)
>=
RQ_THRESHOLD_HW
)
if
(
tty
->
throttle
&&
(
LEFT
(
&
tty
->
read_q
)
>=
RQ_THRESHOLD_HW
)
&&
clear_bit
(
TTY_RQ_THROTTLED
,
&
tty
->
flags
))
&&
clear_bit
(
TTY_RQ_THROTTLED
,
&
tty
->
flags
))
tty
->
throttle
(
tty
,
TTY_THROTTLE_RQ_AVAIL
);
tty
->
throttle
(
tty
,
TTY_THROTTLE_RQ_AVAIL
);
if
(
tty
->
throttle
&&
(
LEFT
(
&
tty
->
secondary
)
>=
SQ_THRESHOLD_HW
)
&&
clear_bit
(
TTY_SQ_THROTTLED
,
&
tty
->
flags
))
tty
->
throttle
(
tty
,
TTY_THROTTLE_SQ_AVAIL
);
}
}
int
is_ignored
(
int
sig
)
int
is_ignored
(
int
sig
)
...
@@ -729,278 +921,205 @@ int is_ignored(int sig)
...
@@ -729,278 +921,205 @@ int is_ignored(int sig)
(
current
->
sigaction
[
sig
-
1
].
sa_handler
==
SIG_IGN
));
(
current
->
sigaction
[
sig
-
1
].
sa_handler
==
SIG_IGN
));
}
}
static
int
available_canon_input
(
struct
tty_struct
*
);
static
inline
int
input_available_p
(
struct
tty_struct
*
tty
)
static
void
__wait_for_canon_input
(
struct
file
*
file
,
struct
tty_struct
*
);
static
void
wait_for_canon_input
(
struct
file
*
file
,
struct
tty_struct
*
tty
)
{
{
if
(
!
available_canon_input
(
tty
))
{
/* Avoid calling TTY_READ_FLUSH unnecessarily. */
if
(
current
->
signal
&
~
current
->
blocked
)
if
(
L_ICANON
(
tty
))
{
return
;
if
(
tty
->
canon_data
||
FULL
(
&
tty
->
read_q
))
__wait_for_canon_input
(
file
,
tty
);
return
1
;
}
}
else
if
(
!
EMPTY
(
&
tty
->
secondary
))
return
1
;
/* Shuffle any pending data down the queues. */
TTY_READ_FLUSH
(
tty
);
if
(
tty
->
link
)
TTY_WRITE_FLUSH
(
tty
->
link
);
if
(
L_ICANON
(
tty
))
{
if
(
tty
->
canon_data
||
FULL
(
&
tty
->
read_q
))
return
1
;
}
else
if
(
!
EMPTY
(
&
tty
->
secondary
))
return
1
;
return
0
;
}
}
static
int
read_chan
(
struct
tty_struct
*
tty
,
struct
file
*
file
,
char
*
buf
,
int
nr
)
static
int
read_chan
(
struct
tty_struct
*
tty
,
struct
file
*
file
,
unsigned
char
*
buf
,
unsigned
int
nr
)
{
{
struct
wait_queue
wait
=
{
current
,
NULL
};
struct
wait_queue
wait
=
{
current
,
NULL
};
int
c
;
int
c
;
char
*
b
=
buf
;
unsigned
char
*
b
=
buf
;
int
minimum
,
time
;
int
minimum
,
time
;
int
retval
=
0
;
if
(
L_CANON
(
tty
))
if
(
L_ICANON
(
tty
))
{
minimum
=
time
=
current
->
timeout
=
0
;
minimum
=
time
=
0
;
else
{
current
->
timeout
=
(
unsigned
long
)
-
1
;
time
=
10L
*
tty
->
termios
->
c_cc
[
VTIME
];
}
else
{
minimum
=
tty
->
termios
->
c_cc
[
VMIN
];
time
=
(
HZ
/
10
)
*
TIME_CHAR
(
tty
);
minimum
=
MIN_CHAR
(
tty
);
if
(
minimum
)
if
(
minimum
)
current
->
timeout
=
0xffffffff
;
current
->
timeout
=
(
unsigned
long
)
-
1
;
else
{
else
{
if
(
time
)
if
(
time
)
{
current
->
timeout
=
time
+
jiffies
;
current
->
timeout
=
time
+
jiffies
;
else
time
=
0
;
}
else
current
->
timeout
=
0
;
current
->
timeout
=
0
;
time
=
0
;
minimum
=
1
;
minimum
=
1
;
}
}
}
}
if
(
file
->
f_flags
&
O_NONBLOCK
)
{
time
=
current
->
timeout
=
0
;
if
(
L_CANON
(
tty
)
&&
!
available_canon_input
(
tty
))
return
-
EAGAIN
;
}
else
if
(
L_CANON
(
tty
))
{
wait_for_canon_input
(
file
,
tty
);
if
(
current
->
signal
&
~
current
->
blocked
)
return
-
ERESTARTSYS
;
}
if
(
minimum
>
nr
)
minimum
=
nr
;
/* deal with packet mode: First test for status change */
if
(
tty
->
packet
&&
tty
->
link
&&
tty
->
link
->
ctrl_status
)
{
put_fs_byte
(
tty
->
link
->
ctrl_status
,
b
);
tty
->
link
->
ctrl_status
=
0
;
return
1
;
}
/* now bump the buffer up one. */
if
(
tty
->
packet
)
{
put_fs_byte
(
0
,
b
++
);
nr
--
;
/* this really shouldn't happen, but we need to
put it here. */
if
(
nr
==
0
)
return
1
;
}
add_wait_queue
(
&
tty
->
secondary
.
proc_list
,
&
wait
);
add_wait_queue
(
&
tty
->
secondary
.
proc_list
,
&
wait
);
while
(
nr
>
0
)
{
while
(
1
)
{
if
(
tty_hung_up_p
(
file
))
{
/* Job control check -- must be done at start and after
file
->
f_flags
&=
~
O_NONBLOCK
;
every sleep (POSIX.1 7.1.1.4). */
break
;
/* force read() to return 0 */
/* don't stop on /dev/console */
}
if
(
file
->
f_inode
->
i_rdev
!=
CONSOLE_DEV
&&
TTY_READ_FLUSH
(
tty
);
current
->
tty
==
tty
->
line
)
{
if
(
tty
->
link
)
if
(
tty
->
pgrp
<=
0
)
TTY_WRITE_FLUSH
(
tty
->
link
);
printk
(
"read_chan: tty->pgrp <= 0!
\n
"
);
while
(
nr
>
0
&&
((
c
=
get_tty_queue
(
&
tty
->
secondary
))
>=
0
))
{
else
if
(
current
->
pgrp
!=
tty
->
pgrp
)
{
if
((
EOF_CHAR
(
tty
)
!=
__DISABLED_CHAR
&&
if
(
is_ignored
(
SIGTTIN
)
||
c
==
EOF_CHAR
(
tty
))
||
c
==
10
)
is_orphaned_pgrp
(
current
->
pgrp
))
{
tty
->
secondary
.
data
--
;
retval
=
-
EIO
;
if
((
EOF_CHAR
(
tty
)
!=
__DISABLED_CHAR
&&
c
==
EOF_CHAR
(
tty
))
&&
L_CANON
(
tty
))
break
;
put_fs_byte
(
c
,
b
++
);
nr
--
;
if
(
time
)
current
->
timeout
=
time
+
jiffies
;
if
(
c
==
10
&&
L_CANON
(
tty
))
break
;
};
wake_up_interruptible
(
&
tty
->
read_q
.
proc_list
);
/*
* If there is enough space in the secondary queue
* now, let the low-level driver know.
*/
if
(
tty
->
throttle
&&
(
LEFT
(
&
tty
->
secondary
)
>=
SQ_THRESHOLD_HW
)
&&
clear_bit
(
TTY_SQ_THROTTLED
,
&
tty
->
flags
))
tty
->
throttle
(
tty
,
TTY_THROTTLE_SQ_AVAIL
);
if
(
tty
->
link
)
{
if
(
IS_A_PTY_MASTER
(
tty
->
line
))
{
if
((
tty
->
flags
&
(
1
<<
TTY_SLAVE_OPENED
))
&&
tty
->
link
->
count
<=
1
)
{
file
->
f_flags
&=
~
O_NONBLOCK
;
break
;
break
;
}
}
}
else
if
(
!
tty
->
link
->
count
)
{
kill_pg
(
current
->
pgrp
,
SIGTTIN
,
1
);
file
->
f_flags
&=
~
O_NONBLOCK
;
retval
=
-
ERESTARTSYS
;
break
;
break
;
}
}
}
}
if
(
b
-
buf
>=
minimum
||
!
current
->
timeout
)
/* First test for status change. */
break
;
if
(
tty
->
packet
&&
tty
->
link
->
ctrl_status
)
{
if
(
current
->
signal
&
~
current
->
blocked
)
if
(
b
!=
buf
)
break
;
put_fs_byte
(
tty
->
link
->
ctrl_status
,
b
++
);
tty
->
link
->
ctrl_status
=
0
;
break
;
break
;
TTY_READ_FLUSH
(
tty
);
}
if
(
tty
->
link
)
/* This statement must be first before checking for input
TTY_WRITE_FLUSH
(
tty
->
link
);
so that any interrupt will set the state back to
if
(
!
EMPTY
(
&
tty
->
secondary
))
TASK_RUNNING. */
continue
;
current
->
state
=
TASK_INTERRUPTIBLE
;
current
->
state
=
TASK_INTERRUPTIBLE
;
if
(
EMPTY
(
&
tty
->
secondary
))
if
(
!
input_available_p
(
tty
))
{
if
(
tty
->
flags
&
(
1
<<
TTY_SLAVE_CLOSED
))
{
retval
=
-
EIO
;
break
;
}
if
(
tty_hung_up_p
(
file
))
break
;
if
(
!
current
->
timeout
)
break
;
if
(
file
->
f_flags
&
O_NONBLOCK
)
{
retval
=
-
EAGAIN
;
break
;
}
if
(
current
->
signal
&
~
current
->
blocked
)
{
retval
=
-
ERESTARTSYS
;
break
;
}
schedule
();
schedule
();
continue
;
}
current
->
state
=
TASK_RUNNING
;
current
->
state
=
TASK_RUNNING
;
}
remove_wait_queue
(
&
tty
->
secondary
.
proc_list
,
&
wait
);
TTY_READ_FLUSH
(
tty
);
if
(
tty
->
link
&&
tty
->
link
->
write
)
TTY_WRITE_FLUSH
(
tty
->
link
);
current
->
timeout
=
0
;
/* packet mode sticks in an extra 0. If that's all we've got,
/* Deal with packet mode. */
we should count it a zero bytes. */
if
(
tty
->
packet
&&
b
==
buf
)
{
if
(
tty
->
packet
)
{
put_fs_byte
(
TIOCPKT_DATA
,
b
++
);
if
((
b
-
buf
)
>
1
)
nr
--
;
return
b
-
buf
;
}
}
else
{
if
(
b
-
buf
)
return
b
-
buf
;
}
if
(
current
->
signal
&
~
current
->
blocked
)
while
(
nr
>
0
)
{
return
-
ERESTARTSYS
;
int
eol
;
if
(
file
->
f_flags
&
O_NONBLOCK
)
return
-
EAGAIN
;
if
(
IS_A_PTY_MASTER
(
tty
->
line
))
return
-
EIO
;
return
0
;
}
static
void
__wait_for_canon_input
(
struct
file
*
file
,
struct
tty_struct
*
tty
)
cli
();
{
if
(
EMPTY
(
&
tty
->
secondary
))
{
struct
wait_queue
wait
=
{
current
,
NULL
};
sti
();
break
;
}
eol
=
clear_bit
(
tty
->
secondary
.
tail
,
&
tty
->
secondary_flags
);
c
=
tty
->
secondary
.
buf
[
tty
->
secondary
.
tail
];
INC
(
tty
->
secondary
.
tail
);
sti
();
if
(
eol
)
{
if
(
--
tty
->
canon_data
<
0
)
{
printk
(
"read_chan: canon_data < 0!
\n
"
);
tty
->
canon_data
=
0
;
}
if
(
c
==
__DISABLED_CHAR
)
break
;
put_fs_byte
(
c
,
b
++
);
nr
--
;
break
;
}
put_fs_byte
(
c
,
b
++
);
nr
--
;
}
add_wait_queue
(
&
tty
->
secondary
.
proc_list
,
&
wait
);
/* If there is enough space in the secondary queue now, let the
while
(
1
)
{
low-level driver know. */
current
->
state
=
TASK_INTERRUPTIBLE
;
if
(
tty
->
throttle
&&
(
LEFT
(
&
tty
->
secondary
)
>=
SQ_THRESHOLD_HW
)
if
(
available_canon_input
(
tty
))
&&
!
clear_bit
(
TTY_SQ_THROTTLED
,
&
tty
->
flags
))
break
;
tty
->
throttle
(
tty
,
TTY_THROTTLE_SQ_AVAIL
)
;
if
(
current
->
signal
&
~
current
->
blocked
)
break
;
/* XXX packet mode's status byte is mistakenly counted */
if
(
tty_hung_up_p
(
file
)
)
if
(
b
-
buf
>=
minimum
||
!
nr
)
break
;
break
;
schedule
();
if
(
time
)
current
->
timeout
=
time
+
jiffies
;
}
}
current
->
state
=
TASK_RUNNING
;
remove_wait_queue
(
&
tty
->
secondary
.
proc_list
,
&
wait
);
remove_wait_queue
(
&
tty
->
secondary
.
proc_list
,
&
wait
);
current
->
state
=
TASK_RUNNING
;
current
->
timeout
=
0
;
return
(
b
-
buf
)
?
b
-
buf
:
retval
;
}
}
static
int
available_canon_input
(
struct
tty_struct
*
tty
)
static
int
write_chan
(
struct
tty_struct
*
tty
,
struct
file
*
file
,
{
unsigned
char
*
buf
,
unsigned
int
nr
)
TTY_READ_FLUSH
(
tty
);
if
(
tty
->
link
)
if
(
tty
->
link
->
count
)
TTY_WRITE_FLUSH
(
tty
->
link
);
else
return
1
;
if
(
FULL
(
&
tty
->
read_q
))
return
1
;
if
(
tty
->
secondary
.
data
)
return
1
;
return
0
;
}
static
int
write_chan
(
struct
tty_struct
*
tty
,
struct
file
*
file
,
char
*
buf
,
int
nr
)
{
{
struct
wait_queue
wait
=
{
current
,
NULL
};
struct
wait_queue
wait
=
{
current
,
NULL
};
char
c
,
*
b
=
buf
;
int
c
;
unsigned
char
*
b
=
buf
;
int
retval
=
0
;
/* Job control check -- must be done at start (POSIX.1 7.1.1.4). */
if
(
L_TOSTOP
(
tty
)
&&
file
->
f_inode
->
i_rdev
!=
CONSOLE_DEV
)
{
retval
=
check_change
(
tty
,
tty
->
line
);
if
(
retval
)
return
retval
;
}
if
(
nr
<
0
)
return
-
EINVAL
;
if
(
!
nr
)
return
0
;
add_wait_queue
(
&
tty
->
write_q
.
proc_list
,
&
wait
);
add_wait_queue
(
&
tty
->
write_q
.
proc_list
,
&
wait
);
while
(
nr
>
0
)
{
while
(
1
)
{
if
(
current
->
signal
&
~
current
->
blocked
)
current
->
state
=
TASK_INTERRUPTIBLE
;
break
;
if
(
current
->
signal
&
~
current
->
blocked
)
{
if
(
tty_hung_up_p
(
file
))
retval
=
-
ERESTARTSYS
;
break
;
if
(
tty
->
link
&&
!
tty
->
link
->
count
)
{
send_sig
(
SIGPIPE
,
current
,
0
);
break
;
break
;
}
}
current
->
state
=
TASK_INTERRUPTIBLE
;
if
(
tty_hung_up_p
(
file
)
||
(
tty
->
link
&&
!
tty
->
link
->
count
))
{
if
(
FULL
(
&
tty
->
write_q
))
{
retval
=
-
EIO
;
TTY_WRITE_FLUSH
(
tty
);
break
;
if
(
FULL
(
&
tty
->
write_q
))
schedule
();
current
->
state
=
TASK_RUNNING
;
continue
;
}
}
current
->
state
=
TASK_RUNNING
;
while
(
nr
>
0
)
{
while
(
nr
>
0
&&
!
FULL
(
&
tty
->
write_q
))
{
c
=
get_fs_byte
(
b
);
c
=
get_fs_byte
(
b
);
/* Care is needed here: opost() can abort even
if
(
O_POST
(
tty
))
{
if the write_q is not full. */
switch
(
c
)
{
if
(
opost
(
c
,
tty
)
<
0
)
case
'\n'
:
break
;
if
(
O_NLRET
(
tty
))
{
tty
->
column
=
0
;
}
if
(
O_NLCR
(
tty
))
{
if
(
!
set_bit
(
TTY_CR_PENDING
,
&
tty
->
flags
))
{
c
=
'\r'
;
tty
->
column
=
0
;
b
--
;
nr
++
;
}
else
{
clear_bit
(
TTY_CR_PENDING
,
&
tty
->
flags
);
}
}
break
;
case
'\r'
:
if
(
O_NOCR
(
tty
)
&&
tty
->
column
==
0
)
{
b
++
;
nr
--
;
continue
;
}
if
(
O_CRNL
(
tty
))
{
c
=
'\n'
;
if
(
O_NLRET
(
tty
))
tty
->
column
=
0
;
break
;
}
tty
->
column
=
0
;
break
;
case
'\t'
:
if
(
O_TABDLY
(
tty
)
==
XTABS
)
{
c
=
' '
;
tty
->
column
++
;
if
(
tty
->
column
%
8
!=
0
)
{
b
--
;
nr
++
;
}
}
break
;
case
'\b'
:
tty
->
column
--
;
break
;
default:
if
(
O_LCUC
(
tty
))
c
=
toupper
(
c
);
tty
->
column
++
;
break
;
}
}
b
++
;
nr
--
;
b
++
;
nr
--
;
put_tty_queue
(
c
,
&
tty
->
write_q
);
}
}
if
(
need_resched
)
TTY_WRITE_FLUSH
(
tty
);
schedule
();
if
(
!
nr
)
break
;
if
(
EMPTY
(
&
tty
->
write_q
)
&&
!
need_resched
)
continue
;
schedule
();
}
}
current
->
state
=
TASK_RUNNING
;
remove_wait_queue
(
&
tty
->
write_q
.
proc_list
,
&
wait
);
remove_wait_queue
(
&
tty
->
write_q
.
proc_list
,
&
wait
);
TTY_WRITE_FLUSH
(
tty
);
return
(
b
-
buf
)
?
b
-
buf
:
retval
;
if
(
b
-
buf
)
return
b
-
buf
;
if
(
tty
->
link
&&
!
tty
->
link
->
count
)
return
-
EPIPE
;
if
(
current
->
signal
&
~
current
->
blocked
)
return
-
ERESTARTSYS
;
return
0
;
}
}
static
int
tty_read
(
struct
inode
*
inode
,
struct
file
*
file
,
char
*
buf
,
int
count
)
static
int
tty_read
(
struct
inode
*
inode
,
struct
file
*
file
,
char
*
buf
,
int
count
)
...
@@ -1017,6 +1136,12 @@ static int tty_read(struct inode * inode, struct file * file, char * buf, int co
...
@@ -1017,6 +1136,12 @@ static int tty_read(struct inode * inode, struct file * file, char * buf, int co
tty
=
TTY_TABLE
(
dev
);
tty
=
TTY_TABLE
(
dev
);
if
(
!
tty
||
(
tty
->
flags
&
(
1
<<
TTY_IO_ERROR
)))
if
(
!
tty
||
(
tty
->
flags
&
(
1
<<
TTY_IO_ERROR
)))
return
-
EIO
;
return
-
EIO
;
/* This check not only needs to be done before reading, but also
whenever read_chan() gets woken up after sleeping, so I've
moved it to there. This should only be done for the N_TTY
line discipline, anyway. Same goes for write_chan(). -- jlc. */
#if 0
if ((inode->i_rdev != CONSOLE_DEV) && /* don't stop on /dev/console */
if ((inode->i_rdev != CONSOLE_DEV) && /* don't stop on /dev/console */
(tty->pgrp > 0) &&
(tty->pgrp > 0) &&
(current->tty == dev) &&
(current->tty == dev) &&
...
@@ -1027,8 +1152,10 @@ static int tty_read(struct inode * inode, struct file * file, char * buf, int co
...
@@ -1027,8 +1152,10 @@ static int tty_read(struct inode * inode, struct file * file, char * buf, int co
(void) kill_pg(current->pgrp, SIGTTIN, 1);
(void) kill_pg(current->pgrp, SIGTTIN, 1);
return -ERESTARTSYS;
return -ERESTARTSYS;
}
}
#endif
if
(
ldiscs
[
tty
->
disc
].
read
)
if
(
ldiscs
[
tty
->
disc
].
read
)
i
=
(
ldiscs
[
tty
->
disc
].
read
)(
tty
,
file
,
buf
,
count
);
/* XXX casts are for what kernel-wide prototypes should be. */
i
=
(
ldiscs
[
tty
->
disc
].
read
)(
tty
,
file
,(
unsigned
char
*
)
buf
,(
unsigned
int
)
count
);
else
else
i
=
-
EIO
;
i
=
-
EIO
;
if
(
i
>
0
)
if
(
i
>
0
)
...
@@ -1054,6 +1181,7 @@ static int tty_write(struct inode * inode, struct file * file, char * buf, int c
...
@@ -1054,6 +1181,7 @@ static int tty_write(struct inode * inode, struct file * file, char * buf, int c
tty
=
TTY_TABLE
(
dev
);
tty
=
TTY_TABLE
(
dev
);
if
(
!
tty
||
!
tty
->
write
||
(
tty
->
flags
&
(
1
<<
TTY_IO_ERROR
)))
if
(
!
tty
||
!
tty
->
write
||
(
tty
->
flags
&
(
1
<<
TTY_IO_ERROR
)))
return
-
EIO
;
return
-
EIO
;
#if 0
if (!is_console && L_TOSTOP(tty) && (tty->pgrp > 0) &&
if (!is_console && L_TOSTOP(tty) && (tty->pgrp > 0) &&
(current->tty == dev) && (tty->pgrp != current->pgrp)) {
(current->tty == dev) && (tty->pgrp != current->pgrp)) {
if (is_orphaned_pgrp(current->pgrp))
if (is_orphaned_pgrp(current->pgrp))
...
@@ -1063,8 +1191,10 @@ static int tty_write(struct inode * inode, struct file * file, char * buf, int c
...
@@ -1063,8 +1191,10 @@ static int tty_write(struct inode * inode, struct file * file, char * buf, int c
return -ERESTARTSYS;
return -ERESTARTSYS;
}
}
}
}
#endif
if
(
ldiscs
[
tty
->
disc
].
write
)
if
(
ldiscs
[
tty
->
disc
].
write
)
i
=
(
ldiscs
[
tty
->
disc
].
write
)(
tty
,
file
,
buf
,
count
);
/* XXX casts are for what kernel-wide prototypes should be. */
i
=
(
ldiscs
[
tty
->
disc
].
write
)(
tty
,
file
,(
unsigned
char
*
)
buf
,(
unsigned
int
)
count
);
else
else
i
=
-
EIO
;
i
=
-
EIO
;
if
(
i
>
0
)
if
(
i
>
0
)
...
@@ -1349,6 +1479,7 @@ static int tty_open(struct inode * inode, struct file * filp)
...
@@ -1349,6 +1479,7 @@ static int tty_open(struct inode * inode, struct file * filp)
if
(
test_bit
(
TTY_EXCLUSIVE
,
&
tty
->
flags
)
&&
!
suser
())
if
(
test_bit
(
TTY_EXCLUSIVE
,
&
tty
->
flags
)
&&
!
suser
())
return
-
EBUSY
;
return
-
EBUSY
;
#if 0
/* clean up the packet stuff. */
/* clean up the packet stuff. */
/*
/*
* Why is this not done in init_dev? Right here, if another
* Why is this not done in init_dev? Right here, if another
...
@@ -1358,9 +1489,12 @@ static int tty_open(struct inode * inode, struct file * filp)
...
@@ -1358,9 +1489,12 @@ static int tty_open(struct inode * inode, struct file * filp)
*
*
* Not to worry, a pty master can only be opened once.
* Not to worry, a pty master can only be opened once.
* And rlogind and telnetd both use packet mode. -- jrs
* And rlogind and telnetd both use packet mode. -- jrs
*
* Not needed. These are cleared in initialize_tty_struct. -- jlc
*/
*/
tty->ctrl_status = 0;
tty->ctrl_status = 0;
tty->packet = 0;
tty->packet = 0;
#endif
if
(
tty
->
open
)
{
if
(
tty
->
open
)
{
retval
=
tty
->
open
(
tty
,
filp
);
retval
=
tty
->
open
(
tty
,
filp
);
...
@@ -1441,26 +1575,16 @@ static int normal_select(struct tty_struct * tty, struct inode * inode,
...
@@ -1441,26 +1575,16 @@ static int normal_select(struct tty_struct * tty, struct inode * inode,
{
{
switch
(
sel_type
)
{
switch
(
sel_type
)
{
case
SEL_IN
:
case
SEL_IN
:
if
(
L_CANON
(
tty
))
{
if
(
input_available_p
(
tty
))
if
(
available_canon_input
(
tty
))
return
1
;
}
else
if
(
!
EMPTY
(
&
tty
->
secondary
))
return
1
;
return
1
;
if
(
tty
->
link
)
{
/* fall through */
if
(
IS_A_PTY_MASTER
(
tty
->
line
))
{
case
SEL_EX
:
if
((
tty
->
flags
&
(
1
<<
TTY_SLAVE_OPENED
))
if
(
tty
->
packet
&&
tty
->
link
->
ctrl_status
)
&&
tty
->
link
->
count
<=
1
)
return
1
;
return
1
;
if
(
tty
->
flags
&
(
1
<<
TTY_SLAVE_CLOSED
))
}
else
{
return
1
;
if
(
!
tty
->
link
->
count
)
if
(
tty_hung_up_p
(
file
))
return
1
;
}
}
/* see if the status byte can be read. */
if
(
tty
->
packet
&&
tty
->
link
&&
tty
->
link
->
ctrl_status
)
return
1
;
return
1
;
select_wait
(
&
tty
->
secondary
.
proc_list
,
wait
);
select_wait
(
&
tty
->
secondary
.
proc_list
,
wait
);
return
0
;
return
0
;
case
SEL_OUT
:
case
SEL_OUT
:
...
@@ -1468,22 +1592,6 @@ static int normal_select(struct tty_struct * tty, struct inode * inode,
...
@@ -1468,22 +1592,6 @@ static int normal_select(struct tty_struct * tty, struct inode * inode,
return
1
;
return
1
;
select_wait
(
&
tty
->
write_q
.
proc_list
,
wait
);
select_wait
(
&
tty
->
write_q
.
proc_list
,
wait
);
return
0
;
return
0
;
case
SEL_EX
:
if
(
tty
->
link
)
{
if
(
IS_A_PTY_MASTER
(
tty
->
line
))
{
if
((
tty
->
flags
&
(
1
<<
TTY_SLAVE_OPENED
))
&&
tty
->
link
->
count
<=
1
)
return
1
;
if
(
tty
->
packet
&&
tty
->
link
->
ctrl_status
)
return
1
;
}
else
{
if
(
!
tty
->
link
->
count
)
return
1
;
}
}
select_wait
(
&
tty
->
except_q
,
wait
);
return
0
;
}
}
return
0
;
return
0
;
}
}
...
@@ -1645,8 +1753,6 @@ static void initialize_tty_struct(int line, struct tty_struct *tty)
...
@@ -1645,8 +1753,6 @@ static void initialize_tty_struct(int line, struct tty_struct *tty)
tty
->
line
=
line
;
tty
->
line
=
line
;
tty
->
disc
=
N_TTY
;
tty
->
disc
=
N_TTY
;
tty
->
pgrp
=
-
1
;
tty
->
pgrp
=
-
1
;
tty
->
winsize
.
ws_row
=
0
;
tty
->
winsize
.
ws_col
=
0
;
if
(
IS_A_CONSOLE
(
line
))
{
if
(
IS_A_CONSOLE
(
line
))
{
tty
->
open
=
con_open
;
tty
->
open
=
con_open
;
tty
->
winsize
.
ws_row
=
video_num_lines
;
tty
->
winsize
.
ws_row
=
video_num_lines
;
...
@@ -1656,31 +1762,26 @@ static void initialize_tty_struct(int line, struct tty_struct *tty)
...
@@ -1656,31 +1762,26 @@ static void initialize_tty_struct(int line, struct tty_struct *tty)
}
else
if
IS_A_PTY
(
line
)
{
}
else
if
IS_A_PTY
(
line
)
{
tty
->
open
=
pty_open
;
tty
->
open
=
pty_open
;
}
}
tty
->
except_q
=
NULL
;
}
}
static
void
initialize_termios
(
int
line
,
struct
termios
*
tp
)
static
void
initialize_termios
(
int
line
,
struct
termios
*
tp
)
{
{
memset
(
tp
,
0
,
sizeof
(
struct
termios
));
memset
(
tp
,
0
,
sizeof
(
struct
termios
));
memcpy
(
tp
->
c_cc
,
INIT_C_CC
,
NCCS
);
memcpy
(
tp
->
c_cc
,
INIT_C_CC
,
NCCS
);
if
(
IS_A_CONSOLE
(
line
))
{
if
(
IS_A_CONSOLE
(
line
)
||
IS_A_PTY_SLAVE
(
line
)
)
{
tp
->
c_iflag
=
ICRNL
|
IXON
;
tp
->
c_iflag
=
ICRNL
|
IXON
;
tp
->
c_oflag
=
OPOST
|
ONLCR
;
tp
->
c_oflag
=
OPOST
|
ONLCR
;
tp
->
c_cflag
=
B38400
|
CS8
|
CREAD
;
tp
->
c_cflag
=
B38400
|
CS8
|
CREAD
;
tp
->
c_lflag
=
ISIG
|
ICANON
|
ECHO
|
tp
->
c_lflag
=
ISIG
|
ICANON
|
ECHO
|
ECHOE
|
ECHOK
|
ECHOCTL
|
ECHOKE
;
ECHOCTL
|
ECHOKE
|
IEXTEN
;
}
else
if
(
IS_A_SERIAL
(
line
))
{
}
else
if
(
IS_A_SERIAL
(
line
))
{
tp
->
c_
cflag
=
B9600
|
CS8
|
CREAD
|
HUPCL
|
CLOCAL
;
tp
->
c_
iflag
=
ICRNL
|
IXON
;
tp
->
c_oflag
=
OPOST
|
ONLCR
|
XTABS
;
tp
->
c_oflag
=
OPOST
|
ONLCR
|
XTABS
;
}
else
if
(
IS_A_PTY_MASTER
(
line
))
{
tp
->
c_cflag
=
B9600
|
CS8
|
CREAD
|
HUPCL
|
CLOCAL
;
tp
->
c_lflag
=
ISIG
|
ICANON
|
ECHO
|
ECHOE
|
ECHOK
|
ECHOCTL
|
ECHOKE
|
IEXTEN
;
}
else
if
(
IS_A_PTY_MASTER
(
line
))
tp
->
c_cflag
=
B9600
|
CS8
|
CREAD
;
tp
->
c_cflag
=
B9600
|
CS8
|
CREAD
;
}
else
if
(
IS_A_PTY_SLAVE
(
line
))
{
tp
->
c_iflag
=
ICRNL
|
IXON
;
tp
->
c_oflag
=
OPOST
|
ONLCR
;
tp
->
c_cflag
=
B38400
|
CS8
|
CREAD
;
tp
->
c_lflag
=
ISIG
|
ICANON
|
ECHO
|
ECHOCTL
|
ECHOKE
;
}
}
}
static
struct
tty_ldisc
tty_ldisc_N_TTY
=
{
static
struct
tty_ldisc
tty_ldisc_N_TTY
=
{
...
...
drivers/char/tty_ioctl.c
View file @
b168ffdf
...
@@ -17,6 +17,7 @@
...
@@ -17,6 +17,7 @@
#include <linux/major.h>
#include <linux/major.h>
#include <linux/tty.h>
#include <linux/tty.h>
#include <linux/fcntl.h>
#include <linux/fcntl.h>
#include <linux/string.h>
#include <asm/io.h>
#include <asm/io.h>
#include <asm/bitops.h>
#include <asm/bitops.h>
...
@@ -41,44 +42,43 @@ extern int paste_selection(struct tty_struct *tty);
...
@@ -41,44 +42,43 @@ extern int paste_selection(struct tty_struct *tty);
static
int
tty_set_ldisc
(
struct
tty_struct
*
tty
,
int
ldisc
);
static
int
tty_set_ldisc
(
struct
tty_struct
*
tty
,
int
ldisc
);
static
void
flush
(
struct
tty_queue
*
queue
)
{
if
(
queue
)
{
cli
();
queue
->
head
=
queue
->
tail
;
sti
();
wake_up_interruptible
(
&
queue
->
proc_list
);
}
}
void
flush_input
(
struct
tty_struct
*
tty
)
void
flush_input
(
struct
tty_struct
*
tty
)
{
{
tty
->
ctrl_status
|=
TIOCPKT_FLUSHREAD
;
cli
();
if
(
tty
->
link
)
tty
->
read_q
.
head
=
tty
->
read_q
.
tail
=
0
;
wake_up_interruptible
(
&
tty
->
link
->
except_q
);
tty
->
secondary
.
head
=
tty
->
secondary
.
tail
=
0
;
flush
(
&
tty
->
read_q
);
tty
->
canon_head
=
tty
->
canon_data
=
tty
->
erasing
=
0
;
wake_up_interruptible
(
&
tty
->
read_q
.
proc_list
);
memset
(
&
tty
->
readq_flags
,
0
,
sizeof
tty
->
readq_flags
);
flush
(
&
tty
->
secondary
);
memset
(
&
tty
->
secondary_flags
,
0
,
sizeof
tty
->
secondary_flags
);
tty
->
secondary
.
data
=
0
;
sti
();
if
(
!
tty
->
link
)
if
((
tty
=
tty
->
link
)
!=
NULL
)
{
return
;
flush
(
&
tty
->
write_q
);
/* No cli() since ptys don't use interrupts. */
wake_up_interruptible
(
&
tty
->
write_q
.
proc_list
);
tty
->
link
->
write_q
.
head
=
tty
->
link
->
write_q
.
tail
=
0
;
wake_up_interruptible
(
&
tty
->
link
->
write_q
.
proc_list
);
if
(
tty
->
link
->
packet
)
{
tty
->
ctrl_status
|=
TIOCPKT_FLUSHREAD
;
wake_up_interruptible
(
&
tty
->
link
->
secondary
.
proc_list
);
}
}
}
}
void
flush_output
(
struct
tty_struct
*
tty
)
void
flush_output
(
struct
tty_struct
*
tty
)
{
{
tty
->
ctrl_status
|=
TIOCPKT_FLUSHWRITE
;
cli
();
if
(
tty
->
link
)
tty
->
write_q
.
head
=
tty
->
write_q
.
tail
=
0
;
wake_up_interruptible
(
&
tty
->
link
->
except_q
);
sti
();
flush
(
&
tty
->
write_q
);
wake_up_interruptible
(
&
tty
->
write_q
.
proc_list
);
wake_up_interruptible
(
&
tty
->
write_q
.
proc_list
);
if
((
tty
=
tty
->
link
)
!=
NULL
)
{
if
(
!
tty
->
link
)
flush
(
&
tty
->
read_q
);
return
;
wake_up_interruptible
(
&
tty
->
read_q
.
proc_list
);
/* No cli() since ptys don't use interrupts. */
flush
(
&
tty
->
secondary
);
tty
->
link
->
read_q
.
head
=
tty
->
link
->
read_q
.
tail
=
0
;
tty
->
secondary
.
data
=
0
;
tty
->
link
->
secondary
.
head
=
tty
->
link
->
secondary
.
tail
=
0
;
tty
->
link
->
canon_head
=
tty
->
link
->
canon_data
=
tty
->
link
->
erasing
=
0
;
memset
(
&
tty
->
link
->
readq_flags
,
0
,
sizeof
tty
->
readq_flags
);
memset
(
&
tty
->
link
->
secondary_flags
,
0
,
sizeof
tty
->
secondary_flags
);
if
(
tty
->
link
->
packet
)
{
tty
->
ctrl_status
|=
TIOCPKT_FLUSHWRITE
;
wake_up_interruptible
(
&
tty
->
link
->
secondary
.
proc_list
);
}
}
}
}
...
@@ -156,65 +156,61 @@ static void unset_locked_termios(struct termios *termios,
...
@@ -156,65 +156,61 @@ static void unset_locked_termios(struct termios *termios,
old
->
c_cc
[
i
]
:
termios
->
c_cc
[
i
];
old
->
c_cc
[
i
]
:
termios
->
c_cc
[
i
];
}
}
static
int
get_termios
(
struct
tty_struct
*
tty
,
struct
termios
*
termios
)
int
check_change
(
struct
tty_struct
*
tty
,
int
channel
)
{
int
i
;
i
=
verify_area
(
VERIFY_WRITE
,
termios
,
sizeof
(
*
termios
));
if
(
i
)
return
i
;
for
(
i
=
0
;
i
<
(
sizeof
(
*
termios
))
;
i
++
)
put_fs_byte
(
((
char
*
)
tty
->
termios
)[
i
]
,
i
+
(
char
*
)
termios
);
return
0
;
}
static
int
check_change
(
struct
tty_struct
*
tty
,
int
channel
)
{
{
/* If we try to set the state of terminal and we're not in the
/* If we try to set the state of terminal and we're not in the
foreground, send a SIGTTOU. If the signal is blocked or
foreground, send a SIGTTOU. If the signal is blocked or
ignored, go ahead and perform the operation. POSIX 7.2) */
ignored, go ahead and perform the operation. POSIX 7.2) */
if
(
current
->
tty
!=
channel
)
if
(
current
->
tty
!=
channel
)
return
0
;
return
0
;
if
(
tty
->
pgrp
<=
0
||
tty
->
pgrp
==
current
->
pgrp
)
if
(
tty
->
pgrp
<=
0
)
{
printk
(
"check_change: tty->pgrp <= 0!
\n
"
);
return
0
;
}
if
(
current
->
pgrp
==
tty
->
pgrp
)
return
0
;
return
0
;
if
(
is_orphaned_pgrp
(
current
->
pgrp
))
return
-
EIO
;
if
(
is_ignored
(
SIGTTOU
))
if
(
is_ignored
(
SIGTTOU
))
return
0
;
return
0
;
if
(
is_orphaned_pgrp
(
current
->
pgrp
))
return
-
EIO
;
(
void
)
kill_pg
(
current
->
pgrp
,
SIGTTOU
,
1
);
(
void
)
kill_pg
(
current
->
pgrp
,
SIGTTOU
,
1
);
return
-
ERESTARTSYS
;
return
-
ERESTARTSYS
;
}
}
static
int
set_termios
(
struct
tty_struct
*
tty
,
struct
termios
*
termios
,
static
int
set_termios_2
(
struct
tty_struct
*
tty
,
struct
termios
*
termios
)
int
channel
)
{
{
int
i
,
old_flow
,
new_flow
;
struct
termios
old_termios
=
*
tty
->
termios
;
struct
termios
old_termios
=
*
tty
->
termios
;
int
canon_change
;
i
=
check_change
(
tty
,
channel
);
if
(
i
)
canon_change
=
(
old_termios
.
c_lflag
^
termios
->
c_lflag
)
&
ICANON
;
return
i
;
cli
();
for
(
i
=
0
;
i
<
(
sizeof
(
*
termios
))
;
i
++
)
*
tty
->
termios
=
*
termios
;
((
char
*
)
tty
->
termios
)[
i
]
=
get_fs_byte
(
i
+
(
char
*
)
termios
);
if
(
canon_change
)
{
memset
(
&
tty
->
secondary_flags
,
0
,
sizeof
tty
->
secondary_flags
);
tty
->
canon_head
=
tty
->
secondary
.
tail
;
tty
->
canon_data
=
0
;
tty
->
erasing
=
0
;
}
sti
();
if
(
canon_change
&&
!
(
tty
->
termios
->
c_lflag
&
ICANON
)
&&
!
EMPTY
(
&
tty
->
secondary
))
/* Get characters left over from canonical mode. */
wake_up_interruptible
(
&
tty
->
secondary
.
proc_list
);
/* see if packet mode change of state */
/* see if packet mode change of state */
old_flow
=
(
old_termios
.
c_iflag
&
IXON
)
&&
/* The BSD man page pty.4 says that TIOCPKT_NOSTOP should be sent
(
old_termios
.
c_cc
[
VSTOP
]
==
'\023'
)
&&
if the new state differs from ^S/^Q, but that's a bad way of
(
old_termios
.
c_cc
[
VSTART
]
==
'\021'
);
detecting a new flow control scheme. Instead, a status byte
is only sent if IXON has changed. */
new_flow
=
(
tty
->
termios
->
c_iflag
&
IXON
)
&&
if
(
tty
->
link
&&
tty
->
link
->
packet
&&
(
tty
->
termios
->
c_cc
[
VSTOP
]
==
'\023'
)
&&
(
old_termios
.
c_iflag
^
tty
->
termios
->
c_iflag
)
&
IXON
)
{
(
tty
->
termios
->
c_cc
[
VSTART
]
==
'\021'
);
tty
->
ctrl_status
&=
~
(
TIOCPKT_DOSTOP
|
TIOCPKT_NOSTOP
);
if
(
tty
->
termios
->
c_iflag
&
IXON
)
if
(
old_flow
!=
new_flow
)
{
tty
->
ctrl_status
&=
~
(
TIOCPKT_DOSTOP
|
TIOCPKT_NOSTOP
);
if
(
new_flow
)
tty
->
ctrl_status
|=
TIOCPKT_DOSTOP
;
tty
->
ctrl_status
|=
TIOCPKT_DOSTOP
;
else
else
tty
->
ctrl_status
|=
TIOCPKT_NOSTOP
;
tty
->
ctrl_status
|=
TIOCPKT_NOSTOP
;
if
(
tty
->
link
)
wake_up_interruptible
(
&
tty
->
link
->
secondary
.
proc_list
);
wake_up_interruptible
(
&
tty
->
link
->
except_q
);
}
}
#if 0
#if 0
...
@@ -241,12 +237,21 @@ static int set_termios(struct tty_struct * tty, struct termios * termios,
...
@@ -241,12 +237,21 @@ static int set_termios(struct tty_struct * tty, struct termios * termios,
return
0
;
return
0
;
}
}
static
int
set_termios
(
struct
tty_struct
*
tty
,
struct
termios
*
termios
,
int
channel
)
{
struct
termios
tmp_termios
;
memcpy_fromfs
(
&
tmp_termios
,
termios
,
sizeof
(
struct
termios
));
return
set_termios_2
(
tty
,
&
tmp_termios
);
}
static
int
get_termio
(
struct
tty_struct
*
tty
,
struct
termio
*
termio
)
static
int
get_termio
(
struct
tty_struct
*
tty
,
struct
termio
*
termio
)
{
{
int
i
;
int
i
;
struct
termio
tmp_termio
;
struct
termio
tmp_termio
;
i
=
verify_area
(
VERIFY_WRITE
,
termio
,
sizeof
(
*
termio
));
i
=
verify_area
(
VERIFY_WRITE
,
termio
,
sizeof
(
struct
termio
));
if
(
i
)
if
(
i
)
return
i
;
return
i
;
tmp_termio
.
c_iflag
=
tty
->
termios
->
c_iflag
;
tmp_termio
.
c_iflag
=
tty
->
termios
->
c_iflag
;
...
@@ -256,128 +261,41 @@ static int get_termio(struct tty_struct * tty, struct termio * termio)
...
@@ -256,128 +261,41 @@ static int get_termio(struct tty_struct * tty, struct termio * termio)
tmp_termio
.
c_line
=
tty
->
termios
->
c_line
;
tmp_termio
.
c_line
=
tty
->
termios
->
c_line
;
for
(
i
=
0
;
i
<
NCC
;
i
++
)
for
(
i
=
0
;
i
<
NCC
;
i
++
)
tmp_termio
.
c_cc
[
i
]
=
tty
->
termios
->
c_cc
[
i
];
tmp_termio
.
c_cc
[
i
]
=
tty
->
termios
->
c_cc
[
i
];
for
(
i
=
0
;
i
<
(
sizeof
(
*
termio
))
;
i
++
)
memcpy_tofs
(
termio
,
&
tmp_termio
,
sizeof
(
struct
termio
));
put_fs_byte
(
((
char
*
)
&
tmp_termio
)[
i
]
,
i
+
(
char
*
)
termio
);
return
0
;
return
0
;
}
}
static
int
set_termio
(
struct
tty_struct
*
tty
,
struct
termio
*
termio
,
static
int
set_termio
(
struct
tty_struct
*
tty
,
struct
termio
*
termio
,
int
channel
)
int
channel
)
{
{
int
i
,
old_flow
,
new_flow
;
struct
termio
tmp_termio
;
struct
termio
tmp_termio
;
struct
termios
old_termios
=
*
tty
->
termios
;
struct
termios
tmp_
termios
;
#define SET_LOW_BITS(x,y) ((x) = (0xffff0000 & (x)) | (y))
tmp_termios
=
*
tty
->
termios
;
memcpy_fromfs
(
&
tmp_termio
,
termio
,
sizeof
(
struct
termio
));
i
=
check_change
(
tty
,
channel
);
if
(
i
)
return
i
;
memcpy_fromfs
(
&
tmp_termio
,
termio
,
sizeof
(
*
termio
));
SET_LOW_BITS
(
tty
->
termios
->
c_iflag
,
tmp_termio
.
c_iflag
);
SET_LOW_BITS
(
tty
->
termios
->
c_oflag
,
tmp_termio
.
c_oflag
);
SET_LOW_BITS
(
tty
->
termios
->
c_cflag
,
tmp_termio
.
c_cflag
);
SET_LOW_BITS
(
tty
->
termios
->
c_lflag
,
tmp_termio
.
c_lflag
);
memcpy
(
tty
->
termios
->
c_cc
,
tmp_termio
.
c_cc
,
NCC
);
/* see if packet mode change of state */
old_flow
=
(
old_termios
.
c_iflag
&
IXON
)
&&
(
old_termios
.
c_cc
[
VSTOP
]
==
'\023'
)
&&
(
old_termios
.
c_cc
[
VSTART
]
==
'\021'
);
new_flow
=
(
tty
->
termios
->
c_iflag
&
IXON
)
&&
(
tty
->
termios
->
c_cc
[
VSTOP
]
==
'\023'
)
&&
(
tty
->
termios
->
c_cc
[
VSTART
]
==
'\021'
);
if
(
old_flow
!=
new_flow
)
{
#define SET_LOW_BITS(x,y) ((x) = (0xffff0000 & (x)) | (y))
tty
->
ctrl_status
&=
~
(
TIOCPKT_DOSTOP
|
TIOCPKT_NOSTOP
);
if
(
new_flow
)
tty
->
ctrl_status
|=
TIOCPKT_DOSTOP
;
else
tty
->
ctrl_status
|=
TIOCPKT_NOSTOP
;
if
(
tty
->
link
)
wake_up_interruptible
(
&
tty
->
link
->
except_q
);
}
unset_locked_termios
(
tty
->
termios
,
&
old_termios
,
termios_locked
[
tty
->
line
]);
#if 0
retval = tty_set_ldisc(tty, tmp_termio.c_line);
if (retval)
return retval;
#endif
if
(
tty
->
set_termios
)
(
*
tty
->
set_termios
)(
tty
,
&
old_termios
);
return
0
;
}
static
int
get_lcktrmios
(
struct
tty_struct
*
tty
,
struct
termios
*
termios
,
int
channel
)
{
int
i
;
i
=
verify_area
(
VERIFY_WRITE
,
termios
,
sizeof
(
*
termios
));
if
(
i
)
return
i
;
for
(
i
=
0
;
i
<
(
sizeof
(
*
termios
))
;
i
++
)
put_fs_byte
(
((
char
*
)
termios_locked
[
channel
])[
i
],
i
+
(
char
*
)
termios
);
return
0
;
}
static
int
set_lcktrmios
(
struct
tty_struct
*
tty
,
struct
termios
*
termios
,
SET_LOW_BITS
(
tmp_termios
.
c_iflag
,
tmp_termio
.
c_iflag
);
int
channel
)
SET_LOW_BITS
(
tmp_termios
.
c_oflag
,
tmp_termio
.
c_oflag
);
{
SET_LOW_BITS
(
tmp_termios
.
c_cflag
,
tmp_termio
.
c_cflag
);
int
i
;
SET_LOW_BITS
(
tmp_termios
.
c_lflag
,
tmp_termio
.
c_lflag
);
memcpy
(
&
tmp_termios
.
c_cc
,
&
tmp_termio
.
c_cc
,
NCC
);
if
(
!
suser
())
#undef SET_LOW_BITS
return
-
EPERM
;
for
(
i
=
0
;
i
<
(
sizeof
(
*
termios
))
;
i
++
)
((
char
*
)
termios_locked
[
channel
])[
i
]
=
get_fs_byte
(
i
+
(
char
*
)
termios
);
return
0
;
return
set_termios_2
(
tty
,
&
tmp_termios
)
;
}
}
static
int
set_window_size
(
struct
tty_struct
*
tty
,
struct
winsize
*
ws
)
static
int
set_window_size
(
struct
tty_struct
*
tty
,
struct
winsize
*
ws
)
{
{
int
i
,
changed
;
struct
winsize
tmp_ws
;
char
c
,
*
tmp
;
if
(
!
ws
)
memcpy_fromfs
(
&
tmp_ws
,
ws
,
sizeof
(
struct
winsize
));
return
-
EINVAL
;
if
(
memcmp
(
&
tmp_ws
,
&
tty
->
winsize
,
sizeof
(
struct
winsize
))
&&
tmp
=
(
char
*
)
&
tty
->
winsize
;
tty
->
pgrp
>
0
)
changed
=
0
;
for
(
i
=
0
;
i
<
sizeof
(
*
ws
)
;
i
++
,
tmp
++
)
{
c
=
get_fs_byte
(
i
+
(
char
*
)
ws
);
if
(
c
==
*
tmp
)
continue
;
changed
=
1
;
*
tmp
=
c
;
}
if
(
changed
)
kill_pg
(
tty
->
pgrp
,
SIGWINCH
,
1
);
kill_pg
(
tty
->
pgrp
,
SIGWINCH
,
1
);
return
0
;
tty
->
winsize
=
tmp_ws
;
}
static
int
get_window_size
(
struct
tty_struct
*
tty
,
struct
winsize
*
ws
)
{
int
i
;
char
*
tmp
;
if
(
!
ws
)
return
-
EINVAL
;
i
=
verify_area
(
VERIFY_WRITE
,
ws
,
sizeof
(
*
ws
));
if
(
i
)
return
i
;
tmp
=
(
char
*
)
ws
;
for
(
i
=
0
;
i
<
sizeof
(
struct
winsize
)
;
i
++
,
tmp
++
)
put_fs_byte
(((
char
*
)
&
tty
->
winsize
)[
i
],
tmp
);
return
0
;
return
0
;
}
}
...
@@ -406,20 +324,19 @@ static int tty_set_ldisc(struct tty_struct *tty, int ldisc)
...
@@ -406,20 +324,19 @@ static int tty_set_ldisc(struct tty_struct *tty, int ldisc)
return
0
;
return
0
;
}
}
static
int
inq_canon
(
struct
tty_struct
*
tty
)
static
unsigned
long
inq_canon
(
struct
tty_struct
*
tty
)
{
{
int
nr
,
head
,
tail
;
int
nr
,
head
,
tail
;
if
(
!
tty
->
secondary
.
data
)
if
(
!
tty
->
canon_
data
)
return
0
;
return
0
;
head
=
tty
->
secondary
.
head
;
head
=
tty
->
canon_
head
;
tail
=
tty
->
secondary
.
tail
;
tail
=
tty
->
secondary
.
tail
;
nr
=
(
head
-
tail
)
&
(
TTY_BUF_SIZE
-
1
);
nr
=
(
head
-
tail
)
&
(
TTY_BUF_SIZE
-
1
);
/* Skip EOF-chars.. */
/* Skip EOF-chars.. */
if
(
EOF_CHAR
(
tty
)
==
__DISABLED_CHAR
)
return
nr
;
while
(
head
!=
tail
)
{
while
(
head
!=
tail
)
{
if
(
tty
->
secondary
.
buf
[
tail
]
==
EOF_CHAR
(
tty
))
if
(
test_bit
(
tail
,
&
tty
->
secondary_flags
)
&&
tty
->
secondary
.
buf
[
tail
]
==
__DISABLED_CHAR
)
nr
--
;
nr
--
;
INC
(
tail
);
INC
(
tail
);
}
}
...
@@ -432,7 +349,7 @@ int tty_ioctl(struct inode * inode, struct file * file,
...
@@ -432,7 +349,7 @@ int tty_ioctl(struct inode * inode, struct file * file,
struct
tty_struct
*
tty
;
struct
tty_struct
*
tty
;
struct
tty_struct
*
other_tty
;
struct
tty_struct
*
other_tty
;
struct
tty_struct
*
termios_tty
;
struct
tty_struct
*
termios_tty
;
in
t
pgrp
;
pid_
t
pgrp
;
int
dev
;
int
dev
;
int
termios_dev
;
int
termios_dev
;
int
retval
;
int
retval
;
...
@@ -449,68 +366,93 @@ int tty_ioctl(struct inode * inode, struct file * file,
...
@@ -449,68 +366,93 @@ int tty_ioctl(struct inode * inode, struct file * file,
other_tty
=
tty_table
[
PTY_OTHER
(
dev
)];
other_tty
=
tty_table
[
PTY_OTHER
(
dev
)];
else
else
other_tty
=
NULL
;
other_tty
=
NULL
;
termios_tty
=
tty
;
termios_dev
=
dev
;
if
(
IS_A_PTY_MASTER
(
dev
))
{
if
(
IS_A_PTY_MASTER
(
dev
))
{
termios_tty
=
other_tty
;
termios_tty
=
other_tty
;
termios_dev
=
PTY_OTHER
(
dev
);
termios_dev
=
PTY_OTHER
(
dev
);
}
else
{
termios_tty
=
tty
;
termios_dev
=
dev
;
}
}
switch
(
cmd
)
{
switch
(
cmd
)
{
case
TCGETS
:
case
TCGETS
:
return
get_termios
(
termios_tty
,(
struct
termios
*
)
arg
);
retval
=
verify_area
(
VERIFY_WRITE
,
(
void
*
)
arg
,
sizeof
(
struct
termios
));
if
(
retval
)
return
retval
;
memcpy_tofs
((
struct
termios
*
)
arg
,
termios_tty
->
termios
,
sizeof
(
struct
termios
));
return
0
;
case
TCSETSF
:
case
TCSETSF
:
flush_input
(
tty
);
/* fallthrough */
case
TCSETSW
:
case
TCSETSW
:
wait_until_sent
(
tty
);
/* fallthrough */
case
TCSETS
:
case
TCSETS
:
return
set_termios
(
termios_tty
,(
struct
termios
*
)
arg
,
termios_dev
);
retval
=
check_change
(
termios_tty
,
termios_dev
);
if
(
retval
)
return
retval
;
if
(
cmd
==
TCSETSF
||
cmd
==
TCSETSW
)
{
if
(
cmd
==
TCSETSF
)
flush_input
(
tty
);
wait_until_sent
(
tty
);
}
return
set_termios
(
termios_tty
,
(
struct
termios
*
)
arg
,
termios_dev
);
case
TCGETA
:
case
TCGETA
:
return
get_termio
(
termios_tty
,(
struct
termio
*
)
arg
);
return
get_termio
(
termios_tty
,(
struct
termio
*
)
arg
);
case
TCSETAF
:
case
TCSETAF
:
flush_input
(
tty
);
/* fallthrough */
case
TCSETAW
:
case
TCSETAW
:
wait_until_sent
(
tty
);
/* fallthrough */
case
TCSETA
:
case
TCSETA
:
return
set_termio
(
termios_tty
,(
struct
termio
*
)
arg
,
termios_dev
);
retval
=
check_change
(
termios_tty
,
termios_dev
);
if
(
retval
)
return
retval
;
if
(
cmd
==
TCSETAF
||
cmd
==
TCSETAW
)
{
if
(
cmd
==
TCSETAF
)
flush_input
(
tty
);
wait_until_sent
(
tty
);
}
return
set_termio
(
termios_tty
,
(
struct
termio
*
)
arg
,
termios_dev
);
case
TCXONC
:
case
TCXONC
:
retval
=
check_change
(
tty
,
dev
);
if
(
retval
)
return
retval
;
switch
(
arg
)
{
switch
(
arg
)
{
case
TCOOFF
:
case
TCOOFF
:
tty
->
stopped
=
1
;
stop_tty
(
tty
);
if
(
tty
->
stop
)
break
;
(
tty
->
stop
)(
tty
);
TTY_WRITE_FLUSH
(
tty
);
return
0
;
case
TCOON
:
case
TCOON
:
tty
->
stopped
=
0
;
start_tty
(
tty
);
if
(
tty
->
start
)
break
;
(
tty
->
start
)(
tty
);
TTY_WRITE_FLUSH
(
tty
);
return
0
;
case
TCIOFF
:
case
TCIOFF
:
if
(
STOP_CHAR
(
tty
))
if
(
STOP_CHAR
(
tty
)
!=
__DISABLED_CHAR
)
put_tty_queue
(
STOP_CHAR
(
tty
),
put_tty_queue
(
STOP_CHAR
(
tty
),
&
tty
->
write_q
);
&
tty
->
write_q
);
return
0
;
break
;
case
TCION
:
case
TCION
:
if
(
START_CHAR
(
tty
))
if
(
START_CHAR
(
tty
)
!=
__DISABLED_CHAR
)
put_tty_queue
(
START_CHAR
(
tty
),
put_tty_queue
(
START_CHAR
(
tty
),
&
tty
->
write_q
);
&
tty
->
write_q
);
return
0
;
break
;
default:
return
-
EINVAL
;
}
}
return
-
EINVAL
;
/* not implemented */
return
0
;
case
TCFLSH
:
case
TCFLSH
:
if
(
arg
==
0
)
retval
=
check_change
(
tty
,
dev
);
if
(
retval
)
return
retval
;
switch
(
arg
)
{
case
TCIFLUSH
:
flush_input
(
tty
);
flush_input
(
tty
);
else
if
(
arg
==
1
)
break
;
flush_output
(
tty
);
case
TCIOFLUSH
:
else
if
(
arg
==
2
)
{
flush_input
(
tty
);
flush_input
(
tty
);
/* fall through */
case
TCOFLUSH
:
flush_output
(
tty
);
flush_output
(
tty
);
}
else
break
;
default:
return
-
EINVAL
;
return
-
EINVAL
;
}
return
0
;
return
0
;
case
TIOCEXCL
:
case
TIOCEXCL
:
set_bit
(
TTY_EXCLUSIVE
,
&
tty
->
flags
);
set_bit
(
TTY_EXCLUSIVE
,
&
tty
->
flags
);
...
@@ -550,16 +492,21 @@ int tty_ioctl(struct inode * inode, struct file * file,
...
@@ -550,16 +492,21 @@ int tty_ioctl(struct inode * inode, struct file * file,
tty
->
pgrp
=
current
->
pgrp
;
tty
->
pgrp
=
current
->
pgrp
;
return
0
;
return
0
;
case
TIOCGPGRP
:
case
TIOCGPGRP
:
retval
=
verify_area
(
VERIFY_WRITE
,
(
void
*
)
arg
,
4
);
retval
=
verify_area
(
VERIFY_WRITE
,
(
void
*
)
arg
,
if
(
!
retval
)
sizeof
(
pid_t
));
put_fs_long
(
termios_tty
->
pgrp
,(
unsigned
long
*
)
arg
);
if
(
retval
)
return
retval
;
return
retval
;
put_fs_long
(
termios_tty
->
pgrp
,
(
pid_t
*
)
arg
);
return
0
;
case
TIOCSPGRP
:
case
TIOCSPGRP
:
retval
=
check_change
(
tty
,
dev
);
if
(
retval
)
return
retval
;
if
((
current
->
tty
<
0
)
||
if
((
current
->
tty
<
0
)
||
(
current
->
tty
!=
termios_dev
)
||
(
current
->
tty
!=
termios_dev
)
||
(
termios_tty
->
session
!=
current
->
session
))
(
termios_tty
->
session
!=
current
->
session
))
return
-
ENOTTY
;
return
-
ENOTTY
;
pgrp
=
get_fs_long
((
unsigned
long
*
)
arg
);
pgrp
=
get_fs_long
((
pid_t
*
)
arg
);
if
(
pgrp
<
0
)
if
(
pgrp
<
0
)
return
-
EINVAL
;
return
-
EINVAL
;
if
(
session_of_pgrp
(
pgrp
)
!=
current
->
session
)
if
(
session_of_pgrp
(
pgrp
)
!=
current
->
session
)
...
@@ -567,16 +514,19 @@ int tty_ioctl(struct inode * inode, struct file * file,
...
@@ -567,16 +514,19 @@ int tty_ioctl(struct inode * inode, struct file * file,
termios_tty
->
pgrp
=
pgrp
;
termios_tty
->
pgrp
=
pgrp
;
return
0
;
return
0
;
case
TIOCOUTQ
:
case
TIOCOUTQ
:
retval
=
verify_area
(
VERIFY_WRITE
,
(
void
*
)
arg
,
4
);
retval
=
verify_area
(
VERIFY_WRITE
,
(
void
*
)
arg
,
if
(
!
retval
)
sizeof
(
unsigned
long
));
put_fs_long
(
CHARS
(
&
tty
->
write_q
),
if
(
retval
)
return
retval
;
put_fs_long
(
CHARS
(
&
tty
->
write_q
),
(
unsigned
long
*
)
arg
);
(
unsigned
long
*
)
arg
);
return
retval
;
return
0
;
case
TIOCINQ
:
case
TIOCINQ
:
retval
=
verify_area
(
VERIFY_WRITE
,
(
void
*
)
arg
,
4
);
retval
=
verify_area
(
VERIFY_WRITE
,
(
void
*
)
arg
,
sizeof
(
unsigned
long
));
if
(
retval
)
if
(
retval
)
return
retval
;
return
retval
;
if
(
L_CANON
(
tty
))
if
(
L_
I
CANON
(
tty
))
put_fs_long
(
inq_canon
(
tty
),
put_fs_long
(
inq_canon
(
tty
),
(
unsigned
long
*
)
arg
);
(
unsigned
long
*
)
arg
);
else
else
...
@@ -587,17 +537,20 @@ int tty_ioctl(struct inode * inode, struct file * file,
...
@@ -587,17 +537,20 @@ int tty_ioctl(struct inode * inode, struct file * file,
if
((
current
->
tty
!=
dev
)
&&
!
suser
())
if
((
current
->
tty
!=
dev
)
&&
!
suser
())
return
-
EACCES
;
return
-
EACCES
;
put_tty_queue
(
get_fs_byte
((
char
*
)
arg
),
&
tty
->
read_q
);
put_tty_queue
(
get_fs_byte
((
char
*
)
arg
),
&
tty
->
read_q
);
TTY_READ_FLUSH
(
tty
);
return
0
;
return
0
;
case
TIOCGWINSZ
:
case
TIOCGWINSZ
:
return
get_window_size
(
tty
,(
struct
winsize
*
)
arg
);
retval
=
verify_area
(
VERIFY_WRITE
,
(
void
*
)
arg
,
sizeof
(
struct
winsize
));
if
(
retval
)
return
retval
;
memcpy_tofs
((
struct
winsize
*
)
arg
,
&
tty
->
winsize
,
sizeof
(
struct
winsize
));
return
0
;
case
TIOCSWINSZ
:
case
TIOCSWINSZ
:
if
(
IS_A_PTY_MASTER
(
dev
))
if
(
IS_A_PTY_MASTER
(
dev
))
set_window_size
(
other_tty
,(
struct
winsize
*
)
arg
);
set_window_size
(
other_tty
,(
struct
winsize
*
)
arg
);
return
set_window_size
(
tty
,(
struct
winsize
*
)
arg
);
return
set_window_size
(
tty
,(
struct
winsize
*
)
arg
);
case
TIOCGSOFTCAR
:
return
-
EINVAL
;
/* not implemented */
case
TIOCSSOFTCAR
:
return
-
EINVAL
;
/* not implemented */
case
TIOCLINUX
:
case
TIOCLINUX
:
switch
(
get_fs_byte
((
char
*
)
arg
))
switch
(
get_fs_byte
((
char
*
)
arg
))
{
{
...
@@ -647,31 +600,55 @@ int tty_ioctl(struct inode * inode, struct file * file,
...
@@ -647,31 +600,55 @@ int tty_ioctl(struct inode * inode, struct file * file,
current
->
tty
=
-
1
;
current
->
tty
=
-
1
;
return
0
;
return
0
;
case
TIOCGETD
:
case
TIOCGETD
:
retval
=
verify_area
(
VERIFY_WRITE
,
(
void
*
)
arg
,
4
);
retval
=
verify_area
(
VERIFY_WRITE
,
(
void
*
)
arg
,
if
(
!
retval
)
sizeof
(
unsigned
long
));
put_fs_long
(
tty
->
disc
,
(
unsigned
long
*
)
arg
);
if
(
retval
)
return
retval
;
return
retval
;
put_fs_long
(
tty
->
disc
,
(
unsigned
long
*
)
arg
);
return
0
;
case
TIOCSETD
:
case
TIOCSETD
:
retval
=
check_change
(
tty
,
dev
);
if
(
retval
)
return
retval
;
arg
=
get_fs_long
((
unsigned
long
*
)
arg
);
arg
=
get_fs_long
((
unsigned
long
*
)
arg
);
return
tty_set_ldisc
(
tty
,
arg
);
return
tty_set_ldisc
(
tty
,
arg
);
case
TIOCGLCKTRMIOS
:
case
TIOCGLCKTRMIOS
:
arg
=
get_fs_long
((
unsigned
long
*
)
arg
);
arg
=
get_fs_long
((
unsigned
long
*
)
arg
);
return
get_lcktrmios
(
tty
,
(
struct
termios
*
)
arg
,
retval
=
verify_area
(
VERIFY_WRITE
,
(
void
*
)
arg
,
termios_dev
);
sizeof
(
struct
termios
));
if
(
retval
)
return
retval
;
memcpy_tofs
((
struct
termios
*
)
arg
,
&
termios_locked
[
termios_dev
],
sizeof
(
struct
termios
));
return
0
;
case
TIOCSLCKTRMIOS
:
case
TIOCSLCKTRMIOS
:
if
(
!
suser
())
return
-
EPERM
;
arg
=
get_fs_long
((
unsigned
long
*
)
arg
);
arg
=
get_fs_long
((
unsigned
long
*
)
arg
);
return
set_lcktrmios
(
tty
,
(
struct
termios
*
)
arg
,
memcpy_fromfs
(
&
termios_locked
[
termios_dev
],
termios_dev
);
(
struct
termios
*
)
arg
,
sizeof
(
struct
termios
));
return
0
;
case
TIOCPKT
:
case
TIOCPKT
:
if
(
!
IS_A_PTY_MASTER
(
dev
))
if
(
!
IS_A_PTY_MASTER
(
dev
))
return
-
EINVAL
;
return
-
EINVAL
;
retval
=
verify_area
(
VERIFY_READ
,
retval
=
verify_area
(
VERIFY_READ
,
(
void
*
)
arg
,
(
unsigned
long
*
)
arg
,
sizeof
(
unsigned
long
));
sizeof
(
unsigned
long
));
if
(
retval
)
if
(
retval
)
return
retval
;
return
retval
;
tty
->
packet
=
(
get_fs_long
((
unsigned
long
*
)
arg
)
!=
0
);
if
(
get_fs_long
(
arg
))
{
if
(
!
tty
->
packet
)
{
tty
->
packet
=
1
;
tty
->
ctrl_status
=
0
;
}
}
else
tty
->
packet
=
0
;
return
0
;
return
0
;
case
TCSBRK
:
case
TCSBRKP
:
case
TCSBRK
:
case
TCSBRKP
:
retval
=
check_change
(
tty
,
dev
);
if
(
retval
)
return
retval
;
wait_until_sent
(
tty
);
wait_until_sent
(
tty
);
if
(
!
tty
->
ioctl
)
if
(
!
tty
->
ioctl
)
return
0
;
return
0
;
...
...
drivers/net/8390.c
View file @
b168ffdf
...
@@ -36,7 +36,6 @@ static char *version =
...
@@ -36,7 +36,6 @@ static char *version =
#include <linux/kernel.h>
#include <linux/kernel.h>
#include <linux/sched.h>
#include <linux/sched.h>
#include <linux/fs.h>
#include <linux/fs.h>
#include <linux/tty.h>
#include <linux/types.h>
#include <linux/types.h>
#include <linux/ptrace.h>
#include <linux/ptrace.h>
#include <linux/string.h>
#include <linux/string.h>
...
...
drivers/net/lance.c
View file @
b168ffdf
...
@@ -563,8 +563,12 @@ lance_start_xmit(struct sk_buff *skb, struct device *dev)
...
@@ -563,8 +563,12 @@ lance_start_xmit(struct sk_buff *skb, struct device *dev)
if
(
skb
->
free
)
if
(
skb
->
free
)
kfree_skb
(
skb
,
FREE_WRITE
);
kfree_skb
(
skb
,
FREE_WRITE
);
}
else
}
else
{
/* Gimme!!! */
if
(
skb
->
free
==
0
)
skb_kept_by_device
(
skb
);
lp
->
tx_ring
[
entry
].
base
=
(
int
)(
skb
+
1
)
|
0x83000000
;
lp
->
tx_ring
[
entry
].
base
=
(
int
)(
skb
+
1
)
|
0x83000000
;
}
lp
->
cur_tx
++
;
lp
->
cur_tx
++
;
/* Trigger an immediate send poll. */
/* Trigger an immediate send poll. */
...
@@ -648,6 +652,9 @@ lance_interrupt(int reg_ptr)
...
@@ -648,6 +652,9 @@ lance_interrupt(int reg_ptr)
struct
sk_buff
*
skb
=
((
struct
sk_buff
*
)
databuff
)
-
1
;
struct
sk_buff
*
skb
=
((
struct
sk_buff
*
)
databuff
)
-
1
;
if
(
skb
->
free
)
if
(
skb
->
free
)
kfree_skb
(
skb
,
FREE_WRITE
);
kfree_skb
(
skb
,
FREE_WRITE
);
else
skb_device_release
(
skb
,
FREE_WRITE
);
/* Warning: skb may well vanish at the point you call device_release! */
}
}
dirty_tx
++
;
dirty_tx
++
;
}
}
...
...
drivers/net/slip.c
View file @
b168ffdf
...
@@ -31,13 +31,11 @@
...
@@ -31,13 +31,11 @@
#include <linux/string.h>
#include <linux/string.h>
#include <linux/mm.h>
#include <linux/mm.h>
#include <linux/socket.h>
#include <linux/socket.h>
#include <linux/termios.h>
#include <linux/sockios.h>
#include <linux/sockios.h>
#include <linux/interrupt.h>
#include <linux/interrupt.h>
#include <linux/tty.h>
#include <linux/tty.h>
#include <linux/errno.h>
#include <linux/errno.h>
#include <linux/stat.h>
#include <linux/stat.h>
#include <linux/tty.h>
#include <linux/in.h>
#include <linux/in.h>
#include "inet.h"
#include "inet.h"
#include "dev.h"
#include "dev.h"
...
...
fs/open.c
View file @
b168ffdf
...
@@ -262,6 +262,8 @@ asmlinkage int sys_fchmod(unsigned int fd, mode_t mode)
...
@@ -262,6 +262,8 @@ asmlinkage int sys_fchmod(unsigned int fd, mode_t mode)
return
-
EPERM
;
return
-
EPERM
;
if
(
IS_RDONLY
(
inode
))
if
(
IS_RDONLY
(
inode
))
return
-
EROFS
;
return
-
EROFS
;
if
(
mode
==
(
mode_t
)
-
1
)
mode
=
inode
->
i_mode
;
inode
->
i_mode
=
(
mode
&
S_IALLUGO
)
|
(
inode
->
i_mode
&
~
S_IALLUGO
);
inode
->
i_mode
=
(
mode
&
S_IALLUGO
)
|
(
inode
->
i_mode
&
~
S_IALLUGO
);
if
(
!
suser
()
&&
!
in_group_p
(
inode
->
i_gid
))
if
(
!
suser
()
&&
!
in_group_p
(
inode
->
i_gid
))
inode
->
i_mode
&=
~
S_ISGID
;
inode
->
i_mode
&=
~
S_ISGID
;
...
@@ -286,6 +288,8 @@ asmlinkage int sys_chmod(const char * filename, mode_t mode)
...
@@ -286,6 +288,8 @@ asmlinkage int sys_chmod(const char * filename, mode_t mode)
iput
(
inode
);
iput
(
inode
);
return
-
EROFS
;
return
-
EROFS
;
}
}
if
(
mode
==
(
mode_t
)
-
1
)
mode
=
inode
->
i_mode
;
inode
->
i_mode
=
(
mode
&
S_IALLUGO
)
|
(
inode
->
i_mode
&
~
S_IALLUGO
);
inode
->
i_mode
=
(
mode
&
S_IALLUGO
)
|
(
inode
->
i_mode
&
~
S_IALLUGO
);
if
(
!
suser
()
&&
!
in_group_p
(
inode
->
i_gid
))
if
(
!
suser
()
&&
!
in_group_p
(
inode
->
i_gid
))
inode
->
i_mode
&=
~
S_ISGID
;
inode
->
i_mode
&=
~
S_ISGID
;
...
...
include/linux/kernel.h
View file @
b168ffdf
...
@@ -14,11 +14,6 @@
...
@@ -14,11 +14,6 @@
#define LONG_MAX ((long)(~0UL>>1))
#define LONG_MAX ((long)(~0UL>>1))
#define ULONG_MAX (~0UL)
#define ULONG_MAX (~0UL)
#define VERIFY_READ 0
#define VERIFY_WRITE 1
int
verify_area
(
int
type
,
void
*
addr
,
unsigned
long
count
);
#define KERN_EMERG "<0>"
/* system is unusable */
#define KERN_EMERG "<0>"
/* system is unusable */
#define KERN_ALERT "<1>"
/* action must be taken immediately */
#define KERN_ALERT "<1>"
/* action must be taken immediately */
#define KERN_CRIT "<2>"
/* critical conditions */
#define KERN_CRIT "<2>"
/* critical conditions */
...
...
include/linux/mm.h
View file @
b168ffdf
...
@@ -2,9 +2,26 @@
...
@@ -2,9 +2,26 @@
#define _LINUX_MM_H
#define _LINUX_MM_H
#include <linux/page.h>
#include <linux/page.h>
#include <linux/fs.h>
#include <linux/sched.h>
#include <linux/errno.h>
#include <linux/kernel.h>
#include <linux/kernel.h>
#define VERIFY_READ 0
#define VERIFY_WRITE 1
int
__verify_write
(
unsigned
long
addr
,
unsigned
long
count
);
extern
inline
int
verify_area
(
int
type
,
void
*
addr
,
unsigned
long
size
)
{
if
(
TASK_SIZE
<=
(
unsigned
long
)
addr
)
return
-
EFAULT
;
if
(
size
>
TASK_SIZE
-
(
unsigned
long
)
addr
)
return
-
EFAULT
;
if
(
wp_works_ok
||
type
==
VERIFY_READ
||
!
size
)
return
0
;
return
__verify_write
((
unsigned
long
)
addr
,
size
);
}
/*
/*
* Linux kernel virtual memory manager primitives.
* Linux kernel virtual memory manager primitives.
* The idea being to have a "virtual" mm in the same way
* The idea being to have a "virtual" mm in the same way
...
...
include/linux/sched.h
View file @
b168ffdf
...
@@ -13,6 +13,21 @@
...
@@ -13,6 +13,21 @@
#define HZ 100
#define HZ 100
/*
* System setup flags..
*/
extern
int
hard_math
;
extern
int
x86
;
extern
int
ignore_irq13
;
extern
int
wp_works_ok
;
/*
* Bus types (default is ISA, but people can check others with these..)
* MCA_bus hardcoded to 0 for now.
*/
extern
int
EISA_bus
;
#define MCA_bus 0
#include <linux/tasks.h>
#include <linux/tasks.h>
#include <asm/system.h>
#include <asm/system.h>
...
@@ -290,21 +305,6 @@ extern unsigned long volatile jiffies;
...
@@ -290,21 +305,6 @@ extern unsigned long volatile jiffies;
extern
struct
timeval
xtime
;
extern
struct
timeval
xtime
;
extern
int
need_resched
;
extern
int
need_resched
;
/*
* System setup flags..
*/
extern
int
hard_math
;
extern
int
x86
;
extern
int
ignore_irq13
;
extern
int
wp_works_ok
;
/*
* Bus types (default is ISA, but people can check others with these..)
* MCA_bus hardcoded to 0 for now.
*/
extern
int
EISA_bus
;
#define MCA_bus 0
#define CURRENT_TIME (xtime.tv_sec)
#define CURRENT_TIME (xtime.tv_sec)
extern
void
sleep_on
(
struct
wait_queue
**
p
);
extern
void
sleep_on
(
struct
wait_queue
**
p
);
...
...
include/linux/termios.h
View file @
b168ffdf
...
@@ -51,6 +51,7 @@
...
@@ -51,6 +51,7 @@
#define TIOCSLCKTRMIOS 0x5457
#define TIOCSLCKTRMIOS 0x5457
/* Used for packet mode */
/* Used for packet mode */
#define TIOCPKT_DATA 0
#define TIOCPKT_FLUSHREAD 1
#define TIOCPKT_FLUSHREAD 1
#define TIOCPKT_FLUSHWRITE 2
#define TIOCPKT_FLUSHWRITE 2
#define TIOCPKT_STOP 4
#define TIOCPKT_STOP 4
...
...
include/linux/tty.h
View file @
b168ffdf
...
@@ -62,7 +62,6 @@ extern struct screen_info screen_info;
...
@@ -62,7 +62,6 @@ extern struct screen_info screen_info;
#define TTY_BUF_SIZE 1024
/* Must be a power of 2 */
#define TTY_BUF_SIZE 1024
/* Must be a power of 2 */
struct
tty_queue
{
struct
tty_queue
{
unsigned
long
data
;
unsigned
long
head
;
unsigned
long
head
;
unsigned
long
tail
;
unsigned
long
tail
;
struct
wait_queue
*
proc_list
;
struct
wait_queue
*
proc_list
;
...
@@ -143,60 +142,88 @@ struct serial_struct {
...
@@ -143,60 +142,88 @@ struct serial_struct {
#define FULL(a) (!LEFT(a))
#define FULL(a) (!LEFT(a))
#define CHARS(a) (((a)->head-(a)->tail)&(TTY_BUF_SIZE-1))
#define CHARS(a) (((a)->head-(a)->tail)&(TTY_BUF_SIZE-1))
extern
void
put_tty_queue
(
char
c
,
struct
tty_queue
*
queue
);
extern
void
put_tty_queue
(
unsigned
char
c
,
struct
tty_queue
*
queue
);
extern
int
get_tty_queue
(
struct
tty_queue
*
queue
);
extern
int
get_tty_queue
(
struct
tty_queue
*
queue
);
#define INTR_CHAR(tty) ((tty)->termios->c_cc[VINTR])
#define INTR_CHAR(tty) ((tty)->termios->c_cc[VINTR])
#define QUIT_CHAR(tty) ((tty)->termios->c_cc[VQUIT])
#define QUIT_CHAR(tty) ((tty)->termios->c_cc[VQUIT])
#define ERASE_CHAR(tty) ((tty)->termios->c_cc[VERASE])
#define ERASE_CHAR(tty) ((tty)->termios->c_cc[VERASE])
#define KILL_CHAR(tty) ((tty)->termios->c_cc[VKILL])
#define KILL_CHAR(tty) ((tty)->termios->c_cc[VKILL])
#define WERASE_CHAR(tty) ((tty)->termios->c_cc[VWERASE])
#define EOF_CHAR(tty) ((tty)->termios->c_cc[VEOF])
#define EOF_CHAR(tty) ((tty)->termios->c_cc[VEOF])
#define TIME_CHAR(tty) ((tty)->termios->c_cc[VTIME])
#define MIN_CHAR(tty) ((tty)->termios->c_cc[VMIN])
#define SWTC_CHAR(tty) ((tty)->termios->c_cc[VSWTC])
#define START_CHAR(tty) ((tty)->termios->c_cc[VSTART])
#define START_CHAR(tty) ((tty)->termios->c_cc[VSTART])
#define STOP_CHAR(tty) ((tty)->termios->c_cc[VSTOP])
#define STOP_CHAR(tty) ((tty)->termios->c_cc[VSTOP])
#define SUSPEND_CHAR(tty) ((tty)->termios->c_cc[VSUSP])
#define SUSP_CHAR(tty) ((tty)->termios->c_cc[VSUSP])
#define EOL_CHAR(tty) ((tty)->termios->c_cc[VEOL])
#define REPRINT_CHAR(tty) ((tty)->termios->c_cc[VREPRINT])
#define DISCARD_CHAR(tty) ((tty)->termios->c_cc[VDISCARD])
#define WERASE_CHAR(tty) ((tty)->termios->c_cc[VWERASE])
#define LNEXT_CHAR(tty) ((tty)->termios->c_cc[VLNEXT])
#define LNEXT_CHAR(tty) ((tty)->termios->c_cc[VLNEXT])
#define EOL2_CHAR(tty) ((tty)->termios->c_cc[VEOL2])
#define _L_FLAG(tty,f) ((tty)->termios->c_lflag & f)
#define _I_FLAG(tty,f) ((tty)->termios->c_iflag & (f))
#define _I_FLAG(tty,f) ((tty)->termios->c_iflag & f)
#define _O_FLAG(tty,f) ((tty)->termios->c_oflag & (f))
#define _O_FLAG(tty,f) ((tty)->termios->c_oflag & f)
#define _C_FLAG(tty,f) ((tty)->termios->c_cflag & (f))
#define _C_FLAG(tty,f) ((tty)->termios->c_cflag & f)
#define _L_FLAG(tty,f) ((tty)->termios->c_lflag & (f))
#define L_CANON(tty) _L_FLAG((tty),ICANON)
#define L_ISIG(tty) _L_FLAG((tty),ISIG)
#define L_ECHO(tty) _L_FLAG((tty),ECHO)
#define L_ECHOE(tty) _L_FLAG((tty),ECHOE)
#define L_ECHOK(tty) _L_FLAG((tty),ECHOK)
#define L_ECHONL(tty) _L_FLAG((tty),ECHONL)
#define L_ECHOCTL(tty) _L_FLAG((tty),ECHOCTL)
#define L_ECHOKE(tty) _L_FLAG((tty),ECHOKE)
#define L_TOSTOP(tty) _L_FLAG((tty),TOSTOP)
#define I_IGNBRK(tty) _I_FLAG((tty),IGNBRK)
#define I_IGNBRK(tty) _I_FLAG((tty),IGNBRK)
#define I_BRKINT(tty) _I_FLAG((tty),BRKINT)
#define I_BRKINT(tty) _I_FLAG((tty),BRKINT)
#define I_IGNPAR(tty) _I_FLAG((tty),IGNPAR)
#define I_IGNPAR(tty) _I_FLAG((tty),IGNPAR)
#define I_PARMRK(tty) _I_FLAG((tty),PARMRK)
#define I_PARMRK(tty) _I_FLAG((tty),PARMRK)
#define I_INPCK(tty) _I_FLAG((tty),INPCK)
#define I_INPCK(tty) _I_FLAG((tty),INPCK)
#define I_UCLC(tty) _I_FLAG((tty),IUCLC)
#define I_ISTRIP(tty) _I_FLAG((tty),ISTRIP)
#define I_NLCR(tty) _I_FLAG((tty),INLCR)
#define I_INLCR(tty) _I_FLAG((tty),INLCR)
#define I_CRNL(tty) _I_FLAG((tty),ICRNL)
#define I_IGNCR(tty) _I_FLAG((tty),IGNCR)
#define I_NOCR(tty) _I_FLAG((tty),IGNCR)
#define I_ICRNL(tty) _I_FLAG((tty),ICRNL)
#define I_IUCLC(tty) _I_FLAG((tty),IUCLC)
#define I_IXON(tty) _I_FLAG((tty),IXON)
#define I_IXON(tty) _I_FLAG((tty),IXON)
#define I_IXANY(tty) _I_FLAG((tty),IXANY)
#define I_IXANY(tty) _I_FLAG((tty),IXANY)
#define I_STRP(tty) _I_FLAG((tty),ISTRIP)
#define I_IXOFF(tty) _I_FLAG((tty),IXOFF)
#define I_IMAXBEL(tty) _I_FLAG((tty),IMAXBEL)
#define O_POST(tty) _O_FLAG((tty),OPOST)
#define O_LCUC(tty) _O_FLAG((tty),OLCUC)
#define O_OPOST(tty) _O_FLAG((tty),OPOST)
#define O_NLCR(tty) _O_FLAG((tty),ONLCR)
#define O_OLCUC(tty) _O_FLAG((tty),OLCUC)
#define O_CRNL(tty) _O_FLAG((tty),OCRNL)
#define O_ONLCR(tty) _O_FLAG((tty),ONLCR)
#define O_NOCR(tty) _O_FLAG((tty),ONOCR)
#define O_OCRNL(tty) _O_FLAG((tty),OCRNL)
#define O_NLRET(tty) _O_FLAG((tty),ONLRET)
#define O_ONOCR(tty) _O_FLAG((tty),ONOCR)
#define O_ONLRET(tty) _O_FLAG((tty),ONLRET)
#define O_OFILL(tty) _O_FLAG((tty),OFILL)
#define O_OFDEL(tty) _O_FLAG((tty),OFDEL)
#define O_NLDLY(tty) _O_FLAG((tty),NLDLY)
#define O_CRDLY(tty) _O_FLAG((tty),CRDLY)
#define O_TABDLY(tty) _O_FLAG((tty),TABDLY)
#define O_TABDLY(tty) _O_FLAG((tty),TABDLY)
#define O_BSDLY(tty) _O_FLAG((tty),BSDLY)
#define O_VTDLY(tty) _O_FLAG((tty),VTDLY)
#define O_FFDLY(tty) _O_FLAG((tty),FFDLY)
#define C_BAUD(tty) _C_FLAG((tty),CBAUD)
#define C_CSIZE(tty) _C_FLAG((tty),CSIZE)
#define C_CSTOPB(tty) _C_FLAG((tty),CSTOPB)
#define C_CREAD(tty) _C_FLAG((tty),CREAD)
#define C_PARENB(tty) _C_FLAG((tty),PARENB)
#define C_PARODD(tty) _C_FLAG((tty),PARODD)
#define C_HUPCL(tty) _C_FLAG((tty),HUPCL)
#define C_CLOCAL(tty) _C_FLAG((tty),CLOCAL)
#define C_CIBAUD(tty) _C_FLAG((tty),CIBAUD)
#define C_CRTSCTS(tty) _C_FLAG((tty),CRTSCTS)
#define C_LOCAL(tty) _C_FLAG((tty),CLOCAL)
#define L_ISIG(tty) _L_FLAG((tty),ISIG)
#define C_RTSCTS(tty) _C_FLAG((tty),CRTSCTS)
#define L_ICANON(tty) _L_FLAG((tty),ICANON)
#define C_SPEED(tty) ((tty)->termios->c_cflag & CBAUD)
#define L_XCASE(tty) _L_FLAG((tty),XCASE)
#define C_HUP(tty) (C_SPEED((tty)) == B0)
#define L_ECHO(tty) _L_FLAG((tty),ECHO)
#define L_ECHOE(tty) _L_FLAG((tty),ECHOE)
#define L_ECHOK(tty) _L_FLAG((tty),ECHOK)
#define L_ECHONL(tty) _L_FLAG((tty),ECHONL)
#define L_NOFLSH(tty) _L_FLAG((tty),NOFLSH)
#define L_TOSTOP(tty) _L_FLAG((tty),TOSTOP)
#define L_ECHOCTL(tty) _L_FLAG((tty),ECHOCTL)
#define L_ECHOPRT(tty) _L_FLAG((tty),ECHOPRT)
#define L_ECHOKE(tty) _L_FLAG((tty),ECHOKE)
#define L_FLUSHO(tty) _L_FLAG((tty),FLUSHO)
#define L_PENDIN(tty) _L_FLAG((tty),PENDIN)
#define L_IEXTEN(tty) _L_FLAG((tty),IEXTEN)
/*
/*
* Where all of the state associated with a tty is kept while the tty
* Where all of the state associated with a tty is kept while the tty
...
@@ -218,12 +245,13 @@ struct tty_struct {
...
@@ -218,12 +245,13 @@ struct tty_struct {
int
session
;
int
session
;
unsigned
char
stopped
:
1
,
hw_stopped
:
1
,
packet
:
1
,
lnext
:
1
;
unsigned
char
stopped
:
1
,
hw_stopped
:
1
,
packet
:
1
,
lnext
:
1
;
unsigned
char
char_error
:
3
;
unsigned
char
char_error
:
3
;
unsigned
char
erasing
:
1
;
unsigned
char
ctrl_status
;
unsigned
char
ctrl_status
;
short
line
;
short
line
;
int
disc
;
int
disc
;
int
flags
;
int
flags
;
int
count
;
int
count
;
int
column
;
unsigned
int
column
;
struct
winsize
winsize
;
struct
winsize
winsize
;
int
(
*
open
)(
struct
tty_struct
*
tty
,
struct
file
*
filp
);
int
(
*
open
)(
struct
tty_struct
*
tty
,
struct
file
*
filp
);
void
(
*
close
)(
struct
tty_struct
*
tty
,
struct
file
*
filp
);
void
(
*
close
)(
struct
tty_struct
*
tty
,
struct
file
*
filp
);
...
@@ -241,10 +269,13 @@ struct tty_struct {
...
@@ -241,10 +269,13 @@ struct tty_struct {
void
(
*
write_data_callback
)(
void
*
data
);
void
(
*
write_data_callback
)(
void
*
data
);
void
*
write_data_arg
;
void
*
write_data_arg
;
int
readq_flags
[
TTY_BUF_SIZE
/
32
];
int
readq_flags
[
TTY_BUF_SIZE
/
32
];
int
secondary_flags
[
TTY_BUF_SIZE
/
32
];
int
canon_data
;
unsigned
long
canon_head
;
unsigned
int
canon_column
;
struct
tty_queue
read_q
;
struct
tty_queue
read_q
;
struct
tty_queue
write_q
;
struct
tty_queue
write_q
;
struct
tty_queue
secondary
;
struct
tty_queue
secondary
;
struct
wait_queue
*
except_q
;
void
*
disc_data
;
void
*
disc_data
;
};
};
...
@@ -256,9 +287,9 @@ struct tty_ldisc {
...
@@ -256,9 +287,9 @@ struct tty_ldisc {
int
(
*
open
)(
struct
tty_struct
*
);
int
(
*
open
)(
struct
tty_struct
*
);
void
(
*
close
)(
struct
tty_struct
*
);
void
(
*
close
)(
struct
tty_struct
*
);
int
(
*
read
)(
struct
tty_struct
*
tty
,
struct
file
*
file
,
int
(
*
read
)(
struct
tty_struct
*
tty
,
struct
file
*
file
,
char
*
buf
,
int
nr
);
unsigned
char
*
buf
,
unsigned
int
nr
);
int
(
*
write
)(
struct
tty_struct
*
tty
,
struct
file
*
file
,
int
(
*
write
)(
struct
tty_struct
*
tty
,
struct
file
*
file
,
char
*
buf
,
int
nr
);
unsigned
char
*
buf
,
unsigned
int
nr
);
int
(
*
ioctl
)(
struct
tty_struct
*
tty
,
struct
file
*
file
,
int
(
*
ioctl
)(
struct
tty_struct
*
tty
,
struct
file
*
file
,
unsigned
int
cmd
,
unsigned
long
arg
);
unsigned
int
cmd
,
unsigned
long
arg
);
int
(
*
select
)(
struct
tty_struct
*
tty
,
struct
inode
*
inode
,
int
(
*
select
)(
struct
tty_struct
*
tty
,
struct
inode
*
inode
,
...
@@ -313,12 +344,11 @@ struct tty_ldisc {
...
@@ -313,12 +344,11 @@ struct tty_ldisc {
*/
*/
#define TTY_WRITE_BUSY 0
#define TTY_WRITE_BUSY 0
#define TTY_READ_BUSY 1
#define TTY_READ_BUSY 1
#define TTY_CR_PENDING 2
#define TTY_SQ_THROTTLED 2
#define TTY_SQ_THROTTLED 3
#define TTY_RQ_THROTTLED 3
#define TTY_RQ_THROTTLED 4
#define TTY_IO_ERROR 4
#define TTY_IO_ERROR 5
#define TTY_SLAVE_CLOSED 5
#define TTY_SLAVE_OPENED 6
#define TTY_EXCLUSIVE 6
#define TTY_EXCLUSIVE 7
/*
/*
* When a break, frame error, or parity error happens, these codes are
* When a break, frame error, or parity error happens, these codes are
...
@@ -336,6 +366,10 @@ struct tty_ldisc {
...
@@ -336,6 +366,10 @@ struct tty_ldisc {
extern
void
tty_write_flush
(
struct
tty_struct
*
);
extern
void
tty_write_flush
(
struct
tty_struct
*
);
extern
void
tty_read_flush
(
struct
tty_struct
*
);
extern
void
tty_read_flush
(
struct
tty_struct
*
);
/* Number of chars that must be available in a write queue before
the queue is awakened. */
#define WAKEUP_CHARS (3*TTY_BUF_SIZE/4)
extern
struct
tty_struct
*
tty_table
[];
extern
struct
tty_struct
*
tty_table
[];
extern
struct
termios
*
tty_termios
[];
extern
struct
termios
*
tty_termios
[];
extern
struct
termios
*
termios_locked
[];
extern
struct
termios
*
termios_locked
[];
...
@@ -366,7 +400,9 @@ extern long tty_init(long);
...
@@ -366,7 +400,9 @@ extern long tty_init(long);
extern
void
flush_input
(
struct
tty_struct
*
tty
);
extern
void
flush_input
(
struct
tty_struct
*
tty
);
extern
void
flush_output
(
struct
tty_struct
*
tty
);
extern
void
flush_output
(
struct
tty_struct
*
tty
);
extern
void
wait_until_sent
(
struct
tty_struct
*
tty
);
extern
void
wait_until_sent
(
struct
tty_struct
*
tty
);
extern
void
copy_to_cooked
(
struct
tty_struct
*
tty
);
extern
int
check_change
(
struct
tty_struct
*
tty
,
int
channel
);
extern
void
stop_tty
(
struct
tty_struct
*
tty
);
extern
void
start_tty
(
struct
tty_struct
*
tty
);
extern
int
tty_register_ldisc
(
int
disc
,
struct
tty_ldisc
*
new_ldisc
);
extern
int
tty_register_ldisc
(
int
disc
,
struct
tty_ldisc
*
new_ldisc
);
extern
int
tty_read_raw_data
(
struct
tty_struct
*
tty
,
unsigned
char
*
bufp
,
extern
int
tty_read_raw_data
(
struct
tty_struct
*
tty
,
unsigned
char
*
bufp
,
int
buflen
);
int
buflen
);
...
...
kernel/fork.c
View file @
b168ffdf
...
@@ -56,7 +56,8 @@ static int find_empty_process(void)
...
@@ -56,7 +56,8 @@ static int find_empty_process(void)
}
}
if
(
task
[
i
]
->
uid
==
current
->
uid
)
if
(
task
[
i
]
->
uid
==
current
->
uid
)
this_user_tasks
++
;
this_user_tasks
++
;
if
(
task
[
i
]
->
pid
==
last_pid
||
task
[
i
]
->
pgrp
==
last_pid
)
if
(
task
[
i
]
->
pid
==
last_pid
||
task
[
i
]
->
pgrp
==
last_pid
||
task
[
i
]
->
session
==
last_pid
)
goto
repeat
;
goto
repeat
;
}
}
if
(
tasks_free
<=
MIN_TASKS_LEFT_FOR_ROOT
||
if
(
tasks_free
<=
MIN_TASKS_LEFT_FOR_ROOT
||
...
...
kernel/ksyms.S
View file @
b168ffdf
...
@@ -9,7 +9,7 @@
...
@@ -9,7 +9,7 @@
_register_chrdev
_register_chrdev
_unregister_chrdev
_unregister_chrdev
_
verify_area
_
__verify_write
_wake_up_interruptible
_wake_up_interruptible
_current
_current
...
...
kernel/sys.c
View file @
b168ffdf
...
@@ -7,7 +7,6 @@
...
@@ -7,7 +7,6 @@
#include <linux/config.h>
#include <linux/config.h>
#include <linux/errno.h>
#include <linux/errno.h>
#include <linux/sched.h>
#include <linux/sched.h>
#include <linux/tty.h>
#include <linux/kernel.h>
#include <linux/kernel.h>
#include <linux/times.h>
#include <linux/times.h>
#include <linux/utsname.h>
#include <linux/utsname.h>
...
@@ -510,7 +509,7 @@ asmlinkage int sys_getpgrp(void)
...
@@ -510,7 +509,7 @@ asmlinkage int sys_getpgrp(void)
asmlinkage
int
sys_setsid
(
void
)
asmlinkage
int
sys_setsid
(
void
)
{
{
if
(
current
->
leader
&&
!
suser
()
)
if
(
current
->
leader
)
return
-
EPERM
;
return
-
EPERM
;
current
->
leader
=
1
;
current
->
leader
=
1
;
current
->
session
=
current
->
pgrp
=
current
->
pid
;
current
->
session
=
current
->
pgrp
=
current
->
pid
;
...
...
mm/memory.c
View file @
b168ffdf
...
@@ -651,17 +651,8 @@ void do_wp_page(unsigned long error_code, unsigned long address,
...
@@ -651,17 +651,8 @@ void do_wp_page(unsigned long error_code, unsigned long address,
*
pg_table
=
0
;
*
pg_table
=
0
;
}
}
int
verify_area
(
int
type
,
void
*
addr
,
unsigned
long
size
)
int
__verify_write
(
unsigned
long
start
,
unsigned
long
size
)
{
{
unsigned
long
start
;
start
=
(
unsigned
long
)
addr
;
if
(
start
>=
TASK_SIZE
)
return
-
EFAULT
;
if
(
size
>
TASK_SIZE
-
start
)
return
-
EFAULT
;
if
(
wp_works_ok
||
type
==
VERIFY_READ
||
!
size
)
return
0
;
size
--
;
size
--
;
size
+=
start
&
~
PAGE_MASK
;
size
+=
start
&
~
PAGE_MASK
;
size
>>=
PAGE_SHIFT
;
size
>>=
PAGE_SHIFT
;
...
...
net/inet/ip.c
View file @
b168ffdf
...
@@ -1464,7 +1464,8 @@ ip_retransmit(struct sock *sk, int all)
...
@@ -1464,7 +1464,8 @@ ip_retransmit(struct sock *sk, int all)
/* If the interface is (still) up and running, kick it. */
/* If the interface is (still) up and running, kick it. */
if
(
dev
->
flags
&
IFF_UP
)
{
if
(
dev
->
flags
&
IFF_UP
)
{
if
(
sk
)
dev
->
queue_xmit
(
skb
,
dev
,
sk
->
priority
);
if
(
sk
&&
!
skb_device_locked
(
skb
))
dev
->
queue_xmit
(
skb
,
dev
,
sk
->
priority
);
/* else dev->queue_xmit(skb, dev, SOPRI_NORMAL ); CANNOT HAVE SK=NULL HERE */
/* else dev->queue_xmit(skb, dev, SOPRI_NORMAL ); CANNOT HAVE SK=NULL HERE */
}
}
...
...
net/inet/skbuff.c
View file @
b168ffdf
...
@@ -381,6 +381,12 @@ void kfree_skb(struct sk_buff *skb, int rw)
...
@@ -381,6 +381,12 @@ void kfree_skb(struct sk_buff *skb, int rw)
return
;
return
;
}
}
IS_SKB
(
skb
);
IS_SKB
(
skb
);
if
(
skb
->
lock
)
{
skb
->
free
=
1
;
/* Free when unlocked */
return
;
}
if
(
skb
->
free
==
2
)
if
(
skb
->
free
==
2
)
printk
(
"Warning: kfree_skb passed an skb that nobody set the free flag on!
\n
"
);
printk
(
"Warning: kfree_skb passed an skb that nobody set the free flag on!
\n
"
);
if
(
skb
->
list
)
if
(
skb
->
list
)
...
@@ -424,6 +430,7 @@ void kfree_skb(struct sk_buff *skb, int rw)
...
@@ -424,6 +430,7 @@ void kfree_skb(struct sk_buff *skb, int rw)
return
NULL
;
return
NULL
;
skb
->
free
=
2
;
/* Invalid so we pick up forgetful users */
skb
->
free
=
2
;
/* Invalid so we pick up forgetful users */
skb
->
list
=
0
;
/* Not on a list */
skb
->
list
=
0
;
/* Not on a list */
skb
->
lock
=
0
;
skb
->
truesize
=
size
;
skb
->
truesize
=
size
;
skb
->
mem_len
=
size
;
skb
->
mem_len
=
size
;
skb
->
mem_addr
=
skb
;
skb
->
mem_addr
=
skb
;
...
@@ -452,3 +459,31 @@ void kfree_skbmem(void *mem,unsigned size)
...
@@ -452,3 +459,31 @@ void kfree_skbmem(void *mem,unsigned size)
}
}
}
}
/*
* Skbuff device locking
*/
void
skb_kept_by_device
(
struct
sk_buff
*
skb
)
{
skb
->
lock
++
;
}
void
skb_device_release
(
struct
sk_buff
*
skb
,
int
mode
)
{
unsigned
long
flags
;
save_flags
(
flags
);
skb
->
lock
--
;
if
(
skb
->
lock
==
0
)
{
if
(
skb
->
free
==
1
)
kfree_skb
(
skb
,
mode
);
}
restore_flags
(
flags
);
}
int
skb_device_locked
(
struct
sk_buff
*
skb
)
{
if
(
skb
->
lock
)
return
1
;
return
0
;
}
net/inet/skbuff.h
View file @
b168ffdf
...
@@ -99,7 +99,9 @@ extern struct sk_buff * skb_peek(struct sk_buff * volatile *list);
...
@@ -99,7 +99,9 @@ extern struct sk_buff * skb_peek(struct sk_buff * volatile *list);
extern
struct
sk_buff
*
skb_peek_copy
(
struct
sk_buff
*
volatile
*
list
);
extern
struct
sk_buff
*
skb_peek_copy
(
struct
sk_buff
*
volatile
*
list
);
extern
struct
sk_buff
*
alloc_skb
(
unsigned
int
size
,
int
priority
);
extern
struct
sk_buff
*
alloc_skb
(
unsigned
int
size
,
int
priority
);
extern
void
kfree_skbmem
(
void
*
mem
,
unsigned
size
);
extern
void
kfree_skbmem
(
void
*
mem
,
unsigned
size
);
extern
void
skb_kept_by_device
(
struct
sk_buff
*
skb
);
extern
void
skb_device_release
(
struct
sk_buff
*
skb
,
int
mode
);
extern
int
skb_device_locked
(
struct
sk_buff
*
skb
);
extern
void
skb_check
(
struct
sk_buff
*
skb
,
int
,
char
*
);
extern
void
skb_check
(
struct
sk_buff
*
skb
,
int
,
char
*
);
#define IS_SKB(skb) skb_check((skb),__LINE__,__FILE__)
#define IS_SKB(skb) skb_check((skb),__LINE__,__FILE__)
...
...
net/inet/tcp.c
View file @
b168ffdf
...
@@ -583,64 +583,41 @@ tcp_check(struct tcphdr *th, int len,
...
@@ -583,64 +583,41 @@ tcp_check(struct tcphdr *th, int len,
}
}
void
void
tcp_send_check
(
struct
tcphdr
*
th
,
unsigned
long
saddr
,
tcp_send_check
(
struct
tcphdr
*
th
,
unsigned
long
saddr
,
unsigned
long
daddr
,
int
len
,
struct
sock
*
sk
)
unsigned
long
daddr
,
int
len
,
struct
sock
*
sk
)
{
th
->
check
=
0
;
th
->
check
=
tcp_check
(
th
,
len
,
saddr
,
daddr
);
return
;
}
static
struct
sk_buff
*
dequeue_partial
(
struct
sock
*
sk
)
{
{
struct
sk_buff
*
skb
;
th
->
check
=
0
;
unsigned
long
flags
;
th
->
check
=
tcp_check
(
th
,
len
,
saddr
,
daddr
);
return
;
save_flags
(
flags
);
cli
();
skb
=
sk
->
send_tmp
;
if
(
skb
)
{
sk
->
send_tmp
=
skb
->
next
;
skb
->
next
=
NULL
;
}
restore_flags
(
flags
);
return
skb
;
}
}
static
void
enqueue_partial
(
struct
sk_buff
*
skb
,
struct
sock
*
sk
)
static
void
tcp_send_skb
(
struct
sock
*
sk
,
struct
sk_buff
*
skb
)
{
{
unsigned
long
flags
;
int
size
;
save_flags
(
flags
);
/* length of packet (not counting length of pre-tcp headers) */
cli
();
size
=
skb
->
len
-
((
unsigned
char
*
)
skb
->
h
.
th
-
skb
->
data
);
skb
->
next
=
sk
->
send_tmp
;
sk
->
send_tmp
=
skb
;
restore_flags
(
flags
);
}
static
void
tcp_send_partial
(
struct
sock
*
sk
)
/* sanity check it.. */
{
if
(
size
<
sizeof
(
struct
tcphdr
)
||
size
>
skb
->
len
)
{
struct
sk_buff
*
skb
;
printk
(
"tcp_send_skb: bad skb (skb = %p, data = %p, th = %p, len = %lu)
\n
"
,
skb
,
skb
->
data
,
skb
->
h
.
th
,
skb
->
len
);
kfree_skb
(
skb
,
FREE_WRITE
);
return
;
}
if
(
sk
==
NULL
)
return
;
while
((
skb
=
dequeue_partial
(
sk
))
!=
NULL
)
{
/* If we have queued a header size packet.. */
/* If we have queued a header size packet.. */
if
(
skb
->
len
-
(
unsigned
long
)
skb
->
h
.
th
+
(
unsigned
long
)
skb
->
data
==
sizeof
(
struct
tcphdr
))
{
if
(
size
==
sizeof
(
struct
tcphdr
))
{
/* If its got a syn or fin its notionally included in the size..*/
/* If its got a syn or fin its notionally included in the size..*/
if
(
!
skb
->
h
.
th
->
syn
&&
!
skb
->
h
.
th
->
fin
)
{
if
(
!
skb
->
h
.
th
->
syn
&&
!
skb
->
h
.
th
->
fin
)
{
printk
(
"tcp_send_
partial
: attempt to queue a bogon.
\n
"
);
printk
(
"tcp_send_
skb
: attempt to queue a bogon.
\n
"
);
kfree_skb
(
skb
,
FREE_WRITE
);
kfree_skb
(
skb
,
FREE_WRITE
);
return
;
return
;
}
}
}
}
/* We need to complete and send the packet. */
/* We need to complete and send the packet. */
tcp_send_check
(
skb
->
h
.
th
,
sk
->
saddr
,
sk
->
daddr
,
tcp_send_check
(
skb
->
h
.
th
,
sk
->
saddr
,
sk
->
daddr
,
size
,
sk
);
skb
->
len
-
(
unsigned
long
)
skb
->
h
.
th
+
(
unsigned
long
)
skb
->
data
,
sk
);
skb
->
h
.
seq
=
sk
->
send_seq
;
skb
->
h
.
seq
=
sk
->
send_seq
;
if
(
after
(
sk
->
send_seq
,
sk
->
window_seq
)
||
if
(
after
(
sk
->
send_seq
,
sk
->
window_seq
)
||
...
@@ -664,9 +641,49 @@ static void tcp_send_partial(struct sock *sk)
...
@@ -664,9 +641,49 @@ static void tcp_send_partial(struct sock *sk)
reset_timer
(
sk
,
TIME_PROBE0
,
reset_timer
(
sk
,
TIME_PROBE0
,
backoff
(
sk
->
backoff
)
*
(
2
*
sk
->
mdev
+
sk
->
rtt
));
backoff
(
sk
->
backoff
)
*
(
2
*
sk
->
mdev
+
sk
->
rtt
));
}
else
{
}
else
{
sk
->
prot
->
queue_xmit
(
sk
,
skb
->
dev
,
skb
,
0
);
sk
->
prot
->
queue_xmit
(
sk
,
skb
->
dev
,
skb
,
0
);
}
}
}
}
static
struct
sk_buff
*
dequeue_partial
(
struct
sock
*
sk
)
{
struct
sk_buff
*
skb
;
unsigned
long
flags
;
save_flags
(
flags
);
cli
();
skb
=
sk
->
send_tmp
;
if
(
skb
)
{
sk
->
send_tmp
=
skb
->
next
;
skb
->
next
=
NULL
;
}
restore_flags
(
flags
);
return
skb
;
}
static
void
enqueue_partial
(
struct
sk_buff
*
skb
,
struct
sock
*
sk
)
{
struct
sk_buff
*
tmp
;
unsigned
long
flags
;
skb
->
next
=
NULL
;
save_flags
(
flags
);
cli
();
tmp
=
sk
->
send_tmp
;
sk
->
send_tmp
=
skb
;
restore_flags
(
flags
);
if
(
tmp
)
tcp_send_skb
(
sk
,
tmp
);
}
static
void
tcp_send_partial
(
struct
sock
*
sk
)
{
struct
sk_buff
*
skb
;
if
(
sk
==
NULL
)
return
;
while
((
skb
=
dequeue_partial
(
sk
))
!=
NULL
)
tcp_send_skb
(
sk
,
skb
);
}
}
...
@@ -901,6 +918,7 @@ tcp_write(struct sock *sk, unsigned char *from,
...
@@ -901,6 +918,7 @@ tcp_write(struct sock *sk, unsigned char *from,
continue
;
continue
;
}
}
#if 0
/*
/*
* We also need to worry about the window.
* We also need to worry about the window.
* If window < 1/4 offered window, don't use it. That's
* If window < 1/4 offered window, don't use it. That's
...
@@ -915,6 +933,10 @@ tcp_write(struct sock *sk, unsigned char *from,
...
@@ -915,6 +933,10 @@ tcp_write(struct sock *sk, unsigned char *from,
copy = sk->mtu;
copy = sk->mtu;
copy = min(copy, sk->mtu);
copy = min(copy, sk->mtu);
copy = min(copy, len);
copy = min(copy, len);
#else
/* This also prevents silly windows by simply ignoring the offered window.. */
copy
=
min
(
sk
->
mtu
,
len
);
#endif
/* We should really check the window here also. */
/* We should really check the window here also. */
if
(
sk
->
packets_out
&&
copy
<
sk
->
mtu
&&
!
(
flags
&
MSG_OOB
))
{
if
(
sk
->
packets_out
&&
copy
<
sk
->
mtu
&&
!
(
flags
&
MSG_OOB
))
{
...
@@ -1011,34 +1033,7 @@ tcp_write(struct sock *sk, unsigned char *from,
...
@@ -1011,34 +1033,7 @@ tcp_write(struct sock *sk, unsigned char *from,
enqueue_partial
(
send_tmp
,
sk
);
enqueue_partial
(
send_tmp
,
sk
);
continue
;
continue
;
}
}
tcp_send_skb
(
sk
,
skb
);
tcp_send_check
((
struct
tcphdr
*
)
buff
,
sk
->
saddr
,
sk
->
daddr
,
copy
+
sizeof
(
struct
tcphdr
),
sk
);
skb
->
h
.
seq
=
sk
->
send_seq
;
if
(
after
(
sk
->
send_seq
,
sk
->
window_seq
)
||
(
sk
->
retransmits
&&
sk
->
timeout
==
TIME_WRITE
)
||
sk
->
packets_out
>=
sk
->
cong_window
)
{
DPRINTF
((
DBG_TCP
,
"sk->cong_window = %d, sk->packets_out = %d
\n
"
,
sk
->
cong_window
,
sk
->
packets_out
));
DPRINTF
((
DBG_TCP
,
"sk->send_seq = %d, sk->window_seq = %d
\n
"
,
sk
->
send_seq
,
sk
->
window_seq
));
skb
->
next
=
NULL
;
skb
->
magic
=
TCP_WRITE_QUEUE_MAGIC
;
if
(
sk
->
wback
==
NULL
)
{
sk
->
wfront
=
skb
;
}
else
{
sk
->
wback
->
next
=
skb
;
}
sk
->
wback
=
skb
;
if
(
before
(
sk
->
window_seq
,
sk
->
wfront
->
h
.
seq
)
&&
sk
->
send_head
==
NULL
&&
sk
->
ack_backlog
==
0
)
reset_timer
(
sk
,
TIME_PROBE0
,
backoff
(
sk
->
backoff
)
*
(
2
*
sk
->
mdev
+
sk
->
rtt
));
}
else
{
prot
->
queue_xmit
(
sk
,
dev
,
skb
,
0
);
}
}
}
sk
->
err
=
0
;
sk
->
err
=
0
;
...
@@ -3604,7 +3599,7 @@ tcp_send_probe0(struct sock *sk)
...
@@ -3604,7 +3599,7 @@ tcp_send_probe0(struct sock *sk)
len
=
hlen
+
sizeof
(
struct
tcphdr
)
+
(
data
?
1
:
0
);
len
=
hlen
+
sizeof
(
struct
tcphdr
)
+
(
data
?
1
:
0
);
/* Allocate buffer. */
/* Allocate buffer. */
if
((
skb2
=
alloc_skb
(
sizeof
(
struct
sk_buff
)
+
len
,
GFP_KERNEL
))
==
NULL
)
{
if
((
skb2
=
alloc_skb
(
sizeof
(
struct
sk_buff
)
+
len
,
GFP_ATOMIC
))
==
NULL
)
{
/* printk("alloc failed raw %x th %x hlen %d data %d len %d\n",
/* printk("alloc failed raw %x th %x hlen %d data %d len %d\n",
raw, skb->h.th, hlen, data, len); */
raw, skb->h.th, hlen, data, len); */
reset_timer
(
sk
,
TIME_PROBE0
,
10
);
/* try again real soon */
reset_timer
(
sk
,
TIME_PROBE0
,
10
);
/* try again real soon */
...
...
net/socket.c
View file @
b168ffdf
...
@@ -28,7 +28,6 @@
...
@@ -28,7 +28,6 @@
#include <linux/stat.h>
#include <linux/stat.h>
#include <linux/socket.h>
#include <linux/socket.h>
#include <linux/fcntl.h>
#include <linux/fcntl.h>
#include <linux/termios.h>
#include <linux/net.h>
#include <linux/net.h>
#include <linux/ddi.h>
#include <linux/ddi.h>
...
...
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