Commit b168ffdf authored by Linus Torvalds's avatar Linus Torvalds

Import 0.99.14v

parent bfeedc98
VERSION = 0.99 VERSION = 0.99
PATCHLEVEL = 14 PATCHLEVEL = 14
ALPHA = u ALPHA = v
all: Version zImage all: Version zImage
......
...@@ -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);
......
/*---------------------------------------------------------------------------+ /*---------------------------------------------------------------------------+
| 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
......
...@@ -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:
......
/*---------------------------------------------------------------------------+ /*---------------------------------------------------------------------------+
| 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))
......
...@@ -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:
......
...@@ -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;
......
...@@ -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("\nEXP=%d, MS=%08x, LS=%08x\n", result->exp, printk("\nEXP=%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 */
......
This diff is collapsed.
...@@ -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"
...@@ -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>
......
...@@ -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>
......
...@@ -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)
......
...@@ -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 srcoll lock 2nd time sends ^Q, ChN */
put_queue(START_CHAR(tty));
else
/* pressing scroll lock 1st time sends ^S, ChN */ /* pressing scroll lock 1st time sends ^S, ChN */
put_queue(STOP_CHAR(tty)); /* pressing scroll lock 2nd time sends ^Q, ChN */
chg_vc_kbd_flag(kbd,VC_SCROLLOCK); /* now done directly without regard to ISIG -- jlc */
if (!vc_kbd_flag(kbd, VC_SCROLLOCK))
stop_tty(tty);
else
start_tty(tty);
} }
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)
......
...@@ -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>
......
...@@ -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);
} }
if (IS_A_PTY_MASTER(to->line))
wake_up_interruptible(&tq->proc_list);
else
TTY_READ_FLUSH(to); TTY_READ_FLUSH(to);
if (!FULL(&from->write_q)) if (LEFT(fq) > WAKEUP_CHARS)
wake_up_interruptible(&from->write_q.proc_list); 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);
......
...@@ -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_CLOCAL(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_CRTSCTS(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_CLOCAL(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_CLOCAL(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
......
This diff is collapsed.
This diff is collapsed.
...@@ -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>
......
...@@ -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++;
} }
......
...@@ -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"
......
...@@ -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;
......
...@@ -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 */
......
...@@ -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
......
...@@ -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);
......
...@@ -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
......
...@@ -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);
......
...@@ -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 ||
......
...@@ -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
......
...@@ -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;
......
...@@ -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;
......
...@@ -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 */
} }
......
...@@ -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;
}
...@@ -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__)
......
...@@ -583,8 +583,7 @@ tcp_check(struct tcphdr *th, int len, ...@@ -583,8 +583,7 @@ 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 = 0;
...@@ -592,55 +591,33 @@ tcp_send_check(struct tcphdr *th, unsigned long saddr, ...@@ -592,55 +591,33 @@ tcp_send_check(struct tcphdr *th, unsigned long saddr,
return; return;
} }
static struct sk_buff * dequeue_partial(struct sock * sk) static void tcp_send_skb(struct sock *sk, struct sk_buff *skb)
{
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)
{ {
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);
if (sk == NULL) kfree_skb(skb, FREE_WRITE);
return; 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 */
......
...@@ -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>
......
Markdown is supported
0%
or
You are about to add 0 people to the discussion. Proceed with caution.
Finish editing this message first!
Please register or to comment