ia64/xen-unstable

changeset 12733:d5d8aeb4fa34

[LINUX] The removal of the console_use_vt hack was premature: it's still
required if CONFIG_VT is enabled but the domain isn't currently
configured to use the PV framebuffer. Put it back in, in a slightly
more palatable form.

Signed-off-by: Steven Smith <sos22@cam.ac.uk>
author Steven Smith <ssmith@xensource.com>
date Fri Dec 01 11:52:33 2006 +0000 (2006-12-01)
parents 000609d8c93f
children 0536dbde1562
files linux-2.6-xen-sparse/arch/i386/kernel/setup-xen.c linux-2.6-xen-sparse/arch/ia64/kernel/setup.c linux-2.6-xen-sparse/arch/x86_64/kernel/setup-xen.c linux-2.6-xen-sparse/drivers/char/tty_io.c linux-2.6-xen-sparse/drivers/xen/console/console.c linux-2.6-xen-sparse/include/xen/xencons.h
line diff
     1.1 --- a/linux-2.6-xen-sparse/arch/i386/kernel/setup-xen.c	Fri Dec 01 11:49:30 2006 +0000
     1.2 +++ b/linux-2.6-xen-sparse/arch/i386/kernel/setup-xen.c	Fri Dec 01 11:52:33 2006 +0000
     1.3 @@ -1871,6 +1871,7 @@ void __init setup_arch(char **cmdline_p)
     1.4  		conswitchp = &dummy_con;
     1.5  #endif
     1.6  	}
     1.7 +	xencons_early_setup();
     1.8  }
     1.9  
    1.10  static int
     2.1 --- a/linux-2.6-xen-sparse/arch/ia64/kernel/setup.c	Fri Dec 01 11:49:30 2006 +0000
     2.2 +++ b/linux-2.6-xen-sparse/arch/ia64/kernel/setup.c	Fri Dec 01 11:52:33 2006 +0000
     2.3 @@ -555,9 +555,11 @@ setup_arch (char **cmdline_p)
     2.4  #endif
     2.5  		}
     2.6  	}
     2.7 +	xencons_early_setup();
     2.8  #endif
     2.9  #endif
    2.10  
    2.11 +
    2.12  	/* enable IA-64 Machine Check Abort Handling unless disabled */
    2.13  	if (!strstr(saved_command_line, "nomca"))
    2.14  		ia64_mca_init();
     3.1 --- a/linux-2.6-xen-sparse/arch/x86_64/kernel/setup-xen.c	Fri Dec 01 11:49:30 2006 +0000
     3.2 +++ b/linux-2.6-xen-sparse/arch/x86_64/kernel/setup-xen.c	Fri Dec 01 11:52:33 2006 +0000
     3.3 @@ -984,10 +984,11 @@ void __init setup_arch(char **cmdline_p)
     3.4  #endif
     3.5  		} else {
     3.6  #if defined(CONFIG_VT) && defined(CONFIG_DUMMY_CONSOLE)
     3.7 -                    conswitchp = &dummy_con;
     3.8 +			conswitchp = &dummy_con;
     3.9  #endif
    3.10                  }
    3.11  	}
    3.12 +	xencons_early_setup();
    3.13  #else	/* CONFIG_XEN */
    3.14  
    3.15  #ifdef CONFIG_VT
     4.1 --- /dev/null	Thu Jan 01 00:00:00 1970 +0000
     4.2 +++ b/linux-2.6-xen-sparse/drivers/char/tty_io.c	Fri Dec 01 11:52:33 2006 +0000
     4.3 @@ -0,0 +1,3264 @@
     4.4 +/*
     4.5 + *  linux/drivers/char/tty_io.c
     4.6 + *
     4.7 + *  Copyright (C) 1991, 1992  Linus Torvalds
     4.8 + */
     4.9 +
    4.10 +/*
    4.11 + * 'tty_io.c' gives an orthogonal feeling to tty's, be they consoles
    4.12 + * or rs-channels. It also implements echoing, cooked mode etc.
    4.13 + *
    4.14 + * Kill-line thanks to John T Kohl, who also corrected VMIN = VTIME = 0.
    4.15 + *
    4.16 + * Modified by Theodore Ts'o, 9/14/92, to dynamically allocate the
    4.17 + * tty_struct and tty_queue structures.  Previously there was an array
    4.18 + * of 256 tty_struct's which was statically allocated, and the
    4.19 + * tty_queue structures were allocated at boot time.  Both are now
    4.20 + * dynamically allocated only when the tty is open.
    4.21 + *
    4.22 + * Also restructured routines so that there is more of a separation
    4.23 + * between the high-level tty routines (tty_io.c and tty_ioctl.c) and
    4.24 + * the low-level tty routines (serial.c, pty.c, console.c).  This
    4.25 + * makes for cleaner and more compact code.  -TYT, 9/17/92 
    4.26 + *
    4.27 + * Modified by Fred N. van Kempen, 01/29/93, to add line disciplines
    4.28 + * which can be dynamically activated and de-activated by the line
    4.29 + * discipline handling modules (like SLIP).
    4.30 + *
    4.31 + * NOTE: pay no attention to the line discipline code (yet); its
    4.32 + * interface is still subject to change in this version...
    4.33 + * -- TYT, 1/31/92
    4.34 + *
    4.35 + * Added functionality to the OPOST tty handling.  No delays, but all
    4.36 + * other bits should be there.
    4.37 + *	-- Nick Holloway <alfie@dcs.warwick.ac.uk>, 27th May 1993.
    4.38 + *
    4.39 + * Rewrote canonical mode and added more termios flags.
    4.40 + * 	-- julian@uhunix.uhcc.hawaii.edu (J. Cowley), 13Jan94
    4.41 + *
    4.42 + * Reorganized FASYNC support so mouse code can share it.
    4.43 + *	-- ctm@ardi.com, 9Sep95
    4.44 + *
    4.45 + * New TIOCLINUX variants added.
    4.46 + *	-- mj@k332.feld.cvut.cz, 19-Nov-95
    4.47 + * 
    4.48 + * Restrict vt switching via ioctl()
    4.49 + *      -- grif@cs.ucr.edu, 5-Dec-95
    4.50 + *
    4.51 + * Move console and virtual terminal code to more appropriate files,
    4.52 + * implement CONFIG_VT and generalize console device interface.
    4.53 + *	-- Marko Kohtala <Marko.Kohtala@hut.fi>, March 97
    4.54 + *
    4.55 + * Rewrote init_dev and release_dev to eliminate races.
    4.56 + *	-- Bill Hawes <whawes@star.net>, June 97
    4.57 + *
    4.58 + * Added devfs support.
    4.59 + *      -- C. Scott Ananian <cananian@alumni.princeton.edu>, 13-Jan-1998
    4.60 + *
    4.61 + * Added support for a Unix98-style ptmx device.
    4.62 + *      -- C. Scott Ananian <cananian@alumni.princeton.edu>, 14-Jan-1998
    4.63 + *
    4.64 + * Reduced memory usage for older ARM systems
    4.65 + *      -- Russell King <rmk@arm.linux.org.uk>
    4.66 + *
    4.67 + * Move do_SAK() into process context.  Less stack use in devfs functions.
    4.68 + * alloc_tty_struct() always uses kmalloc() -- Andrew Morton <andrewm@uow.edu.eu> 17Mar01
    4.69 + */
    4.70 +
    4.71 +#include <linux/config.h>
    4.72 +#include <linux/types.h>
    4.73 +#include <linux/major.h>
    4.74 +#include <linux/errno.h>
    4.75 +#include <linux/signal.h>
    4.76 +#include <linux/fcntl.h>
    4.77 +#include <linux/sched.h>
    4.78 +#include <linux/interrupt.h>
    4.79 +#include <linux/tty.h>
    4.80 +#include <linux/tty_driver.h>
    4.81 +#include <linux/tty_flip.h>
    4.82 +#include <linux/devpts_fs.h>
    4.83 +#include <linux/file.h>
    4.84 +#include <linux/console.h>
    4.85 +#include <linux/timer.h>
    4.86 +#include <linux/ctype.h>
    4.87 +#include <linux/kd.h>
    4.88 +#include <linux/mm.h>
    4.89 +#include <linux/string.h>
    4.90 +#include <linux/slab.h>
    4.91 +#include <linux/poll.h>
    4.92 +#include <linux/proc_fs.h>
    4.93 +#include <linux/init.h>
    4.94 +#include <linux/module.h>
    4.95 +#include <linux/smp_lock.h>
    4.96 +#include <linux/device.h>
    4.97 +#include <linux/idr.h>
    4.98 +#include <linux/wait.h>
    4.99 +#include <linux/bitops.h>
   4.100 +#include <linux/delay.h>
   4.101 +
   4.102 +#include <asm/uaccess.h>
   4.103 +#include <asm/system.h>
   4.104 +
   4.105 +#include <linux/kbd_kern.h>
   4.106 +#include <linux/vt_kern.h>
   4.107 +#include <linux/selection.h>
   4.108 +#include <linux/devfs_fs_kernel.h>
   4.109 +
   4.110 +#include <linux/kmod.h>
   4.111 +
   4.112 +#undef TTY_DEBUG_HANGUP
   4.113 +
   4.114 +#define TTY_PARANOIA_CHECK 1
   4.115 +#define CHECK_TTY_COUNT 1
   4.116 +
   4.117 +struct termios tty_std_termios = {	/* for the benefit of tty drivers  */
   4.118 +	.c_iflag = ICRNL | IXON,
   4.119 +	.c_oflag = OPOST | ONLCR,
   4.120 +	.c_cflag = B38400 | CS8 | CREAD | HUPCL,
   4.121 +	.c_lflag = ISIG | ICANON | ECHO | ECHOE | ECHOK |
   4.122 +		   ECHOCTL | ECHOKE | IEXTEN,
   4.123 +	.c_cc = INIT_C_CC
   4.124 +};
   4.125 +
   4.126 +EXPORT_SYMBOL(tty_std_termios);
   4.127 +
   4.128 +/* This list gets poked at by procfs and various bits of boot up code. This
   4.129 +   could do with some rationalisation such as pulling the tty proc function
   4.130 +   into this file */
   4.131 +   
   4.132 +LIST_HEAD(tty_drivers);			/* linked list of tty drivers */
   4.133 +
   4.134 +/* Semaphore to protect creating and releasing a tty. This is shared with
   4.135 +   vt.c for deeply disgusting hack reasons */
   4.136 +DECLARE_MUTEX(tty_sem);
   4.137 +
   4.138 +int console_use_vt = 1;
   4.139 +
   4.140 +#ifdef CONFIG_UNIX98_PTYS
   4.141 +extern struct tty_driver *ptm_driver;	/* Unix98 pty masters; for /dev/ptmx */
   4.142 +extern int pty_limit;		/* Config limit on Unix98 ptys */
   4.143 +static DEFINE_IDR(allocated_ptys);
   4.144 +static DECLARE_MUTEX(allocated_ptys_lock);
   4.145 +static int ptmx_open(struct inode *, struct file *);
   4.146 +#endif
   4.147 +
   4.148 +extern void disable_early_printk(void);
   4.149 +
   4.150 +static void initialize_tty_struct(struct tty_struct *tty);
   4.151 +
   4.152 +static ssize_t tty_read(struct file *, char __user *, size_t, loff_t *);
   4.153 +static ssize_t tty_write(struct file *, const char __user *, size_t, loff_t *);
   4.154 +ssize_t redirected_tty_write(struct file *, const char __user *, size_t, loff_t *);
   4.155 +static unsigned int tty_poll(struct file *, poll_table *);
   4.156 +static int tty_open(struct inode *, struct file *);
   4.157 +static int tty_release(struct inode *, struct file *);
   4.158 +int tty_ioctl(struct inode * inode, struct file * file,
   4.159 +	      unsigned int cmd, unsigned long arg);
   4.160 +static int tty_fasync(int fd, struct file * filp, int on);
   4.161 +static void release_mem(struct tty_struct *tty, int idx);
   4.162 +
   4.163 +
   4.164 +static struct tty_struct *alloc_tty_struct(void)
   4.165 +{
   4.166 +	struct tty_struct *tty;
   4.167 +
   4.168 +	tty = kmalloc(sizeof(struct tty_struct), GFP_KERNEL);
   4.169 +	if (tty)
   4.170 +		memset(tty, 0, sizeof(struct tty_struct));
   4.171 +	return tty;
   4.172 +}
   4.173 +
   4.174 +static void tty_buffer_free_all(struct tty_struct *);
   4.175 +
   4.176 +static inline void free_tty_struct(struct tty_struct *tty)
   4.177 +{
   4.178 +	kfree(tty->write_buf);
   4.179 +	tty_buffer_free_all(tty);
   4.180 +	kfree(tty);
   4.181 +}
   4.182 +
   4.183 +#define TTY_NUMBER(tty) ((tty)->index + (tty)->driver->name_base)
   4.184 +
   4.185 +char *tty_name(struct tty_struct *tty, char *buf)
   4.186 +{
   4.187 +	if (!tty) /* Hmm.  NULL pointer.  That's fun. */
   4.188 +		strcpy(buf, "NULL tty");
   4.189 +	else
   4.190 +		strcpy(buf, tty->name);
   4.191 +	return buf;
   4.192 +}
   4.193 +
   4.194 +EXPORT_SYMBOL(tty_name);
   4.195 +
   4.196 +int tty_paranoia_check(struct tty_struct *tty, struct inode *inode,
   4.197 +			      const char *routine)
   4.198 +{
   4.199 +#ifdef TTY_PARANOIA_CHECK
   4.200 +	if (!tty) {
   4.201 +		printk(KERN_WARNING
   4.202 +			"null TTY for (%d:%d) in %s\n",
   4.203 +			imajor(inode), iminor(inode), routine);
   4.204 +		return 1;
   4.205 +	}
   4.206 +	if (tty->magic != TTY_MAGIC) {
   4.207 +		printk(KERN_WARNING
   4.208 +			"bad magic number for tty struct (%d:%d) in %s\n",
   4.209 +			imajor(inode), iminor(inode), routine);
   4.210 +		return 1;
   4.211 +	}
   4.212 +#endif
   4.213 +	return 0;
   4.214 +}
   4.215 +
   4.216 +static int check_tty_count(struct tty_struct *tty, const char *routine)
   4.217 +{
   4.218 +#ifdef CHECK_TTY_COUNT
   4.219 +	struct list_head *p;
   4.220 +	int count = 0;
   4.221 +	
   4.222 +	file_list_lock();
   4.223 +	list_for_each(p, &tty->tty_files) {
   4.224 +		count++;
   4.225 +	}
   4.226 +	file_list_unlock();
   4.227 +	if (tty->driver->type == TTY_DRIVER_TYPE_PTY &&
   4.228 +	    tty->driver->subtype == PTY_TYPE_SLAVE &&
   4.229 +	    tty->link && tty->link->count)
   4.230 +		count++;
   4.231 +	if (tty->count != count) {
   4.232 +		printk(KERN_WARNING "Warning: dev (%s) tty->count(%d) "
   4.233 +				    "!= #fd's(%d) in %s\n",
   4.234 +		       tty->name, tty->count, count, routine);
   4.235 +		return count;
   4.236 +       }	
   4.237 +#endif
   4.238 +	return 0;
   4.239 +}
   4.240 +
   4.241 +/*
   4.242 + * Tty buffer allocation management
   4.243 + */
   4.244 +
   4.245 +static void tty_buffer_free_all(struct tty_struct *tty)
   4.246 +{
   4.247 +	struct tty_buffer *thead;
   4.248 +	while((thead = tty->buf.head) != NULL) {
   4.249 +		tty->buf.head = thead->next;
   4.250 +		kfree(thead);
   4.251 +	}
   4.252 +	while((thead = tty->buf.free) != NULL) {
   4.253 +		tty->buf.free = thead->next;
   4.254 +		kfree(thead);
   4.255 +	}
   4.256 +	tty->buf.tail = NULL;
   4.257 +}
   4.258 +
   4.259 +static void tty_buffer_init(struct tty_struct *tty)
   4.260 +{
   4.261 +	spin_lock_init(&tty->buf.lock);
   4.262 +	tty->buf.head = NULL;
   4.263 +	tty->buf.tail = NULL;
   4.264 +	tty->buf.free = NULL;
   4.265 +}
   4.266 +
   4.267 +static struct tty_buffer *tty_buffer_alloc(size_t size)
   4.268 +{
   4.269 +	struct tty_buffer *p = kmalloc(sizeof(struct tty_buffer) + 2 * size, GFP_ATOMIC);
   4.270 +	if(p == NULL)
   4.271 +		return NULL;
   4.272 +	p->used = 0;
   4.273 +	p->size = size;
   4.274 +	p->next = NULL;
   4.275 +	p->active = 0;
   4.276 +	p->commit = 0;
   4.277 +	p->read = 0;
   4.278 +	p->char_buf_ptr = (char *)(p->data);
   4.279 +	p->flag_buf_ptr = (unsigned char *)p->char_buf_ptr + size;
   4.280 +/* 	printk("Flip create %p\n", p); */
   4.281 +	return p;
   4.282 +}
   4.283 +
   4.284 +/* Must be called with the tty_read lock held. This needs to acquire strategy
   4.285 +   code to decide if we should kfree or relink a given expired buffer */
   4.286 +
   4.287 +static void tty_buffer_free(struct tty_struct *tty, struct tty_buffer *b)
   4.288 +{
   4.289 +	/* Dumb strategy for now - should keep some stats */
   4.290 +/* 	printk("Flip dispose %p\n", b); */
   4.291 +	if(b->size >= 512)
   4.292 +		kfree(b);
   4.293 +	else {
   4.294 +		b->next = tty->buf.free;
   4.295 +		tty->buf.free = b;
   4.296 +	}
   4.297 +}
   4.298 +
   4.299 +static struct tty_buffer *tty_buffer_find(struct tty_struct *tty, size_t size)
   4.300 +{
   4.301 +	struct tty_buffer **tbh = &tty->buf.free;
   4.302 +	while((*tbh) != NULL) {
   4.303 +		struct tty_buffer *t = *tbh;
   4.304 +		if(t->size >= size) {
   4.305 +			*tbh = t->next;
   4.306 +			t->next = NULL;
   4.307 +			t->used = 0;
   4.308 +			t->commit = 0;
   4.309 +			t->read = 0;
   4.310 +			/* DEBUG ONLY */
   4.311 +/*			memset(t->data, '*', size); */
   4.312 +/* 			printk("Flip recycle %p\n", t); */
   4.313 +			return t;
   4.314 +		}
   4.315 +		tbh = &((*tbh)->next);
   4.316 +	}
   4.317 +	/* Round the buffer size out */
   4.318 +	size = (size + 0xFF) & ~ 0xFF;
   4.319 +	return tty_buffer_alloc(size);
   4.320 +	/* Should possibly check if this fails for the largest buffer we
   4.321 +	   have queued and recycle that ? */
   4.322 +}
   4.323 +
   4.324 +int tty_buffer_request_room(struct tty_struct *tty, size_t size)
   4.325 +{
   4.326 +	struct tty_buffer *b, *n;
   4.327 +	int left;
   4.328 +	unsigned long flags;
   4.329 +
   4.330 +	spin_lock_irqsave(&tty->buf.lock, flags);
   4.331 +
   4.332 +	/* OPTIMISATION: We could keep a per tty "zero" sized buffer to
   4.333 +	   remove this conditional if its worth it. This would be invisible
   4.334 +	   to the callers */
   4.335 +	if ((b = tty->buf.tail) != NULL) {
   4.336 +		left = b->size - b->used;
   4.337 +		b->active = 1;
   4.338 +	} else
   4.339 +		left = 0;
   4.340 +
   4.341 +	if (left < size) {
   4.342 +		/* This is the slow path - looking for new buffers to use */
   4.343 +		if ((n = tty_buffer_find(tty, size)) != NULL) {
   4.344 +			if (b != NULL) {
   4.345 +				b->next = n;
   4.346 +				b->active = 0;
   4.347 +				b->commit = b->used;
   4.348 +			} else
   4.349 +				tty->buf.head = n;
   4.350 +			tty->buf.tail = n;
   4.351 +			n->active = 1;
   4.352 +		} else
   4.353 +			size = left;
   4.354 +	}
   4.355 +
   4.356 +	spin_unlock_irqrestore(&tty->buf.lock, flags);
   4.357 +	return size;
   4.358 +}
   4.359 +
   4.360 +EXPORT_SYMBOL_GPL(tty_buffer_request_room);
   4.361 +
   4.362 +int tty_insert_flip_string(struct tty_struct *tty, unsigned char *chars, size_t size)
   4.363 +{
   4.364 +	int copied = 0;
   4.365 +	do {
   4.366 +		int space = tty_buffer_request_room(tty, size - copied);
   4.367 +		struct tty_buffer *tb = tty->buf.tail;
   4.368 +		/* If there is no space then tb may be NULL */
   4.369 +		if(unlikely(space == 0))
   4.370 +			break;
   4.371 +		memcpy(tb->char_buf_ptr + tb->used, chars, space);
   4.372 +		memset(tb->flag_buf_ptr + tb->used, TTY_NORMAL, space);
   4.373 +		tb->used += space;
   4.374 +		copied += space;
   4.375 +		chars += space;
   4.376 +/* 		printk("Flip insert %d.\n", space); */
   4.377 +	}
   4.378 +	/* There is a small chance that we need to split the data over
   4.379 +	   several buffers. If this is the case we must loop */
   4.380 +	while (unlikely(size > copied));
   4.381 +	return copied;
   4.382 +}
   4.383 +
   4.384 +EXPORT_SYMBOL_GPL(tty_insert_flip_string);
   4.385 +
   4.386 +int tty_insert_flip_string_flags(struct tty_struct *tty, unsigned char *chars, char *flags, size_t size)
   4.387 +{
   4.388 +	int copied = 0;
   4.389 +	do {
   4.390 +		int space = tty_buffer_request_room(tty, size - copied);
   4.391 +		struct tty_buffer *tb = tty->buf.tail;
   4.392 +		/* If there is no space then tb may be NULL */
   4.393 +		if(unlikely(space == 0))
   4.394 +			break;
   4.395 +		memcpy(tb->char_buf_ptr + tb->used, chars, space);
   4.396 +		memcpy(tb->flag_buf_ptr + tb->used, flags, space);
   4.397 +		tb->used += space;
   4.398 +		copied += space;
   4.399 +		chars += space;
   4.400 +		flags += space;
   4.401 +	}
   4.402 +	/* There is a small chance that we need to split the data over
   4.403 +	   several buffers. If this is the case we must loop */
   4.404 +	while (unlikely(size > copied));
   4.405 +	return copied;
   4.406 +}
   4.407 +
   4.408 +EXPORT_SYMBOL_GPL(tty_insert_flip_string_flags);
   4.409 +
   4.410 +
   4.411 +/*
   4.412 + *	Prepare a block of space in the buffer for data. Returns the length
   4.413 + *	available and buffer pointer to the space which is now allocated and
   4.414 + *	accounted for as ready for normal characters. This is used for drivers
   4.415 + *	that need their own block copy routines into the buffer. There is no
   4.416 + *	guarantee the buffer is a DMA target!
   4.417 + */
   4.418 +
   4.419 +int tty_prepare_flip_string(struct tty_struct *tty, unsigned char **chars, size_t size)
   4.420 +{
   4.421 +	int space = tty_buffer_request_room(tty, size);
   4.422 +	if (likely(space)) {
   4.423 +		struct tty_buffer *tb = tty->buf.tail;
   4.424 +		*chars = tb->char_buf_ptr + tb->used;
   4.425 +		memset(tb->flag_buf_ptr + tb->used, TTY_NORMAL, space);
   4.426 +		tb->used += space;
   4.427 +	}
   4.428 +	return space;
   4.429 +}
   4.430 +
   4.431 +EXPORT_SYMBOL_GPL(tty_prepare_flip_string);
   4.432 +
   4.433 +/*
   4.434 + *	Prepare a block of space in the buffer for data. Returns the length
   4.435 + *	available and buffer pointer to the space which is now allocated and
   4.436 + *	accounted for as ready for characters. This is used for drivers
   4.437 + *	that need their own block copy routines into the buffer. There is no
   4.438 + *	guarantee the buffer is a DMA target!
   4.439 + */
   4.440 +
   4.441 +int tty_prepare_flip_string_flags(struct tty_struct *tty, unsigned char **chars, char **flags, size_t size)
   4.442 +{
   4.443 +	int space = tty_buffer_request_room(tty, size);
   4.444 +	if (likely(space)) {
   4.445 +		struct tty_buffer *tb = tty->buf.tail;
   4.446 +		*chars = tb->char_buf_ptr + tb->used;
   4.447 +		*flags = tb->flag_buf_ptr + tb->used;
   4.448 +		tb->used += space;
   4.449 +	}
   4.450 +	return space;
   4.451 +}
   4.452 +
   4.453 +EXPORT_SYMBOL_GPL(tty_prepare_flip_string_flags);
   4.454 +
   4.455 +
   4.456 +
   4.457 +/*
   4.458 + *	This is probably overkill for real world processors but
   4.459 + *	they are not on hot paths so a little discipline won't do 
   4.460 + *	any harm.
   4.461 + */
   4.462 + 
   4.463 +static void tty_set_termios_ldisc(struct tty_struct *tty, int num)
   4.464 +{
   4.465 +	down(&tty->termios_sem);
   4.466 +	tty->termios->c_line = num;
   4.467 +	up(&tty->termios_sem);
   4.468 +}
   4.469 +
   4.470 +/*
   4.471 + *	This guards the refcounted line discipline lists. The lock
   4.472 + *	must be taken with irqs off because there are hangup path
   4.473 + *	callers who will do ldisc lookups and cannot sleep.
   4.474 + */
   4.475 + 
   4.476 +static DEFINE_SPINLOCK(tty_ldisc_lock);
   4.477 +static DECLARE_WAIT_QUEUE_HEAD(tty_ldisc_wait);
   4.478 +static struct tty_ldisc tty_ldiscs[NR_LDISCS];	/* line disc dispatch table */
   4.479 +
   4.480 +int tty_register_ldisc(int disc, struct tty_ldisc *new_ldisc)
   4.481 +{
   4.482 +	unsigned long flags;
   4.483 +	int ret = 0;
   4.484 +	
   4.485 +	if (disc < N_TTY || disc >= NR_LDISCS)
   4.486 +		return -EINVAL;
   4.487 +	
   4.488 +	spin_lock_irqsave(&tty_ldisc_lock, flags);
   4.489 +	tty_ldiscs[disc] = *new_ldisc;
   4.490 +	tty_ldiscs[disc].num = disc;
   4.491 +	tty_ldiscs[disc].flags |= LDISC_FLAG_DEFINED;
   4.492 +	tty_ldiscs[disc].refcount = 0;
   4.493 +	spin_unlock_irqrestore(&tty_ldisc_lock, flags);
   4.494 +	
   4.495 +	return ret;
   4.496 +}
   4.497 +EXPORT_SYMBOL(tty_register_ldisc);
   4.498 +
   4.499 +int tty_unregister_ldisc(int disc)
   4.500 +{
   4.501 +	unsigned long flags;
   4.502 +	int ret = 0;
   4.503 +
   4.504 +	if (disc < N_TTY || disc >= NR_LDISCS)
   4.505 +		return -EINVAL;
   4.506 +
   4.507 +	spin_lock_irqsave(&tty_ldisc_lock, flags);
   4.508 +	if (tty_ldiscs[disc].refcount)
   4.509 +		ret = -EBUSY;
   4.510 +	else
   4.511 +		tty_ldiscs[disc].flags &= ~LDISC_FLAG_DEFINED;
   4.512 +	spin_unlock_irqrestore(&tty_ldisc_lock, flags);
   4.513 +
   4.514 +	return ret;
   4.515 +}
   4.516 +EXPORT_SYMBOL(tty_unregister_ldisc);
   4.517 +
   4.518 +struct tty_ldisc *tty_ldisc_get(int disc)
   4.519 +{
   4.520 +	unsigned long flags;
   4.521 +	struct tty_ldisc *ld;
   4.522 +
   4.523 +	if (disc < N_TTY || disc >= NR_LDISCS)
   4.524 +		return NULL;
   4.525 +	
   4.526 +	spin_lock_irqsave(&tty_ldisc_lock, flags);
   4.527 +
   4.528 +	ld = &tty_ldiscs[disc];
   4.529 +	/* Check the entry is defined */
   4.530 +	if(ld->flags & LDISC_FLAG_DEFINED)
   4.531 +	{
   4.532 +		/* If the module is being unloaded we can't use it */
   4.533 +		if (!try_module_get(ld->owner))
   4.534 +		       	ld = NULL;
   4.535 +		else /* lock it */
   4.536 +			ld->refcount++;
   4.537 +	}
   4.538 +	else
   4.539 +		ld = NULL;
   4.540 +	spin_unlock_irqrestore(&tty_ldisc_lock, flags);
   4.541 +	return ld;
   4.542 +}
   4.543 +
   4.544 +EXPORT_SYMBOL_GPL(tty_ldisc_get);
   4.545 +
   4.546 +void tty_ldisc_put(int disc)
   4.547 +{
   4.548 +	struct tty_ldisc *ld;
   4.549 +	unsigned long flags;
   4.550 +	
   4.551 +	if (disc < N_TTY || disc >= NR_LDISCS)
   4.552 +		BUG();
   4.553 +		
   4.554 +	spin_lock_irqsave(&tty_ldisc_lock, flags);
   4.555 +	ld = &tty_ldiscs[disc];
   4.556 +	if(ld->refcount == 0)
   4.557 +		BUG();
   4.558 +	ld->refcount --;
   4.559 +	module_put(ld->owner);
   4.560 +	spin_unlock_irqrestore(&tty_ldisc_lock, flags);
   4.561 +}
   4.562 +	
   4.563 +EXPORT_SYMBOL_GPL(tty_ldisc_put);
   4.564 +
   4.565 +static void tty_ldisc_assign(struct tty_struct *tty, struct tty_ldisc *ld)
   4.566 +{
   4.567 +	tty->ldisc = *ld;
   4.568 +	tty->ldisc.refcount = 0;
   4.569 +}
   4.570 +
   4.571 +/**
   4.572 + *	tty_ldisc_try		-	internal helper
   4.573 + *	@tty: the tty
   4.574 + *
   4.575 + *	Make a single attempt to grab and bump the refcount on
   4.576 + *	the tty ldisc. Return 0 on failure or 1 on success. This is
   4.577 + *	used to implement both the waiting and non waiting versions
   4.578 + *	of tty_ldisc_ref
   4.579 + */
   4.580 +
   4.581 +static int tty_ldisc_try(struct tty_struct *tty)
   4.582 +{
   4.583 +	unsigned long flags;
   4.584 +	struct tty_ldisc *ld;
   4.585 +	int ret = 0;
   4.586 +	
   4.587 +	spin_lock_irqsave(&tty_ldisc_lock, flags);
   4.588 +	ld = &tty->ldisc;
   4.589 +	if(test_bit(TTY_LDISC, &tty->flags))
   4.590 +	{
   4.591 +		ld->refcount++;
   4.592 +		ret = 1;
   4.593 +	}
   4.594 +	spin_unlock_irqrestore(&tty_ldisc_lock, flags);
   4.595 +	return ret;
   4.596 +}
   4.597 +
   4.598 +/**
   4.599 + *	tty_ldisc_ref_wait	-	wait for the tty ldisc
   4.600 + *	@tty: tty device
   4.601 + *
   4.602 + *	Dereference the line discipline for the terminal and take a 
   4.603 + *	reference to it. If the line discipline is in flux then 
   4.604 + *	wait patiently until it changes.
   4.605 + *
   4.606 + *	Note: Must not be called from an IRQ/timer context. The caller
   4.607 + *	must also be careful not to hold other locks that will deadlock
   4.608 + *	against a discipline change, such as an existing ldisc reference
   4.609 + *	(which we check for)
   4.610 + */
   4.611 + 
   4.612 +struct tty_ldisc *tty_ldisc_ref_wait(struct tty_struct *tty)
   4.613 +{
   4.614 +	/* wait_event is a macro */
   4.615 +	wait_event(tty_ldisc_wait, tty_ldisc_try(tty));
   4.616 +	if(tty->ldisc.refcount == 0)
   4.617 +		printk(KERN_ERR "tty_ldisc_ref_wait\n");
   4.618 +	return &tty->ldisc;
   4.619 +}
   4.620 +
   4.621 +EXPORT_SYMBOL_GPL(tty_ldisc_ref_wait);
   4.622 +
   4.623 +/**
   4.624 + *	tty_ldisc_ref		-	get the tty ldisc
   4.625 + *	@tty: tty device
   4.626 + *
   4.627 + *	Dereference the line discipline for the terminal and take a 
   4.628 + *	reference to it. If the line discipline is in flux then 
   4.629 + *	return NULL. Can be called from IRQ and timer functions.
   4.630 + */
   4.631 + 
   4.632 +struct tty_ldisc *tty_ldisc_ref(struct tty_struct *tty)
   4.633 +{
   4.634 +	if(tty_ldisc_try(tty))
   4.635 +		return &tty->ldisc;
   4.636 +	return NULL;
   4.637 +}
   4.638 +
   4.639 +EXPORT_SYMBOL_GPL(tty_ldisc_ref);
   4.640 +
   4.641 +/**
   4.642 + *	tty_ldisc_deref		-	free a tty ldisc reference
   4.643 + *	@ld: reference to free up
   4.644 + *
   4.645 + *	Undoes the effect of tty_ldisc_ref or tty_ldisc_ref_wait. May
   4.646 + *	be called in IRQ context.
   4.647 + */
   4.648 + 
   4.649 +void tty_ldisc_deref(struct tty_ldisc *ld)
   4.650 +{
   4.651 +	unsigned long flags;
   4.652 +
   4.653 +	if(ld == NULL)
   4.654 +		BUG();
   4.655 +		
   4.656 +	spin_lock_irqsave(&tty_ldisc_lock, flags);
   4.657 +	if(ld->refcount == 0)
   4.658 +		printk(KERN_ERR "tty_ldisc_deref: no references.\n");
   4.659 +	else
   4.660 +		ld->refcount--;
   4.661 +	if(ld->refcount == 0)
   4.662 +		wake_up(&tty_ldisc_wait);
   4.663 +	spin_unlock_irqrestore(&tty_ldisc_lock, flags);
   4.664 +}
   4.665 +
   4.666 +EXPORT_SYMBOL_GPL(tty_ldisc_deref);
   4.667 +
   4.668 +/**
   4.669 + *	tty_ldisc_enable	-	allow ldisc use
   4.670 + *	@tty: terminal to activate ldisc on
   4.671 + *
   4.672 + *	Set the TTY_LDISC flag when the line discipline can be called
   4.673 + *	again. Do neccessary wakeups for existing sleepers.
   4.674 + *
   4.675 + *	Note: nobody should set this bit except via this function. Clearing
   4.676 + *	directly is allowed.
   4.677 + */
   4.678 +
   4.679 +static void tty_ldisc_enable(struct tty_struct *tty)
   4.680 +{
   4.681 +	set_bit(TTY_LDISC, &tty->flags);
   4.682 +	wake_up(&tty_ldisc_wait);
   4.683 +}
   4.684 +	
   4.685 +/**
   4.686 + *	tty_set_ldisc		-	set line discipline
   4.687 + *	@tty: the terminal to set
   4.688 + *	@ldisc: the line discipline
   4.689 + *
   4.690 + *	Set the discipline of a tty line. Must be called from a process
   4.691 + *	context.
   4.692 + */
   4.693 + 
   4.694 +static int tty_set_ldisc(struct tty_struct *tty, int ldisc)
   4.695 +{
   4.696 +	int retval = 0;
   4.697 +	struct tty_ldisc o_ldisc;
   4.698 +	char buf[64];
   4.699 +	int work;
   4.700 +	unsigned long flags;
   4.701 +	struct tty_ldisc *ld;
   4.702 +	struct tty_struct *o_tty;
   4.703 +
   4.704 +	if ((ldisc < N_TTY) || (ldisc >= NR_LDISCS))
   4.705 +		return -EINVAL;
   4.706 +
   4.707 +restart:
   4.708 +
   4.709 +	ld = tty_ldisc_get(ldisc);
   4.710 +	/* Eduardo Blanco <ejbs@cs.cs.com.uy> */
   4.711 +	/* Cyrus Durgin <cider@speakeasy.org> */
   4.712 +	if (ld == NULL) {
   4.713 +		request_module("tty-ldisc-%d", ldisc);
   4.714 +		ld = tty_ldisc_get(ldisc);
   4.715 +	}
   4.716 +	if (ld == NULL)
   4.717 +		return -EINVAL;
   4.718 +
   4.719 +	/*
   4.720 +	 *	No more input please, we are switching. The new ldisc
   4.721 +	 *	will update this value in the ldisc open function
   4.722 +	 */
   4.723 +
   4.724 +	tty->receive_room = 0;
   4.725 +
   4.726 +	/*
   4.727 +	 *	Problem: What do we do if this blocks ?
   4.728 +	 */
   4.729 +
   4.730 +	tty_wait_until_sent(tty, 0);
   4.731 +
   4.732 +	if (tty->ldisc.num == ldisc) {
   4.733 +		tty_ldisc_put(ldisc);
   4.734 +		return 0;
   4.735 +	}
   4.736 +
   4.737 +	o_ldisc = tty->ldisc;
   4.738 +	o_tty = tty->link;
   4.739 +
   4.740 +	/*
   4.741 +	 *	Make sure we don't change while someone holds a
   4.742 +	 *	reference to the line discipline. The TTY_LDISC bit
   4.743 +	 *	prevents anyone taking a reference once it is clear.
   4.744 +	 *	We need the lock to avoid racing reference takers.
   4.745 +	 */
   4.746 +
   4.747 +	spin_lock_irqsave(&tty_ldisc_lock, flags);
   4.748 +	if (tty->ldisc.refcount || (o_tty && o_tty->ldisc.refcount)) {
   4.749 +		if(tty->ldisc.refcount) {
   4.750 +			/* Free the new ldisc we grabbed. Must drop the lock
   4.751 +			   first. */
   4.752 +			spin_unlock_irqrestore(&tty_ldisc_lock, flags);
   4.753 +			tty_ldisc_put(ldisc);
   4.754 +			/*
   4.755 +			 * There are several reasons we may be busy, including
   4.756 +			 * random momentary I/O traffic. We must therefore
   4.757 +			 * retry. We could distinguish between blocking ops
   4.758 +			 * and retries if we made tty_ldisc_wait() smarter. That
   4.759 +			 * is up for discussion.
   4.760 +			 */
   4.761 +			if (wait_event_interruptible(tty_ldisc_wait, tty->ldisc.refcount == 0) < 0)
   4.762 +				return -ERESTARTSYS;
   4.763 +			goto restart;
   4.764 +		}
   4.765 +		if(o_tty && o_tty->ldisc.refcount) {
   4.766 +			spin_unlock_irqrestore(&tty_ldisc_lock, flags);
   4.767 +			tty_ldisc_put(ldisc);
   4.768 +			if (wait_event_interruptible(tty_ldisc_wait, o_tty->ldisc.refcount == 0) < 0)
   4.769 +				return -ERESTARTSYS;
   4.770 +			goto restart;
   4.771 +		}
   4.772 +	}
   4.773 +
   4.774 +	/* if the TTY_LDISC bit is set, then we are racing against another ldisc change */
   4.775 +
   4.776 +	if (!test_bit(TTY_LDISC, &tty->flags)) {
   4.777 +		spin_unlock_irqrestore(&tty_ldisc_lock, flags);
   4.778 +		tty_ldisc_put(ldisc);
   4.779 +		ld = tty_ldisc_ref_wait(tty);
   4.780 +		tty_ldisc_deref(ld);
   4.781 +		goto restart;
   4.782 +	}
   4.783 +
   4.784 +	clear_bit(TTY_LDISC, &tty->flags);
   4.785 +	clear_bit(TTY_DONT_FLIP, &tty->flags);
   4.786 +	if (o_tty) {
   4.787 +		clear_bit(TTY_LDISC, &o_tty->flags);
   4.788 +		clear_bit(TTY_DONT_FLIP, &o_tty->flags);
   4.789 +	}
   4.790 +	spin_unlock_irqrestore(&tty_ldisc_lock, flags);
   4.791 +
   4.792 +	/*
   4.793 +	 *	From this point on we know nobody has an ldisc
   4.794 +	 *	usage reference, nor can they obtain one until
   4.795 +	 *	we say so later on.
   4.796 +	 */
   4.797 +
   4.798 +	work = cancel_delayed_work(&tty->buf.work);
   4.799 +	/*
   4.800 +	 * Wait for ->hangup_work and ->buf.work handlers to terminate
   4.801 +	 */
   4.802 +	 
   4.803 +	flush_scheduled_work();
   4.804 +	/* Shutdown the current discipline. */
   4.805 +	if (tty->ldisc.close)
   4.806 +		(tty->ldisc.close)(tty);
   4.807 +
   4.808 +	/* Now set up the new line discipline. */
   4.809 +	tty_ldisc_assign(tty, ld);
   4.810 +	tty_set_termios_ldisc(tty, ldisc);
   4.811 +	if (tty->ldisc.open)
   4.812 +		retval = (tty->ldisc.open)(tty);
   4.813 +	if (retval < 0) {
   4.814 +		tty_ldisc_put(ldisc);
   4.815 +		/* There is an outstanding reference here so this is safe */
   4.816 +		tty_ldisc_assign(tty, tty_ldisc_get(o_ldisc.num));
   4.817 +		tty_set_termios_ldisc(tty, tty->ldisc.num);
   4.818 +		if (tty->ldisc.open && (tty->ldisc.open(tty) < 0)) {
   4.819 +			tty_ldisc_put(o_ldisc.num);
   4.820 +			/* This driver is always present */
   4.821 +			tty_ldisc_assign(tty, tty_ldisc_get(N_TTY));
   4.822 +			tty_set_termios_ldisc(tty, N_TTY);
   4.823 +			if (tty->ldisc.open) {
   4.824 +				int r = tty->ldisc.open(tty);
   4.825 +
   4.826 +				if (r < 0)
   4.827 +					panic("Couldn't open N_TTY ldisc for "
   4.828 +					      "%s --- error %d.",
   4.829 +					      tty_name(tty, buf), r);
   4.830 +			}
   4.831 +		}
   4.832 +	}
   4.833 +	/* At this point we hold a reference to the new ldisc and a
   4.834 +	   a reference to the old ldisc. If we ended up flipping back
   4.835 +	   to the existing ldisc we have two references to it */
   4.836 +	
   4.837 +	if (tty->ldisc.num != o_ldisc.num && tty->driver->set_ldisc)
   4.838 +		tty->driver->set_ldisc(tty);
   4.839 +		
   4.840 +	tty_ldisc_put(o_ldisc.num);
   4.841 +	
   4.842 +	/*
   4.843 +	 *	Allow ldisc referencing to occur as soon as the driver
   4.844 +	 *	ldisc callback completes.
   4.845 +	 */
   4.846 +	 
   4.847 +	tty_ldisc_enable(tty);
   4.848 +	if (o_tty)
   4.849 +		tty_ldisc_enable(o_tty);
   4.850 +	
   4.851 +	/* Restart it in case no characters kick it off. Safe if
   4.852 +	   already running */
   4.853 +	if (work)
   4.854 +		schedule_delayed_work(&tty->buf.work, 1);
   4.855 +	return retval;
   4.856 +}
   4.857 +
   4.858 +/*
   4.859 + * This routine returns a tty driver structure, given a device number
   4.860 + */
   4.861 +static struct tty_driver *get_tty_driver(dev_t device, int *index)
   4.862 +{
   4.863 +	struct tty_driver *p;
   4.864 +
   4.865 +	list_for_each_entry(p, &tty_drivers, tty_drivers) {
   4.866 +		dev_t base = MKDEV(p->major, p->minor_start);
   4.867 +		if (device < base || device >= base + p->num)
   4.868 +			continue;
   4.869 +		*index = device - base;
   4.870 +		return p;
   4.871 +	}
   4.872 +	return NULL;
   4.873 +}
   4.874 +
   4.875 +/*
   4.876 + * If we try to write to, or set the state of, a terminal and we're
   4.877 + * not in the foreground, send a SIGTTOU.  If the signal is blocked or
   4.878 + * ignored, go ahead and perform the operation.  (POSIX 7.2)
   4.879 + */
   4.880 +int tty_check_change(struct tty_struct * tty)
   4.881 +{
   4.882 +	if (current->signal->tty != tty)
   4.883 +		return 0;
   4.884 +	if (tty->pgrp <= 0) {
   4.885 +		printk(KERN_WARNING "tty_check_change: tty->pgrp <= 0!\n");
   4.886 +		return 0;
   4.887 +	}
   4.888 +	if (process_group(current) == tty->pgrp)
   4.889 +		return 0;
   4.890 +	if (is_ignored(SIGTTOU))
   4.891 +		return 0;
   4.892 +	if (is_orphaned_pgrp(process_group(current)))
   4.893 +		return -EIO;
   4.894 +	(void) kill_pg(process_group(current), SIGTTOU, 1);
   4.895 +	return -ERESTARTSYS;
   4.896 +}
   4.897 +
   4.898 +EXPORT_SYMBOL(tty_check_change);
   4.899 +
   4.900 +static ssize_t hung_up_tty_read(struct file * file, char __user * buf,
   4.901 +				size_t count, loff_t *ppos)
   4.902 +{
   4.903 +	return 0;
   4.904 +}
   4.905 +
   4.906 +static ssize_t hung_up_tty_write(struct file * file, const char __user * buf,
   4.907 +				 size_t count, loff_t *ppos)
   4.908 +{
   4.909 +	return -EIO;
   4.910 +}
   4.911 +
   4.912 +/* No kernel lock held - none needed ;) */
   4.913 +static unsigned int hung_up_tty_poll(struct file * filp, poll_table * wait)
   4.914 +{
   4.915 +	return POLLIN | POLLOUT | POLLERR | POLLHUP | POLLRDNORM | POLLWRNORM;
   4.916 +}
   4.917 +
   4.918 +static int hung_up_tty_ioctl(struct inode * inode, struct file * file,
   4.919 +			     unsigned int cmd, unsigned long arg)
   4.920 +{
   4.921 +	return cmd == TIOCSPGRP ? -ENOTTY : -EIO;
   4.922 +}
   4.923 +
   4.924 +static struct file_operations tty_fops = {
   4.925 +	.llseek		= no_llseek,
   4.926 +	.read		= tty_read,
   4.927 +	.write		= tty_write,
   4.928 +	.poll		= tty_poll,
   4.929 +	.ioctl		= tty_ioctl,
   4.930 +	.open		= tty_open,
   4.931 +	.release	= tty_release,
   4.932 +	.fasync		= tty_fasync,
   4.933 +};
   4.934 +
   4.935 +#ifdef CONFIG_UNIX98_PTYS
   4.936 +static struct file_operations ptmx_fops = {
   4.937 +	.llseek		= no_llseek,
   4.938 +	.read		= tty_read,
   4.939 +	.write		= tty_write,
   4.940 +	.poll		= tty_poll,
   4.941 +	.ioctl		= tty_ioctl,
   4.942 +	.open		= ptmx_open,
   4.943 +	.release	= tty_release,
   4.944 +	.fasync		= tty_fasync,
   4.945 +};
   4.946 +#endif
   4.947 +
   4.948 +static struct file_operations console_fops = {
   4.949 +	.llseek		= no_llseek,
   4.950 +	.read		= tty_read,
   4.951 +	.write		= redirected_tty_write,
   4.952 +	.poll		= tty_poll,
   4.953 +	.ioctl		= tty_ioctl,
   4.954 +	.open		= tty_open,
   4.955 +	.release	= tty_release,
   4.956 +	.fasync		= tty_fasync,
   4.957 +};
   4.958 +
   4.959 +static struct file_operations hung_up_tty_fops = {
   4.960 +	.llseek		= no_llseek,
   4.961 +	.read		= hung_up_tty_read,
   4.962 +	.write		= hung_up_tty_write,
   4.963 +	.poll		= hung_up_tty_poll,
   4.964 +	.ioctl		= hung_up_tty_ioctl,
   4.965 +	.release	= tty_release,
   4.966 +};
   4.967 +
   4.968 +static DEFINE_SPINLOCK(redirect_lock);
   4.969 +static struct file *redirect;
   4.970 +
   4.971 +/**
   4.972 + *	tty_wakeup	-	request more data
   4.973 + *	@tty: terminal
   4.974 + *
   4.975 + *	Internal and external helper for wakeups of tty. This function
   4.976 + *	informs the line discipline if present that the driver is ready
   4.977 + *	to receive more output data.
   4.978 + */
   4.979 + 
   4.980 +void tty_wakeup(struct tty_struct *tty)
   4.981 +{
   4.982 +	struct tty_ldisc *ld;
   4.983 +	
   4.984 +	if (test_bit(TTY_DO_WRITE_WAKEUP, &tty->flags)) {
   4.985 +		ld = tty_ldisc_ref(tty);
   4.986 +		if(ld) {
   4.987 +			if(ld->write_wakeup)
   4.988 +				ld->write_wakeup(tty);
   4.989 +			tty_ldisc_deref(ld);
   4.990 +		}
   4.991 +	}
   4.992 +	wake_up_interruptible(&tty->write_wait);
   4.993 +}
   4.994 +
   4.995 +EXPORT_SYMBOL_GPL(tty_wakeup);
   4.996 +
   4.997 +/**
   4.998 + *	tty_ldisc_flush	-	flush line discipline queue
   4.999 + *	@tty: tty
  4.1000 + *
  4.1001 + *	Flush the line discipline queue (if any) for this tty. If there
  4.1002 + *	is no line discipline active this is a no-op.
  4.1003 + */
  4.1004 + 
  4.1005 +void tty_ldisc_flush(struct tty_struct *tty)
  4.1006 +{
  4.1007 +	struct tty_ldisc *ld = tty_ldisc_ref(tty);
  4.1008 +	if(ld) {
  4.1009 +		if(ld->flush_buffer)
  4.1010 +			ld->flush_buffer(tty);
  4.1011 +		tty_ldisc_deref(ld);
  4.1012 +	}
  4.1013 +}
  4.1014 +
  4.1015 +EXPORT_SYMBOL_GPL(tty_ldisc_flush);
  4.1016 +	
  4.1017 +/*
  4.1018 + * This can be called by the "eventd" kernel thread.  That is process synchronous,
  4.1019 + * but doesn't hold any locks, so we need to make sure we have the appropriate
  4.1020 + * locks for what we're doing..
  4.1021 + */
  4.1022 +static void do_tty_hangup(void *data)
  4.1023 +{
  4.1024 +	struct tty_struct *tty = (struct tty_struct *) data;
  4.1025 +	struct file * cons_filp = NULL;
  4.1026 +	struct file *filp, *f = NULL;
  4.1027 +	struct task_struct *p;
  4.1028 +	struct tty_ldisc *ld;
  4.1029 +	int    closecount = 0, n;
  4.1030 +
  4.1031 +	if (!tty)
  4.1032 +		return;
  4.1033 +
  4.1034 +	/* inuse_filps is protected by the single kernel lock */
  4.1035 +	lock_kernel();
  4.1036 +
  4.1037 +	spin_lock(&redirect_lock);
  4.1038 +	if (redirect && redirect->private_data == tty) {
  4.1039 +		f = redirect;
  4.1040 +		redirect = NULL;
  4.1041 +	}
  4.1042 +	spin_unlock(&redirect_lock);
  4.1043 +	
  4.1044 +	check_tty_count(tty, "do_tty_hangup");
  4.1045 +	file_list_lock();
  4.1046 +	/* This breaks for file handles being sent over AF_UNIX sockets ? */
  4.1047 +	list_for_each_entry(filp, &tty->tty_files, f_u.fu_list) {
  4.1048 +		if (filp->f_op->write == redirected_tty_write)
  4.1049 +			cons_filp = filp;
  4.1050 +		if (filp->f_op->write != tty_write)
  4.1051 +			continue;
  4.1052 +		closecount++;
  4.1053 +		tty_fasync(-1, filp, 0);	/* can't block */
  4.1054 +		filp->f_op = &hung_up_tty_fops;
  4.1055 +	}
  4.1056 +	file_list_unlock();
  4.1057 +	
  4.1058 +	/* FIXME! What are the locking issues here? This may me overdoing things..
  4.1059 +	 * this question is especially important now that we've removed the irqlock. */
  4.1060 +
  4.1061 +	ld = tty_ldisc_ref(tty);
  4.1062 +	if(ld != NULL)	/* We may have no line discipline at this point */
  4.1063 +	{
  4.1064 +		if (ld->flush_buffer)
  4.1065 +			ld->flush_buffer(tty);
  4.1066 +		if (tty->driver->flush_buffer)
  4.1067 +			tty->driver->flush_buffer(tty);
  4.1068 +		if ((test_bit(TTY_DO_WRITE_WAKEUP, &tty->flags)) &&
  4.1069 +		    ld->write_wakeup)
  4.1070 +			ld->write_wakeup(tty);
  4.1071 +		if (ld->hangup)
  4.1072 +			ld->hangup(tty);
  4.1073 +	}
  4.1074 +
  4.1075 +	/* FIXME: Once we trust the LDISC code better we can wait here for
  4.1076 +	   ldisc completion and fix the driver call race */
  4.1077 +	   
  4.1078 +	wake_up_interruptible(&tty->write_wait);
  4.1079 +	wake_up_interruptible(&tty->read_wait);
  4.1080 +
  4.1081 +	/*
  4.1082 +	 * Shutdown the current line discipline, and reset it to
  4.1083 +	 * N_TTY.
  4.1084 +	 */
  4.1085 +	if (tty->driver->flags & TTY_DRIVER_RESET_TERMIOS)
  4.1086 +	{
  4.1087 +		down(&tty->termios_sem);
  4.1088 +		*tty->termios = tty->driver->init_termios;
  4.1089 +		up(&tty->termios_sem);
  4.1090 +	}
  4.1091 +	
  4.1092 +	/* Defer ldisc switch */
  4.1093 +	/* tty_deferred_ldisc_switch(N_TTY);
  4.1094 +	
  4.1095 +	  This should get done automatically when the port closes and
  4.1096 +	  tty_release is called */
  4.1097 +	
  4.1098 +	read_lock(&tasklist_lock);
  4.1099 +	if (tty->session > 0) {
  4.1100 +		do_each_task_pid(tty->session, PIDTYPE_SID, p) {
  4.1101 +			if (p->signal->tty == tty)
  4.1102 +				p->signal->tty = NULL;
  4.1103 +			if (!p->signal->leader)
  4.1104 +				continue;
  4.1105 +			send_group_sig_info(SIGHUP, SEND_SIG_PRIV, p);
  4.1106 +			send_group_sig_info(SIGCONT, SEND_SIG_PRIV, p);
  4.1107 +			if (tty->pgrp > 0)
  4.1108 +				p->signal->tty_old_pgrp = tty->pgrp;
  4.1109 +		} while_each_task_pid(tty->session, PIDTYPE_SID, p);
  4.1110 +	}
  4.1111 +	read_unlock(&tasklist_lock);
  4.1112 +
  4.1113 +	tty->flags = 0;
  4.1114 +	tty->session = 0;
  4.1115 +	tty->pgrp = -1;
  4.1116 +	tty->ctrl_status = 0;
  4.1117 +	/*
  4.1118 +	 *	If one of the devices matches a console pointer, we
  4.1119 +	 *	cannot just call hangup() because that will cause
  4.1120 +	 *	tty->count and state->count to go out of sync.
  4.1121 +	 *	So we just call close() the right number of times.
  4.1122 +	 */
  4.1123 +	if (cons_filp) {
  4.1124 +		if (tty->driver->close)
  4.1125 +			for (n = 0; n < closecount; n++)
  4.1126 +				tty->driver->close(tty, cons_filp);
  4.1127 +	} else if (tty->driver->hangup)
  4.1128 +		(tty->driver->hangup)(tty);
  4.1129 +		
  4.1130 +	/* We don't want to have driver/ldisc interactions beyond
  4.1131 +	   the ones we did here. The driver layer expects no
  4.1132 +	   calls after ->hangup() from the ldisc side. However we
  4.1133 +	   can't yet guarantee all that */
  4.1134 +
  4.1135 +	set_bit(TTY_HUPPED, &tty->flags);
  4.1136 +	if (ld) {
  4.1137 +		tty_ldisc_enable(tty);
  4.1138 +		tty_ldisc_deref(ld);
  4.1139 +	}
  4.1140 +	unlock_kernel();
  4.1141 +	if (f)
  4.1142 +		fput(f);
  4.1143 +}
  4.1144 +
  4.1145 +void tty_hangup(struct tty_struct * tty)
  4.1146 +{
  4.1147 +#ifdef TTY_DEBUG_HANGUP
  4.1148 +	char	buf[64];
  4.1149 +	
  4.1150 +	printk(KERN_DEBUG "%s hangup...\n", tty_name(tty, buf));
  4.1151 +#endif
  4.1152 +	schedule_work(&tty->hangup_work);
  4.1153 +}
  4.1154 +
  4.1155 +EXPORT_SYMBOL(tty_hangup);
  4.1156 +
  4.1157 +void tty_vhangup(struct tty_struct * tty)
  4.1158 +{
  4.1159 +#ifdef TTY_DEBUG_HANGUP
  4.1160 +	char	buf[64];
  4.1161 +
  4.1162 +	printk(KERN_DEBUG "%s vhangup...\n", tty_name(tty, buf));
  4.1163 +#endif
  4.1164 +	do_tty_hangup((void *) tty);
  4.1165 +}
  4.1166 +EXPORT_SYMBOL(tty_vhangup);
  4.1167 +
  4.1168 +int tty_hung_up_p(struct file * filp)
  4.1169 +{
  4.1170 +	return (filp->f_op == &hung_up_tty_fops);
  4.1171 +}
  4.1172 +
  4.1173 +EXPORT_SYMBOL(tty_hung_up_p);
  4.1174 +
  4.1175 +/*
  4.1176 + * This function is typically called only by the session leader, when
  4.1177 + * it wants to disassociate itself from its controlling tty.
  4.1178 + *
  4.1179 + * It performs the following functions:
  4.1180 + * 	(1)  Sends a SIGHUP and SIGCONT to the foreground process group
  4.1181 + * 	(2)  Clears the tty from being controlling the session
  4.1182 + * 	(3)  Clears the controlling tty for all processes in the
  4.1183 + * 		session group.
  4.1184 + *
  4.1185 + * The argument on_exit is set to 1 if called when a process is
  4.1186 + * exiting; it is 0 if called by the ioctl TIOCNOTTY.
  4.1187 + */
  4.1188 +void disassociate_ctty(int on_exit)
  4.1189 +{
  4.1190 +	struct tty_struct *tty;
  4.1191 +	struct task_struct *p;
  4.1192 +	int tty_pgrp = -1;
  4.1193 +
  4.1194 +	lock_kernel();
  4.1195 +
  4.1196 +	down(&tty_sem);
  4.1197 +	tty = current->signal->tty;
  4.1198 +	if (tty) {
  4.1199 +		tty_pgrp = tty->pgrp;
  4.1200 +		up(&tty_sem);
  4.1201 +		if (on_exit && tty->driver->type != TTY_DRIVER_TYPE_PTY)
  4.1202 +			tty_vhangup(tty);
  4.1203 +	} else {
  4.1204 +		if (current->signal->tty_old_pgrp) {
  4.1205 +			kill_pg(current->signal->tty_old_pgrp, SIGHUP, on_exit);
  4.1206 +			kill_pg(current->signal->tty_old_pgrp, SIGCONT, on_exit);
  4.1207 +		}
  4.1208 +		up(&tty_sem);
  4.1209 +		unlock_kernel();	
  4.1210 +		return;
  4.1211 +	}
  4.1212 +	if (tty_pgrp > 0) {
  4.1213 +		kill_pg(tty_pgrp, SIGHUP, on_exit);
  4.1214 +		if (!on_exit)
  4.1215 +			kill_pg(tty_pgrp, SIGCONT, on_exit);
  4.1216 +	}
  4.1217 +
  4.1218 +	/* Must lock changes to tty_old_pgrp */
  4.1219 +	down(&tty_sem);
  4.1220 +	current->signal->tty_old_pgrp = 0;
  4.1221 +	tty->session = 0;
  4.1222 +	tty->pgrp = -1;
  4.1223 +
  4.1224 +	/* Now clear signal->tty under the lock */
  4.1225 +	read_lock(&tasklist_lock);
  4.1226 +	do_each_task_pid(current->signal->session, PIDTYPE_SID, p) {
  4.1227 +		p->signal->tty = NULL;
  4.1228 +	} while_each_task_pid(current->signal->session, PIDTYPE_SID, p);
  4.1229 +	read_unlock(&tasklist_lock);
  4.1230 +	up(&tty_sem);
  4.1231 +	unlock_kernel();
  4.1232 +}
  4.1233 +
  4.1234 +void stop_tty(struct tty_struct *tty)
  4.1235 +{
  4.1236 +	if (tty->stopped)
  4.1237 +		return;
  4.1238 +	tty->stopped = 1;
  4.1239 +	if (tty->link && tty->link->packet) {
  4.1240 +		tty->ctrl_status &= ~TIOCPKT_START;
  4.1241 +		tty->ctrl_status |= TIOCPKT_STOP;
  4.1242 +		wake_up_interruptible(&tty->link->read_wait);
  4.1243 +	}
  4.1244 +	if (tty->driver->stop)
  4.1245 +		(tty->driver->stop)(tty);
  4.1246 +}
  4.1247 +
  4.1248 +EXPORT_SYMBOL(stop_tty);
  4.1249 +
  4.1250 +void start_tty(struct tty_struct *tty)
  4.1251 +{
  4.1252 +	if (!tty->stopped || tty->flow_stopped)
  4.1253 +		return;
  4.1254 +	tty->stopped = 0;
  4.1255 +	if (tty->link && tty->link->packet) {
  4.1256 +		tty->ctrl_status &= ~TIOCPKT_STOP;
  4.1257 +		tty->ctrl_status |= TIOCPKT_START;
  4.1258 +		wake_up_interruptible(&tty->link->read_wait);
  4.1259 +	}
  4.1260 +	if (tty->driver->start)
  4.1261 +		(tty->driver->start)(tty);
  4.1262 +
  4.1263 +	/* If we have a running line discipline it may need kicking */
  4.1264 +	tty_wakeup(tty);
  4.1265 +	wake_up_interruptible(&tty->write_wait);
  4.1266 +}
  4.1267 +
  4.1268 +EXPORT_SYMBOL(start_tty);
  4.1269 +
  4.1270 +static ssize_t tty_read(struct file * file, char __user * buf, size_t count, 
  4.1271 +			loff_t *ppos)
  4.1272 +{
  4.1273 +	int i;
  4.1274 +	struct tty_struct * tty;
  4.1275 +	struct inode *inode;
  4.1276 +	struct tty_ldisc *ld;
  4.1277 +
  4.1278 +	tty = (struct tty_struct *)file->private_data;
  4.1279 +	inode = file->f_dentry->d_inode;
  4.1280 +	if (tty_paranoia_check(tty, inode, "tty_read"))
  4.1281 +		return -EIO;
  4.1282 +	if (!tty || (test_bit(TTY_IO_ERROR, &tty->flags)))
  4.1283 +		return -EIO;
  4.1284 +
  4.1285 +	/* We want to wait for the line discipline to sort out in this
  4.1286 +	   situation */
  4.1287 +	ld = tty_ldisc_ref_wait(tty);
  4.1288 +	lock_kernel();
  4.1289 +	if (ld->read)
  4.1290 +		i = (ld->read)(tty,file,buf,count);
  4.1291 +	else
  4.1292 +		i = -EIO;
  4.1293 +	tty_ldisc_deref(ld);
  4.1294 +	unlock_kernel();
  4.1295 +	if (i > 0)
  4.1296 +		inode->i_atime = current_fs_time(inode->i_sb);
  4.1297 +	return i;
  4.1298 +}
  4.1299 +
  4.1300 +/*
  4.1301 + * Split writes up in sane blocksizes to avoid
  4.1302 + * denial-of-service type attacks
  4.1303 + */
  4.1304 +static inline ssize_t do_tty_write(
  4.1305 +	ssize_t (*write)(struct tty_struct *, struct file *, const unsigned char *, size_t),
  4.1306 +	struct tty_struct *tty,
  4.1307 +	struct file *file,
  4.1308 +	const char __user *buf,
  4.1309 +	size_t count)
  4.1310 +{
  4.1311 +	ssize_t ret = 0, written = 0;
  4.1312 +	unsigned int chunk;
  4.1313 +	
  4.1314 +	if (down_interruptible(&tty->atomic_write)) {
  4.1315 +		return -ERESTARTSYS;
  4.1316 +	}
  4.1317 +
  4.1318 +	/*
  4.1319 +	 * We chunk up writes into a temporary buffer. This
  4.1320 +	 * simplifies low-level drivers immensely, since they
  4.1321 +	 * don't have locking issues and user mode accesses.
  4.1322 +	 *
  4.1323 +	 * But if TTY_NO_WRITE_SPLIT is set, we should use a
  4.1324 +	 * big chunk-size..
  4.1325 +	 *
  4.1326 +	 * The default chunk-size is 2kB, because the NTTY
  4.1327 +	 * layer has problems with bigger chunks. It will
  4.1328 +	 * claim to be able to handle more characters than
  4.1329 +	 * it actually does.
  4.1330 +	 */
  4.1331 +	chunk = 2048;
  4.1332 +	if (test_bit(TTY_NO_WRITE_SPLIT, &tty->flags))
  4.1333 +		chunk = 65536;
  4.1334 +	if (count < chunk)
  4.1335 +		chunk = count;
  4.1336 +
  4.1337 +	/* write_buf/write_cnt is protected by the atomic_write semaphore */
  4.1338 +	if (tty->write_cnt < chunk) {
  4.1339 +		unsigned char *buf;
  4.1340 +
  4.1341 +		if (chunk < 1024)
  4.1342 +			chunk = 1024;
  4.1343 +
  4.1344 +		buf = kmalloc(chunk, GFP_KERNEL);
  4.1345 +		if (!buf) {
  4.1346 +			up(&tty->atomic_write);
  4.1347 +			return -ENOMEM;
  4.1348 +		}
  4.1349 +		kfree(tty->write_buf);
  4.1350 +		tty->write_cnt = chunk;
  4.1351 +		tty->write_buf = buf;
  4.1352 +	}
  4.1353 +
  4.1354 +	/* Do the write .. */
  4.1355 +	for (;;) {
  4.1356 +		size_t size = count;
  4.1357 +		if (size > chunk)
  4.1358 +			size = chunk;
  4.1359 +		ret = -EFAULT;
  4.1360 +		if (copy_from_user(tty->write_buf, buf, size))
  4.1361 +			break;
  4.1362 +		lock_kernel();
  4.1363 +		ret = write(tty, file, tty->write_buf, size);
  4.1364 +		unlock_kernel();
  4.1365 +		if (ret <= 0)
  4.1366 +			break;
  4.1367 +		written += ret;
  4.1368 +		buf += ret;
  4.1369 +		count -= ret;
  4.1370 +		if (!count)
  4.1371 +			break;
  4.1372 +		ret = -ERESTARTSYS;
  4.1373 +		if (signal_pending(current))
  4.1374 +			break;
  4.1375 +		cond_resched();
  4.1376 +	}
  4.1377 +	if (written) {
  4.1378 +		struct inode *inode = file->f_dentry->d_inode;
  4.1379 +		inode->i_mtime = current_fs_time(inode->i_sb);
  4.1380 +		ret = written;
  4.1381 +	}
  4.1382 +	up(&tty->atomic_write);
  4.1383 +	return ret;
  4.1384 +}
  4.1385 +
  4.1386 +
  4.1387 +static ssize_t tty_write(struct file * file, const char __user * buf, size_t count,
  4.1388 +			 loff_t *ppos)
  4.1389 +{
  4.1390 +	struct tty_struct * tty;
  4.1391 +	struct inode *inode = file->f_dentry->d_inode;
  4.1392 +	ssize_t ret;
  4.1393 +	struct tty_ldisc *ld;
  4.1394 +	
  4.1395 +	tty = (struct tty_struct *)file->private_data;
  4.1396 +	if (tty_paranoia_check(tty, inode, "tty_write"))
  4.1397 +		return -EIO;
  4.1398 +	if (!tty || !tty->driver->write || (test_bit(TTY_IO_ERROR, &tty->flags)))
  4.1399 +		return -EIO;
  4.1400 +
  4.1401 +	ld = tty_ldisc_ref_wait(tty);		
  4.1402 +	if (!ld->write)
  4.1403 +		ret = -EIO;
  4.1404 +	else
  4.1405 +		ret = do_tty_write(ld->write, tty, file, buf, count);
  4.1406 +	tty_ldisc_deref(ld);
  4.1407 +	return ret;
  4.1408 +}
  4.1409 +
  4.1410 +ssize_t redirected_tty_write(struct file * file, const char __user * buf, size_t count,
  4.1411 +			 loff_t *ppos)
  4.1412 +{
  4.1413 +	struct file *p = NULL;
  4.1414 +
  4.1415 +	spin_lock(&redirect_lock);
  4.1416 +	if (redirect) {
  4.1417 +		get_file(redirect);
  4.1418 +		p = redirect;
  4.1419 +	}
  4.1420 +	spin_unlock(&redirect_lock);
  4.1421 +
  4.1422 +	if (p) {
  4.1423 +		ssize_t res;
  4.1424 +		res = vfs_write(p, buf, count, &p->f_pos);
  4.1425 +		fput(p);
  4.1426 +		return res;
  4.1427 +	}
  4.1428 +
  4.1429 +	return tty_write(file, buf, count, ppos);
  4.1430 +}
  4.1431 +
  4.1432 +static char ptychar[] = "pqrstuvwxyzabcde";
  4.1433 +
  4.1434 +static inline void pty_line_name(struct tty_driver *driver, int index, char *p)
  4.1435 +{
  4.1436 +	int i = index + driver->name_base;
  4.1437 +	/* ->name is initialized to "ttyp", but "tty" is expected */
  4.1438 +	sprintf(p, "%s%c%x",
  4.1439 +			driver->subtype == PTY_TYPE_SLAVE ? "tty" : driver->name,
  4.1440 +			ptychar[i >> 4 & 0xf], i & 0xf);
  4.1441 +}
  4.1442 +
  4.1443 +static inline void tty_line_name(struct tty_driver *driver, int index, char *p)
  4.1444 +{
  4.1445 +	sprintf(p, "%s%d", driver->name, index + driver->name_base);
  4.1446 +}
  4.1447 +
  4.1448 +/*
  4.1449 + * WSH 06/09/97: Rewritten to remove races and properly clean up after a
  4.1450 + * failed open.  The new code protects the open with a semaphore, so it's
  4.1451 + * really quite straightforward.  The semaphore locking can probably be
  4.1452 + * relaxed for the (most common) case of reopening a tty.
  4.1453 + */
  4.1454 +static int init_dev(struct tty_driver *driver, int idx,
  4.1455 +	struct tty_struct **ret_tty)
  4.1456 +{
  4.1457 +	struct tty_struct *tty, *o_tty;
  4.1458 +	struct termios *tp, **tp_loc, *o_tp, **o_tp_loc;
  4.1459 +	struct termios *ltp, **ltp_loc, *o_ltp, **o_ltp_loc;
  4.1460 +	int retval=0;
  4.1461 +
  4.1462 +	/* check whether we're reopening an existing tty */
  4.1463 +	if (driver->flags & TTY_DRIVER_DEVPTS_MEM) {
  4.1464 +		tty = devpts_get_tty(idx);
  4.1465 +		if (tty && driver->subtype == PTY_TYPE_MASTER)
  4.1466 +			tty = tty->link;
  4.1467 +	} else {
  4.1468 +		tty = driver->ttys[idx];
  4.1469 +	}
  4.1470 +	if (tty) goto fast_track;
  4.1471 +
  4.1472 +	/*
  4.1473 +	 * First time open is complex, especially for PTY devices.
  4.1474 +	 * This code guarantees that either everything succeeds and the
  4.1475 +	 * TTY is ready for operation, or else the table slots are vacated
  4.1476 +	 * and the allocated memory released.  (Except that the termios 
  4.1477 +	 * and locked termios may be retained.)
  4.1478 +	 */
  4.1479 +
  4.1480 +	if (!try_module_get(driver->owner)) {
  4.1481 +		retval = -ENODEV;
  4.1482 +		goto end_init;
  4.1483 +	}
  4.1484 +
  4.1485 +	o_tty = NULL;
  4.1486 +	tp = o_tp = NULL;
  4.1487 +	ltp = o_ltp = NULL;
  4.1488 +
  4.1489 +	tty = alloc_tty_struct();
  4.1490 +	if(!tty)
  4.1491 +		goto fail_no_mem;
  4.1492 +	initialize_tty_struct(tty);
  4.1493 +	tty->driver = driver;
  4.1494 +	tty->index = idx;
  4.1495 +	tty_line_name(driver, idx, tty->name);
  4.1496 +
  4.1497 +	if (driver->flags & TTY_DRIVER_DEVPTS_MEM) {
  4.1498 +		tp_loc = &tty->termios;
  4.1499 +		ltp_loc = &tty->termios_locked;
  4.1500 +	} else {
  4.1501 +		tp_loc = &driver->termios[idx];
  4.1502 +		ltp_loc = &driver->termios_locked[idx];
  4.1503 +	}
  4.1504 +
  4.1505 +	if (!*tp_loc) {
  4.1506 +		tp = (struct termios *) kmalloc(sizeof(struct termios),
  4.1507 +						GFP_KERNEL);
  4.1508 +		if (!tp)
  4.1509 +			goto free_mem_out;
  4.1510 +		*tp = driver->init_termios;
  4.1511 +	}
  4.1512 +
  4.1513 +	if (!*ltp_loc) {
  4.1514 +		ltp = (struct termios *) kmalloc(sizeof(struct termios),
  4.1515 +						 GFP_KERNEL);
  4.1516 +		if (!ltp)
  4.1517 +			goto free_mem_out;
  4.1518 +		memset(ltp, 0, sizeof(struct termios));
  4.1519 +	}
  4.1520 +
  4.1521 +	if (driver->type == TTY_DRIVER_TYPE_PTY) {
  4.1522 +		o_tty = alloc_tty_struct();
  4.1523 +		if (!o_tty)
  4.1524 +			goto free_mem_out;
  4.1525 +		initialize_tty_struct(o_tty);
  4.1526 +		o_tty->driver = driver->other;
  4.1527 +		o_tty->index = idx;
  4.1528 +		tty_line_name(driver->other, idx, o_tty->name);
  4.1529 +
  4.1530 +		if (driver->flags & TTY_DRIVER_DEVPTS_MEM) {
  4.1531 +			o_tp_loc = &o_tty->termios;
  4.1532 +			o_ltp_loc = &o_tty->termios_locked;
  4.1533 +		} else {
  4.1534 +			o_tp_loc = &driver->other->termios[idx];
  4.1535 +			o_ltp_loc = &driver->other->termios_locked[idx];
  4.1536 +		}
  4.1537 +
  4.1538 +		if (!*o_tp_loc) {
  4.1539 +			o_tp = (struct termios *)
  4.1540 +				kmalloc(sizeof(struct termios), GFP_KERNEL);
  4.1541 +			if (!o_tp)
  4.1542 +				goto free_mem_out;
  4.1543 +			*o_tp = driver->other->init_termios;
  4.1544 +		}
  4.1545 +
  4.1546 +		if (!*o_ltp_loc) {
  4.1547 +			o_ltp = (struct termios *)
  4.1548 +				kmalloc(sizeof(struct termios), GFP_KERNEL);
  4.1549 +			if (!o_ltp)
  4.1550 +				goto free_mem_out;
  4.1551 +			memset(o_ltp, 0, sizeof(struct termios));
  4.1552 +		}
  4.1553 +
  4.1554 +		/*
  4.1555 +		 * Everything allocated ... set up the o_tty structure.
  4.1556 +		 */
  4.1557 +		if (!(driver->other->flags & TTY_DRIVER_DEVPTS_MEM)) {
  4.1558 +			driver->other->ttys[idx] = o_tty;
  4.1559 +		}
  4.1560 +		if (!*o_tp_loc)
  4.1561 +			*o_tp_loc = o_tp;
  4.1562 +		if (!*o_ltp_loc)
  4.1563 +			*o_ltp_loc = o_ltp;
  4.1564 +		o_tty->termios = *o_tp_loc;
  4.1565 +		o_tty->termios_locked = *o_ltp_loc;
  4.1566 +		driver->other->refcount++;
  4.1567 +		if (driver->subtype == PTY_TYPE_MASTER)
  4.1568 +			o_tty->count++;
  4.1569 +
  4.1570 +		/* Establish the links in both directions */
  4.1571 +		tty->link   = o_tty;
  4.1572 +		o_tty->link = tty;
  4.1573 +	}
  4.1574 +
  4.1575 +	/* 
  4.1576 +	 * All structures have been allocated, so now we install them.
  4.1577 +	 * Failures after this point use release_mem to clean up, so 
  4.1578 +	 * there's no need to null out the local pointers.
  4.1579 +	 */
  4.1580 +	if (!(driver->flags & TTY_DRIVER_DEVPTS_MEM)) {
  4.1581 +		driver->ttys[idx] = tty;
  4.1582 +	}
  4.1583 +	
  4.1584 +	if (!*tp_loc)
  4.1585 +		*tp_loc = tp;
  4.1586 +	if (!*ltp_loc)
  4.1587 +		*ltp_loc = ltp;
  4.1588 +	tty->termios = *tp_loc;
  4.1589 +	tty->termios_locked = *ltp_loc;
  4.1590 +	driver->refcount++;
  4.1591 +	tty->count++;
  4.1592 +
  4.1593 +	/* 
  4.1594 +	 * Structures all installed ... call the ldisc open routines.
  4.1595 +	 * If we fail here just call release_mem to clean up.  No need
  4.1596 +	 * to decrement the use counts, as release_mem doesn't care.
  4.1597 +	 */
  4.1598 +
  4.1599 +	if (tty->ldisc.open) {
  4.1600 +		retval = (tty->ldisc.open)(tty);
  4.1601 +		if (retval)
  4.1602 +			goto release_mem_out;
  4.1603 +	}
  4.1604 +	if (o_tty && o_tty->ldisc.open) {
  4.1605 +		retval = (o_tty->ldisc.open)(o_tty);
  4.1606 +		if (retval) {
  4.1607 +			if (tty->ldisc.close)
  4.1608 +				(tty->ldisc.close)(tty);
  4.1609 +			goto release_mem_out;
  4.1610 +		}
  4.1611 +		tty_ldisc_enable(o_tty);
  4.1612 +	}
  4.1613 +	tty_ldisc_enable(tty);
  4.1614 +	goto success;
  4.1615 +
  4.1616 +	/*
  4.1617 +	 * This fast open can be used if the tty is already open.
  4.1618 +	 * No memory is allocated, and the only failures are from
  4.1619 +	 * attempting to open a closing tty or attempting multiple
  4.1620 +	 * opens on a pty master.
  4.1621 +	 */
  4.1622 +fast_track:
  4.1623 +	if (test_bit(TTY_CLOSING, &tty->flags)) {
  4.1624 +		retval = -EIO;
  4.1625 +		goto end_init;
  4.1626 +	}
  4.1627 +	if (driver->type == TTY_DRIVER_TYPE_PTY &&
  4.1628 +	    driver->subtype == PTY_TYPE_MASTER) {
  4.1629 +		/*
  4.1630 +		 * special case for PTY masters: only one open permitted, 
  4.1631 +		 * and the slave side open count is incremented as well.
  4.1632 +		 */
  4.1633 +		if (tty->count) {
  4.1634 +			retval = -EIO;
  4.1635 +			goto end_init;
  4.1636 +		}
  4.1637 +		tty->link->count++;
  4.1638 +	}
  4.1639 +	tty->count++;
  4.1640 +	tty->driver = driver; /* N.B. why do this every time?? */
  4.1641 +
  4.1642 +	/* FIXME */
  4.1643 +	if(!test_bit(TTY_LDISC, &tty->flags))
  4.1644 +		printk(KERN_ERR "init_dev but no ldisc\n");
  4.1645 +success:
  4.1646 +	*ret_tty = tty;
  4.1647 +	
  4.1648 +	/* All paths come through here to release the semaphore */
  4.1649 +end_init:
  4.1650 +	return retval;
  4.1651 +
  4.1652 +	/* Release locally allocated memory ... nothing placed in slots */
  4.1653 +free_mem_out:
  4.1654 +	kfree(o_tp);
  4.1655 +	if (o_tty)
  4.1656 +		free_tty_struct(o_tty);
  4.1657 +	kfree(ltp);
  4.1658 +	kfree(tp);
  4.1659 +	free_tty_struct(tty);
  4.1660 +
  4.1661 +fail_no_mem:
  4.1662 +	module_put(driver->owner);
  4.1663 +	retval = -ENOMEM;
  4.1664 +	goto end_init;
  4.1665 +
  4.1666 +	/* call the tty release_mem routine to clean out this slot */
  4.1667 +release_mem_out:
  4.1668 +	printk(KERN_INFO "init_dev: ldisc open failed, "
  4.1669 +			 "clearing slot %d\n", idx);
  4.1670 +	release_mem(tty, idx);
  4.1671 +	goto end_init;
  4.1672 +}
  4.1673 +
  4.1674 +/*
  4.1675 + * Releases memory associated with a tty structure, and clears out the
  4.1676 + * driver table slots.
  4.1677 + */
  4.1678 +static void release_mem(struct tty_struct *tty, int idx)
  4.1679 +{
  4.1680 +	struct tty_struct *o_tty;
  4.1681 +	struct termios *tp;
  4.1682 +	int devpts = tty->driver->flags & TTY_DRIVER_DEVPTS_MEM;
  4.1683 +
  4.1684 +	if ((o_tty = tty->link) != NULL) {
  4.1685 +		if (!devpts)
  4.1686 +			o_tty->driver->ttys[idx] = NULL;
  4.1687 +		if (o_tty->driver->flags & TTY_DRIVER_RESET_TERMIOS) {
  4.1688 +			tp = o_tty->termios;
  4.1689 +			if (!devpts)
  4.1690 +				o_tty->driver->termios[idx] = NULL;
  4.1691 +			kfree(tp);
  4.1692 +
  4.1693 +			tp = o_tty->termios_locked;
  4.1694 +			if (!devpts)
  4.1695 +				o_tty->driver->termios_locked[idx] = NULL;
  4.1696 +			kfree(tp);
  4.1697 +		}
  4.1698 +		o_tty->magic = 0;
  4.1699 +		o_tty->driver->refcount--;
  4.1700 +		file_list_lock();
  4.1701 +		list_del_init(&o_tty->tty_files);
  4.1702 +		file_list_unlock();
  4.1703 +		free_tty_struct(o_tty);
  4.1704 +	}
  4.1705 +
  4.1706 +	if (!devpts)
  4.1707 +		tty->driver->ttys[idx] = NULL;
  4.1708 +	if (tty->driver->flags & TTY_DRIVER_RESET_TERMIOS) {
  4.1709 +		tp = tty->termios;
  4.1710 +		if (!devpts)
  4.1711 +			tty->driver->termios[idx] = NULL;
  4.1712 +		kfree(tp);
  4.1713 +
  4.1714 +		tp = tty->termios_locked;
  4.1715 +		if (!devpts)
  4.1716 +			tty->driver->termios_locked[idx] = NULL;
  4.1717 +		kfree(tp);
  4.1718 +	}
  4.1719 +
  4.1720 +	tty->magic = 0;
  4.1721 +	tty->driver->refcount--;
  4.1722 +	file_list_lock();
  4.1723 +	list_del_init(&tty->tty_files);
  4.1724 +	file_list_unlock();
  4.1725 +	module_put(tty->driver->owner);
  4.1726 +	free_tty_struct(tty);
  4.1727 +}
  4.1728 +
  4.1729 +/*
  4.1730 + * Even releasing the tty structures is a tricky business.. We have
  4.1731 + * to be very careful that the structures are all released at the
  4.1732 + * same time, as interrupts might otherwise get the wrong pointers.
  4.1733 + *
  4.1734 + * WSH 09/09/97: rewritten to avoid some nasty race conditions that could
  4.1735 + * lead to double frees or releasing memory still in use.
  4.1736 + */
  4.1737 +static void release_dev(struct file * filp)
  4.1738 +{
  4.1739 +	struct tty_struct *tty, *o_tty;
  4.1740 +	int	pty_master, tty_closing, o_tty_closing, do_sleep;
  4.1741 +	int	devpts_master, devpts;
  4.1742 +	int	idx;
  4.1743 +	char	buf[64];
  4.1744 +	unsigned long flags;
  4.1745 +	
  4.1746 +	tty = (struct tty_struct *)filp->private_data;
  4.1747 +	if (tty_paranoia_check(tty, filp->f_dentry->d_inode, "release_dev"))
  4.1748 +		return;
  4.1749 +
  4.1750 +	check_tty_count(tty, "release_dev");
  4.1751 +
  4.1752 +	tty_fasync(-1, filp, 0);
  4.1753 +
  4.1754 +	idx = tty->index;
  4.1755 +	pty_master = (tty->driver->type == TTY_DRIVER_TYPE_PTY &&
  4.1756 +		      tty->driver->subtype == PTY_TYPE_MASTER);
  4.1757 +	devpts = (tty->driver->flags & TTY_DRIVER_DEVPTS_MEM) != 0;
  4.1758 +	devpts_master = pty_master && devpts;
  4.1759 +	o_tty = tty->link;
  4.1760 +
  4.1761 +#ifdef TTY_PARANOIA_CHECK
  4.1762 +	if (idx < 0 || idx >= tty->driver->num) {
  4.1763 +		printk(KERN_DEBUG "release_dev: bad idx when trying to "
  4.1764 +				  "free (%s)\n", tty->name);
  4.1765 +		return;
  4.1766 +	}
  4.1767 +	if (!(tty->driver->flags & TTY_DRIVER_DEVPTS_MEM)) {
  4.1768 +		if (tty != tty->driver->ttys[idx]) {
  4.1769 +			printk(KERN_DEBUG "release_dev: driver.table[%d] not tty "
  4.1770 +			       "for (%s)\n", idx, tty->name);
  4.1771 +			return;
  4.1772 +		}
  4.1773 +		if (tty->termios != tty->driver->termios[idx]) {
  4.1774 +			printk(KERN_DEBUG "release_dev: driver.termios[%d] not termios "
  4.1775 +			       "for (%s)\n",
  4.1776 +			       idx, tty->name);
  4.1777 +			return;
  4.1778 +		}
  4.1779 +		if (tty->termios_locked != tty->driver->termios_locked[idx]) {
  4.1780 +			printk(KERN_DEBUG "release_dev: driver.termios_locked[%d] not "
  4.1781 +			       "termios_locked for (%s)\n",
  4.1782 +			       idx, tty->name);
  4.1783 +			return;
  4.1784 +		}
  4.1785 +	}
  4.1786 +#endif
  4.1787 +
  4.1788 +#ifdef TTY_DEBUG_HANGUP
  4.1789 +	printk(KERN_DEBUG "release_dev of %s (tty count=%d)...",
  4.1790 +	       tty_name(tty, buf), tty->count);
  4.1791 +#endif
  4.1792 +
  4.1793 +#ifdef TTY_PARANOIA_CHECK
  4.1794 +	if (tty->driver->other &&
  4.1795 +	     !(tty->driver->flags & TTY_DRIVER_DEVPTS_MEM)) {
  4.1796 +		if (o_tty != tty->driver->other->ttys[idx]) {
  4.1797 +			printk(KERN_DEBUG "release_dev: other->table[%d] "
  4.1798 +					  "not o_tty for (%s)\n",
  4.1799 +			       idx, tty->name);
  4.1800 +			return;
  4.1801 +		}
  4.1802 +		if (o_tty->termios != tty->driver->other->termios[idx]) {
  4.1803 +			printk(KERN_DEBUG "release_dev: other->termios[%d] "
  4.1804 +					  "not o_termios for (%s)\n",
  4.1805 +			       idx, tty->name);
  4.1806 +			return;
  4.1807 +		}
  4.1808 +		if (o_tty->termios_locked != 
  4.1809 +		      tty->driver->other->termios_locked[idx]) {
  4.1810 +			printk(KERN_DEBUG "release_dev: other->termios_locked["
  4.1811 +					  "%d] not o_termios_locked for (%s)\n",
  4.1812 +			       idx, tty->name);
  4.1813 +			return;
  4.1814 +		}
  4.1815 +		if (o_tty->link != tty) {
  4.1816 +			printk(KERN_DEBUG "release_dev: bad pty pointers\n");
  4.1817 +			return;
  4.1818 +		}
  4.1819 +	}
  4.1820 +#endif
  4.1821 +	if (tty->driver->close)
  4.1822 +		tty->driver->close(tty, filp);
  4.1823 +
  4.1824 +	/*
  4.1825 +	 * Sanity check: if tty->count is going to zero, there shouldn't be
  4.1826 +	 * any waiters on tty->read_wait or tty->write_wait.  We test the
  4.1827 +	 * wait queues and kick everyone out _before_ actually starting to
  4.1828 +	 * close.  This ensures that we won't block while releasing the tty
  4.1829 +	 * structure.
  4.1830 +	 *
  4.1831 +	 * The test for the o_tty closing is necessary, since the master and
  4.1832 +	 * slave sides may close in any order.  If the slave side closes out
  4.1833 +	 * first, its count will be one, since the master side holds an open.
  4.1834 +	 * Thus this test wouldn't be triggered at the time the slave closes,
  4.1835 +	 * so we do it now.
  4.1836 +	 *
  4.1837 +	 * Note that it's possible for the tty to be opened again while we're
  4.1838 +	 * flushing out waiters.  By recalculating the closing flags before
  4.1839 +	 * each iteration we avoid any problems.
  4.1840 +	 */
  4.1841 +	while (1) {
  4.1842 +		/* Guard against races with tty->count changes elsewhere and
  4.1843 +		   opens on /dev/tty */
  4.1844 +		   
  4.1845 +		down(&tty_sem);
  4.1846 +		tty_closing = tty->count <= 1;
  4.1847 +		o_tty_closing = o_tty &&
  4.1848 +			(o_tty->count <= (pty_master ? 1 : 0));
  4.1849 +		do_sleep = 0;
  4.1850 +
  4.1851 +		if (tty_closing) {
  4.1852 +			if (waitqueue_active(&tty->read_wait)) {
  4.1853 +				wake_up(&tty->read_wait);
  4.1854 +				do_sleep++;
  4.1855 +			}
  4.1856 +			if (waitqueue_active(&tty->write_wait)) {
  4.1857 +				wake_up(&tty->write_wait);
  4.1858 +				do_sleep++;
  4.1859 +			}
  4.1860 +		}
  4.1861 +		if (o_tty_closing) {
  4.1862 +			if (waitqueue_active(&o_tty->read_wait)) {
  4.1863 +				wake_up(&o_tty->read_wait);
  4.1864 +				do_sleep++;
  4.1865 +			}
  4.1866 +			if (waitqueue_active(&o_tty->write_wait)) {
  4.1867 +				wake_up(&o_tty->write_wait);
  4.1868 +				do_sleep++;
  4.1869 +			}
  4.1870 +		}
  4.1871 +		if (!do_sleep)
  4.1872 +			break;
  4.1873 +
  4.1874 +		printk(KERN_WARNING "release_dev: %s: read/write wait queue "
  4.1875 +				    "active!\n", tty_name(tty, buf));
  4.1876 +		up(&tty_sem);
  4.1877 +		schedule();
  4.1878 +	}	
  4.1879 +
  4.1880 +	/*
  4.1881 +	 * The closing flags are now consistent with the open counts on 
  4.1882 +	 * both sides, and we've completed the last operation that could 
  4.1883 +	 * block, so it's safe to proceed with closing.
  4.1884 +	 */
  4.1885 +	if (pty_master) {
  4.1886 +		if (--o_tty->count < 0) {
  4.1887 +			printk(KERN_WARNING "release_dev: bad pty slave count "
  4.1888 +					    "(%d) for %s\n",
  4.1889 +			       o_tty->count, tty_name(o_tty, buf));
  4.1890 +			o_tty->count = 0;
  4.1891 +		}
  4.1892 +	}
  4.1893 +	if (--tty->count < 0) {
  4.1894 +		printk(KERN_WARNING "release_dev: bad tty->count (%d) for %s\n",
  4.1895 +		       tty->count, tty_name(tty, buf));
  4.1896 +		tty->count = 0;
  4.1897 +	}
  4.1898 +	
  4.1899 +	/*
  4.1900 +	 * We've decremented tty->count, so we need to remove this file
  4.1901 +	 * descriptor off the tty->tty_files list; this serves two
  4.1902 +	 * purposes:
  4.1903 +	 *  - check_tty_count sees the correct number of file descriptors
  4.1904 +	 *    associated with this tty.
  4.1905 +	 *  - do_tty_hangup no longer sees this file descriptor as
  4.1906 +	 *    something that needs to be handled for hangups.
  4.1907 +	 */
  4.1908 +	file_kill(filp);
  4.1909 +	filp->private_data = NULL;
  4.1910 +
  4.1911 +	/*
  4.1912 +	 * Perform some housekeeping before deciding whether to return.
  4.1913 +	 *
  4.1914 +	 * Set the TTY_CLOSING flag if this was the last open.  In the
  4.1915 +	 * case of a pty we may have to wait around for the other side
  4.1916 +	 * to close, and TTY_CLOSING makes sure we can't be reopened.
  4.1917 +	 */
  4.1918 +	if(tty_closing)
  4.1919 +		set_bit(TTY_CLOSING, &tty->flags);
  4.1920 +	if(o_tty_closing)
  4.1921 +		set_bit(TTY_CLOSING, &o_tty->flags);
  4.1922 +
  4.1923 +	/*
  4.1924 +	 * If _either_ side is closing, make sure there aren't any
  4.1925 +	 * processes that still think tty or o_tty is their controlling
  4.1926 +	 * tty.
  4.1927 +	 */
  4.1928 +	if (tty_closing || o_tty_closing) {
  4.1929 +		struct task_struct *p;
  4.1930 +
  4.1931 +		read_lock(&tasklist_lock);
  4.1932 +		do_each_task_pid(tty->session, PIDTYPE_SID, p) {
  4.1933 +			p->signal->tty = NULL;
  4.1934 +		} while_each_task_pid(tty->session, PIDTYPE_SID, p);
  4.1935 +		if (o_tty)
  4.1936 +			do_each_task_pid(o_tty->session, PIDTYPE_SID, p) {
  4.1937 +				p->signal->tty = NULL;
  4.1938 +			} while_each_task_pid(o_tty->session, PIDTYPE_SID, p);
  4.1939 +		read_unlock(&tasklist_lock);
  4.1940 +	}
  4.1941 +
  4.1942 +	up(&tty_sem);
  4.1943 +
  4.1944 +	/* check whether both sides are closing ... */
  4.1945 +	if (!tty_closing || (o_tty && !o_tty_closing))
  4.1946 +		return;
  4.1947 +	
  4.1948 +#ifdef TTY_DEBUG_HANGUP
  4.1949 +	printk(KERN_DEBUG "freeing tty structure...");
  4.1950 +#endif
  4.1951 +	/*
  4.1952 +	 * Prevent flush_to_ldisc() from rescheduling the work for later.  Then
  4.1953 +	 * kill any delayed work. As this is the final close it does not
  4.1954 +	 * race with the set_ldisc code path.
  4.1955 +	 */
  4.1956 +	clear_bit(TTY_LDISC, &tty->flags);
  4.1957 +	clear_bit(TTY_DONT_FLIP, &tty->flags);
  4.1958 +	cancel_delayed_work(&tty->buf.work);
  4.1959 +
  4.1960 +	/*
  4.1961 +	 * Wait for ->hangup_work and ->buf.work handlers to terminate
  4.1962 +	 */
  4.1963 +	 
  4.1964 +	flush_scheduled_work();
  4.1965 +	
  4.1966 +	/*
  4.1967 +	 * Wait for any short term users (we know they are just driver
  4.1968 +	 * side waiters as the file is closing so user count on the file
  4.1969 +	 * side is zero.
  4.1970 +	 */
  4.1971 +	spin_lock_irqsave(&tty_ldisc_lock, flags);
  4.1972 +	while(tty->ldisc.refcount)
  4.1973 +	{
  4.1974 +		spin_unlock_irqrestore(&tty_ldisc_lock, flags);
  4.1975 +		wait_event(tty_ldisc_wait, tty->ldisc.refcount == 0);
  4.1976 +		spin_lock_irqsave(&tty_ldisc_lock, flags);
  4.1977 +	}
  4.1978 +	spin_unlock_irqrestore(&tty_ldisc_lock, flags);
  4.1979 +	/*
  4.1980 +	 * Shutdown the current line discipline, and reset it to N_TTY.
  4.1981 +	 * N.B. why reset ldisc when we're releasing the memory??
  4.1982 +	 *
  4.1983 +	 * FIXME: this MUST get fixed for the new reflocking
  4.1984 +	 */
  4.1985 +	if (tty->ldisc.close)
  4.1986 +		(tty->ldisc.close)(tty);
  4.1987 +	tty_ldisc_put(tty->ldisc.num);
  4.1988 +	
  4.1989 +	/*
  4.1990 +	 *	Switch the line discipline back
  4.1991 +	 */
  4.1992 +	tty_ldisc_assign(tty, tty_ldisc_get(N_TTY));
  4.1993 +	tty_set_termios_ldisc(tty,N_TTY); 
  4.1994 +	if (o_tty) {
  4.1995 +		/* FIXME: could o_tty be in setldisc here ? */
  4.1996 +		clear_bit(TTY_LDISC, &o_tty->flags);
  4.1997 +		if (o_tty->ldisc.close)
  4.1998 +			(o_tty->ldisc.close)(o_tty);
  4.1999 +		tty_ldisc_put(o_tty->ldisc.num);
  4.2000 +		tty_ldisc_assign(o_tty, tty_ldisc_get(N_TTY));
  4.2001 +		tty_set_termios_ldisc(o_tty,N_TTY); 
  4.2002 +	}
  4.2003 +	/*
  4.2004 +	 * The release_mem function takes care of the details of clearing
  4.2005 +	 * the slots and preserving the termios structure.
  4.2006 +	 */
  4.2007 +	release_mem(tty, idx);
  4.2008 +
  4.2009 +#ifdef CONFIG_UNIX98_PTYS
  4.2010 +	/* Make this pty number available for reallocation */
  4.2011 +	if (devpts) {
  4.2012 +		down(&allocated_ptys_lock);
  4.2013 +		idr_remove(&allocated_ptys, idx);
  4.2014 +		up(&allocated_ptys_lock);
  4.2015 +	}
  4.2016 +#endif
  4.2017 +
  4.2018 +}
  4.2019 +
  4.2020 +/*
  4.2021 + * tty_open and tty_release keep up the tty count that contains the
  4.2022 + * number of opens done on a tty. We cannot use the inode-count, as
  4.2023 + * different inodes might point to the same tty.
  4.2024 + *
  4.2025 + * Open-counting is needed for pty masters, as well as for keeping
  4.2026 + * track of serial lines: DTR is dropped when the last close happens.
  4.2027 + * (This is not done solely through tty->count, now.  - Ted 1/27/92)
  4.2028 + *
  4.2029 + * The termios state of a pty is reset on first open so that
  4.2030 + * settings don't persist across reuse.
  4.2031 + */
  4.2032 +static int tty_open(struct inode * inode, struct file * filp)
  4.2033 +{
  4.2034 +	struct tty_struct *tty;
  4.2035 +	int noctty, retval;
  4.2036 +	struct tty_driver *driver;
  4.2037 +	int index;
  4.2038 +	dev_t device = inode->i_rdev;
  4.2039 +	unsigned short saved_flags = filp->f_flags;
  4.2040 +
  4.2041 +	nonseekable_open(inode, filp);
  4.2042 +	
  4.2043 +retry_open:
  4.2044 +	noctty = filp->f_flags & O_NOCTTY;
  4.2045 +	index  = -1;
  4.2046 +	retval = 0;
  4.2047 +	
  4.2048 +	down(&tty_sem);
  4.2049 +
  4.2050 +	if (device == MKDEV(TTYAUX_MAJOR,0)) {
  4.2051 +		if (!current->signal->tty) {
  4.2052 +			up(&tty_sem);
  4.2053 +			return -ENXIO;
  4.2054 +		}
  4.2055 +		driver = current->signal->tty->driver;
  4.2056 +		index = current->signal->tty->index;
  4.2057 +		filp->f_flags |= O_NONBLOCK; /* Don't let /dev/tty block */
  4.2058 +		/* noctty = 1; */
  4.2059 +		goto got_driver;
  4.2060 +	}
  4.2061 +#ifdef CONFIG_VT
  4.2062 +	if (console_use_vt && (device == MKDEV(TTY_MAJOR,0))) {
  4.2063 +		extern struct tty_driver *console_driver;
  4.2064 +		driver = console_driver;
  4.2065 +		index = fg_console;
  4.2066 +		noctty = 1;
  4.2067 +		goto got_driver;
  4.2068 +	}
  4.2069 +#endif
  4.2070 +	if (device == MKDEV(TTYAUX_MAJOR,1)) {
  4.2071 +		driver = console_device(&index);
  4.2072 +		if (driver) {
  4.2073 +			/* Don't let /dev/console block */
  4.2074 +			filp->f_flags |= O_NONBLOCK;
  4.2075 +			noctty = 1;
  4.2076 +			goto got_driver;
  4.2077 +		}
  4.2078 +		up(&tty_sem);
  4.2079 +		return -ENODEV;
  4.2080 +	}
  4.2081 +
  4.2082 +	driver = get_tty_driver(device, &index);
  4.2083 +	if (!driver) {
  4.2084 +		up(&tty_sem);
  4.2085 +		return -ENODEV;
  4.2086 +	}
  4.2087 +got_driver:
  4.2088 +	retval = init_dev(driver, index, &tty);
  4.2089 +	up(&tty_sem);
  4.2090 +	if (retval)
  4.2091 +		return retval;
  4.2092 +
  4.2093 +	filp->private_data = tty;
  4.2094 +	file_move(filp, &tty->tty_files);
  4.2095 +	check_tty_count(tty, "tty_open");
  4.2096 +	if (tty->driver->type == TTY_DRIVER_TYPE_PTY &&
  4.2097 +	    tty->driver->subtype == PTY_TYPE_MASTER)
  4.2098 +		noctty = 1;
  4.2099 +#ifdef TTY_DEBUG_HANGUP
  4.2100 +	printk(KERN_DEBUG "opening %s...", tty->name);
  4.2101 +#endif
  4.2102 +	if (!retval) {
  4.2103 +		if (tty->driver->open)
  4.2104 +			retval = tty->driver->open(tty, filp);
  4.2105 +		else
  4.2106 +			retval = -ENODEV;
  4.2107 +	}
  4.2108 +	filp->f_flags = saved_flags;
  4.2109 +
  4.2110 +	if (!retval && test_bit(TTY_EXCLUSIVE, &tty->flags) && !capable(CAP_SYS_ADMIN))
  4.2111 +		retval = -EBUSY;
  4.2112 +
  4.2113 +	if (retval) {
  4.2114 +#ifdef TTY_DEBUG_HANGUP
  4.2115 +		printk(KERN_DEBUG "error %d in opening %s...", retval,
  4.2116 +		       tty->name);
  4.2117 +#endif
  4.2118 +		release_dev(filp);
  4.2119 +		if (retval != -ERESTARTSYS)
  4.2120 +			return retval;
  4.2121 +		if (signal_pending(current))
  4.2122 +			return retval;
  4.2123 +		schedule();
  4.2124 +		/*
  4.2125 +		 * Need to reset f_op in case a hangup happened.
  4.2126 +		 */
  4.2127 +		if (filp->f_op == &hung_up_tty_fops)
  4.2128 +			filp->f_op = &tty_fops;
  4.2129 +		goto retry_open;
  4.2130 +	}
  4.2131 +	if (!noctty &&
  4.2132 +	    current->signal->leader &&
  4.2133 +	    !current->signal->tty &&
  4.2134 +	    tty->session == 0) {
  4.2135 +	    	task_lock(current);
  4.2136 +		current->signal->tty = tty;
  4.2137 +		task_unlock(current);
  4.2138 +		current->signal->tty_old_pgrp = 0;
  4.2139 +		tty->session = current->signal->session;
  4.2140 +		tty->pgrp = process_group(current);
  4.2141 +	}
  4.2142 +	return 0;
  4.2143 +}
  4.2144 +
  4.2145 +#ifdef CONFIG_UNIX98_PTYS
  4.2146 +static int ptmx_open(struct inode * inode, struct file * filp)
  4.2147 +{
  4.2148 +	struct tty_struct *tty;
  4.2149 +	int retval;
  4.2150 +	int index;
  4.2151 +	int idr_ret;
  4.2152 +
  4.2153 +	nonseekable_open(inode, filp);
  4.2154 +
  4.2155 +	/* find a device that is not in use. */
  4.2156 +	down(&allocated_ptys_lock);
  4.2157 +	if (!idr_pre_get(&allocated_ptys, GFP_KERNEL)) {
  4.2158 +		up(&allocated_ptys_lock);
  4.2159 +		return -ENOMEM;
  4.2160 +	}
  4.2161 +	idr_ret = idr_get_new(&allocated_ptys, NULL, &index);
  4.2162 +	if (idr_ret < 0) {
  4.2163 +		up(&allocated_ptys_lock);
  4.2164 +		if (idr_ret == -EAGAIN)
  4.2165 +			return -ENOMEM;
  4.2166 +		return -EIO;
  4.2167 +	}
  4.2168 +	if (index >= pty_limit) {
  4.2169 +		idr_remove(&allocated_ptys, index);
  4.2170 +		up(&allocated_ptys_lock);
  4.2171 +		return -EIO;
  4.2172 +	}
  4.2173 +	up(&allocated_ptys_lock);
  4.2174 +
  4.2175 +	down(&tty_sem);
  4.2176 +	retval = init_dev(ptm_driver, index, &tty);
  4.2177 +	up(&tty_sem);
  4.2178 +	
  4.2179 +	if (retval)
  4.2180 +		goto out;
  4.2181 +
  4.2182 +	set_bit(TTY_PTY_LOCK, &tty->flags); /* LOCK THE SLAVE */
  4.2183 +	filp->private_data = tty;
  4.2184 +	file_move(filp, &tty->tty_files);
  4.2185 +
  4.2186 +	retval = -ENOMEM;
  4.2187 +	if (devpts_pty_new(tty->link))
  4.2188 +		goto out1;
  4.2189 +
  4.2190 +	check_tty_count(tty, "tty_open");
  4.2191 +	retval = ptm_driver->open(tty, filp);
  4.2192 +	if (!retval)
  4.2193 +		return 0;
  4.2194 +out1:
  4.2195 +	release_dev(filp);
  4.2196 +out:
  4.2197 +	down(&allocated_ptys_lock);
  4.2198 +	idr_remove(&allocated_ptys, index);
  4.2199 +	up(&allocated_ptys_lock);
  4.2200 +	return retval;
  4.2201 +}
  4.2202 +#endif
  4.2203 +
  4.2204 +static int tty_release(struct inode * inode, struct file * filp)
  4.2205 +{
  4.2206 +	lock_kernel();
  4.2207 +	release_dev(filp);
  4.2208 +	unlock_kernel();
  4.2209 +	return 0;
  4.2210 +}
  4.2211 +
  4.2212 +/* No kernel lock held - fine */
  4.2213 +static unsigned int tty_poll(struct file * filp, poll_table * wait)
  4.2214 +{
  4.2215 +	struct tty_struct * tty;
  4.2216 +	struct tty_ldisc *ld;
  4.2217 +	int ret = 0;
  4.2218 +
  4.2219 +	tty = (struct tty_struct *)filp->private_data;
  4.2220 +	if (tty_paranoia_check(tty, filp->f_dentry->d_inode, "tty_poll"))
  4.2221 +		return 0;
  4.2222 +		
  4.2223 +	ld = tty_ldisc_ref_wait(tty);
  4.2224 +	if (ld->poll)
  4.2225 +		ret = (ld->poll)(tty, filp, wait);
  4.2226 +	tty_ldisc_deref(ld);
  4.2227 +	return ret;
  4.2228 +}
  4.2229 +
  4.2230 +static int tty_fasync(int fd, struct file * filp, int on)
  4.2231 +{
  4.2232 +	struct tty_struct * tty;
  4.2233 +	int retval;
  4.2234 +
  4.2235 +	tty = (struct tty_struct *)filp->private_data;
  4.2236 +	if (tty_paranoia_check(tty, filp->f_dentry->d_inode, "tty_fasync"))
  4.2237 +		return 0;
  4.2238 +	
  4.2239 +	retval = fasync_helper(fd, filp, on, &tty->fasync);
  4.2240 +	if (retval <= 0)
  4.2241 +		return retval;
  4.2242 +
  4.2243 +	if (on) {
  4.2244 +		if (!waitqueue_active(&tty->read_wait))
  4.2245 +			tty->minimum_to_wake = 1;
  4.2246 +		retval = f_setown(filp, (-tty->pgrp) ? : current->pid, 0);
  4.2247 +		if (retval)
  4.2248 +			return retval;
  4.2249 +	} else {
  4.2250 +		if (!tty->fasync && !waitqueue_active(&tty->read_wait))
  4.2251 +			tty->minimum_to_wake = N_TTY_BUF_SIZE;
  4.2252 +	}
  4.2253 +	return 0;
  4.2254 +}
  4.2255 +
  4.2256 +static int tiocsti(struct tty_struct *tty, char __user *p)
  4.2257 +{
  4.2258 +	char ch, mbz = 0;
  4.2259 +	struct tty_ldisc *ld;
  4.2260 +	
  4.2261 +	if ((current->signal->tty != tty) && !capable(CAP_SYS_ADMIN))
  4.2262 +		return -EPERM;
  4.2263 +	if (get_user(ch, p))
  4.2264 +		return -EFAULT;
  4.2265 +	ld = tty_ldisc_ref_wait(tty);
  4.2266 +	ld->receive_buf(tty, &ch, &mbz, 1);
  4.2267 +	tty_ldisc_deref(ld);
  4.2268 +	return 0;
  4.2269 +}
  4.2270 +
  4.2271 +static int tiocgwinsz(struct tty_struct *tty, struct winsize __user * arg)
  4.2272 +{
  4.2273 +	if (copy_to_user(arg, &tty->winsize, sizeof(*arg)))
  4.2274 +		return -EFAULT;
  4.2275 +	return 0;
  4.2276 +}
  4.2277 +
  4.2278 +static int tiocswinsz(struct tty_struct *tty, struct tty_struct *real_tty,
  4.2279 +	struct winsize __user * arg)
  4.2280 +{
  4.2281 +	struct winsize tmp_ws;
  4.2282 +
  4.2283 +	if (copy_from_user(&tmp_ws, arg, sizeof(*arg)))
  4.2284 +		return -EFAULT;
  4.2285 +	if (!memcmp(&tmp_ws, &tty->winsize, sizeof(*arg)))
  4.2286 +		return 0;
  4.2287 +#ifdef CONFIG_VT
  4.2288 +	if (tty->driver->type == TTY_DRIVER_TYPE_CONSOLE) {
  4.2289 +		int rc;
  4.2290 +
  4.2291 +		acquire_console_sem();
  4.2292 +		rc = vc_resize(tty->driver_data, tmp_ws.ws_col, tmp_ws.ws_row);
  4.2293 +		release_console_sem();
  4.2294 +		if (rc)
  4.2295 +			return -ENXIO;
  4.2296 +	}
  4.2297 +#endif
  4.2298 +	if (tty->pgrp > 0)
  4.2299 +		kill_pg(tty->pgrp, SIGWINCH, 1);
  4.2300 +	if ((real_tty->pgrp != tty->pgrp) && (real_tty->pgrp > 0))
  4.2301 +		kill_pg(real_tty->pgrp, SIGWINCH, 1);
  4.2302 +	tty->winsize = tmp_ws;
  4.2303 +	real_tty->winsize = tmp_ws;
  4.2304 +	return 0;
  4.2305 +}
  4.2306 +
  4.2307 +static int tioccons(struct file *file)
  4.2308 +{
  4.2309 +	if (!capable(CAP_SYS_ADMIN))
  4.2310 +		return -EPERM;
  4.2311 +	if (file->f_op->write == redirected_tty_write) {
  4.2312 +		struct file *f;
  4.2313 +		spin_lock(&redirect_lock);
  4.2314 +		f = redirect;
  4.2315 +		redirect = NULL;
  4.2316 +		spin_unlock(&redirect_lock);
  4.2317 +		if (f)
  4.2318 +			fput(f);
  4.2319 +		return 0;
  4.2320 +	}
  4.2321 +	spin_lock(&redirect_lock);
  4.2322 +	if (redirect) {
  4.2323 +		spin_unlock(&redirect_lock);
  4.2324 +		return -EBUSY;
  4.2325 +	}
  4.2326 +	get_file(file);
  4.2327 +	redirect = file;
  4.2328 +	spin_unlock(&redirect_lock);
  4.2329 +	return 0;
  4.2330 +}
  4.2331 +
  4.2332 +
  4.2333 +static int fionbio(struct file *file, int __user *p)
  4.2334 +{
  4.2335 +	int nonblock;
  4.2336 +
  4.2337 +	if (get_user(nonblock, p))
  4.2338 +		return -EFAULT;
  4.2339 +
  4.2340 +	if (nonblock)
  4.2341 +		file->f_flags |= O_NONBLOCK;
  4.2342 +	else
  4.2343 +		file->f_flags &= ~O_NONBLOCK;
  4.2344 +	return 0;
  4.2345 +}
  4.2346 +
  4.2347 +static int tiocsctty(struct tty_struct *tty, int arg)
  4.2348 +{
  4.2349 +	task_t *p;
  4.2350 +
  4.2351 +	if (current->signal->leader &&
  4.2352 +	    (current->signal->session == tty->session))
  4.2353 +		return 0;
  4.2354 +	/*
  4.2355 +	 * The process must be a session leader and
  4.2356 +	 * not have a controlling tty already.
  4.2357 +	 */
  4.2358 +	if (!current->signal->leader || current->signal->tty)
  4.2359 +		return -EPERM;
  4.2360 +	if (tty->session > 0) {
  4.2361 +		/*
  4.2362 +		 * This tty is already the controlling
  4.2363 +		 * tty for another session group!
  4.2364 +		 */
  4.2365 +		if ((arg == 1) && capable(CAP_SYS_ADMIN)) {
  4.2366 +			/*
  4.2367 +			 * Steal it away
  4.2368 +			 */
  4.2369 +
  4.2370 +			read_lock(&tasklist_lock);
  4.2371 +			do_each_task_pid(tty->session, PIDTYPE_SID, p) {
  4.2372 +				p->signal->tty = NULL;
  4.2373 +			} while_each_task_pid(tty->session, PIDTYPE_SID, p);
  4.2374 +			read_unlock(&tasklist_lock);
  4.2375 +		} else
  4.2376 +			return -EPERM;
  4.2377 +	}
  4.2378 +	task_lock(current);
  4.2379 +	current->signal->tty = tty;
  4.2380 +	task_unlock(current);
  4.2381 +	current->signal->tty_old_pgrp = 0;
  4.2382 +	tty->session = current->signal->session;
  4.2383 +	tty->pgrp = process_group(current);
  4.2384 +	return 0;
  4.2385 +}
  4.2386 +
  4.2387 +static int tiocgpgrp(struct tty_struct *tty, struct tty_struct *real_tty, pid_t __user *p)
  4.2388 +{
  4.2389 +	/*
  4.2390 +	 * (tty == real_tty) is a cheap way of
  4.2391 +	 * testing if the tty is NOT a master pty.
  4.2392 +	 */
  4.2393 +	if (tty == real_tty && current->signal->tty != real_tty)
  4.2394 +		return -ENOTTY;
  4.2395 +	return put_user(real_tty->pgrp, p);
  4.2396 +}
  4.2397 +
  4.2398 +static int tiocspgrp(struct tty_struct *tty, struct tty_struct *real_tty, pid_t __user *p)
  4.2399 +{
  4.2400 +	pid_t pgrp;
  4.2401 +	int retval = tty_check_change(real_tty);
  4.2402 +
  4.2403 +	if (retval == -EIO)
  4.2404 +		return -ENOTTY;
  4.2405 +	if (retval)
  4.2406 +		return retval;
  4.2407 +	if (!current->signal->tty ||
  4.2408 +	    (current->signal->tty != real_tty) ||
  4.2409 +	    (real_tty->session != current->signal->session))
  4.2410 +		return -ENOTTY;
  4.2411 +	if (get_user(pgrp, p))
  4.2412 +		return -EFAULT;
  4.2413 +	if (pgrp < 0)
  4.2414 +		return -EINVAL;
  4.2415 +	if (session_of_pgrp(pgrp) != current->signal->session)
  4.2416 +		return -EPERM;
  4.2417 +	real_tty->pgrp = pgrp;
  4.2418 +	return 0;
  4.2419 +}
  4.2420 +
  4.2421 +static int tiocgsid(struct tty_struct *tty, struct tty_struct *real_tty, pid_t __user *p)
  4.2422 +{
  4.2423 +	/*
  4.2424 +	 * (tty == real_tty) is a cheap way of
  4.2425 +	 * testing if the tty is NOT a master pty.
  4.2426 +	*/
  4.2427 +	if (tty == real_tty && current->signal->tty != real_tty)
  4.2428 +		return -ENOTTY;
  4.2429 +	if (real_tty->session <= 0)
  4.2430 +		return -ENOTTY;
  4.2431 +	return put_user(real_tty->session, p);
  4.2432 +}
  4.2433 +
  4.2434 +static int tiocsetd(struct tty_struct *tty, int __user *p)
  4.2435 +{
  4.2436 +	int ldisc;
  4.2437 +
  4.2438 +	if (get_user(ldisc, p))
  4.2439 +		return -EFAULT;
  4.2440 +	return tty_set_ldisc(tty, ldisc);
  4.2441 +}
  4.2442 +
  4.2443 +static int send_break(struct tty_struct *tty, unsigned int duration)
  4.2444 +{
  4.2445 +	tty->driver->break_ctl(tty, -1);
  4.2446 +	if (!signal_pending(current)) {
  4.2447 +		msleep_interruptible(duration);
  4.2448 +	}
  4.2449 +	tty->driver->break_ctl(tty, 0);
  4.2450 +	if (signal_pending(current))
  4.2451 +		return -EINTR;
  4.2452 +	return 0;
  4.2453 +}
  4.2454 +
  4.2455 +static int
  4.2456 +tty_tiocmget(struct tty_struct *tty, struct file *file, int __user *p)
  4.2457 +{
  4.2458 +	int retval = -EINVAL;
  4.2459 +
  4.2460 +	if (tty->driver->tiocmget) {
  4.2461 +		retval = tty->driver->tiocmget(tty, file);
  4.2462 +
  4.2463 +		if (retval >= 0)
  4.2464 +			retval = put_user(retval, p);
  4.2465 +	}
  4.2466 +	return retval;
  4.2467 +}
  4.2468 +
  4.2469 +static int
  4.2470 +tty_tiocmset(struct tty_struct *tty, struct file *file, unsigned int cmd,
  4.2471 +	     unsigned __user *p)
  4.2472 +{
  4.2473 +	int retval = -EINVAL;
  4.2474 +
  4.2475 +	if (tty->driver->tiocmset) {
  4.2476 +		unsigned int set, clear, val;
  4.2477 +
  4.2478 +		retval = get_user(val, p);
  4.2479 +		if (retval)
  4.2480 +			return retval;
  4.2481 +
  4.2482 +		set = clear = 0;
  4.2483 +		switch (cmd) {
  4.2484 +		case TIOCMBIS:
  4.2485 +			set = val;
  4.2486 +			break;
  4.2487 +		case TIOCMBIC:
  4.2488 +			clear = val;
  4.2489 +			break;
  4.2490 +		case TIOCMSET:
  4.2491 +			set = val;
  4.2492 +			clear = ~val;
  4.2493 +			break;
  4.2494 +		}
  4.2495 +
  4.2496 +		set &= TIOCM_DTR|TIOCM_RTS|TIOCM_OUT1|TIOCM_OUT2|TIOCM_LOOP;
  4.2497 +		clear &= TIOCM_DTR|TIOCM_RTS|TIOCM_OUT1|TIOCM_OUT2|TIOCM_LOOP;
  4.2498 +
  4.2499 +		retval = tty->driver->tiocmset(tty, file, set, clear);
  4.2500 +	}
  4.2501 +	return retval;
  4.2502 +}
  4.2503 +
  4.2504 +/*
  4.2505 + * Split this up, as gcc can choke on it otherwise..
  4.2506 + */
  4.2507 +int tty_ioctl(struct inode * inode, struct file * file,
  4.2508 +	      unsigned int cmd, unsigned long arg)
  4.2509 +{
  4.2510 +	struct tty_struct *tty, *real_tty;
  4.2511 +	void __user *p = (void __user *)arg;
  4.2512 +	int retval;
  4.2513 +	struct tty_ldisc *ld;
  4.2514 +	
  4.2515 +	tty = (struct tty_struct *)file->private_data;
  4.2516 +	if (tty_paranoia_check(tty, inode, "tty_ioctl"))
  4.2517 +		return -EINVAL;
  4.2518 +
  4.2519 +	real_tty = tty;
  4.2520 +	if (tty->driver->type == TTY_DRIVER_TYPE_PTY &&
  4.2521 +	    tty->driver->subtype == PTY_TYPE_MASTER)
  4.2522 +		real_tty = tty->link;
  4.2523 +
  4.2524 +	/*
  4.2525 +	 * Break handling by driver
  4.2526 +	 */
  4.2527 +	if (!tty->driver->break_ctl) {
  4.2528 +		switch(cmd) {
  4.2529 +		case TIOCSBRK:
  4.2530 +		case TIOCCBRK:
  4.2531 +			if (tty->driver->ioctl)
  4.2532 +				return tty->driver->ioctl(tty, file, cmd, arg);
  4.2533 +			return -EINVAL;
  4.2534 +			
  4.2535 +		/* These two ioctl's always return success; even if */
  4.2536 +		/* the driver doesn't support them. */
  4.2537 +		case TCSBRK:
  4.2538 +		case TCSBRKP:
  4.2539 +			if (!tty->driver->ioctl)
  4.2540 +				return 0;
  4.2541 +			retval = tty->driver->ioctl(tty, file, cmd, arg);
  4.2542 +			if (retval == -ENOIOCTLCMD)
  4.2543 +				retval = 0;
  4.2544 +			return retval;
  4.2545 +		}
  4.2546 +	}
  4.2547 +
  4.2548 +	/*
  4.2549 +	 * Factor out some common prep work
  4.2550 +	 */
  4.2551 +	switch (cmd) {
  4.2552 +	case TIOCSETD:
  4.2553 +	case TIOCSBRK:
  4.2554 +	case TIOCCBRK:
  4.2555 +	case TCSBRK:
  4.2556 +	case TCSBRKP:			
  4.2557 +		retval = tty_check_change(tty);
  4.2558 +		if (retval)
  4.2559 +			return retval;
  4.2560 +		if (cmd != TIOCCBRK) {
  4.2561 +			tty_wait_until_sent(tty, 0);
  4.2562 +			if (signal_pending(current))
  4.2563 +				return -EINTR;
  4.2564 +		}
  4.2565 +		break;
  4.2566 +	}
  4.2567 +
  4.2568 +	switch (cmd) {
  4.2569 +		case TIOCSTI:
  4.2570 +			return tiocsti(tty, p);
  4.2571 +		case TIOCGWINSZ:
  4.2572 +			return tiocgwinsz(tty, p);
  4.2573 +		case TIOCSWINSZ:
  4.2574 +			return tiocswinsz(tty, real_tty, p);
  4.2575 +		case TIOCCONS:
  4.2576 +			return real_tty!=tty ? -EINVAL : tioccons(file);
  4.2577 +		case FIONBIO:
  4.2578 +			return fionbio(file, p);
  4.2579 +		case TIOCEXCL:
  4.2580 +			set_bit(TTY_EXCLUSIVE, &tty->flags);
  4.2581 +			return 0;
  4.2582 +		case TIOCNXCL:
  4.2583 +			clear_bit(TTY_EXCLUSIVE, &tty->flags);
  4.2584 +			return 0;
  4.2585 +		case TIOCNOTTY:
  4.2586 +			if (current->signal->tty != tty)
  4.2587 +				return -ENOTTY;
  4.2588 +			if (current->signal->leader)
  4.2589 +				disassociate_ctty(0);
  4.2590 +			task_lock(current);
  4.2591 +			current->signal->tty = NULL;
  4.2592 +			task_unlock(current);
  4.2593 +			return 0;
  4.2594 +		case TIOCSCTTY:
  4.2595 +			return tiocsctty(tty, arg);
  4.2596 +		case TIOCGPGRP:
  4.2597 +			return tiocgpgrp(tty, real_tty, p);
  4.2598 +		case TIOCSPGRP:
  4.2599 +			return tiocspgrp(tty, real_tty, p);
  4.2600 +		case TIOCGSID:
  4.2601 +			return tiocgsid(tty, real_tty, p);
  4.2602 +		case TIOCGETD:
  4.2603 +			/* FIXME: check this is ok */
  4.2604 +			return put_user(tty->ldisc.num, (int __user *)p);
  4.2605 +		case TIOCSETD:
  4.2606 +			return tiocsetd(tty, p);
  4.2607 +#ifdef CONFIG_VT
  4.2608 +		case TIOCLINUX:
  4.2609 +			return tioclinux(tty, arg);
  4.2610 +#endif
  4.2611 +		/*
  4.2612 +		 * Break handling
  4.2613 +		 */
  4.2614 +		case TIOCSBRK:	/* Turn break on, unconditionally */
  4.2615 +			tty->driver->break_ctl(tty, -1);
  4.2616 +			return 0;
  4.2617 +			
  4.2618 +		case TIOCCBRK:	/* Turn break off, unconditionally */
  4.2619 +			tty->driver->break_ctl(tty, 0);
  4.2620 +			return 0;
  4.2621 +		case TCSBRK:   /* SVID version: non-zero arg --> no break */
  4.2622 +			/*
  4.2623 +			 * XXX is the above comment correct, or the
  4.2624 +			 * code below correct?  Is this ioctl used at
  4.2625 +			 * all by anyone?
  4.2626 +			 */
  4.2627 +			if (!arg)
  4.2628 +				return send_break(tty, 250);
  4.2629 +			return 0;
  4.2630 +		case TCSBRKP:	/* support for POSIX tcsendbreak() */	
  4.2631 +			return send_break(tty, arg ? arg*100 : 250);
  4.2632 +
  4.2633 +		case TIOCMGET:
  4.2634 +			return tty_tiocmget(tty, file, p);
  4.2635 +
  4.2636 +		case TIOCMSET:
  4.2637 +		case TIOCMBIC:
  4.2638 +		case TIOCMBIS:
  4.2639 +			return tty_tiocmset(tty, file, cmd, p);
  4.2640 +	}
  4.2641 +	if (tty->driver->ioctl) {
  4.2642 +		retval = (tty->driver->ioctl)(tty, file, cmd, arg);
  4.2643 +		if (retval != -ENOIOCTLCMD)
  4.2644 +			return retval;
  4.2645 +	}
  4.2646 +	ld = tty_ldisc_ref_wait(tty);
  4.2647 +	retval = -EINVAL;
  4.2648 +	if (ld->ioctl) {
  4.2649 +		retval = ld->ioctl(tty, file, cmd, arg);
  4.2650 +		if (retval == -ENOIOCTLCMD)
  4.2651 +			retval = -EINVAL;
  4.2652 +	}
  4.2653 +	tty_ldisc_deref(ld);
  4.2654 +	return retval;
  4.2655 +}
  4.2656 +
  4.2657 +
  4.2658 +/*
  4.2659 + * This implements the "Secure Attention Key" ---  the idea is to
  4.2660 + * prevent trojan horses by killing all processes associated with this
  4.2661 + * tty when the user hits the "Secure Attention Key".  Required for
  4.2662 + * super-paranoid applications --- see the Orange Book for more details.
  4.2663 + * 
  4.2664 + * This code could be nicer; ideally it should send a HUP, wait a few
  4.2665 + * seconds, then send a INT, and then a KILL signal.  But you then
  4.2666 + * have to coordinate with the init process, since all processes associated
  4.2667 + * with the current tty must be dead before the new getty is allowed
  4.2668 + * to spawn.
  4.2669 + *
  4.2670 + * Now, if it would be correct ;-/ The current code has a nasty hole -
  4.2671 + * it doesn't catch files in flight. We may send the descriptor to ourselves
  4.2672 + * via AF_UNIX socket, close it and later fetch from socket. FIXME.
  4.2673 + *
  4.2674 + * Nasty bug: do_SAK is being called in interrupt context.  This can
  4.2675 + * deadlock.  We punt it up to process context.  AKPM - 16Mar2001
  4.2676 + */
  4.2677 +static void __do_SAK(void *arg)
  4.2678 +{
  4.2679 +#ifdef TTY_SOFT_SAK
  4.2680 +	tty_hangup(tty);
  4.2681 +#else
  4.2682 +	struct tty_struct *tty = arg;
  4.2683 +	struct task_struct *p;
  4.2684 +	int session;
  4.2685 +	int		i;
  4.2686 +	struct file	*filp;
  4.2687 +	struct tty_ldisc *disc;
  4.2688 +	struct fdtable *fdt;
  4.2689 +	
  4.2690 +	if (!tty)
  4.2691 +		return;
  4.2692 +	session  = tty->session;
  4.2693 +	
  4.2694 +	/* We don't want an ldisc switch during this */
  4.2695 +	disc = tty_ldisc_ref(tty);
  4.2696 +	if (disc && disc->flush_buffer)
  4.2697 +		disc->flush_buffer(tty);
  4.2698 +	tty_ldisc_deref(disc);
  4.2699 +
  4.2700 +	if (tty->driver->flush_buffer)
  4.2701 +		tty->driver->flush_buffer(tty);
  4.2702 +	
  4.2703 +	read_lock(&tasklist_lock);
  4.2704 +	do_each_task_pid(session, PIDTYPE_SID, p) {
  4.2705 +		if (p->signal->tty == tty || session > 0) {
  4.2706 +			printk(KERN_NOTICE "SAK: killed process %d"
  4.2707 +			    " (%s): p->signal->session==tty->session\n",
  4.2708 +			    p->pid, p->comm);
  4.2709 +			send_sig(SIGKILL, p, 1);
  4.2710 +			continue;
  4.2711 +		}
  4.2712 +		task_lock(p);
  4.2713 +		if (p->files) {
  4.2714 +			/*
  4.2715 +			 * We don't take a ref to the file, so we must
  4.2716 +			 * hold ->file_lock instead.
  4.2717 +			 */
  4.2718 +			spin_lock(&p->files->file_lock);
  4.2719 +			fdt = files_fdtable(p->files);
  4.2720 +			for (i=0; i < fdt->max_fds; i++) {
  4.2721 +				filp = fcheck_files(p->files, i);
  4.2722 +				if (!filp)
  4.2723 +					continue;
  4.2724 +				if (filp->f_op->read == tty_read &&
  4.2725 +				    filp->private_data == tty) {
  4.2726 +					printk(KERN_NOTICE "SAK: killed process %d"
  4.2727 +					    " (%s): fd#%d opened to the tty\n",
  4.2728 +					    p->pid, p->comm, i);
  4.2729 +					send_sig(SIGKILL, p, 1);
  4.2730 +					break;
  4.2731 +				}
  4.2732 +			}
  4.2733 +			spin_unlock(&p->files->file_lock);
  4.2734 +		}
  4.2735 +		task_unlock(p);
  4.2736 +	} while_each_task_pid(session, PIDTYPE_SID, p);
  4.2737 +	read_unlock(&tasklist_lock);
  4.2738 +#endif
  4.2739 +}
  4.2740 +
  4.2741 +/*
  4.2742 + * The tq handling here is a little racy - tty->SAK_work may already be queued.
  4.2743 + * Fortunately we don't need to worry, because if ->SAK_work is already queued,
  4.2744 + * the values which we write to it will be identical to the values which it
  4.2745 + * already has. --akpm
  4.2746 + */
  4.2747 +void do_SAK(struct tty_struct *tty)
  4.2748 +{
  4.2749 +	if (!tty)
  4.2750 +		return;
  4.2751 +	PREPARE_WORK(&tty->SAK_work, __do_SAK, tty);
  4.2752 +	schedule_work(&tty->SAK_work);
  4.2753 +}
  4.2754 +
  4.2755 +EXPORT_SYMBOL(do_SAK);
  4.2756 +
  4.2757 +/*
  4.2758 + * This routine is called out of the software interrupt to flush data
  4.2759 + * from the buffer chain to the line discipline.
  4.2760 + */
  4.2761 + 
  4.2762 +static void flush_to_ldisc(void *private_)
  4.2763 +{
  4.2764 +	struct tty_struct *tty = (struct tty_struct *) private_;
  4.2765 +	unsigned long 	flags;
  4.2766 +	struct tty_ldisc *disc;
  4.2767 +	struct tty_buffer *tbuf, *head;
  4.2768 +	int count;
  4.2769 +	char *char_buf;
  4.2770 +	unsigned char *flag_buf;
  4.2771 +
  4.2772 +	disc = tty_ldisc_ref(tty);
  4.2773 +	if (disc == NULL)	/*  !TTY_LDISC */
  4.2774 +		return;
  4.2775 +
  4.2776 +	if (test_bit(TTY_DONT_FLIP, &tty->flags)) {
  4.2777 +		/*
  4.2778 +		 * Do it after the next timer tick:
  4.2779 +		 */
  4.2780 +		schedule_delayed_work(&tty->buf.work, 1);
  4.2781 +		goto out;
  4.2782 +	}
  4.2783 +	spin_lock_irqsave(&tty->buf.lock, flags);
  4.2784 +	head = tty->buf.head;
  4.2785 +	tty->buf.head = NULL;
  4.2786 +	while((tbuf = head) != NULL) {
  4.2787 +		while ((count = tbuf->commit - tbuf->read) != 0) {
  4.2788 +			char_buf = tbuf->char_buf_ptr + tbuf->read;
  4.2789 +			flag_buf = tbuf->flag_buf_ptr + tbuf->read;
  4.2790 +			tbuf->read += count;
  4.2791 +			spin_unlock_irqrestore(&tty->buf.lock, flags);
  4.2792 +			disc->receive_buf(tty, char_buf, flag_buf, count);
  4.2793 +			spin_lock_irqsave(&tty->buf.lock, flags);
  4.2794 +		}
  4.2795 +		if (tbuf->active) {
  4.2796 +			tty->buf.head = head;
  4.2797 +			break;
  4.2798 +		}
  4.2799 +		head = tbuf->next;
  4.2800 +		if (head == NULL)
  4.2801 +			tty->buf.tail = NULL;
  4.2802 +		tty_buffer_free(tty, tbuf);
  4.2803 +	}
  4.2804 +	spin_unlock_irqrestore(&tty->buf.lock, flags);
  4.2805 +out:
  4.2806 +	tty_ldisc_deref(disc);
  4.2807 +}
  4.2808 +
  4.2809 +/*
  4.2810 + * Routine which returns the baud rate of the tty
  4.2811 + *
  4.2812 + * Note that the baud_table needs to be kept in sync with the
  4.2813 + * include/asm/termbits.h file.
  4.2814 + */
  4.2815 +static int baud_table[] = {
  4.2816 +	0, 50, 75, 110, 134, 150, 200, 300, 600, 1200, 1800, 2400, 4800,
  4.2817 +	9600, 19200, 38400, 57600, 115200, 230400, 460800,
  4.2818 +#ifdef __sparc__
  4.2819 +	76800, 153600, 307200, 614400, 921600
  4.2820 +#else
  4.2821 +	500000, 576000, 921600, 1000000, 1152000, 1500000, 2000000,
  4.2822 +	2500000, 3000000, 3500000, 4000000
  4.2823 +#endif
  4.2824 +};
  4.2825 +
  4.2826 +static int n_baud_table = ARRAY_SIZE(baud_table);
  4.2827 +
  4.2828 +/**
  4.2829 + *	tty_termios_baud_rate
  4.2830 + *	@termios: termios structure
  4.2831 + *
  4.2832 + *	Convert termios baud rate data into a speed. This should be called
  4.2833 + *	with the termios lock held if this termios is a terminal termios
  4.2834 + *	structure. May change the termios data.
  4.2835 + */
  4.2836 + 
  4.2837 +int tty_termios_baud_rate(struct termios *termios)
  4.2838 +{
  4.2839 +	unsigned int cbaud;
  4.2840 +	
  4.2841 +	cbaud = termios->c_cflag & CBAUD;
  4.2842 +
  4.2843 +	if (cbaud & CBAUDEX) {
  4.2844 +		cbaud &= ~CBAUDEX;
  4.2845 +
  4.2846 +		if (cbaud < 1 || cbaud + 15 > n_baud_table)
  4.2847 +			termios->c_cflag &= ~CBAUDEX;
  4.2848 +		else
  4.2849 +			cbaud += 15;
  4.2850 +	}
  4.2851 +	return baud_table[cbaud];
  4.2852 +}
  4.2853 +
  4.2854 +EXPORT_SYMBOL(tty_termios_baud_rate);
  4.2855 +
  4.2856 +/**
  4.2857 + *	tty_get_baud_rate	-	get tty bit rates
  4.2858 + *	@tty: tty to query
  4.2859 + *
  4.2860 + *	Returns the baud rate as an integer for this terminal. The
  4.2861 + *	termios lock must be held by the caller and the terminal bit
  4.2862 + *	flags may be updated.
  4.2863 + */
  4.2864 + 
  4.2865 +int tty_get_baud_rate(struct tty_struct *tty)
  4.2866 +{
  4.2867 +	int baud = tty_termios_baud_rate(tty->termios);
  4.2868 +
  4.2869 +	if (baud == 38400 && tty->alt_speed) {
  4.2870 +		if (!tty->warned) {
  4.2871 +			printk(KERN_WARNING "Use of setserial/setrocket to "
  4.2872 +					    "set SPD_* flags is deprecated\n");
  4.2873 +			tty->warned = 1;
  4.2874 +		}
  4.2875 +		baud = tty->alt_speed;
  4.2876 +	}
  4.2877 +	
  4.2878 +	return baud;
  4.2879 +}
  4.2880 +
  4.2881 +EXPORT_SYMBOL(tty_get_baud_rate);
  4.2882 +
  4.2883 +/**
  4.2884 + *	tty_flip_buffer_push	-	terminal
  4.2885 + *	@tty: tty to push
  4.2886 + *
  4.2887 + *	Queue a push of the terminal flip buffers to the line discipline. This
  4.2888 + *	function must not be called from IRQ context if tty->low_latency is set.
  4.2889 + *
  4.2890 + *	In the event of the queue being busy for flipping the work will be
  4.2891 + *	held off and retried later.
  4.2892 + */
  4.2893 +
  4.2894 +void tty_flip_buffer_push(struct tty_struct *tty)
  4.2895 +{
  4.2896 +	unsigned long flags;
  4.2897 +	spin_lock_irqsave(&tty->buf.lock, flags);
  4.2898 +	if (tty->buf.tail != NULL) {
  4.2899 +		tty->buf.tail->active = 0;
  4.2900 +		tty->buf.tail->commit = tty->buf.tail->used;
  4.2901 +	}
  4.2902 +	spin_unlock_irqrestore(&tty->buf.lock, flags);
  4.2903 +
  4.2904 +	if (tty->low_latency)
  4.2905 +		flush_to_ldisc((void *) tty);
  4.2906 +	else
  4.2907 +		schedule_delayed_work(&tty->buf.work, 1);
  4.2908 +}
  4.2909 +
  4.2910 +EXPORT_SYMBOL(tty_flip_buffer_push);
  4.2911 +
  4.2912 +
  4.2913 +/*
  4.2914 + * This subroutine initializes a tty structure.
  4.2915 + */
  4.2916 +static void initialize_tty_struct(struct tty_struct *tty)
  4.2917 +{
  4.2918 +	memset(tty, 0, sizeof(struct tty_struct));
  4.2919 +	tty->magic = TTY_MAGIC;
  4.2920 +	tty_ldisc_assign(tty, tty_ldisc_get(N_TTY));
  4.2921 +	tty->pgrp = -1;
  4.2922 +	tty->overrun_time = jiffies;
  4.2923 +	tty->buf.head = tty->buf.tail = NULL;
  4.2924 +	tty_buffer_init(tty);
  4.2925 +	INIT_WORK(&tty->buf.work, flush_to_ldisc, tty);
  4.2926 +	init_MUTEX(&tty->buf.pty_sem);
  4.2927 +	init_MUTEX(&tty->termios_sem);
  4.2928 +	init_waitqueue_head(&tty->write_wait);
  4.2929 +	init_waitqueue_head(&tty->read_wait);
  4.2930 +	INIT_WORK(&tty->hangup_work, do_tty_hangup, tty);
  4.2931 +	sema_init(&tty->atomic_read, 1);
  4.2932 +	sema_init(&tty->atomic_write, 1);
  4.2933 +	spin_lock_init(&tty->read_lock);
  4.2934 +	INIT_LIST_HEAD(&tty->tty_files);
  4.2935 +	INIT_WORK(&tty->SAK_work, NULL, NULL);
  4.2936 +}
  4.2937 +
  4.2938 +/*
  4.2939 + * The default put_char routine if the driver did not define one.
  4.2940 + */
  4.2941 +static void tty_default_put_char(struct tty_struct *tty, unsigned char ch)
  4.2942 +{
  4.2943 +	tty->driver->write(tty, &ch, 1);
  4.2944 +}
  4.2945 +
  4.2946 +static struct class *tty_class;
  4.2947 +
  4.2948 +/**
  4.2949 + * tty_register_device - register a tty device
  4.2950 + * @driver: the tty driver that describes the tty device
  4.2951 + * @index: the index in the tty driver for this tty device
  4.2952 + * @device: a struct device that is associated with this tty device.
  4.2953 + *	This field is optional, if there is no known struct device for this
  4.2954 + *	tty device it can be set to NULL safely.
  4.2955 + *
  4.2956 + * This call is required to be made to register an individual tty device if
  4.2957 + * the tty driver's flags have the TTY_DRIVER_NO_DEVFS bit set.  If that
  4.2958 + * bit is not set, this function should not be called.
  4.2959 + */
  4.2960 +void tty_register_device(struct tty_driver *driver, unsigned index,
  4.2961 +			 struct device *device)
  4.2962 +{
  4.2963 +	char name[64];
  4.2964 +	dev_t dev = MKDEV(driver->major, driver->minor_start) + index;
  4.2965 +
  4.2966 +	if (index >= driver->num) {
  4.2967 +		printk(KERN_ERR "Attempt to register invalid tty line number "
  4.2968 +		       " (%d).\n", index);
  4.2969 +		return;
  4.2970 +	}
  4.2971 +
  4.2972 +	devfs_mk_cdev(dev, S_IFCHR | S_IRUSR | S_IWUSR,
  4.2973 +			"%s%d", driver->devfs_name, index + driver->name_base);
  4.2974 +
  4.2975 +	if (driver->type == TTY_DRIVER_TYPE_PTY)
  4.2976 +		pty_line_name(driver, index, name);
  4.2977 +	else
  4.2978 +		tty_line_name(driver, index, name);
  4.2979 +	class_device_create(tty_class, NULL, dev, device, "%s", name);
  4.2980 +}
  4.2981 +
  4.2982 +/**
  4.2983 + * tty_unregister_device - unregister a tty device
  4.2984 + * @driver: the tty driver that describes the tty device
  4.2985 + * @index: the index in the tty driver for this tty device
  4.2986 + *
  4.2987 + * If a tty device is registered with a call to tty_register_device() then
  4.2988 + * this function must be made when the tty device is gone.
  4.2989 + */
  4.2990 +void tty_unregister_device(struct tty_driver *driver, unsigned index)
  4.2991 +{
  4.2992 +	devfs_remove("%s%d", driver->devfs_name, index + driver->name_base);
  4.2993 +	class_device_destroy(tty_class, MKDEV(driver->major, driver->minor_start) + index);
  4.2994 +}
  4.2995 +
  4.2996 +EXPORT_SYMBOL(tty_register_device);
  4.2997 +EXPORT_SYMBOL(tty_unregister_device);
  4.2998 +
  4.2999 +struct tty_driver *alloc_tty_driver(int lines)
  4.3000 +{
  4.3001 +	struct tty_driver *driver;
  4.3002 +
  4.3003 +	driver = kmalloc(sizeof(struct tty_driver), GFP_KERNEL);
  4.3004 +	if (driver) {
  4.3005 +		memset(driver, 0, sizeof(struct tty_driver));
  4.3006 +		driver->magic = TTY_DRIVER_MAGIC;
  4.3007 +		driver->num = lines;
  4.3008 +		/* later we'll move allocation of tables here */
  4.3009 +	}
  4.3010 +	return driver;
  4.3011 +}
  4.3012 +
  4.3013 +void put_tty_driver(struct tty_driver *driver)
  4.3014 +{
  4.3015 +	kfree(driver);
  4.3016 +}
  4.3017 +
  4.3018 +void tty_set_operations(struct tty_driver *driver, struct tty_operations *op)
  4.3019 +{
  4.3020 +	driver->open = op->open;
  4.3021 +	driver->close = op->close;
  4.3022 +	driver->write = op->write;
  4.3023 +	driver->put_char = op->put_char;
  4.3024 +	driver->flush_chars = op->flush_chars;
  4.3025 +	driver->write_room = op->write_room;
  4.3026 +	driver->chars_in_buffer = op->chars_in_buffer;
  4.3027 +	driver->ioctl = op->ioctl;
  4.3028 +	driver->set_termios = op->set_termios;
  4.3029 +	driver->throttle = op->throttle;
  4.3030 +	driver->unthrottle = op->unthrottle;
  4.3031 +	driver->stop = op->stop;
  4.3032 +	driver->start = op->start;
  4.3033 +	driver->hangup = op->hangup;
  4.3034 +	driver->break_ctl = op->break_ctl;
  4.3035 +	driver->flush_buffer = op->flush_buffer;
  4.3036 +	driver->set_ldisc = op->set_ldisc;
  4.3037 +	driver->wait_until_sent = op->wait_until_sent;
  4.3038 +	driver->send_xchar = op->send_xchar;
  4.3039 +	driver->read_proc = op->read_proc;
  4.3040 +	driver->write_proc = op->write_proc;
  4.3041 +	driver->tiocmget = op->tiocmget;
  4.3042 +	driver->tiocmset = op->tiocmset;
  4.3043 +}
  4.3044 +
  4.3045 +
  4.3046 +EXPORT_SYMBOL(alloc_tty_driver);
  4.3047 +EXPORT_SYMBOL(put_tty_driver);
  4.3048 +EXPORT_SYMBOL(tty_set_operations);
  4.3049 +
  4.3050 +/*
  4.3051 + * Called by a tty driver to register itself.
  4.3052 + */
  4.3053 +int tty_register_driver(struct tty_driver *driver)
  4.3054 +{
  4.3055 +	int error;
  4.3056 +        int i;
  4.3057 +	dev_t dev;
  4.3058 +	void **p = NULL;
  4.3059 +
  4.3060 +	if (driver->flags & TTY_DRIVER_INSTALLED)
  4.3061 +		return 0;
  4.3062 +
  4.3063 +	if (!(driver->flags & TTY_DRIVER_DEVPTS_MEM)) {
  4.3064 +		p = kmalloc(driver->num * 3 * sizeof(void *), GFP_KERNEL);
  4.3065 +		if (!p)
  4.3066 +			return -ENOMEM;
  4.3067 +		memset(p, 0, driver->num * 3 * sizeof(void *));
  4.3068 +	}
  4.3069 +
  4.3070 +	if (!driver->major) {
  4.3071 +		error = alloc_chrdev_region(&dev, driver->minor_start, driver->num,
  4.3072 +						(char*)driver->name);
  4.3073 +		if (!error) {
  4.3074 +			driver->major = MAJOR(dev);
  4.3075 +			driver->minor_start = MINOR(dev);
  4.3076 +		}
  4.3077 +	} else {
  4.3078 +		dev = MKDEV(driver->major, driver->minor_start);
  4.3079 +		error = register_chrdev_region(dev, driver->num,
  4.3080 +						(char*)driver->name);
  4.3081 +	}
  4.3082 +	if (error < 0) {
  4.3083 +		kfree(p);
  4.3084 +		return error;
  4.3085 +	}
  4.3086 +
  4.3087 +	if (p) {
  4.3088 +		driver->ttys = (struct tty_struct **)p;
  4.3089 +		driver->termios = (struct termios **)(p + driver->num);
  4.3090 +		driver->termios_locked = (struct termios **)(p + driver->num * 2);
  4.3091 +	} else {
  4.3092 +		driver->ttys = NULL;
  4.3093 +		driver->termios = NULL;
  4.3094 +		driver->termios_locked = NULL;
  4.3095 +	}
  4.3096 +
  4.3097 +	cdev_init(&driver->cdev, &tty_fops);
  4.3098 +	driver->cdev.owner = driver->owner;
  4.3099 +	error = cdev_add(&driver->cdev, dev, driver->num);
  4.3100 +	if (error) {
  4.3101 +		cdev_del(&driver->cdev);
  4.3102 +		unregister_chrdev_region(dev, driver->num);
  4.3103 +		driver->ttys = NULL;
  4.3104 +		driver->termios = driver->termios_locked = NULL;
  4.3105 +		kfree(p);
  4.3106 +		return error;
  4.3107 +	}
  4.3108 +
  4.3109 +	if (!driver->put_char)
  4.3110 +		driver->put_char = tty_default_put_char;
  4.3111 +	
  4.3112 +	list_add(&driver->tty_drivers, &tty_drivers);
  4.3113 +	
  4.3114 +	if ( !(driver->flags & TTY_DRIVER_NO_DEVFS) ) {
  4.3115 +		for(i = 0; i < driver->num; i++)
  4.3116 +		    tty_register_device(driver, i, NULL);
  4.3117 +	}
  4.3118 +	proc_tty_register_driver(driver);
  4.3119 +	return 0;
  4.3120 +}
  4.3121 +
  4.3122 +EXPORT_SYMBOL(tty_register_driver);
  4.3123 +
  4.3124 +/*
  4.3125 + * Called by a tty driver to unregister itself.
  4.3126 + */
  4.3127 +int tty_unregister_driver(struct tty_driver *driver)
  4.3128 +{
  4.3129 +	int i;
  4.3130 +	struct termios *tp;
  4.3131 +	void *p;
  4.3132 +
  4.3133 +	if (driver->refcount)
  4.3134 +		return -EBUSY;
  4.3135 +
  4.3136 +	unregister_chrdev_region(MKDEV(driver->major, driver->minor_start),
  4.3137 +				driver->num);
  4.3138 +
  4.3139 +	list_del(&driver->tty_drivers);
  4.3140 +
  4.3141 +	/*
  4.3142 +	 * Free the termios and termios_locked structures because
  4.3143 +	 * we don't want to get memory leaks when modular tty
  4.3144 +	 * drivers are removed from the kernel.
  4.3145 +	 */
  4.3146 +	for (i = 0; i < driver->num; i++) {
  4.3147 +		tp = driver->termios[i];
  4.3148 +		if (tp) {
  4.3149 +			driver->termios[i] = NULL;
  4.3150 +			kfree(tp);
  4.3151 +		}
  4.3152 +		tp = driver->termios_locked[i];
  4.3153 +		if (tp) {
  4.3154 +			driver->termios_locked[i] = NULL;
  4.3155 +			kfree(tp);
  4.3156 +		}
  4.3157 +		if (!(driver->flags & TTY_DRIVER_NO_DEVFS))
  4.3158 +			tty_unregister_device(driver, i);
  4.3159 +	}
  4.3160 +	p = driver->ttys;
  4.3161 +	proc_tty_unregister_driver(driver);
  4.3162 +	driver->ttys = NULL;
  4.3163 +	driver->termios = driver->termios_locked = NULL;
  4.3164 +	kfree(p);
  4.3165 +	cdev_del(&driver->cdev);
  4.3166 +	return 0;
  4.3167 +}
  4.3168 +
  4.3169 +EXPORT_SYMBOL(tty_unregister_driver);
  4.3170 +
  4.3171 +
  4.3172 +/*
  4.3173 + * Initialize the console device. This is called *early*, so
  4.3174 + * we can't necessarily depend on lots of kernel help here.
  4.3175 + * Just do some early initializations, and do the complex setup
  4.3176 + * later.
  4.3177 + */
  4.3178 +void __init console_init(void)
  4.3179 +{
  4.3180 +	initcall_t *call;
  4.3181 +
  4.3182 +	/* Setup the default TTY line discipline. */
  4.3183 +	(void) tty_register_ldisc(N_TTY, &tty_ldisc_N_TTY);
  4.3184 +
  4.3185 +	/*
  4.3186 +	 * set up the console device so that later boot sequences can 
  4.3187 +	 * inform about problems etc..
  4.3188 +	 */
  4.3189 +#ifdef CONFIG_EARLY_PRINTK
  4.3190 +	disable_early_printk();
  4.3191 +#endif
  4.3192 +	call = __con_initcall_start;
  4.3193 +	while (call < __con_initcall_end) {
  4.3194 +		(*call)();
  4.3195 +		call++;
  4.3196 +	}
  4.3197 +}
  4.3198 +
  4.3199 +#ifdef CONFIG_VT
  4.3200 +extern int vty_init(void);
  4.3201 +#endif
  4.3202 +
  4.3203 +static int __init tty_class_init(void)
  4.3204 +{
  4.3205 +	tty_class = class_create(THIS_MODULE, "tty");
  4.3206 +	if (IS_ERR(tty_class))
  4.3207 +		return PTR_ERR(tty_class);
  4.3208 +	return 0;
  4.3209 +}
  4.3210 +
  4.3211 +postcore_initcall(tty_class_init);
  4.3212 +
  4.3213 +/* 3/2004 jmc: why do these devices exist? */
  4.3214 +
  4.3215 +static struct cdev tty_cdev, console_cdev;
  4.3216 +#ifdef CONFIG_UNIX98_PTYS
  4.3217 +static struct cdev ptmx_cdev;
  4.3218 +#endif
  4.3219 +#ifdef CONFIG_VT
  4.3220 +static struct cdev vc0_cdev;
  4.3221 +#endif
  4.3222 +
  4.3223 +/*
  4.3224 + * Ok, now we can initialize the rest of the tty devices and can count
  4.3225 + * on memory allocations, interrupts etc..
  4.3226 + */
  4.3227 +static int __init tty_init(void)
  4.3228 +{
  4.3229 +	cdev_init(&tty_cdev, &tty_fops);
  4.3230 +	if (cdev_add(&tty_cdev, MKDEV(TTYAUX_MAJOR, 0), 1) ||
  4.3231 +	    register_chrdev_region(MKDEV(TTYAUX_MAJOR, 0), 1, "/dev/tty") < 0)
  4.3232 +		panic("Couldn't register /dev/tty driver\n");
  4.3233 +	devfs_mk_cdev(MKDEV(TTYAUX_MAJOR, 0), S_IFCHR|S_IRUGO|S_IWUGO, "tty");
  4.3234 +	class_device_create(tty_class, NULL, MKDEV(TTYAUX_MAJOR, 0), NULL, "tty");
  4.3235 +
  4.3236 +	cdev_init(&console_cdev, &console_fops);
  4.3237 +	if (cdev_add(&console_cdev, MKDEV(TTYAUX_MAJOR, 1), 1) ||
  4.3238 +	    register_chrdev_region(MKDEV(TTYAUX_MAJOR, 1), 1, "/dev/console") < 0)
  4.3239 +		panic("Couldn't register /dev/console driver\n");
  4.3240 +	devfs_mk_cdev(MKDEV(TTYAUX_MAJOR, 1), S_IFCHR|S_IRUSR|S_IWUSR, "console");
  4.3241 +	class_device_create(tty_class, NULL, MKDEV(TTYAUX_MAJOR, 1), NULL, "console");
  4.3242 +
  4.3243 +#ifdef CONFIG_UNIX98_PTYS
  4.3244 +	cdev_init(&ptmx_cdev, &ptmx_fops);
  4.3245 +	if (cdev_add(&ptmx_cdev, MKDEV(TTYAUX_MAJOR, 2), 1) ||
  4.3246 +	    register_chrdev_region(MKDEV(TTYAUX_MAJOR, 2), 1, "/dev/ptmx") < 0)
  4.3247 +		panic("Couldn't register /dev/ptmx driver\n");
  4.3248 +	devfs_mk_cdev(MKDEV(TTYAUX_MAJOR, 2), S_IFCHR|S_IRUGO|S_IWUGO, "ptmx");
  4.3249 +	class_device_create(tty_class, NULL, MKDEV(TTYAUX_MAJOR, 2), NULL, "ptmx");
  4.3250 +#endif
  4.3251 +
  4.3252 +#ifdef CONFIG_VT
  4.3253 +	if (!console_use_vt)
  4.3254 +		goto out_vt;
  4.3255 +	cdev_init(&vc0_cdev, &console_fops);
  4.3256 +	if (cdev_add(&vc0_cdev, MKDEV(TTY_MAJOR, 0), 1) ||
  4.3257 +	    register_chrdev_region(MKDEV(TTY_MAJOR, 0), 1, "/dev/vc/0") < 0)
  4.3258 +		panic("Couldn't register /dev/tty0 driver\n");
  4.3259 +	devfs_mk_cdev(MKDEV(TTY_MAJOR, 0), S_IFCHR|S_IRUSR|S_IWUSR, "vc/0");
  4.3260 +	class_device_create(tty_class, NULL, MKDEV(TTY_MAJOR, 0), NULL, "tty0");
  4.3261 +
  4.3262 +	vty_init();
  4.3263 + out_vt:
  4.3264 +#endif
  4.3265 +	return 0;
  4.3266 +}
  4.3267 +module_init(tty_init);
     5.1 --- a/linux-2.6-xen-sparse/drivers/xen/console/console.c	Fri Dec 01 11:49:30 2006 +0000
     5.2 +++ b/linux-2.6-xen-sparse/drivers/xen/console/console.c	Fri Dec 01 11:52:33 2006 +0000
     5.3 @@ -66,14 +66,14 @@
     5.4   *  'xencons=tty'  [XC_TTY]:     Console attached to '/dev/tty[0-9]+'.
     5.5   *  'xencons=ttyS' [XC_SERIAL]:  Console attached to '/dev/ttyS[0-9]+'.
     5.6   *  'xencons=xvc'  [XC_XVC]:     Console attached to '/dev/xvc0'.
     5.7 - *                 [XC_DEFAULT]: DOM0 -> XC_SERIAL ; all others -> XC_TTY.
     5.8 + *  default:                     DOM0 -> XC_SERIAL ; all others -> XC_TTY.
     5.9   * 
    5.10   * NB. In mode XC_TTY, we create dummy consoles for tty2-63. This suppresses
    5.11   * warnings from standard distro startup scripts.
    5.12   */
    5.13  static enum {
    5.14 -	XC_OFF, XC_DEFAULT, XC_TTY, XC_SERIAL, XC_XVC
    5.15 -} xc_mode = XC_DEFAULT;
    5.16 +	XC_OFF, XC_TTY, XC_SERIAL, XC_XVC
    5.17 +} xc_mode;
    5.18  static int xc_num = -1;
    5.19  
    5.20  /* /dev/xvc0 device number allocated by lanana.org. */
    5.21 @@ -85,17 +85,32 @@ static unsigned long sysrq_requested;
    5.22  extern int sysrq_enabled;
    5.23  #endif
    5.24  
    5.25 +void xencons_early_setup(void)
    5.26 +{
    5.27 +	extern int console_use_vt;
    5.28 +
    5.29 +	if (is_initial_xendomain()) {
    5.30 +		xc_mode = XC_SERIAL;
    5.31 +	} else {
    5.32 +		xc_mode = XC_TTY;
    5.33 +		console_use_vt = 0;
    5.34 +	}
    5.35 +}
    5.36 +
    5.37  static int __init xencons_setup(char *str)
    5.38  {
    5.39  	char *q;
    5.40  	int n;
    5.41 +	extern int console_use_vt;
    5.42  
    5.43 +	console_use_vt = 1;
    5.44  	if (!strncmp(str, "ttyS", 4)) {
    5.45  		xc_mode = XC_SERIAL;
    5.46  		str += 4;
    5.47  	} else if (!strncmp(str, "tty", 3)) {
    5.48  		xc_mode = XC_TTY;
    5.49  		str += 3;
    5.50 +		console_use_vt = 0;
    5.51  	} else if (!strncmp(str, "xvc", 3)) {
    5.52  		xc_mode = XC_XVC;
    5.53  		str += 3;
    5.54 @@ -193,14 +208,10 @@ static int __init xen_console_init(void)
    5.55  		goto out;
    5.56  
    5.57  	if (is_initial_xendomain()) {
    5.58 -		if (xc_mode == XC_DEFAULT)
    5.59 -			xc_mode = XC_SERIAL;
    5.60  		kcons_info.write = kcons_write_dom0;
    5.61  	} else {
    5.62  		if (!xen_start_info->console.domU.evtchn)
    5.63  			goto out;
    5.64 -		if (xc_mode == XC_DEFAULT)
    5.65 -			xc_mode = XC_TTY;
    5.66  		kcons_info.write = kcons_write;
    5.67  	}
    5.68  
    5.69 @@ -699,15 +710,6 @@ static int __init xencons_init(void)
    5.70  	printk("Xen virtual console successfully installed as %s%d\n",
    5.71  	       DRV(xencons_driver)->name, xc_num);
    5.72  
    5.73 -        /* Check about framebuffer messing up the console */
    5.74 -        if (!is_initial_xendomain() &&
    5.75 -	    !xenbus_exists(XBT_NIL, "device", "vfb")) {
    5.76 -		/* FIXME: this is ugly */
    5.77 -		unregister_console(&kcons_info);
    5.78 -		kcons_info.flags |= CON_CONSDEV;
    5.79 -		register_console(&kcons_info);
    5.80 -	}
    5.81 -
    5.82  	return 0;
    5.83  }
    5.84  
     6.1 --- a/linux-2.6-xen-sparse/include/xen/xencons.h	Fri Dec 01 11:49:30 2006 +0000
     6.2 +++ b/linux-2.6-xen-sparse/include/xen/xencons.h	Fri Dec 01 11:52:33 2006 +0000
     6.3 @@ -14,4 +14,6 @@ void xencons_tx(void);
     6.4  int xencons_ring_init(void);
     6.5  int xencons_ring_send(const char *data, unsigned len);
     6.6  
     6.7 +void xencons_early_setup(void);
     6.8 +
     6.9  #endif /* __ASM_XENCONS_H__ */