diff options
Diffstat (limited to 'drivers/char/tty_io.c')
-rw-r--r-- | drivers/char/tty_io.c | 127 |
1 files changed, 117 insertions, 10 deletions
diff --git a/drivers/char/tty_io.c b/drivers/char/tty_io.c index abc27bb91..705d876b3 100644 --- a/drivers/char/tty_io.c +++ b/drivers/char/tty_io.c @@ -52,6 +52,9 @@ * Rewrote init_dev and release_dev to eliminate races. * -- Bill Hawes <whawes@star.net>, June 97 * + * Added devfs support. + * -- C. Scott Ananian <cananian@alumni.princeton.edu>, 13-Jan-1998 + * * Added support for a Unix98-style ptmx device. * -- C. Scott Ananian <cananian@alumni.princeton.edu>, 14-Jan-1998 */ @@ -79,6 +82,7 @@ #include <linux/poll.h> #include <linux/proc_fs.h> #include <linux/init.h> +#include <linux/module.h> #include <linux/smp_lock.h> #include <asm/uaccess.h> @@ -88,9 +92,17 @@ #include <linux/kbd_kern.h> #include <linux/vt_kern.h> #include <linux/selection.h> +#include <linux/devfs_fs_kernel.h> #include <linux/kmod.h> +#ifdef CONFIG_VT +extern void con_init_devfs (void); +#endif +void tty_register_devfs (struct tty_driver *driver, unsigned int flags, + unsigned minor); +void tty_unregister_devfs (struct tty_driver *driver, unsigned minor); + #define CONSOLE_DEV MKDEV(TTY_MAJOR,0) #define TTY_DEV MKDEV(TTYAUX_MAJOR,0) #define SYSCONS_DEV MKDEV(TTYAUX_MAJOR,1) @@ -107,6 +119,7 @@ struct tty_ldisc ldiscs[NR_LDISCS]; /* line disc dispatch table */ #ifdef CONFIG_UNIX98_PTYS extern struct tty_driver ptm_driver[]; /* Unix98 pty masters; for /dev/ptmx */ +extern struct tty_driver pts_driver[]; /* Unix98 pty slaves; for /dev/ptmx */ #endif /* @@ -149,16 +162,26 @@ extern int rs_8xx_init(void); /* * This routine returns the name of tty. */ +static char * +_tty_make_name(struct tty_struct *tty, const char *name, char *buf) +{ + int idx = (tty)?MINOR(tty->device) - tty->driver.minor_start:0; + + if (!tty) /* Hmm. NULL pointer. That's fun. */ + strcpy(buf, "NULL tty"); + else + sprintf(buf, name, + idx + tty->driver.name_base); + + return buf; +} + #define TTY_NUMBER(tty) (MINOR((tty)->device) - (tty)->driver.minor_start + \ (tty)->driver.name_base) - + char *tty_name(struct tty_struct *tty, char *buf) { - if (tty) - sprintf(buf, "%s%d", tty->driver.name, TTY_NUMBER(tty)); - else - strcpy(buf, "NULL tty"); - return buf; + return _tty_make_name(tty, (tty)?tty->driver.name:NULL, buf); } inline int tty_paranoia_check(struct tty_struct *tty, kdev_t device, @@ -1298,6 +1321,8 @@ retry_open: set_bit(TTY_PTY_LOCK, &tty->flags); /* LOCK THE SLAVE */ minor -= driver->minor_start; devpts_pty_new(driver->other->name_base + minor, MKDEV(driver->other->major, minor + driver->other->minor_start)); + tty_register_devfs(&pts_driver[major], 0, + pts_driver[major].minor_start + minor); noctty = 1; goto init_dev_done; @@ -1966,16 +1991,86 @@ void tty_default_put_char(struct tty_struct *tty, unsigned char ch) } /* + * Register a tty device described by <driver>, with minor number <minor>. + */ +void tty_register_devfs (struct tty_driver *driver, unsigned int flags, + unsigned int minor) +{ +#ifdef CONFIG_DEVFS_FS + umode_t mode = S_IFCHR | S_IRUSR | S_IWUSR; + uid_t uid = 0; + gid_t gid = 0; + struct tty_struct tty; + char buf[32]; + + flags |= DEVFS_FL_DEFAULT; + tty.driver = *driver; + tty.device = MKDEV (driver->major, minor); + switch (tty.device) { + case TTY_DEV: + case PTMX_DEV: + mode |= S_IRGRP | S_IWGRP | S_IROTH | S_IWOTH; + break; + default: + flags |= DEVFS_FL_AUTO_OWNER; + break; + } + if ((minor < driver->minor_start) || + (minor >= driver->minor_start + driver->num)) { + printk(KERN_ERR "Attempt to register invalid minor number " + "with devfs (%d:%d).\n", (int)driver->major,(int)minor); + return; + } + if (driver->type == TTY_DRIVER_TYPE_CONSOLE) { + flags |= DEVFS_FL_AOPEN_NOTIFY; + flags &= ~DEVFS_FL_AUTO_OWNER; + } +# ifdef CONFIG_UNIX98_PTYS + if ( (driver->major >= UNIX98_PTY_SLAVE_MAJOR) && + (driver->major < UNIX98_PTY_SLAVE_MAJOR + UNIX98_NR_MAJORS) ) { + flags &= ~DEVFS_FL_AUTO_OWNER; + uid = current->uid; + gid = current->gid; + } +# endif + devfs_register (NULL, tty_name (&tty, buf), 0, flags, + driver->major, minor, mode, uid, gid, + &tty_fops, NULL); +#endif /* CONFIG_DEVFS_FS */ +} + +void tty_unregister_devfs (struct tty_driver *driver, unsigned minor) +{ +#ifdef CONFIG_DEVFS_FS + void * handle; + struct tty_struct tty; + char buf[32]; + + tty.driver = *driver; + tty.device = MKDEV(driver->major, minor); + + handle = devfs_find_handle (NULL, tty_name (&tty, buf), 0, + driver->major, minor, + DEVFS_SPECIAL_CHR, 0); + devfs_unregister (handle); +#endif /* CONFIG_DEVFS_FS */ +} + +EXPORT_SYMBOL(tty_register_devfs); +EXPORT_SYMBOL(tty_unregister_devfs); + +/* * Called by a tty driver to register itself. */ int tty_register_driver(struct tty_driver *driver) { int error; + int i; if (driver->flags & TTY_DRIVER_INSTALLED) return 0; - error = register_chrdev(driver->major, driver->name, &tty_fops); + error = devfs_register_chrdev(driver->major, driver->name, &tty_fops); if (error < 0) return error; else if(driver->major == 0) @@ -1989,6 +2084,10 @@ int tty_register_driver(struct tty_driver *driver) if (tty_drivers) tty_drivers->prev = driver; tty_drivers = driver; + if ( !(driver->flags & TTY_DRIVER_NO_DEVFS) ) { + for(i = 0; i < driver->num; i++) + tty_register_devfs(driver, 0, driver->minor_start + i); + } proc_tty_register_driver(driver); return error; } @@ -2018,11 +2117,11 @@ int tty_unregister_driver(struct tty_driver *driver) return -ENOENT; if (othername == NULL) { - retval = unregister_chrdev(driver->major, driver->name); + retval = devfs_unregister_chrdev(driver->major, driver->name); if (retval) return retval; } else - register_chrdev(driver->major, othername, &tty_fops); + devfs_register_chrdev(driver->major, othername, &tty_fops); if (driver->prev) driver->prev->next = driver->next; @@ -2048,6 +2147,7 @@ int tty_unregister_driver(struct tty_driver *driver) driver->termios_locked[i] = NULL; kfree_s(tp, sizeof(struct termios)); } + tty_unregister_devfs(driver, driver->minor_start + i); } proc_tty_unregister_driver(driver); return 0; @@ -2148,6 +2248,13 @@ void __init tty_init(void) if (tty_register_driver(&dev_syscons_driver)) panic("Couldn't register /dev/console driver\n"); + /* console calls tty_register_driver() before kmalloc() works. + * Thus, we can't devfs_register() then. Do so now, instead. + */ +#ifdef CONFIG_VT + con_init_devfs(); +#endif + #ifdef CONFIG_UNIX98_PTYS dev_ptmx_driver = dev_tty_driver; dev_ptmx_driver.driver_name = "/dev/ptmx"; @@ -2163,7 +2270,7 @@ void __init tty_init(void) #ifdef CONFIG_VT dev_console_driver = dev_tty_driver; - dev_console_driver.driver_name = "/dev/tty0"; + dev_console_driver.driver_name = "/dev/vc/0"; dev_console_driver.name = dev_console_driver.driver_name + 5; dev_console_driver.major = TTY_MAJOR; dev_console_driver.type = TTY_DRIVER_TYPE_SYSTEM; |