summaryrefslogtreecommitdiffstats
path: root/drivers/char/tty_io.c
diff options
context:
space:
mode:
Diffstat (limited to 'drivers/char/tty_io.c')
-rw-r--r--drivers/char/tty_io.c127
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;