--- zzzz-none-000/linux-2.6.13.1/drivers/char/tty_io.c 2005-09-10 02:42:58.000000000 +0000 +++ ohio-7170-487/linux-2.6.13.1/drivers/char/tty_io.c 2008-03-20 11:37:43.000000000 +0000 @@ -19,7 +19,7 @@ * Also restructured routines so that there is more of a separation * between the high-level tty routines (tty_io.c and tty_ioctl.c) and * the low-level tty routines (serial.c, pty.c, console.c). This - * makes for cleaner and more compact code. -TYT, 9/17/92 + * makes for cleaner and more compact code. -TYT, 9/17/92 * * Modified by Fred N. van Kempen, 01/29/93, to add line disciplines * which can be dynamically activated and de-activated by the line @@ -41,7 +41,7 @@ * * New TIOCLINUX variants added. * -- mj@k332.feld.cvut.cz, 19-Nov-95 - * + * * Restrict vt switching via ioctl() * -- grif@cs.ucr.edu, 5-Dec-95 * @@ -125,7 +125,7 @@ /* This list gets poked at by procfs and various bits of boot up code. This could do with some rationalisation such as pulling the tty proc function into this file */ - + LIST_HEAD(tty_drivers); /* linked list of tty drivers */ /* Semaphore to protect creating and releasing a tty. This is shared with @@ -211,7 +211,7 @@ #ifdef CHECK_TTY_COUNT struct list_head *p; int count = 0; - + file_list_lock(); list_for_each(p, &tty->tty_files) { count++; @@ -226,17 +226,17 @@ "!= #fd's(%d) in %s\n", tty->name, tty->count, count, routine); return count; - } + } #endif return 0; } /* * This is probably overkill for real world processors but - * they are not on hot paths so a little discipline won't do + * they are not on hot paths so a little discipline won't do * any harm. */ - + static void tty_set_termios_ldisc(struct tty_struct *tty, int num) { down(&tty->termios_sem); @@ -249,7 +249,7 @@ * must be taken with irqs off because there are hangup path * callers who will do ldisc lookups and cannot sleep. */ - + static DEFINE_SPINLOCK(tty_ldisc_lock); static DECLARE_WAIT_QUEUE_HEAD(tty_ldisc_wait); static struct tty_ldisc tty_ldiscs[NR_LDISCS]; /* line disc dispatch table */ @@ -258,17 +258,17 @@ { unsigned long flags; int ret = 0; - + if (disc < N_TTY || disc >= NR_LDISCS) return -EINVAL; - + spin_lock_irqsave(&tty_ldisc_lock, flags); tty_ldiscs[disc] = *new_ldisc; tty_ldiscs[disc].num = disc; tty_ldiscs[disc].flags |= LDISC_FLAG_DEFINED; tty_ldiscs[disc].refcount = 0; spin_unlock_irqrestore(&tty_ldisc_lock, flags); - + return ret; } EXPORT_SYMBOL(tty_register_ldisc); @@ -299,7 +299,7 @@ if (disc < N_TTY || disc >= NR_LDISCS) return NULL; - + spin_lock_irqsave(&tty_ldisc_lock, flags); ld = &tty_ldiscs[disc]; @@ -324,10 +324,10 @@ { struct tty_ldisc *ld; unsigned long flags; - + if (disc < N_TTY || disc >= NR_LDISCS) BUG(); - + spin_lock_irqsave(&tty_ldisc_lock, flags); ld = &tty_ldiscs[disc]; if(ld->refcount == 0) @@ -336,7 +336,7 @@ module_put(ld->owner); spin_unlock_irqrestore(&tty_ldisc_lock, flags); } - + EXPORT_SYMBOL_GPL(tty_ldisc_put); static void tty_ldisc_assign(struct tty_struct *tty, struct tty_ldisc *ld) @@ -360,7 +360,7 @@ unsigned long flags; struct tty_ldisc *ld; int ret = 0; - + spin_lock_irqsave(&tty_ldisc_lock, flags); ld = &tty->ldisc; if(test_bit(TTY_LDISC, &tty->flags)) @@ -376,8 +376,8 @@ * tty_ldisc_ref_wait - wait for the tty ldisc * @tty: tty device * - * Dereference the line discipline for the terminal and take a - * reference to it. If the line discipline is in flux then + * Dereference the line discipline for the terminal and take a + * reference to it. If the line discipline is in flux then * wait patiently until it changes. * * Note: Must not be called from an IRQ/timer context. The caller @@ -385,7 +385,7 @@ * against a discipline change, such as an existing ldisc reference * (which we check for) */ - + struct tty_ldisc *tty_ldisc_ref_wait(struct tty_struct *tty) { /* wait_event is a macro */ @@ -401,11 +401,11 @@ * tty_ldisc_ref - get the tty ldisc * @tty: tty device * - * Dereference the line discipline for the terminal and take a - * reference to it. If the line discipline is in flux then + * Dereference the line discipline for the terminal and take a + * reference to it. If the line discipline is in flux then * return NULL. Can be called from IRQ and timer functions. */ - + struct tty_ldisc *tty_ldisc_ref(struct tty_struct *tty) { if(tty_ldisc_try(tty)) @@ -422,14 +422,14 @@ * Undoes the effect of tty_ldisc_ref or tty_ldisc_ref_wait. May * be called in IRQ context. */ - + void tty_ldisc_deref(struct tty_ldisc *ld) { unsigned long flags; if(ld == NULL) BUG(); - + spin_lock_irqsave(&tty_ldisc_lock, flags); if(ld->refcount == 0) printk(KERN_ERR "tty_ldisc_deref: no references.\n"); @@ -458,7 +458,7 @@ set_bit(TTY_LDISC, &tty->flags); wake_up(&tty_ldisc_wait); } - + /** * tty_set_ldisc - set line discipline * @tty: the terminal to set @@ -467,7 +467,7 @@ * Set the discipline of a tty line. Must be called from a process * context. */ - + static int tty_set_ldisc(struct tty_struct *tty, int ldisc) { int retval = 0; @@ -484,7 +484,7 @@ if (tty->ldisc.num == ldisc) return 0; /* We are already in the desired discipline */ - + ld = tty_ldisc_get(ldisc); /* Eduardo Blanco */ /* Cyrus Durgin */ @@ -505,7 +505,7 @@ * prevents anyone taking a reference once it is clear. * We need the lock to avoid racing reference takers. */ - + spin_lock_irqsave(&tty_ldisc_lock, flags); if(tty->ldisc.refcount) { @@ -521,24 +521,24 @@ * is up for discussion. */ if(wait_event_interruptible(tty_ldisc_wait, tty->ldisc.refcount == 0) < 0) - return -ERESTARTSYS; + return -ERESTARTSYS; goto restart; } - clear_bit(TTY_LDISC, &tty->flags); + clear_bit(TTY_LDISC, &tty->flags); clear_bit(TTY_DONT_FLIP, &tty->flags); spin_unlock_irqrestore(&tty_ldisc_lock, flags); - + /* * From this point on we know nobody has an ldisc * usage reference, nor can they obtain one until * we say so later on. */ - + work = cancel_delayed_work(&tty->flip.work); /* * Wait for ->hangup_work and ->flip.work handlers to terminate */ - + flush_scheduled_work(); /* Shutdown the current discipline. */ if (tty->ldisc.close) @@ -572,19 +572,19 @@ /* At this point we hold a reference to the new ldisc and a a reference to the old ldisc. If we ended up flipping back to the existing ldisc we have two references to it */ - + if (tty->ldisc.num != o_ldisc.num && tty->driver->set_ldisc) tty->driver->set_ldisc(tty); - + tty_ldisc_put(o_ldisc.num); - + /* * Allow ldisc referencing to occur as soon as the driver * ldisc callback completes. */ - + tty_ldisc_enable(tty); - + /* Restart it in case no characters kick it off. Safe if already running */ if(work) @@ -713,11 +713,11 @@ * informs the line discipline if present that the driver is ready * to receive more output data. */ - + void tty_wakeup(struct tty_struct *tty) { struct tty_ldisc *ld; - + if (test_bit(TTY_DO_WRITE_WAKEUP, &tty->flags)) { ld = tty_ldisc_ref(tty); if(ld) { @@ -738,7 +738,7 @@ * Flush the line discipline queue (if any) for this tty. If there * is no line discipline active this is a no-op. */ - + void tty_ldisc_flush(struct tty_struct *tty) { struct tty_ldisc *ld = tty_ldisc_ref(tty); @@ -750,7 +750,7 @@ } EXPORT_SYMBOL_GPL(tty_ldisc_flush); - + /* * This can be called by the "eventd" kernel thread. That is process synchronous, * but doesn't hold any locks, so we need to make sure we have the appropriate @@ -777,7 +777,7 @@ redirect = NULL; } spin_unlock(&redirect_lock); - + check_tty_count(tty, "do_tty_hangup"); file_list_lock(); /* This breaks for file handles being sent over AF_UNIX sockets ? */ @@ -791,7 +791,7 @@ filp->f_op = &hung_up_tty_fops; } file_list_unlock(); - + /* FIXME! What are the locking issues here? This may me overdoing things.. * this question is especially important now that we've removed the irqlock. */ @@ -811,7 +811,7 @@ /* FIXME: Once we trust the LDISC code better we can wait here for ldisc completion and fix the driver call race */ - + wake_up_interruptible(&tty->write_wait); wake_up_interruptible(&tty->read_wait); @@ -825,13 +825,13 @@ *tty->termios = tty->driver->init_termios; up(&tty->termios_sem); } - + /* Defer ldisc switch */ /* tty_deferred_ldisc_switch(N_TTY); - + This should get done automatically when the port closes and tty_release is called */ - + read_lock(&tasklist_lock); if (tty->session > 0) { do_each_task_pid(tty->session, PIDTYPE_SID, p) { @@ -863,7 +863,7 @@ tty->driver->close(tty, cons_filp); } else if (tty->driver->hangup) (tty->driver->hangup)(tty); - + /* We don't want to have driver/ldisc interactions beyond the ones we did here. The driver layer expects no calls after ->hangup() from the ldisc side. However we @@ -883,7 +883,7 @@ { #ifdef TTY_DEBUG_HANGUP char buf[64]; - + printk(KERN_DEBUG "%s hangup...\n", tty_name(tty, buf)); #endif schedule_work(&tty->hangup_work); @@ -943,7 +943,7 @@ kill_pg(current->signal->tty_old_pgrp, SIGCONT, on_exit); } up(&tty_sem); - unlock_kernel(); + unlock_kernel(); return; } if (tty_pgrp > 0) { @@ -1004,7 +1004,7 @@ EXPORT_SYMBOL(start_tty); -static ssize_t tty_read(struct file * file, char __user * buf, size_t count, +static ssize_t tty_read(struct file * file, char __user * buf, size_t count, loff_t *ppos) { int i; @@ -1047,7 +1047,7 @@ { ssize_t ret = 0, written = 0; unsigned int chunk; - + if (down_interruptible(&tty->atomic_write)) { return -ERESTARTSYS; } @@ -1128,14 +1128,14 @@ struct inode *inode = file->f_dentry->d_inode; ssize_t ret; struct tty_ldisc *ld; - + tty = (struct tty_struct *)file->private_data; if (tty_paranoia_check(tty, inode, "tty_write")) return -EIO; if (!tty || !tty->driver->write || (test_bit(TTY_IO_ERROR, &tty->flags))) return -EIO; - ld = tty_ldisc_ref_wait(tty); + ld = tty_ldisc_ref_wait(tty); if (!ld->write) ret = -EIO; else @@ -1210,7 +1210,7 @@ * First time open is complex, especially for PTY devices. * This code guarantees that either everything succeeds and the * TTY is ready for operation, or else the table slots are vacated - * and the allocated memory released. (Except that the termios + * and the allocated memory released. (Except that the termios * and locked termios may be retained.) */ @@ -1309,15 +1309,15 @@ o_tty->link = tty; } - /* + /* * All structures have been allocated, so now we install them. - * Failures after this point use release_mem to clean up, so + * Failures after this point use release_mem to clean up, so * there's no need to null out the local pointers. */ if (!(driver->flags & TTY_DRIVER_DEVPTS_MEM)) { driver->ttys[idx] = tty; } - + if (!*tp_loc) *tp_loc = tp; if (!*ltp_loc) @@ -1327,7 +1327,7 @@ driver->refcount++; tty->count++; - /* + /* * Structures all installed ... call the ldisc open routines. * If we fail here just call release_mem to clean up. No need * to decrement the use counts, as release_mem doesn't care. @@ -1364,7 +1364,7 @@ if (driver->type == TTY_DRIVER_TYPE_PTY && driver->subtype == PTY_TYPE_MASTER) { /* - * special case for PTY masters: only one open permitted, + * special case for PTY masters: only one open permitted, * and the slave side open count is incremented as well. */ if (tty->count) { @@ -1381,7 +1381,7 @@ printk(KERN_ERR "init_dev but no ldisc\n"); success: *ret_tty = tty; - + /* All paths come through here to release the semaphore */ end_init: return retval; @@ -1482,7 +1482,7 @@ int idx; char buf[64]; unsigned long flags; - + tty = (struct tty_struct *)filp->private_data; if (tty_paranoia_check(tty, filp->f_dentry->d_inode, "release_dev")) return; @@ -1545,7 +1545,7 @@ idx, tty->name); return; } - if (o_tty->termios_locked != + if (o_tty->termios_locked != tty->driver->other->termios_locked[idx]) { printk(KERN_DEBUG "release_dev: other->termios_locked[" "%d] not o_termios_locked for (%s)\n", @@ -1581,7 +1581,7 @@ while (1) { /* Guard against races with tty->count changes elsewhere and opens on /dev/tty */ - + down(&tty_sem); tty_closing = tty->count <= 1; o_tty_closing = o_tty && @@ -1615,14 +1615,14 @@ printk(KERN_WARNING "release_dev: %s: read/write wait queue " "active!\n", tty_name(tty, buf)); schedule(); - } + } /* - * The closing flags are now consistent with the open counts on - * both sides, and we've completed the last operation that could + * The closing flags are now consistent with the open counts on + * both sides, and we've completed the last operation that could * block, so it's safe to proceed with closing. */ - + down(&tty_sem); if (pty_master) { if (--o_tty->count < 0) { @@ -1638,7 +1638,7 @@ tty->count = 0; } up(&tty_sem); - + /* * We've decremented tty->count, so we need to remove this file * descriptor off the tty->tty_files list; this serves two @@ -1685,7 +1685,7 @@ /* check whether both sides are closing ... */ if (!tty_closing || (o_tty && !o_tty_closing)) return; - + #ifdef TTY_DEBUG_HANGUP printk(KERN_DEBUG "freeing tty structure..."); #endif @@ -1701,9 +1701,9 @@ /* * Wait for ->hangup_work and ->flip.work handlers to terminate */ - + flush_scheduled_work(); - + /* * Wait for any short term users (we know they are just driver * side waiters as the file is closing so user count on the file @@ -1726,12 +1726,12 @@ if (tty->ldisc.close) (tty->ldisc.close)(tty); tty_ldisc_put(tty->ldisc.num); - + /* * Switch the line discipline back */ tty_ldisc_assign(tty, tty_ldisc_get(N_TTY)); - tty_set_termios_ldisc(tty,N_TTY); + tty_set_termios_ldisc(tty,N_TTY); if (o_tty) { /* FIXME: could o_tty be in setldisc here ? */ clear_bit(TTY_LDISC, &o_tty->flags); @@ -1739,7 +1739,7 @@ (o_tty->ldisc.close)(o_tty); tty_ldisc_put(o_tty->ldisc.num); tty_ldisc_assign(o_tty, tty_ldisc_get(N_TTY)); - tty_set_termios_ldisc(o_tty,N_TTY); + tty_set_termios_ldisc(o_tty,N_TTY); } /* * The release_mem function takes care of the details of clearing @@ -1780,12 +1780,12 @@ unsigned short saved_flags = filp->f_flags; nonseekable_open(inode, filp); - + retry_open: noctty = filp->f_flags & O_NOCTTY; index = -1; retval = 0; - + down(&tty_sem); if (device == MKDEV(TTYAUX_MAJOR,0)) { @@ -1869,6 +1869,15 @@ filp->f_op = &tty_fops; goto retry_open; } + /*--- printk(KERN_ERR "tty_open() tty->name=%s noctty=%d current->signal->leader " ---*/ + /*--- "%x current->signal->tty %x tty->session %x\n", ---*/ + /*--- tty->name, noctty, current->signal->leader, !current->signal->tty, tty->session); ---*/ + + if(!strcmp(tty->name, "ttyS0")) { + /*--- printk(KERN_ERR "[tty_open] disable \"no console tty\" on /dev/ttyS0\n"); ---*/ + noctty = 0; + } + if (!noctty && current->signal->leader && !current->signal->tty && @@ -1916,7 +1925,7 @@ down(&tty_sem); retval = init_dev(ptm_driver, index, &tty); up(&tty_sem); - + if (retval) goto out; @@ -1960,7 +1969,7 @@ tty = (struct tty_struct *)filp->private_data; if (tty_paranoia_check(tty, filp->f_dentry->d_inode, "tty_poll")) return 0; - + ld = tty_ldisc_ref_wait(tty); if (ld->poll) ret = (ld->poll)(tty, filp, wait); @@ -1976,7 +1985,7 @@ tty = (struct tty_struct *)filp->private_data; if (tty_paranoia_check(tty, filp->f_dentry->d_inode, "tty_fasync")) return 0; - + retval = fasync_helper(fd, filp, on, &tty->fasync); if (retval <= 0) return retval; @@ -1998,7 +2007,7 @@ { char ch, mbz = 0; struct tty_ldisc *ld; - + if ((current->signal->tty != tty) && !capable(CAP_SYS_ADMIN)) return -EPERM; if (get_user(ch, p)) @@ -2252,7 +2261,7 @@ void __user *p = (void __user *)arg; int retval; struct tty_ldisc *ld; - + tty = (struct tty_struct *)file->private_data; if (tty_paranoia_check(tty, inode, "tty_ioctl")) return -EINVAL; @@ -2272,7 +2281,7 @@ if (tty->driver->ioctl) return tty->driver->ioctl(tty, file, cmd, arg); return -EINVAL; - + /* These two ioctl's always return success; even if */ /* the driver doesn't support them. */ case TCSBRK: @@ -2294,7 +2303,7 @@ case TIOCSBRK: case TIOCCBRK: case TCSBRK: - case TCSBRKP: + case TCSBRKP: retval = tty_check_change(tty); if (retval) return retval; @@ -2355,7 +2364,7 @@ case TIOCSBRK: /* Turn break on, unconditionally */ tty->driver->break_ctl(tty, -1); return 0; - + case TIOCCBRK: /* Turn break off, unconditionally */ tty->driver->break_ctl(tty, 0); return 0; @@ -2368,7 +2377,7 @@ if (!arg) return send_break(tty, 250); return 0; - case TCSBRKP: /* support for POSIX tcsendbreak() */ + case TCSBRKP: /* support for POSIX tcsendbreak() */ return send_break(tty, arg ? arg*100 : 250); case TIOCMGET: @@ -2401,7 +2410,7 @@ * prevent trojan horses by killing all processes associated with this * tty when the user hits the "Secure Attention Key". Required for * super-paranoid applications --- see the Orange Book for more details. - * + * * This code could be nicer; ideally it should send a HUP, wait a few * seconds, then send a INT, and then a KILL signal. But you then * have to coordinate with the init process, since all processes associated @@ -2426,11 +2435,11 @@ int i; struct file *filp; struct tty_ldisc *disc; - + if (!tty) return; session = tty->session; - + /* We don't want an ldisc switch during this */ disc = tty_ldisc_ref(tty); if (disc && disc->flush_buffer) @@ -2439,7 +2448,7 @@ if (tty->driver->flush_buffer) tty->driver->flush_buffer(tty); - + read_lock(&tasklist_lock); do_each_task_pid(session, PIDTYPE_SID, p) { if (p->signal->tty == tty || session > 0) { @@ -2491,9 +2500,9 @@ /* * This routine is called out of the software interrupt to flush data - * from the flip buffer to the line discipline. + * from the flip buffer to the line discipline. */ - + static void flush_to_ldisc(void *private_) { struct tty_struct *tty = (struct tty_struct *) private_; @@ -2564,11 +2573,11 @@ * with the termios lock held if this termios is a terminal termios * structure. May change the termios data. */ - + int tty_termios_baud_rate(struct termios *termios) { unsigned int cbaud; - + cbaud = termios->c_cflag & CBAUD; if (cbaud & CBAUDEX) { @@ -2592,7 +2601,7 @@ * termios lock must be held by the caller and the terminal bit * flags may be updated. */ - + int tty_get_baud_rate(struct tty_struct *tty) { int baud = tty_termios_baud_rate(tty->termios); @@ -2605,7 +2614,7 @@ } baud = tty->alt_speed; } - + return baud; } @@ -2830,14 +2839,16 @@ if (!driver->put_char) driver->put_char = tty_default_put_char; - + list_add(&driver->tty_drivers, &tty_drivers); - + if ( !(driver->flags & TTY_DRIVER_NO_DEVFS) ) { for(i = 0; i < driver->num; i++) tty_register_device(driver, i, NULL); } +#if defined(CONFIG_PROC_FS) proc_tty_register_driver(driver); +#endif /*--- #if defined(CONFIG_PROC_FS) ---*/ return 0; } @@ -2880,7 +2891,9 @@ tty_unregister_device(driver, i); } p = driver->ttys; +#if defined(CONFIG_PROC_FS) proc_tty_unregister_driver(driver); +#endif /*--- #if defined(CONFIG_PROC_FS) ---*/ driver->ttys = NULL; driver->termios = driver->termios_locked = NULL; kfree(p); @@ -2905,12 +2918,13 @@ (void) tty_register_ldisc(N_TTY, &tty_ldisc_N_TTY); /* - * set up the console device so that later boot sequences can + * set up the console device so that later boot sequences can * inform about problems etc.. */ #ifdef CONFIG_EARLY_PRINTK disable_early_printk(); #endif + #ifdef CONFIG_SERIAL_68360 /* This is not a console initcall. I know not what it's doing here. So I haven't moved it. dwmw2 */ @@ -2957,14 +2971,12 @@ if (cdev_add(&tty_cdev, MKDEV(TTYAUX_MAJOR, 0), 1) || register_chrdev_region(MKDEV(TTYAUX_MAJOR, 0), 1, "/dev/tty") < 0) panic("Couldn't register /dev/tty driver\n"); - devfs_mk_cdev(MKDEV(TTYAUX_MAJOR, 0), S_IFCHR|S_IRUGO|S_IWUGO, "tty"); class_device_create(tty_class, MKDEV(TTYAUX_MAJOR, 0), NULL, "tty"); cdev_init(&console_cdev, &console_fops); if (cdev_add(&console_cdev, MKDEV(TTYAUX_MAJOR, 1), 1) || register_chrdev_region(MKDEV(TTYAUX_MAJOR, 1), 1, "/dev/console") < 0) panic("Couldn't register /dev/console driver\n"); - devfs_mk_cdev(MKDEV(TTYAUX_MAJOR, 1), S_IFCHR|S_IRUSR|S_IWUSR, "console"); class_device_create(tty_class, MKDEV(TTYAUX_MAJOR, 1), NULL, "console"); #ifdef CONFIG_UNIX98_PTYS @@ -2972,16 +2984,14 @@ if (cdev_add(&ptmx_cdev, MKDEV(TTYAUX_MAJOR, 2), 1) || register_chrdev_region(MKDEV(TTYAUX_MAJOR, 2), 1, "/dev/ptmx") < 0) panic("Couldn't register /dev/ptmx driver\n"); - devfs_mk_cdev(MKDEV(TTYAUX_MAJOR, 2), S_IFCHR|S_IRUGO|S_IWUGO, "ptmx"); - class_device_create(tty_class, MKDEV(TTYAUX_MAJOR, 2), NULL, "ptmx"); + class_device_create(tty_class, MKDEV(TTYAUX_MAJOR, 2), NULL, "ptmx"); #endif #ifdef CONFIG_VT cdev_init(&vc0_cdev, &console_fops); if (cdev_add(&vc0_cdev, MKDEV(TTY_MAJOR, 0), 1) || register_chrdev_region(MKDEV(TTY_MAJOR, 0), 1, "/dev/vc/0") < 0) - panic("Couldn't register /dev/tty0 driver\n"); - devfs_mk_cdev(MKDEV(TTY_MAJOR, 0), S_IFCHR|S_IRUSR|S_IWUSR, "vc/0"); + panic("Couldn't register /dev/vc0 driver\n"); class_device_create(tty_class, MKDEV(TTY_MAJOR, 0), NULL, "tty0"); vty_init();