/*
       *  linux/drivers/char/tty_io.c
       *
       *  Copyright (C) 1991, 1992  Linus Torvalds
       */
      
      /*
       * 'tty_io.c' gives an orthogonal feeling to tty's, be they consoles
       * or rs-channels. It also implements echoing, cooked mode etc.
       *
       * Kill-line thanks to John T Kohl, who also corrected VMIN = VTIME = 0.
       *
       * Modified by Theodore Ts'o, 9/14/92, to dynamically allocate the
       * tty_struct and tty_queue structures.  Previously there was an array
       * of 256 tty_struct's which was statically allocated, and the
       * tty_queue structures were allocated at boot time.  Both are now
       * dynamically allocated only when the tty is open.
       *
       * Also restructured routines so that there is more of a separation
       * between the high-level tty routines (tty_io.c and tty_ioctl.c) and
       * the low-level tty routines (serial.c, pty.c, console.c).  This
       * makes for cleaner and more compact code.  -TYT, 9/17/92 
       *
       * Modified by Fred N. van Kempen, 01/29/93, to add line disciplines
       * which can be dynamically activated and de-activated by the line
       * discipline handling modules (like SLIP).
       *
       * NOTE: pay no attention to the line discipline code (yet); its
       * interface is still subject to change in this version...
       * -- TYT, 1/31/92
       *
       * Added functionality to the OPOST tty handling.  No delays, but all
       * other bits should be there.
       *	-- 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
       *
       * Reorganized FASYNC support so mouse code can share it.
       *	-- ctm@ardi.com, 9Sep95
       *
       * New TIOCLINUX variants added.
       *	-- mj@k332.feld.cvut.cz, 19-Nov-95
       * 
       * Restrict vt switching via ioctl()
       *      -- grif@cs.ucr.edu, 5-Dec-95
       *
       * Move console and virtual terminal code to more appropriate files,
       * implement CONFIG_VT and generalize console device interface.
       *	-- Marko Kohtala <Marko.Kohtala@hut.fi>, March 97
       *
       * Rewrote init_dev and release_dev to eliminate races.
       *	-- Bill Hawes <whawes@star.net>, June 97
       *
       * Added devfs support.
       *      -- C. Scott Ananian <cananian@alumni.princeton.edu>, 13-Jan-1998
       *
       * Added support for a Unix98-style ptmx device.
       *      -- C. Scott Ananian <cananian@alumni.princeton.edu>, 14-Jan-1998
       *
       * Reduced memory usage for older ARM systems
       *      -- Russell King <rmk@arm.linux.org.uk>
       */
      
      #include <linux/config.h>
      #include <linux/types.h>
      #include <linux/major.h>
      #include <linux/errno.h>
      #include <linux/signal.h>
      #include <linux/fcntl.h>
      #include <linux/sched.h>
      #include <linux/interrupt.h>
      #include <linux/tty.h>
      #include <linux/tty_driver.h>
      #include <linux/tty_flip.h>
      #include <linux/devpts_fs.h>
      #include <linux/file.h>
      #include <linux/console.h>
      #include <linux/timer.h>
      #include <linux/ctype.h>
      #include <linux/kd.h>
      #include <linux/mm.h>
      #include <linux/string.h>
      #include <linux/malloc.h>
      #include <linux/poll.h>
      #include <linux/proc_fs.h>
      #include <linux/init.h>
      #include <linux/module.h>
      #include <linux/smp_lock.h>
      
      #include <asm/uaccess.h>
      #include <asm/system.h>
      #include <asm/bitops.h>
      
      #include <linux/kbd_kern.h>
      #include <linux/vt_kern.h>
      #include <linux/selection.h>
      #include <linux/devfs_fs_kernel.h>
      
      #include <linux/kmod.h>
      
      #ifdef CONFIG_VT
      extern void con_init_devfs (void);
      #endif
      extern int rio_init(void);
      
      #define CONSOLE_DEV MKDEV(TTY_MAJOR,0)
      #define TTY_DEV MKDEV(TTYAUX_MAJOR,0)
      #define SYSCONS_DEV MKDEV(TTYAUX_MAJOR,1)
      #define PTMX_DEV MKDEV(TTYAUX_MAJOR,2)
      
      #undef TTY_DEBUG_HANGUP
      
      #define TTY_PARANOIA_CHECK 1
      #define CHECK_TTY_COUNT 1
      
      struct termios tty_std_termios;		/* for the benefit of tty drivers  */
      struct tty_driver *tty_drivers;		/* linked list of tty drivers */
      struct tty_ldisc ldiscs[NR_LDISCS];	/* line disc dispatch table	*/
      
      #ifdef CONFIG_UNIX98_PTYS
      extern struct tty_driver ptm_driver[];	/* Unix98 pty masters; for /dev/ptmx */
      extern struct tty_driver pts_driver[];	/* Unix98 pty slaves;  for /dev/ptmx */
      #endif
      
      /*
       * redirect is the pseudo-tty that console output
       * is redirected to if asked by TIOCCONS.
       */
      struct tty_struct * redirect;
      
      static void initialize_tty_struct(struct tty_struct *tty);
      
      static ssize_t tty_read(struct file *, char *, size_t, loff_t *);
      static ssize_t tty_write(struct file *, const char *, size_t, loff_t *);
      static unsigned int tty_poll(struct file *, poll_table *);
      static int tty_open(struct inode *, struct file *);
      static int tty_release(struct inode *, struct file *);
      int tty_ioctl(struct inode * inode, struct file * file,
      	      unsigned int cmd, unsigned long arg);
      static int tty_fasync(int fd, struct file * filp, int on);
      extern int sx_init (void);
      extern int vme_scc_init (void);
      extern long vme_scc_console_init(void);
      extern int serial167_init(void);
      extern long serial167_console_init(void);
      extern void console_8xx_init(void);
      extern int rs_8xx_init(void);
      extern void hwc_console_init(void);
      extern void con3215_init(void);
      extern void rs285_console_init(void);
      extern void sa1100_rs_console_init(void);
      extern void sgi_serial_console_init(void);
      extern void sci_console_init(void);
      
      #ifndef MIN
      #define MIN(a,b)	((a) < (b) ? (a) : (b))
      #endif
      #ifndef MAX
      #define MAX(a,b)	((a) < (b) ? (b) : (a))
      #endif
      
 163  static inline struct tty_struct *alloc_tty_struct(void)
      {
      	struct tty_struct *tty;
      
 167  	if (PAGE_SIZE > 8192) {
      		tty = kmalloc(sizeof(struct tty_struct), GFP_KERNEL);
 169  		if (tty)
      			memset(tty, 0, sizeof(struct tty_struct));
 171  	} else
      		tty = (struct tty_struct *)get_zeroed_page(GFP_KERNEL);
      
 174  	return tty;
      }
      
 177  static inline void free_tty_struct(struct tty_struct *tty)
      {
 179  	if (PAGE_SIZE > 8192)
      		kfree(tty);
 181  	else
      		free_page((unsigned long) tty);
      }
      
      /*
       * This routine returns the name of tty.
       */
      static char *
 189  _tty_make_name(struct tty_struct *tty, const char *name, char *buf)
      {
      	int idx = (tty)?MINOR(tty->device) - tty->driver.minor_start:0;
      
 193  	if (!tty) /* Hmm.  NULL pointer.  That's fun. */
      		strcpy(buf, "NULL tty");
 195  	else
      		sprintf(buf, name,
      			idx + tty->driver.name_base);
      		
 199  	return buf;
      }
      
      #define TTY_NUMBER(tty) (MINOR((tty)->device) - (tty)->driver.minor_start + \
      			 (tty)->driver.name_base)
      
 205  char *tty_name(struct tty_struct *tty, char *buf)
      {
 207  	return _tty_make_name(tty, (tty)?tty->driver.name:NULL, buf);
      }
      
 210  inline int tty_paranoia_check(struct tty_struct *tty, kdev_t device,
      			      const char *routine)
      {
      #ifdef TTY_PARANOIA_CHECK
      	static const char *badmagic =
      		"Warning: bad magic number for tty struct (%s) in %s\n";
      	static const char *badtty =
      		"Warning: null TTY for (%s) in %s\n";
      
 219  	if (!tty) {
      		printk(badtty, kdevname(device), routine);
 221  		return 1;
      	}
 223  	if (tty->magic != TTY_MAGIC) {
      		printk(badmagic, kdevname(device), routine);
 225  		return 1;
      	}
      #endif
 228  	return 0;
      }
      
 231  static int check_tty_count(struct tty_struct *tty, const char *routine)
      {
      #ifdef CHECK_TTY_COUNT
      	struct list_head *p;
      	int count = 0;
      	
      	file_list_lock();
 238  	for(p = tty->tty_files.next; p != &tty->tty_files; p = p->next) {
 239  		if(list_entry(p, struct file, f_list)->private_data == tty)
      			count++;
      	}
 242  	file_list_unlock();
      	if (tty->driver.type == TTY_DRIVER_TYPE_PTY &&
      	    tty->driver.subtype == PTY_TYPE_SLAVE &&
 245  	    tty->link && tty->link->count)
      		count++;
 247  	if (tty->count != count) {
      		printk("Warning: dev (%s) tty->count(%d) != #fd's(%d) in %s\n",
      		       kdevname(tty->device), tty->count, count, routine);
 250  		return count;
             }	
      #endif
 253  	return 0;
      }
      
 256  int tty_register_ldisc(int disc, struct tty_ldisc *new_ldisc)
      {
 258  	if (disc < N_TTY || disc >= NR_LDISCS)
 259  		return -EINVAL;
      	
 261  	if (new_ldisc) {
      		ldiscs[disc] = *new_ldisc;
      		ldiscs[disc].flags |= LDISC_FLAG_DEFINED;
      		ldiscs[disc].num = disc;
 265  	} else
      		memset(&ldiscs[disc], 0, sizeof(struct tty_ldisc));
      	
 268  	return 0;
      }
      
      /* Set the discipline of a tty line. */
 272  static int tty_set_ldisc(struct tty_struct *tty, int ldisc)
      {
      	int	retval = 0;
      	struct	tty_ldisc o_ldisc;
      	char buf[64];
      
 278  	if ((ldisc < N_TTY) || (ldisc >= NR_LDISCS))
 279  		return -EINVAL;
      	/* Eduardo Blanco <ejbs@cs.cs.com.uy> */
      	/* Cyrus Durgin <cider@speakeasy.org> */
 282  	if (!(ldiscs[ldisc].flags & LDISC_FLAG_DEFINED)) {
      		char modname [20];
      		sprintf(modname, "tty-ldisc-%d", ldisc);
      		request_module (modname);
      	}
 287  	if (!(ldiscs[ldisc].flags & LDISC_FLAG_DEFINED))
 288  		return -EINVAL;
      
 290  	if (tty->ldisc.num == ldisc)
 291  		return 0;	/* We are already in the desired discipline */
      	o_ldisc = tty->ldisc;
      
      	tty_wait_until_sent(tty, 0);
      	
      	/* Shutdown the current discipline. */
 297  	if (tty->ldisc.close)
      		(tty->ldisc.close)(tty);
      
      	/* Now set up the new line discipline. */
      	tty->ldisc = ldiscs[ldisc];
      	tty->termios->c_line = ldisc;
 303  	if (tty->ldisc.open)
      		retval = (tty->ldisc.open)(tty);
 305  	if (retval < 0) {
      		tty->ldisc = o_ldisc;
      		tty->termios->c_line = tty->ldisc.num;
 308  		if (tty->ldisc.open && (tty->ldisc.open(tty) < 0)) {
      			tty->ldisc = ldiscs[N_TTY];
      			tty->termios->c_line = N_TTY;
 311  			if (tty->ldisc.open) {
      				int r = tty->ldisc.open(tty);
      
 314  				if (r < 0)
      					panic("Couldn't open N_TTY ldisc for "
      					      "%s --- error %d.",
      					      tty_name(tty, buf), r);
      			}
      		}
      	}
 321  	if (tty->ldisc.num != o_ldisc.num && tty->driver.set_ldisc)
      		tty->driver.set_ldisc(tty);
 323  	return retval;
      }
      
      /*
       * This routine returns a tty driver structure, given a device number
       */
 329  struct tty_driver *get_tty_driver(kdev_t device)
      {
      	int	major, minor;
      	struct tty_driver *p;
      	
      	minor = MINOR(device);
      	major = MAJOR(device);
      
 337  	for (p = tty_drivers; p; p = p->next) {
 338  		if (p->major != major)
 339  			continue;
 340  		if (minor < p->minor_start)
 341  			continue;
 342  		if (minor >= p->minor_start + p->num)
 343  			continue;
 344  		return p;
      	}
 346  	return NULL;
      }
      
      /*
       * If we try to write to, or set the state of, a terminal and we're
       * not in the foreground, send a SIGTTOU.  If the signal is blocked or
       * ignored, go ahead and perform the operation.  (POSIX 7.2)
       */
 354  int tty_check_change(struct tty_struct * tty)
      {
 356  	if (current->tty != tty)
 357  		return 0;
 358  	if (tty->pgrp <= 0) {
      		printk("tty_check_change: tty->pgrp <= 0!\n");
 360  		return 0;
      	}
 362  	if (current->pgrp == tty->pgrp)
 363  		return 0;
 364  	if (is_ignored(SIGTTOU))
 365  		return 0;
 366  	if (is_orphaned_pgrp(current->pgrp))
 367  		return -EIO;
      	(void) kill_pg(current->pgrp,SIGTTOU,1);
 369  	return -ERESTARTSYS;
      }
      
 372  static ssize_t hung_up_tty_read(struct file * file, char * buf,
      				size_t count, loff_t *ppos)
      {
      	/* Can't seek (pread) on ttys.  */
 376  	if (ppos != &file->f_pos)
 377  		return -ESPIPE;
 378  	return 0;
      }
      
 381  static ssize_t hung_up_tty_write(struct file * file, const char * buf,
      				 size_t count, loff_t *ppos)
      {
      	/* Can't seek (pwrite) on ttys.  */
 385  	if (ppos != &file->f_pos)
 386  		return -ESPIPE;
 387  	return -EIO;
      }
      
      /* No kernel lock held - none needed ;) */
 391  static unsigned int hung_up_tty_poll(struct file * filp, poll_table * wait)
      {
 393  	return POLLIN | POLLOUT | POLLERR | POLLHUP | POLLRDNORM | POLLWRNORM;
      }
      
 396  static int hung_up_tty_ioctl(struct inode * inode, struct file * file,
      			     unsigned int cmd, unsigned long arg)
      {
 399  	return cmd == TIOCSPGRP ? -ENOTTY : -EIO;
      }
      
 402  static loff_t tty_lseek(struct file * file, loff_t offset, int orig)
      {
 404  	return -ESPIPE;
      }
      
      static struct file_operations tty_fops = {
      	llseek:		tty_lseek,
      	read:		tty_read,
      	write:		tty_write,
      	poll:		tty_poll,
      	ioctl:		tty_ioctl,
      	open:		tty_open,
      	release:	tty_release,
      	fasync:		tty_fasync,
      };
      
      static struct file_operations hung_up_tty_fops = {
      	llseek:		tty_lseek,
      	read:		hung_up_tty_read,
      	write:		hung_up_tty_write,
      	poll:		hung_up_tty_poll,
      	ioctl:		hung_up_tty_ioctl,
      	release:	tty_release,
      };
      
      /*
       * This can be called by the "eventd" kernel thread.  That is process synchronous,
       * but doesn't hold any locks, so we need to make sure we have the appropriate
       * locks for what we're doing..
       */
 432  void do_tty_hangup(void *data)
      {
      	struct tty_struct *tty = (struct tty_struct *) data;
      	struct file * cons_filp = NULL;
      	struct task_struct *p;
      	struct list_head *l;
      	int    closecount = 0, n;
      
 440  	if (!tty)
 441  		return;
      
      	/* inuse_filps is protected by the single kernel lock */
 444  	lock_kernel();
      	
      	check_tty_count(tty, "do_tty_hangup");
      	file_list_lock();
 448  	for (l = tty->tty_files.next; l != &tty->tty_files; l = l->next) {
      		struct file * filp = list_entry(l, struct file, f_list);
 450  		if (!filp->f_dentry)
 451  			continue;
      		if (filp->f_dentry->d_inode->i_rdev == CONSOLE_DEV ||
 453  		    filp->f_dentry->d_inode->i_rdev == SYSCONS_DEV) {
      			cons_filp = filp;
 455  			continue;
      		}
 457  		if (filp->f_op != &tty_fops)
 458  			continue;
      		closecount++;
      		tty_fasync(-1, filp, 0);	/* can't block */
      		filp->f_op = &hung_up_tty_fops;
      	}
 463  	file_list_unlock();
      	
      	/* FIXME! What are the locking issues here? This may me overdoing things.. */
      	{
      		unsigned long flags;
      
      		save_flags(flags); cli();
 470  		if (tty->ldisc.flush_buffer)
      			tty->ldisc.flush_buffer(tty);
 472  		if (tty->driver.flush_buffer)
      			tty->driver.flush_buffer(tty);
      		if ((test_bit(TTY_DO_WRITE_WAKEUP, &tty->flags)) &&
 475  		    tty->ldisc.write_wakeup)
      			(tty->ldisc.write_wakeup)(tty);
      		restore_flags(flags);
      	}
      
      	wake_up_interruptible(&tty->write_wait);
      	wake_up_interruptible(&tty->read_wait);
      
      	/*
      	 * Shutdown the current line discipline, and reset it to
      	 * N_TTY.
      	 */
 487  	if (tty->driver.flags & TTY_DRIVER_RESET_TERMIOS)
      		*tty->termios = tty->driver.init_termios;
 489  	if (tty->ldisc.num != ldiscs[N_TTY].num) {
 490  		if (tty->ldisc.close)
      			(tty->ldisc.close)(tty);
      		tty->ldisc = ldiscs[N_TTY];
      		tty->termios->c_line = N_TTY;
 494  		if (tty->ldisc.open) {
      			int i = (tty->ldisc.open)(tty);
 496  			if (i < 0)
      				printk("do_tty_hangup: N_TTY open: error %d\n",
      				       -i);
      		}
      	}
      	
      	read_lock(&tasklist_lock);
 503   	for_each_task(p) {
      		if ((tty->session > 0) && (p->session == tty->session) &&
 505  		    p->leader) {
      			send_sig(SIGHUP,p,1);
      			send_sig(SIGCONT,p,1);
 508  			if (tty->pgrp > 0)
      				p->tty_old_pgrp = tty->pgrp;
      		}
 511  		if (p->tty == tty)
      			p->tty = NULL;
      	}
 514  	read_unlock(&tasklist_lock);
      
      	tty->flags = 0;
      	tty->session = 0;
      	tty->pgrp = -1;
      	tty->ctrl_status = 0;
      	/*
      	 *	If one of the devices matches a console pointer, we
      	 *	cannot just call hangup() because that will cause
      	 *	tty->count and state->count to go out of sync.
      	 *	So we just call close() the right number of times.
      	 */
 526  	if (cons_filp) {
 527  		if (tty->driver.close)
 528  			for (n = 0; n < closecount; n++)
      				tty->driver.close(tty, cons_filp);
 530  	} else if (tty->driver.hangup)
      		(tty->driver.hangup)(tty);
 532  	unlock_kernel();
      }
      
 535  void tty_hangup(struct tty_struct * tty)
      {
      #ifdef TTY_DEBUG_HANGUP
      	char	buf[64];
      	
      	printk("%s hangup...\n", tty_name(tty, buf));
      #endif
      	schedule_task(&tty->tq_hangup);
      }
      
 545  void tty_vhangup(struct tty_struct * tty)
      {
      #ifdef TTY_DEBUG_HANGUP
      	char	buf[64];
      
      	printk("%s vhangup...\n", tty_name(tty, buf));
      #endif
      	do_tty_hangup((void *) tty);
      }
      
 555  int tty_hung_up_p(struct file * filp)
      {
 557  	return (filp->f_op == &hung_up_tty_fops);
      }
      
      /*
       * This function is typically called only by the session leader, when
       * it wants to disassociate itself from its controlling tty.
       *
       * It performs the following functions:
       * 	(1)  Sends a SIGHUP and SIGCONT to the foreground process group
       * 	(2)  Clears the tty from being controlling the session
       * 	(3)  Clears the controlling tty for all processes in the
       * 		session group.
       *
       * The argument on_exit is set to 1 if called when a process is
       * exiting; it is 0 if called by the ioctl TIOCNOTTY.
       */
 573  void disassociate_ctty(int on_exit)
      {
      	struct tty_struct *tty = current->tty;
      	struct task_struct *p;
      	int tty_pgrp = -1;
      
 579  	if (tty) {
      		tty_pgrp = tty->pgrp;
 581  		if (on_exit && tty->driver.type != TTY_DRIVER_TYPE_PTY)
      			tty_vhangup(tty);
 583  	} else {
 584  		if (current->tty_old_pgrp) {
      			kill_pg(current->tty_old_pgrp, SIGHUP, on_exit);
      			kill_pg(current->tty_old_pgrp, SIGCONT, on_exit);
      		}
 588  		return;
      	}
 590  	if (tty_pgrp > 0) {
      		kill_pg(tty_pgrp, SIGHUP, on_exit);
 592  		if (!on_exit)
      			kill_pg(tty_pgrp, SIGCONT, on_exit);
      	}
      
      	current->tty_old_pgrp = 0;
      	tty->session = 0;
      	tty->pgrp = -1;
      
      	read_lock(&tasklist_lock);
 601  	for_each_task(p)
 602  	  	if (p->session == current->session)
      			p->tty = NULL;
 604  	read_unlock(&tasklist_lock);
      }
      
 607  void wait_for_keypress(void)
      {
              struct console *c = console_drivers;
 610          if (c) c->wait_key(c);
      }
      
 613  void stop_tty(struct tty_struct *tty)
      {
 615  	if (tty->stopped)
 616  		return;
      	tty->stopped = 1;
 618  	if (tty->link && tty->link->packet) {
      		tty->ctrl_status &= ~TIOCPKT_START;
      		tty->ctrl_status |= TIOCPKT_STOP;
      		wake_up_interruptible(&tty->link->read_wait);
      	}
 623  	if (tty->driver.stop)
      		(tty->driver.stop)(tty);
      }
      
 627  void start_tty(struct tty_struct *tty)
      {
 629  	if (!tty->stopped || tty->flow_stopped)
 630  		return;
      	tty->stopped = 0;
 632  	if (tty->link && tty->link->packet) {
      		tty->ctrl_status &= ~TIOCPKT_STOP;
      		tty->ctrl_status |= TIOCPKT_START;
      		wake_up_interruptible(&tty->link->read_wait);
      	}
 637  	if (tty->driver.start)
      		(tty->driver.start)(tty);
      	if ((test_bit(TTY_DO_WRITE_WAKEUP, &tty->flags)) &&
 640  	    tty->ldisc.write_wakeup)
      		(tty->ldisc.write_wakeup)(tty);
      	wake_up_interruptible(&tty->write_wait);
      }
      
 645  static ssize_t tty_read(struct file * file, char * buf, size_t count, 
      			loff_t *ppos)
      {
      	int i;
      	struct tty_struct * tty;
      	struct inode *inode;
      
      	/* Can't seek (pread) on ttys.  */
 653  	if (ppos != &file->f_pos)
 654  		return -ESPIPE;
      
      	tty = (struct tty_struct *)file->private_data;
      	inode = file->f_dentry->d_inode;
 658  	if (tty_paranoia_check(tty, inode->i_rdev, "tty_read"))
 659  		return -EIO;
 660  	if (!tty || (test_bit(TTY_IO_ERROR, &tty->flags)))
 661  		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 */
      	    (tty->pgrp > 0) &&
      	    (current->tty == tty) &&
      	    (tty->pgrp != current->pgrp))
      		if (is_ignored(SIGTTIN) || is_orphaned_pgrp(current->pgrp))
      			return -EIO;
      		else {
      			(void) kill_pg(current->pgrp, SIGTTIN, 1);
      			return -ERESTARTSYS;
      		}
      #endif
 679  	lock_kernel();
 680  	if (tty->ldisc.read)
      		i = (tty->ldisc.read)(tty,file,buf,count);
 682  	else
      		i = -EIO;
 684  	unlock_kernel();
 685  	if (i > 0)
      		inode->i_atime = CURRENT_TIME;
 687  	return i;
      }
      
      /*
       * Split writes up in sane blocksizes to avoid
       * denial-of-service type attacks
       */
 694  static inline ssize_t do_tty_write(
      	ssize_t (*write)(struct tty_struct *, struct file *, const unsigned char *, size_t),
      	struct tty_struct *tty,
      	struct file *file,
      	const unsigned char *buf,
      	size_t count)
      {
      	ssize_t ret = 0, written = 0;
      	
 703  	if (down_interruptible(&tty->atomic_write)) {
 704  		return -ERESTARTSYS;
      	}
 706  	if ( test_bit(TTY_NO_WRITE_SPLIT, &tty->flags) ) {
 707  		lock_kernel();
      		written = write(tty, file, buf, count);
 709  		unlock_kernel();
 710  	} else {
 711  		for (;;) {
      			unsigned long size = MAX(PAGE_SIZE*2,16384);
 713  			if (size > count)
      				size = count;
 715  			lock_kernel();
      			ret = write(tty, file, buf, size);
 717  			unlock_kernel();
 718  			if (ret <= 0)
 719  				break;
      			written += ret;
      			buf += ret;
      			count -= ret;
 723  			if (!count)
 724  				break;
      			ret = -ERESTARTSYS;
 726  			if (signal_pending(current))
 727  				break;
 728  			if (current->need_resched)
      				schedule();
      		}
      	}
 732  	if (written) {
      		file->f_dentry->d_inode->i_mtime = CURRENT_TIME;
      		ret = written;
      	}
      	up(&tty->atomic_write);
 737  	return ret;
      }
      
      
 741  static ssize_t tty_write(struct file * file, const char * buf, size_t count,
      			 loff_t *ppos)
      {
      	int is_console;
      	struct tty_struct * tty;
      	struct inode *inode;
      
      	/* Can't seek (pwrite) on ttys.  */
 749  	if (ppos != &file->f_pos)
 750  		return -ESPIPE;
      
      	/*
      	 *      For now, we redirect writes from /dev/console as
      	 *      well as /dev/tty0.
      	 */
      	inode = file->f_dentry->d_inode;
      	is_console = (inode->i_rdev == SYSCONS_DEV ||
      		      inode->i_rdev == CONSOLE_DEV);
      
 760  	if (is_console && redirect)
      		tty = redirect;
 762  	else
      		tty = (struct tty_struct *)file->private_data;
 764  	if (tty_paranoia_check(tty, inode->i_rdev, "tty_write"))
 765  		return -EIO;
 766  	if (!tty || !tty->driver.write || (test_bit(TTY_IO_ERROR, &tty->flags)))
 767  		return -EIO;
      #if 0
      	if (!is_console && L_TOSTOP(tty) && (tty->pgrp > 0) &&
      	    (current->tty == tty) && (tty->pgrp != current->pgrp)) {
      		if (is_orphaned_pgrp(current->pgrp))
      			return -EIO;
      		if (!is_ignored(SIGTTOU)) {
      			(void) kill_pg(current->pgrp, SIGTTOU, 1);
      			return -ERESTARTSYS;
      		}
      	}
      #endif
 779  	if (!tty->ldisc.write)
 780  		return -EIO;
      	return do_tty_write(tty->ldisc.write, tty, file,
 782  			    (const unsigned char *)buf, count);
      }
      
      /* Semaphore to protect creating and releasing a tty */
      static DECLARE_MUTEX(tty_sem);
      
 788  static void down_tty_sem(int index)
      {
      	down(&tty_sem);
      }
      
 793  static void up_tty_sem(int index)
      {
      	up(&tty_sem);
      }
      
      static void release_mem(struct tty_struct *tty, int idx);
      
      /*
       * WSH 06/09/97: Rewritten to remove races and properly clean up after a
       * failed open.  The new code protects the open with a semaphore, so it's
       * really quite straightforward.  The semaphore locking can probably be
       * relaxed for the (most common) case of reopening a tty.
       */
 806  static int init_dev(kdev_t device, struct tty_struct **ret_tty)
      {
      	struct tty_struct *tty, *o_tty;
      	struct termios *tp, **tp_loc, *o_tp, **o_tp_loc;
      	struct termios *ltp, **ltp_loc, *o_ltp, **o_ltp_loc;
      	struct tty_driver *driver;	
      	int retval=0;
      	int idx;
      
      	driver = get_tty_driver(device);
 816  	if (!driver)
 817  		return -ENODEV;
      
      	idx = MINOR(device) - driver->minor_start;
      
      	/* 
      	 * Check whether we need to acquire the tty semaphore to avoid
      	 * race conditions.  For now, play it safe.
      	 */
      	down_tty_sem(idx);
      
      	/* check whether we're reopening an existing tty */
      	tty = driver->table[idx];
 829  	if (tty) goto fast_track;
      
      	/*
      	 * First time open is complex, especially for PTY devices.
      	 * This code guarantees that either everything succeeds and the
      	 * TTY is ready for operation, or else the table slots are vacated
      	 * and the allocated memory released.  (Except that the termios 
      	 * and locked termios may be retained.)
      	 */
      
      	o_tty = NULL;
      	tp = o_tp = NULL;
      	ltp = o_ltp = NULL;
      
      	tty = alloc_tty_struct();
 844  	if(!tty)
 845  		goto fail_no_mem;
      	initialize_tty_struct(tty);
      	tty->device = device;
      	tty->driver = *driver;
      
      	tp_loc = &driver->termios[idx];
 851  	if (!*tp_loc) {
      		tp = (struct termios *) kmalloc(sizeof(struct termios),
      						GFP_KERNEL);
 854  		if (!tp)
 855  			goto free_mem_out;
      		*tp = driver->init_termios;
      	}
      
      	ltp_loc = &driver->termios_locked[idx];
 860  	if (!*ltp_loc) {
      		ltp = (struct termios *) kmalloc(sizeof(struct termios),
      						 GFP_KERNEL);
 863  		if (!ltp)
 864  			goto free_mem_out;
      		memset(ltp, 0, sizeof(struct termios));
      	}
      
 868  	if (driver->type == TTY_DRIVER_TYPE_PTY) {
      		o_tty = alloc_tty_struct();
 870  		if (!o_tty)
 871  			goto free_mem_out;
      		initialize_tty_struct(o_tty);
      		o_tty->device = (kdev_t) MKDEV(driver->other->major,
      					driver->other->minor_start + idx);
      		o_tty->driver = *driver->other;
      
      		o_tp_loc  = &driver->other->termios[idx];
 878  		if (!*o_tp_loc) {
      			o_tp = (struct termios *)
      				kmalloc(sizeof(struct termios), GFP_KERNEL);
 881  			if (!o_tp)
 882  				goto free_mem_out;
      			*o_tp = driver->other->init_termios;
      		}
      
      		o_ltp_loc = &driver->other->termios_locked[idx];
 887  		if (!*o_ltp_loc) {
      			o_ltp = (struct termios *)
      				kmalloc(sizeof(struct termios), GFP_KERNEL);
 890  			if (!o_ltp)
 891  				goto free_mem_out;
      			memset(o_ltp, 0, sizeof(struct termios));
      		}
      
      		/*
      		 * Everything allocated ... set up the o_tty structure.
      		 */
      		driver->other->table[idx] = o_tty;
 899  		if (!*o_tp_loc)
      			*o_tp_loc = o_tp;
 901  		if (!*o_ltp_loc)
      			*o_ltp_loc = o_ltp;
      		o_tty->termios = *o_tp_loc;
      		o_tty->termios_locked = *o_ltp_loc;
      		(*driver->other->refcount)++;
 906  		if (driver->subtype == PTY_TYPE_MASTER)
      			o_tty->count++;
      
      		/* Establish the links in both directions */
      		tty->link   = o_tty;
      		o_tty->link = tty;
      	}
      
      	/* 
      	 * All structures have been allocated, so now we install them.
      	 * Failures after this point use release_mem to clean up, so 
      	 * there's no need to null out the local pointers.
      	 */
      	driver->table[idx] = tty;
      	
 921  	if (!*tp_loc)
      		*tp_loc = tp;
 923  	if (!*ltp_loc)
      		*ltp_loc = ltp;
      	tty->termios = *tp_loc;
      	tty->termios_locked = *ltp_loc;
      	(*driver->refcount)++;
      	tty->count++;
      
      	/* 
      	 * Structures all installed ... call the ldisc open routines.
      	 * If we fail here just call release_mem to clean up.  No need
      	 * to decrement the use counts, as release_mem doesn't care.
      	 */
 935  	if (tty->ldisc.open) {
      		retval = (tty->ldisc.open)(tty);
 937  		if (retval)
 938  			goto release_mem_out;
      	}
 940  	if (o_tty && o_tty->ldisc.open) {
      		retval = (o_tty->ldisc.open)(o_tty);
 942  		if (retval) {
 943  			if (tty->ldisc.close)
      				(tty->ldisc.close)(tty);
 945  			goto release_mem_out;
      		}
      	}
 948  	goto success;
      
      	/*
      	 * This fast open can be used if the tty is already open.
      	 * No memory is allocated, and the only failures are from
      	 * attempting to open a closing tty or attempting multiple
      	 * opens on a pty master.
      	 */
      fast_track:
 957  	if (test_bit(TTY_CLOSING, &tty->flags)) {
      		retval = -EIO;
 959  		goto end_init;
      	}
      	if (driver->type == TTY_DRIVER_TYPE_PTY &&
 962  	    driver->subtype == PTY_TYPE_MASTER) {
      		/*
      		 * special case for PTY masters: only one open permitted, 
      		 * and the slave side open count is incremented as well.
      		 */
 967  		if (tty->count) {
      			retval = -EIO;
 969  			goto end_init;
      		}
      		tty->link->count++;
      	}
      	tty->count++;
      	tty->driver = *driver; /* N.B. why do this every time?? */
      
      success:
      	*ret_tty = tty;
      	
      	/* All paths come through here to release the semaphore */
      end_init:
      	up_tty_sem(idx);
 982  	return retval;
      
      	/* Release locally allocated memory ... nothing placed in slots */
      free_mem_out:
 986  	if (o_tp)
      		kfree(o_tp);
 988  	if (o_tty)
      		free_tty_struct(o_tty);
 990  	if (ltp)
      		kfree(ltp);
 992  	if (tp)
      		kfree(tp);
      	free_tty_struct(tty);
      
      fail_no_mem:
      	retval = -ENOMEM;
 998  	goto end_init;
      
      	/* call the tty release_mem routine to clean out this slot */
      release_mem_out:
      	printk("init_dev: ldisc open failed, clearing slot %d\n", idx);
      	release_mem(tty, idx);
1004  	goto end_init;
      }
      
      /*
       * Releases memory associated with a tty structure, and clears out the
       * driver table slots.
       */
1011  static void release_mem(struct tty_struct *tty, int idx)
      {
      	struct tty_struct *o_tty;
      	struct termios *tp;
      
1016  	if ((o_tty = tty->link) != NULL) {
      		o_tty->driver.table[idx] = NULL;
1018  		if (o_tty->driver.flags & TTY_DRIVER_RESET_TERMIOS) {
      			tp = o_tty->driver.termios[idx];
      			o_tty->driver.termios[idx] = NULL;
      			kfree(tp);
      		}
      		o_tty->magic = 0;
      		(*o_tty->driver.refcount)--;
      		free_tty_struct(o_tty);
      	}
      
      	tty->driver.table[idx] = NULL;
1029  	if (tty->driver.flags & TTY_DRIVER_RESET_TERMIOS) {
      		tp = tty->driver.termios[idx];
      		tty->driver.termios[idx] = NULL;
      		kfree(tp);
      	}
      	tty->magic = 0;
      	(*tty->driver.refcount)--;
      	free_tty_struct(tty);
      }
      
      /*
       * Even releasing the tty structures is a tricky business.. We have
       * to be very careful that the structures are all released at the
       * same time, as interrupts might otherwise get the wrong pointers.
       *
       * WSH 09/09/97: rewritten to avoid some nasty race conditions that could
       * lead to double frees or releasing memory still in use.
       */
1047  static void release_dev(struct file * filp)
      {
      	struct tty_struct *tty, *o_tty;
      	int	pty_master, tty_closing, o_tty_closing, do_sleep;
      	int	idx;
      	char	buf[64];
      	
      	tty = (struct tty_struct *)filp->private_data;
1055  	if (tty_paranoia_check(tty, filp->f_dentry->d_inode->i_rdev, "release_dev"))
1056  		return;
      
      	check_tty_count(tty, "release_dev");
      
      	tty_fasync(-1, filp, 0);
      
      	idx = MINOR(tty->device) - tty->driver.minor_start;
      	pty_master = (tty->driver.type == TTY_DRIVER_TYPE_PTY &&
      		      tty->driver.subtype == PTY_TYPE_MASTER);
      	o_tty = tty->link;
      
      #ifdef TTY_PARANOIA_CHECK
1068  	if (idx < 0 || idx >= tty->driver.num) {
      		printk("release_dev: bad idx when trying to free (%s)\n",
      		       kdevname(tty->device));
1071  		return;
      	}
1073  	if (tty != tty->driver.table[idx]) {
      		printk("release_dev: driver.table[%d] not tty for (%s)\n",
      		       idx, kdevname(tty->device));
1076  		return;
      	}
1078  	if (tty->termios != tty->driver.termios[idx]) {
      		printk("release_dev: driver.termios[%d] not termios "
      		       "for (%s)\n",
      		       idx, kdevname(tty->device));
1082  		return;
      	}
1084  	if (tty->termios_locked != tty->driver.termios_locked[idx]) {
      		printk("release_dev: driver.termios_locked[%d] not "
      		       "termios_locked for (%s)\n",
      		       idx, kdevname(tty->device));
1088  		return;
      	}
      #endif
      
      #ifdef TTY_DEBUG_HANGUP
      	printk("release_dev of %s (tty count=%d)...", tty_name(tty, buf),
      	       tty->count);
      #endif
      
      #ifdef TTY_PARANOIA_CHECK
1098  	if (tty->driver.other) {
1099  		if (o_tty != tty->driver.other->table[idx]) {
      			printk("release_dev: other->table[%d] not o_tty for ("
      			       "%s)\n",
      			       idx, kdevname(tty->device));
1103  			return;
      		}
1105  		if (o_tty->termios != tty->driver.other->termios[idx]) {
      			printk("release_dev: other->termios[%d] not o_termios "
      			       "for (%s)\n",
      			       idx, kdevname(tty->device));
1109  			return;
      		}
      		if (o_tty->termios_locked != 
1112  		      tty->driver.other->termios_locked[idx]) {
      			printk("release_dev: other->termios_locked[%d] not "
      			       "o_termios_locked for (%s)\n",
      			       idx, kdevname(tty->device));
1116  			return;
      		}
1118  		if (o_tty->link != tty) {
      			printk("release_dev: bad pty pointers\n");
1120  			return;
      		}
      	}
      #endif
      
1125  	if (tty->driver.close)
      		tty->driver.close(tty, filp);
      
      	/*
      	 * Sanity check: if tty->count is going to zero, there shouldn't be
      	 * any waiters on tty->read_wait or tty->write_wait.  We test the
      	 * wait queues and kick everyone out _before_ actually starting to
      	 * close.  This ensures that we won't block while releasing the tty
      	 * structure.
      	 *
      	 * The test for the o_tty closing is necessary, since the master and
      	 * slave sides may close in any order.  If the slave side closes out
      	 * first, its count will be one, since the master side holds an open.
      	 * Thus this test wouldn't be triggered at the time the slave closes,
      	 * so we do it now.
      	 *
      	 * Note that it's possible for the tty to be opened again while we're
      	 * flushing out waiters.  By recalculating the closing flags before
      	 * each iteration we avoid any problems.
      	 */
1145  	while (1) {
      		tty_closing = tty->count <= 1;
      		o_tty_closing = o_tty &&
      			(o_tty->count <= (pty_master ? 1 : 0));
      		do_sleep = 0;
      
1151  		if (tty_closing) {
1152  			if (waitqueue_active(&tty->read_wait)) {
      				wake_up(&tty->read_wait);
      				do_sleep++;
      			}
1156  			if (waitqueue_active(&tty->write_wait)) {
      				wake_up(&tty->write_wait);
      				do_sleep++;
      			}
      		}
1161  		if (o_tty_closing) {
1162  			if (waitqueue_active(&o_tty->read_wait)) {
      				wake_up(&o_tty->read_wait);
      				do_sleep++;
      			}
1166  			if (waitqueue_active(&o_tty->write_wait)) {
      				wake_up(&o_tty->write_wait);
      				do_sleep++;
      			}
      		}
1171  		if (!do_sleep)
1172  			break;
      
      		printk("release_dev: %s: read/write wait queue active!\n",
      		       tty_name(tty, buf));
      		schedule();
      	}	
      
      	/*
      	 * The closing flags are now consistent with the open counts on 
      	 * both sides, and we've completed the last operation that could 
      	 * block, so it's safe to proceed with closing.
      	 */
1184  	if (pty_master) {
1185  		if (--o_tty->count < 0) {
      			printk("release_dev: bad pty slave count (%d) for %s\n",
      			       o_tty->count, tty_name(o_tty, buf));
      			o_tty->count = 0;
      		}
      	}
1191  	if (--tty->count < 0) {
      		printk("release_dev: bad tty->count (%d) for %s\n",
      		       tty->count, tty_name(tty, buf));
      		tty->count = 0;
      	}
      
      	/*
      	 * We've decremented tty->count, so we should zero out
      	 * filp->private_data, to break the link between the tty and
      	 * the file descriptor.  Otherwise if filp_close() blocks before
      	 * the the file descriptor is removed from the inuse_filp
      	 * list, check_tty_count() could observe a discrepancy and
      	 * printk a warning message to the user.
      	 */
      	filp->private_data = 0;
      
      	/*
      	 * Perform some housekeeping before deciding whether to return.
      	 *
      	 * Set the TTY_CLOSING flag if this was the last open.  In the
      	 * case of a pty we may have to wait around for the other side
      	 * to close, and TTY_CLOSING makes sure we can't be reopened.
      	 */
1214  	if(tty_closing)
      		set_bit(TTY_CLOSING, &tty->flags);
1216  	if(o_tty_closing)
      		set_bit(TTY_CLOSING, &o_tty->flags);
      
      	/*
      	 * If _either_ side is closing, make sure there aren't any
      	 * processes that still think tty or o_tty is their controlling
      	 * tty.  Also, clear redirect if it points to either tty.
      	 */
1224  	if (tty_closing || o_tty_closing) {
      		struct task_struct *p;
      
      		read_lock(&tasklist_lock);
1228  		for_each_task(p) {
1229  			if (p->tty == tty || (o_tty && p->tty == o_tty))
      				p->tty = NULL;
      		}
1232  		read_unlock(&tasklist_lock);
      
1234  		if (redirect == tty || (o_tty && redirect == o_tty))
      			redirect = NULL;
      	}
      
      	/* check whether both sides are closing ... */
1239  	if (!tty_closing || (o_tty && !o_tty_closing))
1240  		return;
      	
      #ifdef TTY_DEBUG_HANGUP
      	printk("freeing tty structure...");
      #endif
      
      	/*
      	 * Shutdown the current line discipline, and reset it to N_TTY.
      	 * N.B. why reset ldisc when we're releasing the memory??
      	 */
1250  	if (tty->ldisc.close)
      		(tty->ldisc.close)(tty);
      	tty->ldisc = ldiscs[N_TTY];
      	tty->termios->c_line = N_TTY;
1254  	if (o_tty) {
1255  		if (o_tty->ldisc.close)
      			(o_tty->ldisc.close)(o_tty);
      		o_tty->ldisc = ldiscs[N_TTY];
      	}
      	
      	/*
      	 * Make sure that the tty's task queue isn't activated. 
      	 */
      	run_task_queue(&tq_timer);
      	flush_scheduled_tasks();
      
      	/* 
      	 * The release_mem function takes care of the details of clearing
      	 * the slots and preserving the termios structure.
      	 */
      	release_mem(tty, idx);
      }
      
      /*
       * tty_open and tty_release keep up the tty count that contains the
       * number of opens done on a tty. We cannot use the inode-count, as
       * different inodes might point to the same tty.
       *
       * Open-counting is needed for pty masters, as well as for keeping
       * track of serial lines: DTR is dropped when the last close happens.
       * (This is not done solely through tty->count, now.  - Ted 1/27/92)
       *
       * The termios state of a pty is reset on first open so that
       * settings don't persist across reuse.
       */
1285  static int tty_open(struct inode * inode, struct file * filp)
      {
      	struct tty_struct *tty;
      	int noctty, retval;
      	kdev_t device;
      	unsigned short saved_flags;
      	char	buf[64];
      
      	saved_flags = filp->f_flags;
      retry_open:
      	noctty = filp->f_flags & O_NOCTTY;
      	device = inode->i_rdev;
1297  	if (device == TTY_DEV) {
1298  		if (!current->tty)
1299  			return -ENXIO;
      		device = current->tty->device;
      		filp->f_flags |= O_NONBLOCK; /* Don't let /dev/tty block */
      		/* noctty = 1; */
      	}
      #ifdef CONFIG_VT
1305  	if (device == CONSOLE_DEV) {
      		extern int fg_console;
      		device = MKDEV(TTY_MAJOR, fg_console + 1);
      		noctty = 1;
      	}
      #endif
1311  	if (device == SYSCONS_DEV) {
      		struct console *c = console_drivers;
1313  		while(c && !c->device)
      			c = c->next;
1315  		if (!c)
1316                          return -ENODEV;
                      device = c->device(c);
      		filp->f_flags |= O_NONBLOCK; /* Don't let /dev/console block */
      		noctty = 1;
      	}
      
1322  	if (device == PTMX_DEV) {
      #ifdef CONFIG_UNIX98_PTYS
      
      		/* find a free pty. */
      		int major, minor;
      		struct tty_driver *driver;
      
      		/* find a device that is not in use. */
      		retval = -1;
      		for ( major = 0 ; major < UNIX98_NR_MAJORS ; major++ ) {
      			driver = &ptm_driver[major];
      			for (minor = driver->minor_start ;
      			     minor < driver->minor_start + driver->num ;
      			     minor++) {
      				device = MKDEV(driver->major, minor);
      				if (!init_dev(device, &tty)) goto ptmx_found; /* ok! */
      			}
      		}
      		return -EIO; /* no free ptys */
      	ptmx_found:
      		set_bit(TTY_PTY_LOCK, &tty->flags); /* LOCK THE SLAVE */
      		minor -= driver->minor_start;
      		devpts_pty_new(driver->other->name_base + minor, MKDEV(driver->other->major, minor + driver->other->minor_start));
      		tty_register_devfs(&pts_driver[major], DEVFS_FL_NO_PERSISTENCE,
      				   pts_driver[major].minor_start + minor);
      		noctty = 1;
      		goto init_dev_done;
      
      #else   /* CONFIG_UNIX_98_PTYS */
      
1352  		return -ENODEV;
      
      #endif  /* CONFIG_UNIX_98_PTYS */
      	}
      
      	retval = init_dev(device, &tty);
1358  	if (retval)
1359  		return retval;
      
      #ifdef CONFIG_UNIX98_PTYS
      init_dev_done:
      #endif
      	filp->private_data = tty;
      	file_move(filp, &tty->tty_files);
      	check_tty_count(tty, "tty_open");
      	if (tty->driver.type == TTY_DRIVER_TYPE_PTY &&
1368  	    tty->driver.subtype == PTY_TYPE_MASTER)
      		noctty = 1;
      #ifdef TTY_DEBUG_HANGUP
      	printk("opening %s...", tty_name(tty, buf));
      #endif
1373  	if (tty->driver.open)
      		retval = tty->driver.open(tty, filp);
1375  	else
      		retval = -ENODEV;
      	filp->f_flags = saved_flags;
      
1379  	if (!retval && test_bit(TTY_EXCLUSIVE, &tty->flags) && !suser())
      		retval = -EBUSY;
      
1382  	if (retval) {
      #ifdef TTY_DEBUG_HANGUP
      		printk("error %d in opening %s...", retval,
      		       tty_name(tty, buf));
      #endif
      
      		release_dev(filp);
1389  		if (retval != -ERESTARTSYS)
1390  			return retval;
1391  		if (signal_pending(current))
1392  			return retval;
      		schedule();
      		/*
      		 * Need to reset f_op in case a hangup happened.
      		 */
      		filp->f_op = &tty_fops;
1398  		goto retry_open;
      	}
      	if (!noctty &&
      	    current->leader &&
      	    !current->tty &&
1403  	    tty->session == 0) {
      	    	task_lock(current);
      		current->tty = tty;
      		task_unlock(current);
      		current->tty_old_pgrp = 0;
      		tty->session = current->session;
      		tty->pgrp = current->pgrp;
      	}
      	if ((tty->driver.type == TTY_DRIVER_TYPE_SERIAL) &&
      	    (tty->driver.subtype == SERIAL_TYPE_CALLOUT) &&
1413  	    (tty->count == 1)) {
      		static int nr_warns;
1415  		if (nr_warns < 5) {
      			printk(KERN_WARNING "tty_io.c: "
      				"process %d (%s) used obsolete /dev/%s - "
      				"update software to use /dev/ttyS%d\n",
      				current->pid, current->comm,
      				tty_name(tty, buf), TTY_NUMBER(tty));
      			nr_warns++;
      		}
      	}
1424  	return 0;
      }
      
1427  static int tty_release(struct inode * inode, struct file * filp)
      {
1429  	lock_kernel();
      	release_dev(filp);
1431  	unlock_kernel();
1432  	return 0;
      }
      
      /* No kernel lock held - fine */
1436  static unsigned int tty_poll(struct file * filp, poll_table * wait)
      {
      	struct tty_struct * tty;
      
      	tty = (struct tty_struct *)filp->private_data;
1441  	if (tty_paranoia_check(tty, filp->f_dentry->d_inode->i_rdev, "tty_poll"))
1442  		return 0;
      
1444  	if (tty->ldisc.poll)
1445  		return (tty->ldisc.poll)(tty, filp, wait);
1446  	return 0;
      }
      
1449  static int tty_fasync(int fd, struct file * filp, int on)
      {
      	struct tty_struct * tty;
      	int retval;
      
      	tty = (struct tty_struct *)filp->private_data;
1455  	if (tty_paranoia_check(tty, filp->f_dentry->d_inode->i_rdev, "tty_fasync"))
1456  		return 0;
      	
      	retval = fasync_helper(fd, filp, on, &tty->fasync);
1459  	if (retval <= 0)
1460  		return retval;
      
1462  	if (on) {
1463  		if (!waitqueue_active(&tty->read_wait))
      			tty->minimum_to_wake = 1;
1465  		if (filp->f_owner.pid == 0) {
      			filp->f_owner.pid = (-tty->pgrp) ? : current->pid;
      			filp->f_owner.uid = current->uid;
      			filp->f_owner.euid = current->euid;
      		}
1470  	} else {
1471  		if (!tty->fasync && !waitqueue_active(&tty->read_wait))
      			tty->minimum_to_wake = N_TTY_BUF_SIZE;
      	}
1474  	return 0;
      }
      
1477  static int tiocsti(struct tty_struct *tty, char * arg)
      {
      	char ch, mbz = 0;
      
1481  	if ((current->tty != tty) && !suser())
1482  		return -EPERM;
1483  	if (get_user(ch, arg))
1484  		return -EFAULT;
      	tty->ldisc.receive_buf(tty, &ch, &mbz, 1);
1486  	return 0;
      }
      
1489  static int tiocgwinsz(struct tty_struct *tty, struct winsize * arg)
      {
1491  	if (copy_to_user(arg, &tty->winsize, sizeof(*arg)))
1492  		return -EFAULT;
1493  	return 0;
      }
      
1496  static int tiocswinsz(struct tty_struct *tty, struct tty_struct *real_tty,
      	struct winsize * arg)
      {
      	struct winsize tmp_ws;
      
1501  	if (copy_from_user(&tmp_ws, arg, sizeof(*arg)))
1502  		return -EFAULT;
1503  	if (!memcmp(&tmp_ws, &tty->winsize, sizeof(*arg)))
1504  		return 0;
1505  	if (tty->pgrp > 0)
      		kill_pg(tty->pgrp, SIGWINCH, 1);
1507  	if ((real_tty->pgrp != tty->pgrp) && (real_tty->pgrp > 0))
      		kill_pg(real_tty->pgrp, SIGWINCH, 1);
      	tty->winsize = tmp_ws;
      	real_tty->winsize = tmp_ws;
1511  	return 0;
      }
      
1514  static int tioccons(struct inode *inode,
      	struct tty_struct *tty, struct tty_struct *real_tty)
      {
      	if (inode->i_rdev == SYSCONS_DEV ||
1518  	    inode->i_rdev == CONSOLE_DEV) {
1519  		if (!suser())
1520  			return -EPERM;
      		redirect = NULL;
1522  		return 0;
      	}
1524  	if (redirect)
1525  		return -EBUSY;
      	redirect = real_tty;
1527  	return 0;
      }
      
      
1531  static int fionbio(struct file *file, int *arg)
      {
      	int nonblock;
      
1535  	if (get_user(nonblock, arg))
1536  		return -EFAULT;
      
1538  	if (nonblock)
      		file->f_flags |= O_NONBLOCK;
1540  	else
      		file->f_flags &= ~O_NONBLOCK;
1542  	return 0;
      }
      
1545  static int tiocsctty(struct tty_struct *tty, int arg)
      {
      	if (current->leader &&
1548  	    (current->session == tty->session))
1549  		return 0;
      	/*
      	 * The process must be a session leader and
      	 * not have a controlling tty already.
      	 */
1554  	if (!current->leader || current->tty)
1555  		return -EPERM;
1556  	if (tty->session > 0) {
      		/*
      		 * This tty is already the controlling
      		 * tty for another session group!
      		 */
1561  		if ((arg == 1) && suser()) {
      			/*
      			 * Steal it away
      			 */
      			struct task_struct *p;
      
      			read_lock(&tasklist_lock);
1568  			for_each_task(p)
1569  				if (p->tty == tty)
      					p->tty = NULL;
1571  			read_unlock(&tasklist_lock);
1572  		} else
1573  			return -EPERM;
      	}
      	task_lock(current);
      	current->tty = tty;
      	task_unlock(current);
      	current->tty_old_pgrp = 0;
      	tty->session = current->session;
      	tty->pgrp = current->pgrp;
1581  	return 0;
      }
      
1584  static int tiocgpgrp(struct tty_struct *tty, struct tty_struct *real_tty, pid_t *arg)
      {
      	/*
      	 * (tty == real_tty) is a cheap way of
      	 * testing if the tty is NOT a master pty.
      	 */
1590  	if (tty == real_tty && current->tty != real_tty)
1591  		return -ENOTTY;
1592  	return put_user(real_tty->pgrp, arg);
      }
      
1595  static int tiocspgrp(struct tty_struct *tty, struct tty_struct *real_tty, pid_t *arg)
      {
      	pid_t pgrp;
      	int retval = tty_check_change(real_tty);
      
1600  	if (retval == -EIO)
1601  		return -ENOTTY;
1602  	if (retval)
1603  		return retval;
      	if (!current->tty ||
      	    (current->tty != real_tty) ||
1606  	    (real_tty->session != current->session))
1607  		return -ENOTTY;
      	get_user(pgrp, (pid_t *) arg);
1609  	if (pgrp < 0)
1610  		return -EINVAL;
1611  	if (session_of_pgrp(pgrp) != current->session)
1612  		return -EPERM;
      	real_tty->pgrp = pgrp;
1614  	return 0;
      }
      
1617  static int tiocgsid(struct tty_struct *tty, struct tty_struct *real_tty, pid_t *arg)
      {
      	/*
      	 * (tty == real_tty) is a cheap way of
      	 * testing if the tty is NOT a master pty.
      	*/
1623  	if (tty == real_tty && current->tty != real_tty)
1624  		return -ENOTTY;
1625  	if (real_tty->session <= 0)
1626  		return -ENOTTY;
1627  	return put_user(real_tty->session, arg);
      }
      
1630  static int tiocttygstruct(struct tty_struct *tty, struct tty_struct *arg)
      {
1632  	if (copy_to_user(arg, tty, sizeof(*arg)))
1633  		return -EFAULT;
1634  	return 0;
      }
      
1637  static int tiocsetd(struct tty_struct *tty, int *arg)
      {
      	int retval, ldisc;
      
      	retval = get_user(ldisc, arg);
1642  	if (retval)
1643  		return retval;
1644  	return tty_set_ldisc(tty, ldisc);
      }
      
1647  static int send_break(struct tty_struct *tty, int duration)
      {
1649  	set_current_state(TASK_INTERRUPTIBLE);
      
      	tty->driver.break_ctl(tty, -1);
1652  	if (!signal_pending(current))
      		schedule_timeout(duration);
      	tty->driver.break_ctl(tty, 0);
1655  	if (signal_pending(current))
1656  		return -EINTR;
1657  	return 0;
      }
      
      /*
       * Split this up, as gcc can choke on it otherwise..
       */
1663  int tty_ioctl(struct inode * inode, struct file * file,
      	      unsigned int cmd, unsigned long arg)
      {
      	struct tty_struct *tty, *real_tty;
      	int retval;
      	
      	tty = (struct tty_struct *)file->private_data;
1670  	if (tty_paranoia_check(tty, inode->i_rdev, "tty_ioctl"))
1671  		return -EINVAL;
      
      	real_tty = tty;
      	if (tty->driver.type == TTY_DRIVER_TYPE_PTY &&
1675  	    tty->driver.subtype == PTY_TYPE_MASTER)
      		real_tty = tty->link;
      
      	/*
      	 * Break handling by driver
      	 */
1681  	if (!tty->driver.break_ctl) {
1682  		switch(cmd) {
1683  		case TIOCSBRK:
1684  		case TIOCCBRK:
1685  			if (tty->driver.ioctl)
1686  				return tty->driver.ioctl(tty, file, cmd, arg);
1687  			return -EINVAL;
      			
      		/* These two ioctl's always return success; even if */
      		/* the driver doesn't support them. */
1691  		case TCSBRK:
1692  		case TCSBRKP:
1693  			if (!tty->driver.ioctl)
1694  				return 0;
      			retval = tty->driver.ioctl(tty, file, cmd, arg);
1696  			if (retval == -ENOIOCTLCMD)
      				retval = 0;
1698  			return retval;
      		}
      	}
      
      	/*
      	 * Factor out some common prep work
      	 */
1705  	switch (cmd) {
1706  	case TIOCSETD:
1707  	case TIOCSBRK:
1708  	case TIOCCBRK:
1709  	case TCSBRK:
1710  	case TCSBRKP:			
      		retval = tty_check_change(tty);
1712  		if (retval)
1713  			return retval;
1714  		if (cmd != TIOCCBRK) {
      			tty_wait_until_sent(tty, 0);
1716  			if (signal_pending(current))
1717  				return -EINTR;
      		}
1719  		break;
      	}
      
1722  	switch (cmd) {
1723  		case TIOCSTI:
1724  			return tiocsti(tty, (char *)arg);
1725  		case TIOCGWINSZ:
1726  			return tiocgwinsz(tty, (struct winsize *) arg);
1727  		case TIOCSWINSZ:
1728  			return tiocswinsz(tty, real_tty, (struct winsize *) arg);
1729  		case TIOCCONS:
1730  			return tioccons(inode, tty, real_tty);
1731  		case FIONBIO:
1732  			return fionbio(file, (int *) arg);
1733  		case TIOCEXCL:
      			set_bit(TTY_EXCLUSIVE, &tty->flags);
1735  			return 0;
1736  		case TIOCNXCL:
      			clear_bit(TTY_EXCLUSIVE, &tty->flags);
1738  			return 0;
1739  		case TIOCNOTTY:
1740  			if (current->tty != tty)
1741  				return -ENOTTY;
1742  			if (current->leader)
      				disassociate_ctty(0);
      			task_lock(current);
      			current->tty = NULL;
      			task_unlock(current);
1747  			return 0;
1748  		case TIOCSCTTY:
1749  			return tiocsctty(tty, arg);
1750  		case TIOCGPGRP:
1751  			return tiocgpgrp(tty, real_tty, (pid_t *) arg);
1752  		case TIOCSPGRP:
1753  			return tiocspgrp(tty, real_tty, (pid_t *) arg);
1754  		case TIOCGSID:
1755  			return tiocgsid(tty, real_tty, (pid_t *) arg);
1756  		case TIOCGETD:
1757  			return put_user(tty->ldisc.num, (int *) arg);
1758  		case TIOCSETD:
1759  			return tiocsetd(tty, (int *) arg);
      #ifdef CONFIG_VT
1761  		case TIOCLINUX:
1762  			return tioclinux(tty, arg);
      #endif
1764  		case TIOCTTYGSTRUCT:
1765  			return tiocttygstruct(tty, (struct tty_struct *) arg);
      
      		/*
      		 * Break handling
      		 */
1770  		case TIOCSBRK:	/* Turn break on, unconditionally */
      			tty->driver.break_ctl(tty, -1);
1772  			return 0;
      			
1774  		case TIOCCBRK:	/* Turn break off, unconditionally */
      			tty->driver.break_ctl(tty, 0);
1776  			return 0;
1777  		case TCSBRK:   /* SVID version: non-zero arg --> no break */
      			/*
      			 * XXX is the above comment correct, or the
      			 * code below correct?  Is this ioctl used at
      			 * all by anyone?
      			 */
1783  			if (!arg)
1784  				return send_break(tty, HZ/4);
1785  			return 0;
1786  		case TCSBRKP:	/* support for POSIX tcsendbreak() */	
1787  			return send_break(tty, arg ? arg*(HZ/10) : HZ/4);
      	}
1789  	if (tty->driver.ioctl) {
      		int retval = (tty->driver.ioctl)(tty, file, cmd, arg);
1791  		if (retval != -ENOIOCTLCMD)
1792  			return retval;
      	}
1794  	if (tty->ldisc.ioctl) {
      		int retval = (tty->ldisc.ioctl)(tty, file, cmd, arg);
1796  		if (retval != -ENOIOCTLCMD)
1797  			return retval;
      	}
1799  	return -EINVAL;
      }
      
      
      /*
       * This implements the "Secure Attention Key" ---  the idea is to
       * prevent trojan horses by killing all processes associated with this
       * tty when the user hits the "Secure Attention Key".  Required for
       * super-paranoid applications --- see the Orange Book for more details.
       * 
       * This code could be nicer; ideally it should send a HUP, wait a few
       * seconds, then send a INT, and then a KILL signal.  But you then
       * have to coordinate with the init process, since all processes associated
       * with the current tty must be dead before the new getty is allowed
       * to spawn.
       *
       * Now, if it would be correct ;-/ The current code has a nasty hole -
       * it doesn't catch files in flight. We may send the descriptor to ourselves
       * via AF_UNIX socket, close it and later fetch from socket. FIXME.
       */
1819  void do_SAK( struct tty_struct *tty)
      {
      #ifdef TTY_SOFT_SAK
      	tty_hangup(tty);
      #else
      	struct task_struct *p;
      	int session;
      	int		i;
      	struct file	*filp;
      	
1829  	if (!tty)
1830  		return;
      	session  = tty->session;
1832  	if (tty->ldisc.flush_buffer)
      		tty->ldisc.flush_buffer(tty);
1834  	if (tty->driver.flush_buffer)
      		tty->driver.flush_buffer(tty);
      	read_lock(&tasklist_lock);
1837  	for_each_task(p) {
      		if ((p->tty == tty) ||
1839  		    ((session > 0) && (p->session == session))) {
      			send_sig(SIGKILL, p, 1);
1841  			continue;
      		}
      		task_lock(p);
1844  		if (p->files) {
      			read_lock(&p->files->file_lock);
      			/* FIXME: p->files could change */
1847  			for (i=0; i < p->files->max_fds; i++) {
      				filp = fcheck_files(p->files, i);
      				if (filp && (filp->f_op == &tty_fops) &&
1850  				    (filp->private_data == tty)) {
      					send_sig(SIGKILL, p, 1);
1852  					break;
      				}
      			}
1855  			read_unlock(&p->files->file_lock);
      		}
      		task_unlock(p);
      	}
1859  	read_unlock(&tasklist_lock);
      #endif
      }
      
      /*
       * This routine is called out of the software interrupt to flush data
       * from the flip buffer to the line discipline.
       */
1867  static void flush_to_ldisc(void *private_)
      {
      	struct tty_struct *tty = (struct tty_struct *) private_;
      	unsigned char	*cp;
      	char		*fp;
      	int		count;
      	unsigned long flags;
      
1875  	if (test_bit(TTY_DONT_FLIP, &tty->flags)) {
      		queue_task(&tty->flip.tqueue, &tq_timer);
1877  		return;
      	}
1879  	if (tty->flip.buf_num) {
      		cp = tty->flip.char_buf + TTY_FLIPBUF_SIZE;
      		fp = tty->flip.flag_buf + TTY_FLIPBUF_SIZE;
      		tty->flip.buf_num = 0;
      
      		save_flags(flags); cli();
      		tty->flip.char_buf_ptr = tty->flip.char_buf;
      		tty->flip.flag_buf_ptr = tty->flip.flag_buf;
1887  	} else {
      		cp = tty->flip.char_buf;
      		fp = tty->flip.flag_buf;
      		tty->flip.buf_num = 1;
      
      		save_flags(flags); cli();
      		tty->flip.char_buf_ptr = tty->flip.char_buf + TTY_FLIPBUF_SIZE;
      		tty->flip.flag_buf_ptr = tty->flip.flag_buf + TTY_FLIPBUF_SIZE;
      	}
      	count = tty->flip.count;
      	tty->flip.count = 0;
      	restore_flags(flags);
      	
      	tty->ldisc.receive_buf(tty, cp, fp, count);
      }
      
      /*
       * Routine which returns the baud rate of the tty
       *
       * Note that the baud_table needs to be kept in sync with the
       * include/asm/termbits.h file.
       */
      static int baud_table[] = {
      	0, 50, 75, 110, 134, 150, 200, 300, 600, 1200, 1800, 2400, 4800,
      	9600, 19200, 38400, 57600, 115200, 230400, 460800,
      #ifdef __sparc__
      	76800, 153600, 307200, 614400, 921600
      #else
      	500000, 576000, 921600, 1000000, 1152000, 1500000, 2000000,
      	2500000, 3000000, 3500000, 4000000
      #endif
      };
      
      static int n_baud_table = sizeof(baud_table)/sizeof(int);
      
1922  int tty_get_baud_rate(struct tty_struct *tty)
      {
      	unsigned int cflag, i;
      
      	cflag = tty->termios->c_cflag;
      
      	i = cflag & CBAUD;
1929  	if (i & CBAUDEX) {
      		i &= ~CBAUDEX;
1931  		if (i < 1 || i+15 >= n_baud_table) 
      			tty->termios->c_cflag &= ~CBAUDEX;
1933  		else
      			i += 15;
      	}
1936  	if (i==15 && tty->alt_speed) {
1937  		if (!tty->warned) {
      			printk("Use of setserial/setrocket to set SPD_* flags is deprecated\n");
      			tty->warned = 1;
      		}
1941  		return(tty->alt_speed);
      	}
      	
1944  	return baud_table[i];
      }
      
1947  void tty_flip_buffer_push(struct tty_struct *tty)
      {
1949  	if (tty->low_latency)
      		flush_to_ldisc((void *) tty);
1951  	else
      		queue_task(&tty->flip.tqueue, &tq_timer);
      }
      
      /*
       * This subroutine initializes a tty structure.
       */
1958  static void initialize_tty_struct(struct tty_struct *tty)
      {
      	memset(tty, 0, sizeof(struct tty_struct));
      	tty->magic = TTY_MAGIC;
      	tty->ldisc = ldiscs[N_TTY];
      	tty->pgrp = -1;
      	tty->flip.char_buf_ptr = tty->flip.char_buf;
      	tty->flip.flag_buf_ptr = tty->flip.flag_buf;
      	tty->flip.tqueue.routine = flush_to_ldisc;
      	tty->flip.tqueue.data = tty;
      	init_MUTEX(&tty->flip.pty_sem);
      	init_waitqueue_head(&tty->write_wait);
      	init_waitqueue_head(&tty->read_wait);
      	tty->tq_hangup.routine = do_tty_hangup;
      	tty->tq_hangup.data = tty;
      	sema_init(&tty->atomic_read, 1);
      	sema_init(&tty->atomic_write, 1);
1975  	spin_lock_init(&tty->read_lock);
1976  	INIT_LIST_HEAD(&tty->tty_files);
      }
      
      /*
       * The default put_char routine if the driver did not define one.
       */
1982  void tty_default_put_char(struct tty_struct *tty, unsigned char ch)
      {
      	tty->driver.write(tty, 0, &ch, 1);
      }
      
      /*
       * Register a tty device described by <driver>, with minor number <minor>.
       */
1990  void tty_register_devfs (struct tty_driver *driver, unsigned int flags,
      			 unsigned int minor)
      {
      #ifdef CONFIG_DEVFS_FS
      	umode_t mode = S_IFCHR | S_IRUSR | S_IWUSR;
      	struct tty_struct tty;
      	char buf[32];
      
      	tty.driver = *driver;
      	tty.device = MKDEV (driver->major, minor);
      	switch (tty.device) {
      		case TTY_DEV:
      		case PTMX_DEV:
      			mode |= S_IRGRP | S_IWGRP | S_IROTH | S_IWOTH;
      			break;
      		default:
      			if (driver->major == PTY_MASTER_MAJOR)
      				flags |= DEVFS_FL_AUTO_OWNER;
      			break;
      	}
      	if ( (minor <  driver->minor_start) || 
      	     (minor >= driver->minor_start + driver->num) ) {
      		printk(KERN_ERR "Attempt to register invalid minor number "
      		       "with devfs (%d:%d).\n", (int)driver->major,(int)minor);
      		return;
      	}
      #  ifdef CONFIG_UNIX98_PTYS
      	if ( (driver->major >= UNIX98_PTY_SLAVE_MAJOR) &&
      	     (driver->major < UNIX98_PTY_SLAVE_MAJOR + UNIX98_NR_MAJORS) )
      		flags |= DEVFS_FL_CURRENT_OWNER;
      #  endif
      	devfs_register (NULL, tty_name (&tty, buf), flags | DEVFS_FL_DEFAULT,
      			driver->major, minor, mode, &tty_fops, NULL);
      #endif /* CONFIG_DEVFS_FS */
      }
      
2026  void tty_unregister_devfs (struct tty_driver *driver, unsigned minor)
      {
      #ifdef CONFIG_DEVFS_FS
      	void * handle;
      	struct tty_struct tty;
      	char buf[32];
      
      	tty.driver = *driver;
      	tty.device = MKDEV(driver->major, minor);
      	
      	handle = devfs_find_handle (NULL, tty_name (&tty, buf),
      				    driver->major, minor,
      				    DEVFS_SPECIAL_CHR, 0);
      	devfs_unregister (handle);
      #endif /* CONFIG_DEVFS_FS */
      }
      
      EXPORT_SYMBOL(tty_register_devfs);
      EXPORT_SYMBOL(tty_unregister_devfs);
      
      /*
       * Called by a tty driver to register itself.
       */
2049  int tty_register_driver(struct tty_driver *driver)
      {
      	int error;
              int i;
      
2054  	if (driver->flags & TTY_DRIVER_INSTALLED)
2055  		return 0;
      
      	error = devfs_register_chrdev(driver->major, driver->name, &tty_fops);
2058  	if (error < 0)
2059  		return error;
2060  	else if(driver->major == 0)
      		driver->major = error;
      
2063  	if (!driver->put_char)
      		driver->put_char = tty_default_put_char;
      	
      	driver->prev = 0;
      	driver->next = tty_drivers;
2068  	if (tty_drivers) tty_drivers->prev = driver;
      	tty_drivers = driver;
      	
2071  	if ( !(driver->flags & TTY_DRIVER_NO_DEVFS) ) {
2072  		for(i = 0; i < driver->num; i++)
      		    tty_register_devfs(driver, 0, driver->minor_start + i);
      	}
      	proc_tty_register_driver(driver);
2076  	return error;
      }
      
      /*
       * Called by a tty driver to unregister itself.
       */
2082  int tty_unregister_driver(struct tty_driver *driver)
      {
      	int	retval;
      	struct tty_driver *p;
      	int	i, found = 0;
      	struct termios *tp;
      	const char *othername = NULL;
      	
2090  	if (*driver->refcount)
2091  		return -EBUSY;
      
2093  	for (p = tty_drivers; p; p = p->next) {
2094  		if (p == driver)
      			found++;
2096  		else if (p->major == driver->major)
      			othername = p->name;
      	}
      	
2100  	if (!found)
2101  		return -ENOENT;
      
2103  	if (othername == NULL) {
      		retval = devfs_unregister_chrdev(driver->major, driver->name);
2105  		if (retval)
2106  			return retval;
2107  	} else
      		devfs_register_chrdev(driver->major, othername, &tty_fops);
      
2110  	if (driver->prev)
      		driver->prev->next = driver->next;
2112  	else
      		tty_drivers = driver->next;
      	
2115  	if (driver->next)
      		driver->next->prev = driver->prev;
      
      	/*
      	 * Free the termios and termios_locked structures because
      	 * we don't want to get memory leaks when modular tty
      	 * drivers are removed from the kernel.
      	 */
2123  	for (i = 0; i < driver->num; i++) {
      		tp = driver->termios[i];
2125  		if (tp) {
      			driver->termios[i] = NULL;
      			kfree(tp);
      		}
      		tp = driver->termios_locked[i];
2130  		if (tp) {
      			driver->termios_locked[i] = NULL;
      			kfree(tp);
      		}
      		tty_unregister_devfs(driver, driver->minor_start + i);
      	}
      	proc_tty_unregister_driver(driver);
2137  	return 0;
      }
      
      
      /*
       * Initialize the console device. This is called *early*, so
       * we can't necessarily depend on lots of kernel help here.
       * Just do some early initializations, and do the complex setup
       * later.
       */
2147  void __init console_init(void)
      {
      	/* Setup the default TTY line discipline. */
      	memset(ldiscs, 0, sizeof(ldiscs));
      	(void) tty_register_ldisc(N_TTY, &tty_ldisc_N_TTY);
      
      	/*
      	 * Set up the standard termios.  Individual tty drivers may 
      	 * deviate from this; this is used as a template.
      	 */
      	memset(&tty_std_termios, 0, sizeof(struct termios));
      	memcpy(tty_std_termios.c_cc, INIT_C_CC, NCCS);
      	tty_std_termios.c_iflag = ICRNL | IXON;
      	tty_std_termios.c_oflag = OPOST | ONLCR;
      	tty_std_termios.c_cflag = B38400 | CS8 | CREAD | HUPCL;
      	tty_std_termios.c_lflag = ISIG | ICANON | ECHO | ECHOE | ECHOK |
      		ECHOCTL | ECHOKE | IEXTEN;
      
      	/*
      	 * set up the console device so that later boot sequences can 
      	 * inform about problems etc..
      	 */
      #ifdef CONFIG_VT
      	con_init();
      #endif
      #ifdef CONFIG_SERIAL_CONSOLE
      #if (defined(CONFIG_8xx) || defined(CONFIG_8260))
      	console_8xx_init();
      #elif defined(CONFIG_SERIAL)
      	serial_console_init();
      #endif /* CONFIG_8xx */
      #ifdef CONFIG_SGI_SERIAL
      	sgi_serial_console_init();
      #endif
      #if defined(CONFIG_MVME162_SCC) || defined(CONFIG_BVME6000_SCC) || defined(CONFIG_MVME147_SCC)
      	vme_scc_console_init();
      #endif
      #if defined(CONFIG_SERIAL167)
      	serial167_console_init();
      #endif
      #if defined(CONFIG_SH_SCI)
      	sci_console_init();
      #endif
      #endif
      #ifdef CONFIG_3215
              con3215_init();
      #endif
      #ifdef CONFIG_HWC
              hwc_console_init();
      #endif
      #ifdef CONFIG_SERIAL_21285_CONSOLE
      	rs285_console_init();
      #endif
      #ifdef CONFIG_SERIAL_SA1100_CONSOLE
      	sa1100_rs_console_init();
      #endif
      #ifdef CONFIG_SERIAL_AMBA_CONSOLE
      	ambauart_console_init();
      #endif
      }
      
      static struct tty_driver dev_tty_driver, dev_syscons_driver;
      #ifdef CONFIG_UNIX98_PTYS
      static struct tty_driver dev_ptmx_driver;
      #endif
      #ifdef CONFIG_VT
      static struct tty_driver dev_console_driver;
      #endif
      
      /*
       * Ok, now we can initialize the rest of the tty devices and can count
       * on memory allocations, interrupts etc..
       */
2220  void __init tty_init(void)
      {
2222  	if (sizeof(struct tty_struct) > PAGE_SIZE)
      		panic("size of tty structure > PAGE_SIZE!");
      
      	/*
      	 * dev_tty_driver and dev_console_driver are actually magic
      	 * devices which get redirected at open time.  Nevertheless,
      	 * we register them so that register_chrdev is called
      	 * appropriately.
      	 */
      	memset(&dev_tty_driver, 0, sizeof(struct tty_driver));
      	dev_tty_driver.magic = TTY_DRIVER_MAGIC;
      	dev_tty_driver.driver_name = "/dev/tty";
      	dev_tty_driver.name = dev_tty_driver.driver_name + 5;
      	dev_tty_driver.name_base = 0;
      	dev_tty_driver.major = TTYAUX_MAJOR;
      	dev_tty_driver.minor_start = 0;
      	dev_tty_driver.num = 1;
      	dev_tty_driver.type = TTY_DRIVER_TYPE_SYSTEM;
      	dev_tty_driver.subtype = SYSTEM_TYPE_TTY;
      	
2242  	if (tty_register_driver(&dev_tty_driver))
      		panic("Couldn't register /dev/tty driver\n");
      
      	dev_syscons_driver = dev_tty_driver;
      	dev_syscons_driver.driver_name = "/dev/console";
      	dev_syscons_driver.name = dev_syscons_driver.driver_name + 5;
      	dev_syscons_driver.major = TTYAUX_MAJOR;
      	dev_syscons_driver.minor_start = 1;
      	dev_syscons_driver.type = TTY_DRIVER_TYPE_SYSTEM;
      	dev_syscons_driver.subtype = SYSTEM_TYPE_SYSCONS;
      
2253  	if (tty_register_driver(&dev_syscons_driver))
      		panic("Couldn't register /dev/console driver\n");
      
      	/* console calls tty_register_driver() before kmalloc() works.
      	 * Thus, we can't devfs_register() then.  Do so now, instead. 
      	 */
      #ifdef CONFIG_VT
      	con_init_devfs();
      #endif
      
      #ifdef CONFIG_UNIX98_PTYS
      	dev_ptmx_driver = dev_tty_driver;
      	dev_ptmx_driver.driver_name = "/dev/ptmx";
      	dev_ptmx_driver.name = dev_ptmx_driver.driver_name + 5;
      	dev_ptmx_driver.major= MAJOR(PTMX_DEV);
      	dev_ptmx_driver.minor_start = MINOR(PTMX_DEV);
      	dev_ptmx_driver.type = TTY_DRIVER_TYPE_SYSTEM;
      	dev_ptmx_driver.subtype = SYSTEM_TYPE_SYSPTMX;
      
      	if (tty_register_driver(&dev_ptmx_driver))
      		panic("Couldn't register /dev/ptmx driver\n");
      #endif
      	
      #ifdef CONFIG_VT
      	dev_console_driver = dev_tty_driver;
      	dev_console_driver.driver_name = "/dev/vc/0";
      	dev_console_driver.name = dev_console_driver.driver_name + 5;
      	dev_console_driver.major = TTY_MAJOR;
      	dev_console_driver.type = TTY_DRIVER_TYPE_SYSTEM;
      	dev_console_driver.subtype = SYSTEM_TYPE_CONSOLE;
      
2284  	if (tty_register_driver(&dev_console_driver))
      		panic("Couldn't register /dev/tty0 driver\n");
      
      	kbd_init();
      #endif
      #ifdef CONFIG_ESPSERIAL  /* init ESP before rs, so rs doesn't see the port */
      	espserial_init();
      #endif
      #if defined(CONFIG_MVME162_SCC) || defined(CONFIG_BVME6000_SCC) || defined(CONFIG_MVME147_SCC)
      	vme_scc_init();
      #endif
      #ifdef CONFIG_COMPUTONE
      	ip2_init();
      #endif
      #ifdef CONFIG_MAC_SERIAL
      	macserial_init();
      #endif
      #ifdef CONFIG_ROCKETPORT
      	rp_init();
      #endif
      #ifdef CONFIG_SERIAL167
      	serial167_init();
      #endif
      #ifdef CONFIG_CYCLADES
      	cy_init();
      #endif
      #ifdef CONFIG_STALLION
      	stl_init();
      #endif
      #ifdef CONFIG_ISTALLION
      	stli_init();
      #endif
      #ifdef CONFIG_DIGI
      	pcxe_init();
      #endif
      #ifdef CONFIG_DIGIEPCA
      	pc_init();
      #endif
      #ifdef CONFIG_SPECIALIX
      	specialix_init();
      #endif
      #ifdef CONFIG_RIO
      	rio_init();
      #endif
      #if (defined(CONFIG_8xx) || defined(CONFIG_8260))
      	rs_8xx_init();
      #endif /* CONFIG_8xx */
      	pty_init();
      #ifdef CONFIG_MOXA_SMARTIO
      	mxser_init();
      #endif	
      #ifdef CONFIG_MOXA_INTELLIO
      	moxa_init();
      #endif	
      #ifdef CONFIG_VT
      	vcs_init();
      #endif
      }