Version:
@./makever.sh
- @echo \#define UTS_RELEASE \"0.96a-`cat .version`\" > include/linux/config_rel.h
+ @echo \#define UTS_RELEASE \"0.96b.pl2-`cat .version`\" > include/linux/config_rel.h
@echo \#define UTS_VERSION \"`date +%D`\" > include/linux/config_ver.h
touch include/linux/config.h
if (tty = get_tty(inode))
if (!EMPTY(tty->secondary))
return 1;
+ else if (tty->link && !tty->link->count)
+ return 1;
else
add_wait(&tty->secondary->proc_list, wait);
else if (inode->i_pipe)
static inline void PUTCH(char c, struct tty_queue * queue)
{
int head;
+ unsigned long flags;
- cli();
+ __asm__("pushfl ; popl %0 ; cli":"=r" (flags));
head = (queue->head + 1) & (TTY_BUF_SIZE-1);
if (head != queue->tail) {
queue->buf[queue->head] = c;
queue->head = head;
}
- sti();
+ __asm__("pushl %0 ; popfl"::"r" (flags));
}
static inline int GETCH(struct tty_queue * queue)
{
int result = -1;
+ unsigned long flags;
+ __asm__("pushfl ; popl %0 ; cli":"=r" (flags));
if (queue->tail != queue->head) {
result = 0xff & queue->buf[queue->tail];
queue->tail = (queue->tail + 1) & (TTY_BUF_SIZE-1);
}
+ __asm__("pushl %0 ; popfl"::"r" (flags));
return result;
}
int count;
struct winsize winsize;
void (*write)(struct tty_struct * tty);
+ struct tty_struct *link;
struct tty_queue *read_q;
struct tty_queue *write_q;
struct tty_queue *secondary;
extern long tty_init(long);
extern void flush_input(struct tty_struct * tty);
+extern void flush_output(struct tty_struct * tty);
+extern void copy_to_cooked(struct tty_struct * tty);
extern int tty_ioctl(struct inode *, struct file *, unsigned int, unsigned int);
extern int is_orphaned_pgrp(int pgrp);
extern int is_ignored(int sig);
extern int tty_signal(int sig, struct tty_struct *tty);
+extern int kill_pg(int pgrp, int sig, int priv);
+
+/* tty write functions */
extern void rs_write(struct tty_struct * tty);
extern void con_write(struct tty_struct * tty);
extern void mpty_write(struct tty_struct * tty);
extern void spty_write(struct tty_struct * tty);
+/* serial.c */
+
extern int serial_open(unsigned int line, struct file * filp);
extern void serial_close(unsigned int line, struct file * filp);
+extern void change_speed(unsigned int line);
+extern void send_break(unsigned int line);
extern int get_serial_info(unsigned int, struct serial_struct *);
extern int set_serial_info(unsigned int, struct serial_struct *);
-void copy_to_cooked(struct tty_struct * tty);
+/* pty.c */
+
+extern int pty_open(unsigned int dev, struct file * filp);
+extern void pty_close(unsigned int dev, struct file * filp);
+
+/* console.c */
void update_screen(int new_console);
void blank_screen(void);
void unblank_screen(void);
-int kill_pg(int pgrp, int sig, int priv);
-
#endif
#include <asm/system.h>
#include <asm/io.h>
+#include<errno.h>
+#include<fcntl.h>
+
+int pty_open(unsigned int dev, struct file * filp)
+{
+ struct tty_struct * tty;
+
+ tty = tty_table + dev;
+ if (!tty->link)
+ return -ENODEV;
+ wake_up(&tty->read_q->proc_list);
+ if (filp->f_flags & O_NDELAY)
+ return 0;
+ if (IS_A_PTY_MASTER(dev))
+ return 0;
+#if 0
+ while (!tty->link->count && !(current->signal & ~current->blocked))
+ interruptible_sleep_on(&tty->link->read_q->proc_list);
+ if (!tty->link->count)
+ return -ERESTARTSYS;
+#endif
+ return 0;
+}
+
+void pty_close(unsigned int dev, struct file * filp)
+{
+ struct tty_struct * tty;
+
+ tty = tty_table + dev;
+ wake_up(&tty->read_q->proc_list);
+ if (IS_A_PTY_MASTER(dev)) {
+ if (tty->link->pgrp > 0)
+ kill_pg(tty->link->pgrp,SIGHUP,1);
+ }
+}
+
static inline void pty_copy(struct tty_struct * from, struct tty_struct * to)
{
int c;
*/
void mpty_write(struct tty_struct * tty)
{
- int nr = tty - tty_table;
-
- if ((nr >> 6) != 2)
- printk("bad mpty\n\r");
- else
- pty_copy(tty,tty+64);
+ if (tty->link)
+ pty_copy(tty,tty->link);
}
void spty_write(struct tty_struct * tty)
{
- int nr = tty - tty_table;
-
- if ((nr >> 6) != 3)
- printk("bad spty\n\r");
- else
- pty_copy(tty,tty-64);
+ if (tty->link)
+ pty_copy(tty,tty->link);
}
#endif
}
+void send_break(unsigned int line)
+{
+ unsigned short port;
+ struct serial_struct * info;
+
+ if (line >= NR_SERIALS)
+ return;
+ info = serial_table + line;
+ if (!(port = info->port))
+ return;
+ port += 3;
+ current->state = TASK_INTERRUPTIBLE;
+ current->timeout = jiffies + 25;
+ outb_p(inb_p(port) | 0x40,port);
+ schedule();
+ outb_p(inb_p(port) & 0xbf,port);
+}
+
/*
* There are several races here: we avoid most of them by disabling timer_active
* for the crucial part of the process.. That's a good idea anyway.
unsigned short port = info->port;
struct tty_queue * queue = info->tty->read_q;
- while (inb(port+5) & 1)
+ do {
PUTCH(inb(port),queue);
+ } while (inb(port+5) & 1);
timer_active |= (1<<SER1_TIMER)<<info->line;
}
}
}
-/*
- * IRQ3 normally handles com2 and com4
- */
-void do_IRQ3(void)
-{
- check_tty(irq_info[3]);
-}
-
-/*
- * IRQ4 normally handles com1 and com3
- */
-void do_IRQ4(void)
+void do_IRQ(int irq)
{
- check_tty(irq_info[4]);
-}
-
-void do_IRQ5(void)
-{
- check_tty(irq_info[5]);
-}
-
-void do_IRQ9(void)
-{
- check_tty(irq_info[9]);
+ check_tty(irq_info[irq]);
}
static void com1_timer(void)
inb(port+2);
}
+void change_speed(unsigned int line)
+{
+ struct serial_struct * info;
+ unsigned short port,quot;
+ unsigned cflag;
+ static unsigned short quotient[] = {
+ 0, 2304, 1536, 1047, 857,
+ 768, 576, 384, 192, 96,
+ 64, 48, 24, 12, 6, 3
+ };
+
+ if (line >= NR_SERIALS)
+ return;
+ info = serial_table + line;
+ cflag = info->tty->termios.c_cflag;
+ if (!(port = info->port))
+ return;
+ quot = quotient[cflag & CBAUD];
+ if (!quot)
+ outb(0x00,port+4);
+ else if (!inb(port+4))
+ startup(port);
+ cli();
+ outb_p(0x80,port+3); /* set DLAB */
+ outb_p(quot & 0xff,port); /* LS of divisor */
+ outb_p(quot >> 8,port+1); /* MS of divisor */
+ outb(0x03,port+3); /* reset DLAB */
+ sti();
+/* set byte size and parity */
+ quot = cflag & (CSIZE | CSTOPB);
+ quot >>= 4;
+ if (cflag & PARENB)
+ quot |= 8;
+ if (!(cflag & PARODD))
+ quot |= 16;
+ outb(quot,port+3);
+}
+
/*
* this routine enables interrupts on 'line', and disables them for any
* other serial line that shared the same IRQ. Braindamaged AT hardware.
return;
}
while (1) {
- if (EMPTY(tty->read_q))
+ if (FULL(tty->secondary))
break;
- if (FULL(tty->secondary)) {
- if (tty->secondary->proc_list)
- if (tty->secondary->proc_list != current)
- current->counter = 0;
- break;
- }
c = GETCH(tty->read_q);
+ if (c < 0)
+ break;
if (I_STRP(tty))
c &= 0x7f;
if (c==13) {
int tty_signal(int sig, struct tty_struct *tty)
{
(void) kill_pg(current->pgrp,sig,1);
- if (current->sigaction[sig-1].sa_handler)
- return -EINTR; /* We _will_ be interrupted :-) */
- else
- return -ERESTARTSYS; /* We _will_ be interrupted :-) */
- /* (but restart after we continue) */
+ return -ERESTARTSYS;
}
static int read_chan(unsigned int channel, struct file * file, char * buf, int nr)
break;
if (IS_A_PTY_SLAVE(channel) && C_HUP(other_tty))
break;
+ if (other_tty && !other_tty->count)
+ break;
interruptible_sleep_on(&tty->secondary->proc_list);
sti();
TTY_READ_FLUSH(tty);
static int tty_open(struct inode * inode, struct file * filp)
{
struct tty_struct *tty;
- int dev;
+ int dev, retval;
dev = inode->i_rdev;
if (MAJOR(dev) == 5)
if (tty->count)
return -EAGAIN;
}
+ if (!tty->count && (!tty->link || !tty->link->count)) {
+ flush_input(tty);
+ flush_output(tty);
+ }
tty->count++;
+ retval = 0;
if (!(filp->f_flags & O_NOCTTY) &&
current->leader &&
current->tty<0 &&
tty->pgrp = current->pgrp;
}
if (IS_A_SERIAL(dev))
- return serial_open(dev-64,filp);
- return 0;
+ retval = serial_open(dev-64,filp);
+ else if (IS_A_PTY(dev))
+ retval = pty_open(dev,filp);
+ if (retval)
+ tty->count--;
+ return retval;
}
static void tty_release(struct inode * inode, struct file * filp)
{
int dev;
- struct tty_struct * tty, * slave;
+ struct tty_struct * tty;
dev = inode->i_rdev;
if (MAJOR(dev) == 5)
redirect = NULL;
if (IS_A_SERIAL(dev))
serial_close(dev-64,filp);
- else if (IS_A_PTY_MASTER(dev)) {
- slave = tty_table + PTY_OTHER(dev);
- if (slave->pgrp > 0)
- kill_pg(slave->pgrp,SIGHUP,1);
- }
+ else if (IS_A_PTY(dev))
+ pty_close(dev,filp);
}
static struct file_operations tty_fops = {
tty_table[i] = (struct tty_struct) {
{0, 0, 0, 0, 0, INIT_C_CC},
-1, 0, 0, 0, 0, {0,0,0,0},
- NULL, NULL, NULL, NULL
+ NULL, NULL, NULL, NULL, NULL
};
}
kmem_start = con_init(kmem_start);
0, /* initial count */
{video_num_lines,video_num_columns,0,0},
con_write,
+ NULL, /* other-tty */
con_queues+0+i*3,con_queues+1+i*3,con_queues+2+i*3
};
}
0,
{25,80,0,0},
rs_write,
+ NULL, /* other-tty */
rs_queues+0+i*3,rs_queues+1+i*3,rs_queues+2+i*3
};
}
0,
{25,80,0,0},
mpty_write,
+ spty_table+i,
mpty_queues+0+i*3,mpty_queues+1+i*3,mpty_queues+2+i*3
};
spty_table[i] = (struct tty_struct) {
0,
{25,80,0,0},
spty_write,
+ mpty_table+i,
spty_queues+0+i*3,spty_queues+1+i*3,spty_queues+2+i*3
};
}
extern int kill_pg(int pgrp, int sig, int priv);
extern int vt_ioctl(struct tty_struct *tty, int dev, int cmd, int arg);
-static unsigned short quotient[] = {
- 0, 2304, 1536, 1047, 857,
- 768, 576, 384, 192, 96,
- 64, 48, 24, 12, 6, 3
-};
-
-static void change_speed(struct serial_struct * info)
-{
- unsigned short port,quot;
-
- if (!(port = info->port))
- return;
- quot = quotient[info->tty->termios.c_cflag & CBAUD];
- cli();
- outb_p(0x80,port+3); /* set DLAB */
- outb_p(quot & 0xff,port); /* LS of divisor */
- outb_p(quot >> 8,port+1); /* MS of divisor */
- outb(0x03,port+3); /* reset DLAB */
- sti();
-}
-
static void flush(struct tty_queue * queue)
{
if (queue) {
flush(tty->secondary);
tty->secondary->data = 0;
wake_up(&tty->read_q->proc_list);
+ if (tty = tty->link) {
+ flush(tty->write_q);
+ wake_up(&tty->write_q->proc_list);
+ }
+}
+
+void flush_output(struct tty_struct * tty)
+{
+ flush(tty->write_q);
+ wake_up(&tty->write_q->proc_list);
+ if (tty = tty->link) {
+ flush(tty->read_q);
+ flush(tty->secondary);
+ tty->secondary->data = 0;
+ wake_up(&tty->read_q->proc_list);
+ }
}
static void wait_until_sent(struct tty_struct * tty)
sti();
}
-static void send_break(struct serial_struct * info)
-{
- unsigned short port;
-
- if (!(port = info->port))
- return;
- port += 3;
- current->state = TASK_INTERRUPTIBLE;
- current->timeout = jiffies + 25;
- outb_p(inb_p(port) | 0x40,port);
- schedule();
- outb_p(inb_p(port) & 0xbf,port);
-}
-
static int do_get_ps_info(int arg)
{
struct tstruct {
for (i=0 ; i< (sizeof (*termios)) ; i++)
((char *)&tty->termios)[i]=get_fs_byte(i+(char *)termios);
if (IS_A_SERIAL(channel))
- change_speed(serial_table+channel-64);
+ change_speed(channel-64);
return 0;
}
for(i=0 ; i < NCC ; i++)
tty->termios.c_cc[i] = tmp_termio.c_cc[i];
if (IS_A_SERIAL(channel))
- change_speed(serial_table+channel-64);
+ change_speed(channel-64);
return 0;
}
return get_termios(tty,(struct termios *) arg);
case TCSETSF:
flush_input(tty);
- if (other_tty)
- flush(other_tty->write_q);
/* fallthrough */
case TCSETSW:
wait_until_sent(tty);
return get_termio(tty,(struct termio *) arg);
case TCSETAF:
flush_input(tty);
- if (other_tty)
- flush(other_tty->write_q);
/* fallthrough */
case TCSETAW:
wait_until_sent(tty); /* fallthrough */
return -EINVAL;
wait_until_sent(tty);
if (!arg)
- send_break(serial_table+dev-64);
+ send_break(dev-64);
return 0;
case TCXONC:
switch (arg) {
}
return -EINVAL; /* not implemented */
case TCFLSH:
- if (arg==0) {
+ if (arg==0)
flush_input(tty);
- if (other_tty)
- flush(other_tty->write_q);
- } else if (arg==1)
- flush(tty->write_q);
+ else if (arg==1)
+ flush_output(tty);
else if (arg==2) {
flush_input(tty);
- flush(tty->write_q);
- if (other_tty)
- flush(other_tty->write_q);
+ flush_output(tty);
} else
return -EINVAL;
return 0;
p->p_osptr->p_ysptr = p;
p->p_pptr->p_cptr = p;
if (p->state == TASK_ZOMBIE)
- p->p_pptr->signal |= (1<<(SIGCHLD-1));
+ send_sig(SIGCHLD,p->p_pptr,1);
/*
* process group orphan check
* Case ii: Our child is in a different pgrp
src[3] = s->b;
d->exponent = 0;
d->a = d->b = 0;
- if (exponent) /* fsqrt(0.0) = 0.0 */
+ if (!exponent) /* fsqrt(0.0) = 0.0 */
return;
if (!src[2] && !src[3])
return;
for (task_p = &LAST_TASK; task_p >= &FIRST_TASK; task_p--)
if (*task_p && (*task_p)->it_real_value
&& !(--(*task_p)->it_real_value)) {
- (*task_p)->signal |= (1<<(SIGALRM-1));
+ send_sig(SIGALRM,*task_p,1);
(*task_p)->it_real_value = (*task_p)->it_real_incr;
need_resched = 1;
}
/* Update ITIMER_PROF for the current task */
if (current->it_prof_value && !(--current->it_prof_value)) {
current->it_prof_value = current->it_prof_incr;
- current->signal |= (1<<(SIGPROF-1));
+ send_sig(SIGPROF,current,1);
}
/* Update ITIMER_VIRT for current task if not in a system call */
if (cpl && current->it_virt_value && !(--current->it_virt_value)) {
current->it_virt_value = current->it_virt_incr;
- current->signal |= (1<<(SIGVTALRM-1));
+ send_sig(SIGVTALRM,current,1);
}
if (cpl)
SAVE_ALL
ACK_FIRST(0x08)
sti
- call _do_IRQ3
+ pushl $3
+ call _do_IRQ
+ addl $4,%esp
cli
UNBLK_FIRST(0x08)
jmp ret_from_sys_call
SAVE_ALL
ACK_FIRST(0x10)
sti
- call _do_IRQ4
+ pushl $4
+ call _do_IRQ
+ addl $4,%esp
cli
UNBLK_FIRST(0x10)
jmp ret_from_sys_call
SAVE_ALL
ACK_FIRST(0x20)
sti
- call _do_IRQ5
+ pushl $5
+ call _do_IRQ
+ addl $4,%esp
cli
UNBLK_FIRST(0x20)
jmp ret_from_sys_call
SAVE_ALL
ACK_SECOND(0x02)
sti
- call _do_IRQ9
+ pushl $9
+ call _do_IRQ
+ addl $4,%esp
cli
UNBLK_SECOND(0x02)
jmp ret_from_sys_call
if (avail <= 0) {
PRINTK("unix_proto_read: AVAIL IS NEGATIVE!!!\n");
- current->signal |= (1 << (SIGKILL-1));
+ send_sig(SIGKILL,current,1);
return -EINTR;
}
if (sock->state != SS_CONNECTED) {
PRINTK("unix_proto_write: socket not connected\n");
if (sock->state == SS_DISCONNECTING) {
- current->signal |= (1 << (SIGPIPE-1));
+ send_sig(SIGPIPE,current,1);
return -EINTR;
}
return -EINVAL;
}
if (sock->state == SS_DISCONNECTING) {
PRINTK("unix_proto_write: disconnected (SIGPIPE)\n");
- current->signal |= (1 << (SIGPIPE-1));
+ send_sig(SIGPIPE,current,1);
return -EINTR;
}
}
if (space <= 0) {
PRINTK("unix_proto_write: SPACE IS NEGATIVE!!!\n");
- current->signal |= (1 << (SIGKILL-1));
+ send_sig(SIGKILL,current,1);
return -EINTR;
}
* for it (peerupd is safe until we close)
*/
if (sock->state == SS_DISCONNECTING) {
- current->signal |= (1 << (SIGPIPE-1));
+ send_sig(SIGPIPE,current,1);
return -EINTR;
}
if ((cando = todo) > space)