patch-2.3.46 linux/drivers/char/tty_io.c

Next file: linux/drivers/char/vc_screen.c
Previous file: linux/drivers/char/tpqic02.c
Back to the patch index
Back to the overall index

diff -u --recursive --new-file v2.3.45/linux/drivers/char/tty_io.c linux/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 @@
 
 #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 @@
 /*
  * 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 @@
 		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 @@
 }
 
 /*
+ * 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 @@
 	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 @@
 		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 @@
 			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 @@
 	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 @@
 	
 #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;

FUNET's LINUX-ADM group, linux-adm@nic.funet.fi
TCL-scripts by Sam Shen (who was at: slshen@lbl.gov)