vt_ioctl.c revision 247ff8e610cb63c015de19191db9666754c2ed79
11da177e4c3f41524e886b7f1b8a0c1fc7321cacLinus Torvalds/*
21da177e4c3f41524e886b7f1b8a0c1fc7321cacLinus Torvalds *  Copyright (C) 1992 obz under the linux copyright
31da177e4c3f41524e886b7f1b8a0c1fc7321cacLinus Torvalds *
41da177e4c3f41524e886b7f1b8a0c1fc7321cacLinus Torvalds *  Dynamic diacritical handling - aeb@cwi.nl - Dec 1993
51da177e4c3f41524e886b7f1b8a0c1fc7321cacLinus Torvalds *  Dynamic keymap and string allocation - aeb@cwi.nl - May 1994
61da177e4c3f41524e886b7f1b8a0c1fc7321cacLinus Torvalds *  Restrict VT switching via ioctl() - grif@cs.ucr.edu - Dec 1995
71da177e4c3f41524e886b7f1b8a0c1fc7321cacLinus Torvalds *  Some code moved for less code duplication - Andi Kleen - Mar 1997
81da177e4c3f41524e886b7f1b8a0c1fc7321cacLinus Torvalds *  Check put/get_user, cleanups - acme@conectiva.com.br - Jun 2001
91da177e4c3f41524e886b7f1b8a0c1fc7321cacLinus Torvalds */
101da177e4c3f41524e886b7f1b8a0c1fc7321cacLinus Torvalds
111da177e4c3f41524e886b7f1b8a0c1fc7321cacLinus Torvalds#include <linux/types.h>
121da177e4c3f41524e886b7f1b8a0c1fc7321cacLinus Torvalds#include <linux/errno.h>
131da177e4c3f41524e886b7f1b8a0c1fc7321cacLinus Torvalds#include <linux/sched.h>
141da177e4c3f41524e886b7f1b8a0c1fc7321cacLinus Torvalds#include <linux/tty.h>
151da177e4c3f41524e886b7f1b8a0c1fc7321cacLinus Torvalds#include <linux/timer.h>
161da177e4c3f41524e886b7f1b8a0c1fc7321cacLinus Torvalds#include <linux/kernel.h>
17e92166517e3ca9bfb416f91e69cf0373b55b6edeArnd Bergmann#include <linux/compat.h>
188d233558cd99a888571bb5a88a74970879e0aba4Alan Cox#include <linux/module.h>
191da177e4c3f41524e886b7f1b8a0c1fc7321cacLinus Torvalds#include <linux/kd.h>
201da177e4c3f41524e886b7f1b8a0c1fc7321cacLinus Torvalds#include <linux/vt.h>
211da177e4c3f41524e886b7f1b8a0c1fc7321cacLinus Torvalds#include <linux/string.h>
221da177e4c3f41524e886b7f1b8a0c1fc7321cacLinus Torvalds#include <linux/slab.h>
231da177e4c3f41524e886b7f1b8a0c1fc7321cacLinus Torvalds#include <linux/major.h>
241da177e4c3f41524e886b7f1b8a0c1fc7321cacLinus Torvalds#include <linux/fs.h>
251da177e4c3f41524e886b7f1b8a0c1fc7321cacLinus Torvalds#include <linux/console.h>
2604c71976500352d02f60616d2b960267d8c5fe24Samuel Thibault#include <linux/consolemap.h>
277ed20e1ad521b5f5df61bf6559ae60738e393741Jesper Juhl#include <linux/signal.h>
28bcc8ca09920755520ba8a1e2d9f72fe8ff892643Emmanuel Colbus#include <linux/timex.h>
291da177e4c3f41524e886b7f1b8a0c1fc7321cacLinus Torvalds
301da177e4c3f41524e886b7f1b8a0c1fc7321cacLinus Torvalds#include <asm/io.h>
311da177e4c3f41524e886b7f1b8a0c1fc7321cacLinus Torvalds#include <asm/uaccess.h>
321da177e4c3f41524e886b7f1b8a0c1fc7321cacLinus Torvalds
331da177e4c3f41524e886b7f1b8a0c1fc7321cacLinus Torvalds#include <linux/kbd_kern.h>
341da177e4c3f41524e886b7f1b8a0c1fc7321cacLinus Torvalds#include <linux/vt_kern.h>
351da177e4c3f41524e886b7f1b8a0c1fc7321cacLinus Torvalds#include <linux/kbd_diacr.h>
361da177e4c3f41524e886b7f1b8a0c1fc7321cacLinus Torvalds#include <linux/selection.h>
371da177e4c3f41524e886b7f1b8a0c1fc7321cacLinus Torvalds
38b257bc051f06607beb3004d9a1c297085e728becAndrew Johnsonchar vt_dont_switch;
391da177e4c3f41524e886b7f1b8a0c1fc7321cacLinus Torvaldsextern struct tty_driver *console_driver;
401da177e4c3f41524e886b7f1b8a0c1fc7321cacLinus Torvalds
411da177e4c3f41524e886b7f1b8a0c1fc7321cacLinus Torvalds#define VT_IS_IN_USE(i)	(console_driver->ttys[i] && console_driver->ttys[i]->count)
421da177e4c3f41524e886b7f1b8a0c1fc7321cacLinus Torvalds#define VT_BUSY(i)	(VT_IS_IN_USE(i) || i == fg_console || vc_cons[i].d == sel_cons)
431da177e4c3f41524e886b7f1b8a0c1fc7321cacLinus Torvalds
441da177e4c3f41524e886b7f1b8a0c1fc7321cacLinus Torvalds/*
451da177e4c3f41524e886b7f1b8a0c1fc7321cacLinus Torvalds * Console (vt and kd) routines, as defined by USL SVR4 manual, and by
461da177e4c3f41524e886b7f1b8a0c1fc7321cacLinus Torvalds * experimentation and study of X386 SYSV handling.
471da177e4c3f41524e886b7f1b8a0c1fc7321cacLinus Torvalds *
481da177e4c3f41524e886b7f1b8a0c1fc7321cacLinus Torvalds * One point of difference: SYSV vt's are /dev/vtX, which X >= 0, and
491da177e4c3f41524e886b7f1b8a0c1fc7321cacLinus Torvalds * /dev/console is a separate ttyp. Under Linux, /dev/tty0 is /dev/console,
501da177e4c3f41524e886b7f1b8a0c1fc7321cacLinus Torvalds * and the vc start at /dev/ttyX, X >= 1. We maintain that here, so we will
511da177e4c3f41524e886b7f1b8a0c1fc7321cacLinus Torvalds * always treat our set of vt as numbered 1..MAX_NR_CONSOLES (corresponding to
521da177e4c3f41524e886b7f1b8a0c1fc7321cacLinus Torvalds * ttys 0..MAX_NR_CONSOLES-1). Explicitly naming VT 0 is illegal, but using
531da177e4c3f41524e886b7f1b8a0c1fc7321cacLinus Torvalds * /dev/tty0 (fg_console) as a target is legal, since an implicit aliasing
541da177e4c3f41524e886b7f1b8a0c1fc7321cacLinus Torvalds * to the current console is done by the main ioctl code.
551da177e4c3f41524e886b7f1b8a0c1fc7321cacLinus Torvalds */
561da177e4c3f41524e886b7f1b8a0c1fc7321cacLinus Torvalds
571da177e4c3f41524e886b7f1b8a0c1fc7321cacLinus Torvalds#ifdef CONFIG_X86
581da177e4c3f41524e886b7f1b8a0c1fc7321cacLinus Torvalds#include <linux/syscalls.h>
591da177e4c3f41524e886b7f1b8a0c1fc7321cacLinus Torvalds#endif
601da177e4c3f41524e886b7f1b8a0c1fc7321cacLinus Torvalds
611da177e4c3f41524e886b7f1b8a0c1fc7321cacLinus Torvaldsstatic void complete_change_console(struct vc_data *vc);
621da177e4c3f41524e886b7f1b8a0c1fc7321cacLinus Torvalds
631da177e4c3f41524e886b7f1b8a0c1fc7321cacLinus Torvalds/*
648b92e87d39bfd046e7581e1fe0f40eac40f88608Alan Cox *	User space VT_EVENT handlers
658b92e87d39bfd046e7581e1fe0f40eac40f88608Alan Cox */
668b92e87d39bfd046e7581e1fe0f40eac40f88608Alan Cox
678b92e87d39bfd046e7581e1fe0f40eac40f88608Alan Coxstruct vt_event_wait {
688b92e87d39bfd046e7581e1fe0f40eac40f88608Alan Cox	struct list_head list;
698b92e87d39bfd046e7581e1fe0f40eac40f88608Alan Cox	struct vt_event event;
708b92e87d39bfd046e7581e1fe0f40eac40f88608Alan Cox	int done;
718b92e87d39bfd046e7581e1fe0f40eac40f88608Alan Cox};
728b92e87d39bfd046e7581e1fe0f40eac40f88608Alan Cox
738b92e87d39bfd046e7581e1fe0f40eac40f88608Alan Coxstatic LIST_HEAD(vt_events);
748b92e87d39bfd046e7581e1fe0f40eac40f88608Alan Coxstatic DEFINE_SPINLOCK(vt_event_lock);
758b92e87d39bfd046e7581e1fe0f40eac40f88608Alan Coxstatic DECLARE_WAIT_QUEUE_HEAD(vt_event_waitqueue);
768b92e87d39bfd046e7581e1fe0f40eac40f88608Alan Cox
778b92e87d39bfd046e7581e1fe0f40eac40f88608Alan Cox/**
788b92e87d39bfd046e7581e1fe0f40eac40f88608Alan Cox *	vt_event_post
798b92e87d39bfd046e7581e1fe0f40eac40f88608Alan Cox *	@event: the event that occurred
808b92e87d39bfd046e7581e1fe0f40eac40f88608Alan Cox *	@old: old console
818b92e87d39bfd046e7581e1fe0f40eac40f88608Alan Cox *	@new: new console
828b92e87d39bfd046e7581e1fe0f40eac40f88608Alan Cox *
838b92e87d39bfd046e7581e1fe0f40eac40f88608Alan Cox *	Post an VT event to interested VT handlers
848b92e87d39bfd046e7581e1fe0f40eac40f88608Alan Cox */
858b92e87d39bfd046e7581e1fe0f40eac40f88608Alan Cox
868b92e87d39bfd046e7581e1fe0f40eac40f88608Alan Coxvoid vt_event_post(unsigned int event, unsigned int old, unsigned int new)
878b92e87d39bfd046e7581e1fe0f40eac40f88608Alan Cox{
888b92e87d39bfd046e7581e1fe0f40eac40f88608Alan Cox	struct list_head *pos, *head;
898b92e87d39bfd046e7581e1fe0f40eac40f88608Alan Cox	unsigned long flags;
908b92e87d39bfd046e7581e1fe0f40eac40f88608Alan Cox	int wake = 0;
918b92e87d39bfd046e7581e1fe0f40eac40f88608Alan Cox
928b92e87d39bfd046e7581e1fe0f40eac40f88608Alan Cox	spin_lock_irqsave(&vt_event_lock, flags);
938b92e87d39bfd046e7581e1fe0f40eac40f88608Alan Cox	head = &vt_events;
948b92e87d39bfd046e7581e1fe0f40eac40f88608Alan Cox
958b92e87d39bfd046e7581e1fe0f40eac40f88608Alan Cox	list_for_each(pos, head) {
968b92e87d39bfd046e7581e1fe0f40eac40f88608Alan Cox		struct vt_event_wait *ve = list_entry(pos,
978b92e87d39bfd046e7581e1fe0f40eac40f88608Alan Cox						struct vt_event_wait, list);
988b92e87d39bfd046e7581e1fe0f40eac40f88608Alan Cox		if (!(ve->event.event & event))
998b92e87d39bfd046e7581e1fe0f40eac40f88608Alan Cox			continue;
1008b92e87d39bfd046e7581e1fe0f40eac40f88608Alan Cox		ve->event.event = event;
1018b92e87d39bfd046e7581e1fe0f40eac40f88608Alan Cox		/* kernel view is consoles 0..n-1, user space view is
1028b92e87d39bfd046e7581e1fe0f40eac40f88608Alan Cox		   console 1..n with 0 meaning current, so we must bias */
103308efab5e231d1510cd35931d87629bf5171caaeAlan Cox		ve->event.oldev = old + 1;
104308efab5e231d1510cd35931d87629bf5171caaeAlan Cox		ve->event.newev = new + 1;
1058b92e87d39bfd046e7581e1fe0f40eac40f88608Alan Cox		wake = 1;
1068b92e87d39bfd046e7581e1fe0f40eac40f88608Alan Cox		ve->done = 1;
1078b92e87d39bfd046e7581e1fe0f40eac40f88608Alan Cox	}
1088b92e87d39bfd046e7581e1fe0f40eac40f88608Alan Cox	spin_unlock_irqrestore(&vt_event_lock, flags);
1098b92e87d39bfd046e7581e1fe0f40eac40f88608Alan Cox	if (wake)
1108b92e87d39bfd046e7581e1fe0f40eac40f88608Alan Cox		wake_up_interruptible(&vt_event_waitqueue);
1118b92e87d39bfd046e7581e1fe0f40eac40f88608Alan Cox}
1128b92e87d39bfd046e7581e1fe0f40eac40f88608Alan Cox
1138b92e87d39bfd046e7581e1fe0f40eac40f88608Alan Cox/**
1148b92e87d39bfd046e7581e1fe0f40eac40f88608Alan Cox *	vt_event_wait		-	wait for an event
1158b92e87d39bfd046e7581e1fe0f40eac40f88608Alan Cox *	@vw: our event
1168b92e87d39bfd046e7581e1fe0f40eac40f88608Alan Cox *
1178b92e87d39bfd046e7581e1fe0f40eac40f88608Alan Cox *	Waits for an event to occur which completes our vt_event_wait
1188b92e87d39bfd046e7581e1fe0f40eac40f88608Alan Cox *	structure. On return the structure has wv->done set to 1 for success
1198b92e87d39bfd046e7581e1fe0f40eac40f88608Alan Cox *	or 0 if some event such as a signal ended the wait.
1208b92e87d39bfd046e7581e1fe0f40eac40f88608Alan Cox */
1218b92e87d39bfd046e7581e1fe0f40eac40f88608Alan Cox
1228b92e87d39bfd046e7581e1fe0f40eac40f88608Alan Coxstatic void vt_event_wait(struct vt_event_wait *vw)
1238b92e87d39bfd046e7581e1fe0f40eac40f88608Alan Cox{
1248b92e87d39bfd046e7581e1fe0f40eac40f88608Alan Cox	unsigned long flags;
1258b92e87d39bfd046e7581e1fe0f40eac40f88608Alan Cox	/* Prepare the event */
1268b92e87d39bfd046e7581e1fe0f40eac40f88608Alan Cox	INIT_LIST_HEAD(&vw->list);
1278b92e87d39bfd046e7581e1fe0f40eac40f88608Alan Cox	vw->done = 0;
1288b92e87d39bfd046e7581e1fe0f40eac40f88608Alan Cox	/* Queue our event */
1298b92e87d39bfd046e7581e1fe0f40eac40f88608Alan Cox	spin_lock_irqsave(&vt_event_lock, flags);
1308b92e87d39bfd046e7581e1fe0f40eac40f88608Alan Cox	list_add(&vw->list, &vt_events);
1318b92e87d39bfd046e7581e1fe0f40eac40f88608Alan Cox	spin_unlock_irqrestore(&vt_event_lock, flags);
1328b92e87d39bfd046e7581e1fe0f40eac40f88608Alan Cox	/* Wait for it to pass */
133be1bc2889a4db4961ef69f47fb471ecae9f23adeArnd Bergmann	wait_event_interruptible_tty(vt_event_waitqueue, vw->done);
1348b92e87d39bfd046e7581e1fe0f40eac40f88608Alan Cox	/* Dequeue it */
1358b92e87d39bfd046e7581e1fe0f40eac40f88608Alan Cox	spin_lock_irqsave(&vt_event_lock, flags);
1368b92e87d39bfd046e7581e1fe0f40eac40f88608Alan Cox	list_del(&vw->list);
1378b92e87d39bfd046e7581e1fe0f40eac40f88608Alan Cox	spin_unlock_irqrestore(&vt_event_lock, flags);
1388b92e87d39bfd046e7581e1fe0f40eac40f88608Alan Cox}
1398b92e87d39bfd046e7581e1fe0f40eac40f88608Alan Cox
1408b92e87d39bfd046e7581e1fe0f40eac40f88608Alan Cox/**
1418b92e87d39bfd046e7581e1fe0f40eac40f88608Alan Cox *	vt_event_wait_ioctl	-	event ioctl handler
1428b92e87d39bfd046e7581e1fe0f40eac40f88608Alan Cox *	@arg: argument to ioctl
1438b92e87d39bfd046e7581e1fe0f40eac40f88608Alan Cox *
1448b92e87d39bfd046e7581e1fe0f40eac40f88608Alan Cox *	Implement the VT_WAITEVENT ioctl using the VT event interface
1458b92e87d39bfd046e7581e1fe0f40eac40f88608Alan Cox */
1468b92e87d39bfd046e7581e1fe0f40eac40f88608Alan Cox
1478b92e87d39bfd046e7581e1fe0f40eac40f88608Alan Coxstatic int vt_event_wait_ioctl(struct vt_event __user *event)
1488b92e87d39bfd046e7581e1fe0f40eac40f88608Alan Cox{
1498b92e87d39bfd046e7581e1fe0f40eac40f88608Alan Cox	struct vt_event_wait vw;
1508b92e87d39bfd046e7581e1fe0f40eac40f88608Alan Cox
1518b92e87d39bfd046e7581e1fe0f40eac40f88608Alan Cox	if (copy_from_user(&vw.event, event, sizeof(struct vt_event)))
1528b92e87d39bfd046e7581e1fe0f40eac40f88608Alan Cox		return -EFAULT;
1538b92e87d39bfd046e7581e1fe0f40eac40f88608Alan Cox	/* Highest supported event for now */
1548b92e87d39bfd046e7581e1fe0f40eac40f88608Alan Cox	if (vw.event.event & ~VT_MAX_EVENT)
1558b92e87d39bfd046e7581e1fe0f40eac40f88608Alan Cox		return -EINVAL;
1568b92e87d39bfd046e7581e1fe0f40eac40f88608Alan Cox
1578b92e87d39bfd046e7581e1fe0f40eac40f88608Alan Cox	vt_event_wait(&vw);
1588b92e87d39bfd046e7581e1fe0f40eac40f88608Alan Cox	/* If it occurred report it */
1598b92e87d39bfd046e7581e1fe0f40eac40f88608Alan Cox	if (vw.done) {
1608b92e87d39bfd046e7581e1fe0f40eac40f88608Alan Cox		if (copy_to_user(event, &vw.event, sizeof(struct vt_event)))
1618b92e87d39bfd046e7581e1fe0f40eac40f88608Alan Cox			return -EFAULT;
1628b92e87d39bfd046e7581e1fe0f40eac40f88608Alan Cox		return 0;
1638b92e87d39bfd046e7581e1fe0f40eac40f88608Alan Cox	}
1648b92e87d39bfd046e7581e1fe0f40eac40f88608Alan Cox	return -EINTR;
1658b92e87d39bfd046e7581e1fe0f40eac40f88608Alan Cox}
1668b92e87d39bfd046e7581e1fe0f40eac40f88608Alan Cox
1678b92e87d39bfd046e7581e1fe0f40eac40f88608Alan Cox/**
1688b92e87d39bfd046e7581e1fe0f40eac40f88608Alan Cox *	vt_waitactive	-	active console wait
1698b92e87d39bfd046e7581e1fe0f40eac40f88608Alan Cox *	@event: event code
1708b92e87d39bfd046e7581e1fe0f40eac40f88608Alan Cox *	@n: new console
1718b92e87d39bfd046e7581e1fe0f40eac40f88608Alan Cox *
1728b92e87d39bfd046e7581e1fe0f40eac40f88608Alan Cox *	Helper for event waits. Used to implement the legacy
1738b92e87d39bfd046e7581e1fe0f40eac40f88608Alan Cox *	event waiting ioctls in terms of events
1748b92e87d39bfd046e7581e1fe0f40eac40f88608Alan Cox */
1758b92e87d39bfd046e7581e1fe0f40eac40f88608Alan Cox
1768b92e87d39bfd046e7581e1fe0f40eac40f88608Alan Coxint vt_waitactive(int n)
1778b92e87d39bfd046e7581e1fe0f40eac40f88608Alan Cox{
1788b92e87d39bfd046e7581e1fe0f40eac40f88608Alan Cox	struct vt_event_wait vw;
1798b92e87d39bfd046e7581e1fe0f40eac40f88608Alan Cox	do {
1808b92e87d39bfd046e7581e1fe0f40eac40f88608Alan Cox		if (n == fg_console + 1)
1818b92e87d39bfd046e7581e1fe0f40eac40f88608Alan Cox			break;
1828b92e87d39bfd046e7581e1fe0f40eac40f88608Alan Cox		vw.event.event = VT_EVENT_SWITCH;
1838b92e87d39bfd046e7581e1fe0f40eac40f88608Alan Cox		vt_event_wait(&vw);
1848b92e87d39bfd046e7581e1fe0f40eac40f88608Alan Cox		if (vw.done == 0)
1858b92e87d39bfd046e7581e1fe0f40eac40f88608Alan Cox			return -EINTR;
186308efab5e231d1510cd35931d87629bf5171caaeAlan Cox	} while (vw.event.newev != n);
1878b92e87d39bfd046e7581e1fe0f40eac40f88608Alan Cox	return 0;
1888b92e87d39bfd046e7581e1fe0f40eac40f88608Alan Cox}
1898b92e87d39bfd046e7581e1fe0f40eac40f88608Alan Cox
1908b92e87d39bfd046e7581e1fe0f40eac40f88608Alan Cox/*
1911da177e4c3f41524e886b7f1b8a0c1fc7321cacLinus Torvalds * these are the valid i/o ports we're allowed to change. they map all the
1921da177e4c3f41524e886b7f1b8a0c1fc7321cacLinus Torvalds * video ports
1931da177e4c3f41524e886b7f1b8a0c1fc7321cacLinus Torvalds */
1941da177e4c3f41524e886b7f1b8a0c1fc7321cacLinus Torvalds#define GPFIRST 0x3b4
1951da177e4c3f41524e886b7f1b8a0c1fc7321cacLinus Torvalds#define GPLAST 0x3df
1961da177e4c3f41524e886b7f1b8a0c1fc7321cacLinus Torvalds#define GPNUM (GPLAST - GPFIRST + 1)
1971da177e4c3f41524e886b7f1b8a0c1fc7321cacLinus Torvalds
1981da177e4c3f41524e886b7f1b8a0c1fc7321cacLinus Torvalds#define i (tmp.kb_index)
1991da177e4c3f41524e886b7f1b8a0c1fc7321cacLinus Torvalds#define s (tmp.kb_table)
2001da177e4c3f41524e886b7f1b8a0c1fc7321cacLinus Torvalds#define v (tmp.kb_value)
2011da177e4c3f41524e886b7f1b8a0c1fc7321cacLinus Torvaldsstatic inline int
2021da177e4c3f41524e886b7f1b8a0c1fc7321cacLinus Torvaldsdo_kdsk_ioctl(int cmd, struct kbentry __user *user_kbe, int perm, struct kbd_struct *kbd)
2031da177e4c3f41524e886b7f1b8a0c1fc7321cacLinus Torvalds{
2041da177e4c3f41524e886b7f1b8a0c1fc7321cacLinus Torvalds	struct kbentry tmp;
2051da177e4c3f41524e886b7f1b8a0c1fc7321cacLinus Torvalds	ushort *key_map, val, ov;
2061da177e4c3f41524e886b7f1b8a0c1fc7321cacLinus Torvalds
2071da177e4c3f41524e886b7f1b8a0c1fc7321cacLinus Torvalds	if (copy_from_user(&tmp, user_kbe, sizeof(struct kbentry)))
2081da177e4c3f41524e886b7f1b8a0c1fc7321cacLinus Torvalds		return -EFAULT;
2091da177e4c3f41524e886b7f1b8a0c1fc7321cacLinus Torvalds
210e3f17f0f6e98f58edb13cb38810d93e6d4808e68Marcelo Tosatti	if (!capable(CAP_SYS_TTY_CONFIG))
211e3f17f0f6e98f58edb13cb38810d93e6d4808e68Marcelo Tosatti		perm = 0;
212e3f17f0f6e98f58edb13cb38810d93e6d4808e68Marcelo Tosatti
2131da177e4c3f41524e886b7f1b8a0c1fc7321cacLinus Torvalds	switch (cmd) {
2141da177e4c3f41524e886b7f1b8a0c1fc7321cacLinus Torvalds	case KDGKBENT:
2151da177e4c3f41524e886b7f1b8a0c1fc7321cacLinus Torvalds		key_map = key_maps[s];
2161da177e4c3f41524e886b7f1b8a0c1fc7321cacLinus Torvalds		if (key_map) {
2171da177e4c3f41524e886b7f1b8a0c1fc7321cacLinus Torvalds		    val = U(key_map[i]);
2181da177e4c3f41524e886b7f1b8a0c1fc7321cacLinus Torvalds		    if (kbd->kbdmode != VC_UNICODE && KTYP(val) >= NR_TYPES)
2191da177e4c3f41524e886b7f1b8a0c1fc7321cacLinus Torvalds			val = K_HOLE;
2201da177e4c3f41524e886b7f1b8a0c1fc7321cacLinus Torvalds		} else
2211da177e4c3f41524e886b7f1b8a0c1fc7321cacLinus Torvalds		    val = (i ? K_HOLE : K_NOSUCHMAP);
2221da177e4c3f41524e886b7f1b8a0c1fc7321cacLinus Torvalds		return put_user(val, &user_kbe->kb_value);
2231da177e4c3f41524e886b7f1b8a0c1fc7321cacLinus Torvalds	case KDSKBENT:
2241da177e4c3f41524e886b7f1b8a0c1fc7321cacLinus Torvalds		if (!perm)
2251da177e4c3f41524e886b7f1b8a0c1fc7321cacLinus Torvalds			return -EPERM;
2261da177e4c3f41524e886b7f1b8a0c1fc7321cacLinus Torvalds		if (!i && v == K_NOSUCHMAP) {
227ca9bda00b4aafc42cd3d1b9d32934463e2993b4cAlan Cox			/* deallocate map */
2281da177e4c3f41524e886b7f1b8a0c1fc7321cacLinus Torvalds			key_map = key_maps[s];
2291da177e4c3f41524e886b7f1b8a0c1fc7321cacLinus Torvalds			if (s && key_map) {
2301da177e4c3f41524e886b7f1b8a0c1fc7321cacLinus Torvalds			    key_maps[s] = NULL;
2311da177e4c3f41524e886b7f1b8a0c1fc7321cacLinus Torvalds			    if (key_map[0] == U(K_ALLOCATED)) {
2321da177e4c3f41524e886b7f1b8a0c1fc7321cacLinus Torvalds					kfree(key_map);
2331da177e4c3f41524e886b7f1b8a0c1fc7321cacLinus Torvalds					keymap_count--;
2341da177e4c3f41524e886b7f1b8a0c1fc7321cacLinus Torvalds			    }
2351da177e4c3f41524e886b7f1b8a0c1fc7321cacLinus Torvalds			}
2361da177e4c3f41524e886b7f1b8a0c1fc7321cacLinus Torvalds			break;
2371da177e4c3f41524e886b7f1b8a0c1fc7321cacLinus Torvalds		}
2381da177e4c3f41524e886b7f1b8a0c1fc7321cacLinus Torvalds
2391da177e4c3f41524e886b7f1b8a0c1fc7321cacLinus Torvalds		if (KTYP(v) < NR_TYPES) {
2401da177e4c3f41524e886b7f1b8a0c1fc7321cacLinus Torvalds		    if (KVAL(v) > max_vals[KTYP(v)])
2411da177e4c3f41524e886b7f1b8a0c1fc7321cacLinus Torvalds				return -EINVAL;
2421da177e4c3f41524e886b7f1b8a0c1fc7321cacLinus Torvalds		} else
2431da177e4c3f41524e886b7f1b8a0c1fc7321cacLinus Torvalds		    if (kbd->kbdmode != VC_UNICODE)
2441da177e4c3f41524e886b7f1b8a0c1fc7321cacLinus Torvalds				return -EINVAL;
2451da177e4c3f41524e886b7f1b8a0c1fc7321cacLinus Torvalds
2461da177e4c3f41524e886b7f1b8a0c1fc7321cacLinus Torvalds		/* ++Geert: non-PC keyboards may generate keycode zero */
2471da177e4c3f41524e886b7f1b8a0c1fc7321cacLinus Torvalds#if !defined(__mc68000__) && !defined(__powerpc__)
2481da177e4c3f41524e886b7f1b8a0c1fc7321cacLinus Torvalds		/* assignment to entry 0 only tests validity of args */
2491da177e4c3f41524e886b7f1b8a0c1fc7321cacLinus Torvalds		if (!i)
2501da177e4c3f41524e886b7f1b8a0c1fc7321cacLinus Torvalds			break;
2511da177e4c3f41524e886b7f1b8a0c1fc7321cacLinus Torvalds#endif
2521da177e4c3f41524e886b7f1b8a0c1fc7321cacLinus Torvalds
2531da177e4c3f41524e886b7f1b8a0c1fc7321cacLinus Torvalds		if (!(key_map = key_maps[s])) {
2541da177e4c3f41524e886b7f1b8a0c1fc7321cacLinus Torvalds			int j;
2551da177e4c3f41524e886b7f1b8a0c1fc7321cacLinus Torvalds
2561da177e4c3f41524e886b7f1b8a0c1fc7321cacLinus Torvalds			if (keymap_count >= MAX_NR_OF_USER_KEYMAPS &&
2571da177e4c3f41524e886b7f1b8a0c1fc7321cacLinus Torvalds			    !capable(CAP_SYS_RESOURCE))
2581da177e4c3f41524e886b7f1b8a0c1fc7321cacLinus Torvalds				return -EPERM;
2591da177e4c3f41524e886b7f1b8a0c1fc7321cacLinus Torvalds
2605cbded585d129d0226cb48ac4202b253c781be26Robert P. J. Day			key_map = kmalloc(sizeof(plain_map),
2611da177e4c3f41524e886b7f1b8a0c1fc7321cacLinus Torvalds						     GFP_KERNEL);
2621da177e4c3f41524e886b7f1b8a0c1fc7321cacLinus Torvalds			if (!key_map)
2631da177e4c3f41524e886b7f1b8a0c1fc7321cacLinus Torvalds				return -ENOMEM;
2641da177e4c3f41524e886b7f1b8a0c1fc7321cacLinus Torvalds			key_maps[s] = key_map;
2651da177e4c3f41524e886b7f1b8a0c1fc7321cacLinus Torvalds			key_map[0] = U(K_ALLOCATED);
2661da177e4c3f41524e886b7f1b8a0c1fc7321cacLinus Torvalds			for (j = 1; j < NR_KEYS; j++)
2671da177e4c3f41524e886b7f1b8a0c1fc7321cacLinus Torvalds				key_map[j] = U(K_HOLE);
2681da177e4c3f41524e886b7f1b8a0c1fc7321cacLinus Torvalds			keymap_count++;
2691da177e4c3f41524e886b7f1b8a0c1fc7321cacLinus Torvalds		}
2701da177e4c3f41524e886b7f1b8a0c1fc7321cacLinus Torvalds		ov = U(key_map[i]);
2711da177e4c3f41524e886b7f1b8a0c1fc7321cacLinus Torvalds		if (v == ov)
2721da177e4c3f41524e886b7f1b8a0c1fc7321cacLinus Torvalds			break;	/* nothing to do */
2731da177e4c3f41524e886b7f1b8a0c1fc7321cacLinus Torvalds		/*
2741da177e4c3f41524e886b7f1b8a0c1fc7321cacLinus Torvalds		 * Attention Key.
2751da177e4c3f41524e886b7f1b8a0c1fc7321cacLinus Torvalds		 */
2761da177e4c3f41524e886b7f1b8a0c1fc7321cacLinus Torvalds		if (((ov == K_SAK) || (v == K_SAK)) && !capable(CAP_SYS_ADMIN))
2771da177e4c3f41524e886b7f1b8a0c1fc7321cacLinus Torvalds			return -EPERM;
2781da177e4c3f41524e886b7f1b8a0c1fc7321cacLinus Torvalds		key_map[i] = U(v);
2791da177e4c3f41524e886b7f1b8a0c1fc7321cacLinus Torvalds		if (!s && (KTYP(ov) == KT_SHIFT || KTYP(v) == KT_SHIFT))
2801da177e4c3f41524e886b7f1b8a0c1fc7321cacLinus Torvalds			compute_shiftstate();
2811da177e4c3f41524e886b7f1b8a0c1fc7321cacLinus Torvalds		break;
2821da177e4c3f41524e886b7f1b8a0c1fc7321cacLinus Torvalds	}
2831da177e4c3f41524e886b7f1b8a0c1fc7321cacLinus Torvalds	return 0;
2841da177e4c3f41524e886b7f1b8a0c1fc7321cacLinus Torvalds}
2851da177e4c3f41524e886b7f1b8a0c1fc7321cacLinus Torvalds#undef i
2861da177e4c3f41524e886b7f1b8a0c1fc7321cacLinus Torvalds#undef s
2871da177e4c3f41524e886b7f1b8a0c1fc7321cacLinus Torvalds#undef v
2881da177e4c3f41524e886b7f1b8a0c1fc7321cacLinus Torvalds
2891da177e4c3f41524e886b7f1b8a0c1fc7321cacLinus Torvaldsstatic inline int
2901da177e4c3f41524e886b7f1b8a0c1fc7321cacLinus Torvaldsdo_kbkeycode_ioctl(int cmd, struct kbkeycode __user *user_kbkc, int perm)
2911da177e4c3f41524e886b7f1b8a0c1fc7321cacLinus Torvalds{
2921da177e4c3f41524e886b7f1b8a0c1fc7321cacLinus Torvalds	struct kbkeycode tmp;
2931da177e4c3f41524e886b7f1b8a0c1fc7321cacLinus Torvalds	int kc = 0;
2941da177e4c3f41524e886b7f1b8a0c1fc7321cacLinus Torvalds
2951da177e4c3f41524e886b7f1b8a0c1fc7321cacLinus Torvalds	if (copy_from_user(&tmp, user_kbkc, sizeof(struct kbkeycode)))
2961da177e4c3f41524e886b7f1b8a0c1fc7321cacLinus Torvalds		return -EFAULT;
2971da177e4c3f41524e886b7f1b8a0c1fc7321cacLinus Torvalds	switch (cmd) {
2981da177e4c3f41524e886b7f1b8a0c1fc7321cacLinus Torvalds	case KDGETKEYCODE:
2991da177e4c3f41524e886b7f1b8a0c1fc7321cacLinus Torvalds		kc = getkeycode(tmp.scancode);
3001da177e4c3f41524e886b7f1b8a0c1fc7321cacLinus Torvalds		if (kc >= 0)
3011da177e4c3f41524e886b7f1b8a0c1fc7321cacLinus Torvalds			kc = put_user(kc, &user_kbkc->keycode);
3021da177e4c3f41524e886b7f1b8a0c1fc7321cacLinus Torvalds		break;
3031da177e4c3f41524e886b7f1b8a0c1fc7321cacLinus Torvalds	case KDSETKEYCODE:
3041da177e4c3f41524e886b7f1b8a0c1fc7321cacLinus Torvalds		if (!perm)
3051da177e4c3f41524e886b7f1b8a0c1fc7321cacLinus Torvalds			return -EPERM;
3061da177e4c3f41524e886b7f1b8a0c1fc7321cacLinus Torvalds		kc = setkeycode(tmp.scancode, tmp.keycode);
3071da177e4c3f41524e886b7f1b8a0c1fc7321cacLinus Torvalds		break;
3081da177e4c3f41524e886b7f1b8a0c1fc7321cacLinus Torvalds	}
3091da177e4c3f41524e886b7f1b8a0c1fc7321cacLinus Torvalds	return kc;
3101da177e4c3f41524e886b7f1b8a0c1fc7321cacLinus Torvalds}
3111da177e4c3f41524e886b7f1b8a0c1fc7321cacLinus Torvalds
3121da177e4c3f41524e886b7f1b8a0c1fc7321cacLinus Torvaldsstatic inline int
3131da177e4c3f41524e886b7f1b8a0c1fc7321cacLinus Torvaldsdo_kdgkb_ioctl(int cmd, struct kbsentry __user *user_kdgkb, int perm)
3141da177e4c3f41524e886b7f1b8a0c1fc7321cacLinus Torvalds{
3151da177e4c3f41524e886b7f1b8a0c1fc7321cacLinus Torvalds	struct kbsentry *kbs;
3161da177e4c3f41524e886b7f1b8a0c1fc7321cacLinus Torvalds	char *p;
3171da177e4c3f41524e886b7f1b8a0c1fc7321cacLinus Torvalds	u_char *q;
3181da177e4c3f41524e886b7f1b8a0c1fc7321cacLinus Torvalds	u_char __user *up;
3191da177e4c3f41524e886b7f1b8a0c1fc7321cacLinus Torvalds	int sz;
3201da177e4c3f41524e886b7f1b8a0c1fc7321cacLinus Torvalds	int delta;
3211da177e4c3f41524e886b7f1b8a0c1fc7321cacLinus Torvalds	char *first_free, *fj, *fnw;
3221da177e4c3f41524e886b7f1b8a0c1fc7321cacLinus Torvalds	int i, j, k;
3231da177e4c3f41524e886b7f1b8a0c1fc7321cacLinus Torvalds	int ret;
3241da177e4c3f41524e886b7f1b8a0c1fc7321cacLinus Torvalds
3250b360adbdb54d5b98b78d57ba0916bc4b8871968Andrew Morton	if (!capable(CAP_SYS_TTY_CONFIG))
326e3f17f0f6e98f58edb13cb38810d93e6d4808e68Marcelo Tosatti		perm = 0;
3270b360adbdb54d5b98b78d57ba0916bc4b8871968Andrew Morton
3281da177e4c3f41524e886b7f1b8a0c1fc7321cacLinus Torvalds	kbs = kmalloc(sizeof(*kbs), GFP_KERNEL);
3291da177e4c3f41524e886b7f1b8a0c1fc7321cacLinus Torvalds	if (!kbs) {
3301da177e4c3f41524e886b7f1b8a0c1fc7321cacLinus Torvalds		ret = -ENOMEM;
3311da177e4c3f41524e886b7f1b8a0c1fc7321cacLinus Torvalds		goto reterr;
3321da177e4c3f41524e886b7f1b8a0c1fc7321cacLinus Torvalds	}
3331da177e4c3f41524e886b7f1b8a0c1fc7321cacLinus Torvalds
3341da177e4c3f41524e886b7f1b8a0c1fc7321cacLinus Torvalds	/* we mostly copy too much here (512bytes), but who cares ;) */
3351da177e4c3f41524e886b7f1b8a0c1fc7321cacLinus Torvalds	if (copy_from_user(kbs, user_kdgkb, sizeof(struct kbsentry))) {
3361da177e4c3f41524e886b7f1b8a0c1fc7321cacLinus Torvalds		ret = -EFAULT;
3371da177e4c3f41524e886b7f1b8a0c1fc7321cacLinus Torvalds		goto reterr;
3381da177e4c3f41524e886b7f1b8a0c1fc7321cacLinus Torvalds	}
3391da177e4c3f41524e886b7f1b8a0c1fc7321cacLinus Torvalds	kbs->kb_string[sizeof(kbs->kb_string)-1] = '\0';
3401da177e4c3f41524e886b7f1b8a0c1fc7321cacLinus Torvalds	i = kbs->kb_func;
3411da177e4c3f41524e886b7f1b8a0c1fc7321cacLinus Torvalds
3421da177e4c3f41524e886b7f1b8a0c1fc7321cacLinus Torvalds	switch (cmd) {
3431da177e4c3f41524e886b7f1b8a0c1fc7321cacLinus Torvalds	case KDGKBSENT:
3441da177e4c3f41524e886b7f1b8a0c1fc7321cacLinus Torvalds		sz = sizeof(kbs->kb_string) - 1; /* sz should have been
3451da177e4c3f41524e886b7f1b8a0c1fc7321cacLinus Torvalds						  a struct member */
3461da177e4c3f41524e886b7f1b8a0c1fc7321cacLinus Torvalds		up = user_kdgkb->kb_string;
3471da177e4c3f41524e886b7f1b8a0c1fc7321cacLinus Torvalds		p = func_table[i];
3481da177e4c3f41524e886b7f1b8a0c1fc7321cacLinus Torvalds		if(p)
3491da177e4c3f41524e886b7f1b8a0c1fc7321cacLinus Torvalds			for ( ; *p && sz; p++, sz--)
3501da177e4c3f41524e886b7f1b8a0c1fc7321cacLinus Torvalds				if (put_user(*p, up++)) {
3511da177e4c3f41524e886b7f1b8a0c1fc7321cacLinus Torvalds					ret = -EFAULT;
3521da177e4c3f41524e886b7f1b8a0c1fc7321cacLinus Torvalds					goto reterr;
3531da177e4c3f41524e886b7f1b8a0c1fc7321cacLinus Torvalds				}
3541da177e4c3f41524e886b7f1b8a0c1fc7321cacLinus Torvalds		if (put_user('\0', up)) {
3551da177e4c3f41524e886b7f1b8a0c1fc7321cacLinus Torvalds			ret = -EFAULT;
3561da177e4c3f41524e886b7f1b8a0c1fc7321cacLinus Torvalds			goto reterr;
3571da177e4c3f41524e886b7f1b8a0c1fc7321cacLinus Torvalds		}
3581da177e4c3f41524e886b7f1b8a0c1fc7321cacLinus Torvalds		kfree(kbs);
3591da177e4c3f41524e886b7f1b8a0c1fc7321cacLinus Torvalds		return ((p && *p) ? -EOVERFLOW : 0);
3601da177e4c3f41524e886b7f1b8a0c1fc7321cacLinus Torvalds	case KDSKBSENT:
3611da177e4c3f41524e886b7f1b8a0c1fc7321cacLinus Torvalds		if (!perm) {
3621da177e4c3f41524e886b7f1b8a0c1fc7321cacLinus Torvalds			ret = -EPERM;
3631da177e4c3f41524e886b7f1b8a0c1fc7321cacLinus Torvalds			goto reterr;
3641da177e4c3f41524e886b7f1b8a0c1fc7321cacLinus Torvalds		}
3651da177e4c3f41524e886b7f1b8a0c1fc7321cacLinus Torvalds
3661da177e4c3f41524e886b7f1b8a0c1fc7321cacLinus Torvalds		q = func_table[i];
3671da177e4c3f41524e886b7f1b8a0c1fc7321cacLinus Torvalds		first_free = funcbufptr + (funcbufsize - funcbufleft);
3681da177e4c3f41524e886b7f1b8a0c1fc7321cacLinus Torvalds		for (j = i+1; j < MAX_NR_FUNC && !func_table[j]; j++)
3691da177e4c3f41524e886b7f1b8a0c1fc7321cacLinus Torvalds			;
3701da177e4c3f41524e886b7f1b8a0c1fc7321cacLinus Torvalds		if (j < MAX_NR_FUNC)
3711da177e4c3f41524e886b7f1b8a0c1fc7321cacLinus Torvalds			fj = func_table[j];
3721da177e4c3f41524e886b7f1b8a0c1fc7321cacLinus Torvalds		else
3731da177e4c3f41524e886b7f1b8a0c1fc7321cacLinus Torvalds			fj = first_free;
3741da177e4c3f41524e886b7f1b8a0c1fc7321cacLinus Torvalds
3751da177e4c3f41524e886b7f1b8a0c1fc7321cacLinus Torvalds		delta = (q ? -strlen(q) : 1) + strlen(kbs->kb_string);
3761da177e4c3f41524e886b7f1b8a0c1fc7321cacLinus Torvalds		if (delta <= funcbufleft) { 	/* it fits in current buf */
3771da177e4c3f41524e886b7f1b8a0c1fc7321cacLinus Torvalds		    if (j < MAX_NR_FUNC) {
3781da177e4c3f41524e886b7f1b8a0c1fc7321cacLinus Torvalds			memmove(fj + delta, fj, first_free - fj);
3791da177e4c3f41524e886b7f1b8a0c1fc7321cacLinus Torvalds			for (k = j; k < MAX_NR_FUNC; k++)
3801da177e4c3f41524e886b7f1b8a0c1fc7321cacLinus Torvalds			    if (func_table[k])
3811da177e4c3f41524e886b7f1b8a0c1fc7321cacLinus Torvalds				func_table[k] += delta;
3821da177e4c3f41524e886b7f1b8a0c1fc7321cacLinus Torvalds		    }
3831da177e4c3f41524e886b7f1b8a0c1fc7321cacLinus Torvalds		    if (!q)
3841da177e4c3f41524e886b7f1b8a0c1fc7321cacLinus Torvalds		      func_table[i] = fj;
3851da177e4c3f41524e886b7f1b8a0c1fc7321cacLinus Torvalds		    funcbufleft -= delta;
3861da177e4c3f41524e886b7f1b8a0c1fc7321cacLinus Torvalds		} else {			/* allocate a larger buffer */
3871da177e4c3f41524e886b7f1b8a0c1fc7321cacLinus Torvalds		    sz = 256;
3881da177e4c3f41524e886b7f1b8a0c1fc7321cacLinus Torvalds		    while (sz < funcbufsize - funcbufleft + delta)
3891da177e4c3f41524e886b7f1b8a0c1fc7321cacLinus Torvalds		      sz <<= 1;
3905cbded585d129d0226cb48ac4202b253c781be26Robert P. J. Day		    fnw = kmalloc(sz, GFP_KERNEL);
3911da177e4c3f41524e886b7f1b8a0c1fc7321cacLinus Torvalds		    if(!fnw) {
3921da177e4c3f41524e886b7f1b8a0c1fc7321cacLinus Torvalds		      ret = -ENOMEM;
3931da177e4c3f41524e886b7f1b8a0c1fc7321cacLinus Torvalds		      goto reterr;
3941da177e4c3f41524e886b7f1b8a0c1fc7321cacLinus Torvalds		    }
3951da177e4c3f41524e886b7f1b8a0c1fc7321cacLinus Torvalds
3961da177e4c3f41524e886b7f1b8a0c1fc7321cacLinus Torvalds		    if (!q)
3971da177e4c3f41524e886b7f1b8a0c1fc7321cacLinus Torvalds		      func_table[i] = fj;
3981da177e4c3f41524e886b7f1b8a0c1fc7321cacLinus Torvalds		    if (fj > funcbufptr)
3991da177e4c3f41524e886b7f1b8a0c1fc7321cacLinus Torvalds			memmove(fnw, funcbufptr, fj - funcbufptr);
4001da177e4c3f41524e886b7f1b8a0c1fc7321cacLinus Torvalds		    for (k = 0; k < j; k++)
4011da177e4c3f41524e886b7f1b8a0c1fc7321cacLinus Torvalds		      if (func_table[k])
4021da177e4c3f41524e886b7f1b8a0c1fc7321cacLinus Torvalds			func_table[k] = fnw + (func_table[k] - funcbufptr);
4031da177e4c3f41524e886b7f1b8a0c1fc7321cacLinus Torvalds
4041da177e4c3f41524e886b7f1b8a0c1fc7321cacLinus Torvalds		    if (first_free > fj) {
4051da177e4c3f41524e886b7f1b8a0c1fc7321cacLinus Torvalds			memmove(fnw + (fj - funcbufptr) + delta, fj, first_free - fj);
4061da177e4c3f41524e886b7f1b8a0c1fc7321cacLinus Torvalds			for (k = j; k < MAX_NR_FUNC; k++)
4071da177e4c3f41524e886b7f1b8a0c1fc7321cacLinus Torvalds			  if (func_table[k])
4081da177e4c3f41524e886b7f1b8a0c1fc7321cacLinus Torvalds			    func_table[k] = fnw + (func_table[k] - funcbufptr) + delta;
4091da177e4c3f41524e886b7f1b8a0c1fc7321cacLinus Torvalds		    }
4101da177e4c3f41524e886b7f1b8a0c1fc7321cacLinus Torvalds		    if (funcbufptr != func_buf)
4111da177e4c3f41524e886b7f1b8a0c1fc7321cacLinus Torvalds		      kfree(funcbufptr);
4121da177e4c3f41524e886b7f1b8a0c1fc7321cacLinus Torvalds		    funcbufptr = fnw;
4131da177e4c3f41524e886b7f1b8a0c1fc7321cacLinus Torvalds		    funcbufleft = funcbufleft - delta + sz - funcbufsize;
4141da177e4c3f41524e886b7f1b8a0c1fc7321cacLinus Torvalds		    funcbufsize = sz;
4151da177e4c3f41524e886b7f1b8a0c1fc7321cacLinus Torvalds		}
4161da177e4c3f41524e886b7f1b8a0c1fc7321cacLinus Torvalds		strcpy(func_table[i], kbs->kb_string);
4171da177e4c3f41524e886b7f1b8a0c1fc7321cacLinus Torvalds		break;
4181da177e4c3f41524e886b7f1b8a0c1fc7321cacLinus Torvalds	}
4191da177e4c3f41524e886b7f1b8a0c1fc7321cacLinus Torvalds	ret = 0;
4201da177e4c3f41524e886b7f1b8a0c1fc7321cacLinus Torvaldsreterr:
4211da177e4c3f41524e886b7f1b8a0c1fc7321cacLinus Torvalds	kfree(kbs);
4221da177e4c3f41524e886b7f1b8a0c1fc7321cacLinus Torvalds	return ret;
4231da177e4c3f41524e886b7f1b8a0c1fc7321cacLinus Torvalds}
4241da177e4c3f41524e886b7f1b8a0c1fc7321cacLinus Torvalds
4251da177e4c3f41524e886b7f1b8a0c1fc7321cacLinus Torvaldsstatic inline int
4261da177e4c3f41524e886b7f1b8a0c1fc7321cacLinus Torvaldsdo_fontx_ioctl(int cmd, struct consolefontdesc __user *user_cfd, int perm, struct console_font_op *op)
4271da177e4c3f41524e886b7f1b8a0c1fc7321cacLinus Torvalds{
4281da177e4c3f41524e886b7f1b8a0c1fc7321cacLinus Torvalds	struct consolefontdesc cfdarg;
4291da177e4c3f41524e886b7f1b8a0c1fc7321cacLinus Torvalds	int i;
4301da177e4c3f41524e886b7f1b8a0c1fc7321cacLinus Torvalds
4311da177e4c3f41524e886b7f1b8a0c1fc7321cacLinus Torvalds	if (copy_from_user(&cfdarg, user_cfd, sizeof(struct consolefontdesc)))
4321da177e4c3f41524e886b7f1b8a0c1fc7321cacLinus Torvalds		return -EFAULT;
4331da177e4c3f41524e886b7f1b8a0c1fc7321cacLinus Torvalds
4341da177e4c3f41524e886b7f1b8a0c1fc7321cacLinus Torvalds	switch (cmd) {
4351da177e4c3f41524e886b7f1b8a0c1fc7321cacLinus Torvalds	case PIO_FONTX:
4361da177e4c3f41524e886b7f1b8a0c1fc7321cacLinus Torvalds		if (!perm)
4371da177e4c3f41524e886b7f1b8a0c1fc7321cacLinus Torvalds			return -EPERM;
4381da177e4c3f41524e886b7f1b8a0c1fc7321cacLinus Torvalds		op->op = KD_FONT_OP_SET;
4391da177e4c3f41524e886b7f1b8a0c1fc7321cacLinus Torvalds		op->flags = KD_FONT_FLAG_OLD;
4401da177e4c3f41524e886b7f1b8a0c1fc7321cacLinus Torvalds		op->width = 8;
4411da177e4c3f41524e886b7f1b8a0c1fc7321cacLinus Torvalds		op->height = cfdarg.charheight;
4421da177e4c3f41524e886b7f1b8a0c1fc7321cacLinus Torvalds		op->charcount = cfdarg.charcount;
4431da177e4c3f41524e886b7f1b8a0c1fc7321cacLinus Torvalds		op->data = cfdarg.chardata;
4441da177e4c3f41524e886b7f1b8a0c1fc7321cacLinus Torvalds		return con_font_op(vc_cons[fg_console].d, op);
4451da177e4c3f41524e886b7f1b8a0c1fc7321cacLinus Torvalds	case GIO_FONTX: {
4461da177e4c3f41524e886b7f1b8a0c1fc7321cacLinus Torvalds		op->op = KD_FONT_OP_GET;
4471da177e4c3f41524e886b7f1b8a0c1fc7321cacLinus Torvalds		op->flags = KD_FONT_FLAG_OLD;
4481da177e4c3f41524e886b7f1b8a0c1fc7321cacLinus Torvalds		op->width = 8;
4491da177e4c3f41524e886b7f1b8a0c1fc7321cacLinus Torvalds		op->height = cfdarg.charheight;
4501da177e4c3f41524e886b7f1b8a0c1fc7321cacLinus Torvalds		op->charcount = cfdarg.charcount;
4511da177e4c3f41524e886b7f1b8a0c1fc7321cacLinus Torvalds		op->data = cfdarg.chardata;
4521da177e4c3f41524e886b7f1b8a0c1fc7321cacLinus Torvalds		i = con_font_op(vc_cons[fg_console].d, op);
4531da177e4c3f41524e886b7f1b8a0c1fc7321cacLinus Torvalds		if (i)
4541da177e4c3f41524e886b7f1b8a0c1fc7321cacLinus Torvalds			return i;
4551da177e4c3f41524e886b7f1b8a0c1fc7321cacLinus Torvalds		cfdarg.charheight = op->height;
4561da177e4c3f41524e886b7f1b8a0c1fc7321cacLinus Torvalds		cfdarg.charcount = op->charcount;
4571da177e4c3f41524e886b7f1b8a0c1fc7321cacLinus Torvalds		if (copy_to_user(user_cfd, &cfdarg, sizeof(struct consolefontdesc)))
4581da177e4c3f41524e886b7f1b8a0c1fc7321cacLinus Torvalds			return -EFAULT;
4591da177e4c3f41524e886b7f1b8a0c1fc7321cacLinus Torvalds		return 0;
4601da177e4c3f41524e886b7f1b8a0c1fc7321cacLinus Torvalds		}
4611da177e4c3f41524e886b7f1b8a0c1fc7321cacLinus Torvalds	}
4621da177e4c3f41524e886b7f1b8a0c1fc7321cacLinus Torvalds	return -EINVAL;
4631da177e4c3f41524e886b7f1b8a0c1fc7321cacLinus Torvalds}
4641da177e4c3f41524e886b7f1b8a0c1fc7321cacLinus Torvalds
4651da177e4c3f41524e886b7f1b8a0c1fc7321cacLinus Torvaldsstatic inline int
4661da177e4c3f41524e886b7f1b8a0c1fc7321cacLinus Torvaldsdo_unimap_ioctl(int cmd, struct unimapdesc __user *user_ud, int perm, struct vc_data *vc)
4671da177e4c3f41524e886b7f1b8a0c1fc7321cacLinus Torvalds{
4681da177e4c3f41524e886b7f1b8a0c1fc7321cacLinus Torvalds	struct unimapdesc tmp;
4691da177e4c3f41524e886b7f1b8a0c1fc7321cacLinus Torvalds
4701da177e4c3f41524e886b7f1b8a0c1fc7321cacLinus Torvalds	if (copy_from_user(&tmp, user_ud, sizeof tmp))
4711da177e4c3f41524e886b7f1b8a0c1fc7321cacLinus Torvalds		return -EFAULT;
4721da177e4c3f41524e886b7f1b8a0c1fc7321cacLinus Torvalds	if (tmp.entries)
4731da177e4c3f41524e886b7f1b8a0c1fc7321cacLinus Torvalds		if (!access_ok(VERIFY_WRITE, tmp.entries,
4741da177e4c3f41524e886b7f1b8a0c1fc7321cacLinus Torvalds				tmp.entry_ct*sizeof(struct unipair)))
4751da177e4c3f41524e886b7f1b8a0c1fc7321cacLinus Torvalds			return -EFAULT;
4761da177e4c3f41524e886b7f1b8a0c1fc7321cacLinus Torvalds	switch (cmd) {
4771da177e4c3f41524e886b7f1b8a0c1fc7321cacLinus Torvalds	case PIO_UNIMAP:
4781da177e4c3f41524e886b7f1b8a0c1fc7321cacLinus Torvalds		if (!perm)
4791da177e4c3f41524e886b7f1b8a0c1fc7321cacLinus Torvalds			return -EPERM;
4801da177e4c3f41524e886b7f1b8a0c1fc7321cacLinus Torvalds		return con_set_unimap(vc, tmp.entry_ct, tmp.entries);
4811da177e4c3f41524e886b7f1b8a0c1fc7321cacLinus Torvalds	case GIO_UNIMAP:
4821da177e4c3f41524e886b7f1b8a0c1fc7321cacLinus Torvalds		if (!perm && fg_console != vc->vc_num)
4831da177e4c3f41524e886b7f1b8a0c1fc7321cacLinus Torvalds			return -EPERM;
4841da177e4c3f41524e886b7f1b8a0c1fc7321cacLinus Torvalds		return con_get_unimap(vc, tmp.entry_ct, &(user_ud->entry_ct), tmp.entries);
4851da177e4c3f41524e886b7f1b8a0c1fc7321cacLinus Torvalds	}
4861da177e4c3f41524e886b7f1b8a0c1fc7321cacLinus Torvalds	return 0;
4871da177e4c3f41524e886b7f1b8a0c1fc7321cacLinus Torvalds}
4881da177e4c3f41524e886b7f1b8a0c1fc7321cacLinus Torvalds
4898b92e87d39bfd046e7581e1fe0f40eac40f88608Alan Cox
4908b92e87d39bfd046e7581e1fe0f40eac40f88608Alan Cox
4911da177e4c3f41524e886b7f1b8a0c1fc7321cacLinus Torvalds/*
4921da177e4c3f41524e886b7f1b8a0c1fc7321cacLinus Torvalds * We handle the console-specific ioctl's here.  We allow the
4931da177e4c3f41524e886b7f1b8a0c1fc7321cacLinus Torvalds * capability to modify any console, not just the fg_console.
4941da177e4c3f41524e886b7f1b8a0c1fc7321cacLinus Torvalds */
4956caa76b7786891b42b66a0e61e2c2fff2c884620Alan Coxint vt_ioctl(struct tty_struct *tty,
4961da177e4c3f41524e886b7f1b8a0c1fc7321cacLinus Torvalds	     unsigned int cmd, unsigned long arg)
4971da177e4c3f41524e886b7f1b8a0c1fc7321cacLinus Torvalds{
498c9f19e96a2f33cd56c2bd19f87a0c4982d011c2bAlan Cox	struct vc_data *vc = tty->driver_data;
4991da177e4c3f41524e886b7f1b8a0c1fc7321cacLinus Torvalds	struct console_font_op op;	/* used in multiple places here */
5001da177e4c3f41524e886b7f1b8a0c1fc7321cacLinus Torvalds	struct kbd_struct * kbd;
5011da177e4c3f41524e886b7f1b8a0c1fc7321cacLinus Torvalds	unsigned int console;
5021da177e4c3f41524e886b7f1b8a0c1fc7321cacLinus Torvalds	unsigned char ucval;
5031e0ad2881d50becaeea70ec696a80afeadf944d2Graham Gower	unsigned int uival;
5041da177e4c3f41524e886b7f1b8a0c1fc7321cacLinus Torvalds	void __user *up = (void __user *)arg;
5051da177e4c3f41524e886b7f1b8a0c1fc7321cacLinus Torvalds	int i, perm;
5069cc3c22bf017f33612748aeb466fdc3695fb1e1dAlan Cox	int ret = 0;
5079cc3c22bf017f33612748aeb466fdc3695fb1e1dAlan Cox
5081da177e4c3f41524e886b7f1b8a0c1fc7321cacLinus Torvalds	console = vc->vc_num;
5091da177e4c3f41524e886b7f1b8a0c1fc7321cacLinus Torvalds
510ec79d6056de58511d8e46d9ae59d3878f958dc3eArnd Bergmann	tty_lock();
5119cc3c22bf017f33612748aeb466fdc3695fb1e1dAlan Cox
5129cc3c22bf017f33612748aeb466fdc3695fb1e1dAlan Cox	if (!vc_cons_allocated(console)) { 	/* impossible? */
5139cc3c22bf017f33612748aeb466fdc3695fb1e1dAlan Cox		ret = -ENOIOCTLCMD;
5149cc3c22bf017f33612748aeb466fdc3695fb1e1dAlan Cox		goto out;
5159cc3c22bf017f33612748aeb466fdc3695fb1e1dAlan Cox	}
5169cc3c22bf017f33612748aeb466fdc3695fb1e1dAlan Cox
5171da177e4c3f41524e886b7f1b8a0c1fc7321cacLinus Torvalds
5181da177e4c3f41524e886b7f1b8a0c1fc7321cacLinus Torvalds	/*
5191da177e4c3f41524e886b7f1b8a0c1fc7321cacLinus Torvalds	 * To have permissions to do most of the vt ioctls, we either have
5201da177e4c3f41524e886b7f1b8a0c1fc7321cacLinus Torvalds	 * to be the owner of the tty, or have CAP_SYS_TTY_CONFIG.
5211da177e4c3f41524e886b7f1b8a0c1fc7321cacLinus Torvalds	 */
5221da177e4c3f41524e886b7f1b8a0c1fc7321cacLinus Torvalds	perm = 0;
5231da177e4c3f41524e886b7f1b8a0c1fc7321cacLinus Torvalds	if (current->signal->tty == tty || capable(CAP_SYS_TTY_CONFIG))
5241da177e4c3f41524e886b7f1b8a0c1fc7321cacLinus Torvalds		perm = 1;
5251da177e4c3f41524e886b7f1b8a0c1fc7321cacLinus Torvalds
5261da177e4c3f41524e886b7f1b8a0c1fc7321cacLinus Torvalds	kbd = kbd_table + console;
5271da177e4c3f41524e886b7f1b8a0c1fc7321cacLinus Torvalds	switch (cmd) {
528e6885107736a4dd23e7d3bc103fe6d043c63c4deAlan Cox	case TIOCLINUX:
529a115902f67ef51fbbe83e214fb761aaa9734c1ceJiri Slaby		ret = tioclinux(tty, arg);
530a115902f67ef51fbbe83e214fb761aaa9734c1ceJiri Slaby		break;
5311da177e4c3f41524e886b7f1b8a0c1fc7321cacLinus Torvalds	case KIOCSOUND:
5321da177e4c3f41524e886b7f1b8a0c1fc7321cacLinus Torvalds		if (!perm)
5339cc3c22bf017f33612748aeb466fdc3695fb1e1dAlan Cox			goto eperm;
5342c4e9671edfef534e9726366707d64e63d44e7e6Arnd Bergmann		/*
5352c4e9671edfef534e9726366707d64e63d44e7e6Arnd Bergmann		 * The use of PIT_TICK_RATE is historic, it used to be
5362c4e9671edfef534e9726366707d64e63d44e7e6Arnd Bergmann		 * the platform-dependent CLOCK_TICK_RATE between 2.6.12
5372c4e9671edfef534e9726366707d64e63d44e7e6Arnd Bergmann		 * and 2.6.36, which was a minor but unfortunate ABI
5382c4e9671edfef534e9726366707d64e63d44e7e6Arnd Bergmann		 * change.
5392c4e9671edfef534e9726366707d64e63d44e7e6Arnd Bergmann		 */
5401da177e4c3f41524e886b7f1b8a0c1fc7321cacLinus Torvalds		if (arg)
5412c4e9671edfef534e9726366707d64e63d44e7e6Arnd Bergmann			arg = PIT_TICK_RATE / arg;
5421da177e4c3f41524e886b7f1b8a0c1fc7321cacLinus Torvalds		kd_mksound(arg, 0);
5439cc3c22bf017f33612748aeb466fdc3695fb1e1dAlan Cox		break;
5441da177e4c3f41524e886b7f1b8a0c1fc7321cacLinus Torvalds
5451da177e4c3f41524e886b7f1b8a0c1fc7321cacLinus Torvalds	case KDMKTONE:
5461da177e4c3f41524e886b7f1b8a0c1fc7321cacLinus Torvalds		if (!perm)
5479cc3c22bf017f33612748aeb466fdc3695fb1e1dAlan Cox			goto eperm;
5481da177e4c3f41524e886b7f1b8a0c1fc7321cacLinus Torvalds	{
5491da177e4c3f41524e886b7f1b8a0c1fc7321cacLinus Torvalds		unsigned int ticks, count;
5501da177e4c3f41524e886b7f1b8a0c1fc7321cacLinus Torvalds
5511da177e4c3f41524e886b7f1b8a0c1fc7321cacLinus Torvalds		/*
5521da177e4c3f41524e886b7f1b8a0c1fc7321cacLinus Torvalds		 * Generate the tone for the appropriate number of ticks.
5531da177e4c3f41524e886b7f1b8a0c1fc7321cacLinus Torvalds		 * If the time is zero, turn off sound ourselves.
5541da177e4c3f41524e886b7f1b8a0c1fc7321cacLinus Torvalds		 */
5551da177e4c3f41524e886b7f1b8a0c1fc7321cacLinus Torvalds		ticks = HZ * ((arg >> 16) & 0xffff) / 1000;
5561da177e4c3f41524e886b7f1b8a0c1fc7321cacLinus Torvalds		count = ticks ? (arg & 0xffff) : 0;
5571da177e4c3f41524e886b7f1b8a0c1fc7321cacLinus Torvalds		if (count)
5582c4e9671edfef534e9726366707d64e63d44e7e6Arnd Bergmann			count = PIT_TICK_RATE / count;
5591da177e4c3f41524e886b7f1b8a0c1fc7321cacLinus Torvalds		kd_mksound(count, ticks);
5609cc3c22bf017f33612748aeb466fdc3695fb1e1dAlan Cox		break;
5611da177e4c3f41524e886b7f1b8a0c1fc7321cacLinus Torvalds	}
5621da177e4c3f41524e886b7f1b8a0c1fc7321cacLinus Torvalds
5631da177e4c3f41524e886b7f1b8a0c1fc7321cacLinus Torvalds	case KDGKBTYPE:
5641da177e4c3f41524e886b7f1b8a0c1fc7321cacLinus Torvalds		/*
5651da177e4c3f41524e886b7f1b8a0c1fc7321cacLinus Torvalds		 * this is naive.
5661da177e4c3f41524e886b7f1b8a0c1fc7321cacLinus Torvalds		 */
5671da177e4c3f41524e886b7f1b8a0c1fc7321cacLinus Torvalds		ucval = KB_101;
5681da177e4c3f41524e886b7f1b8a0c1fc7321cacLinus Torvalds		goto setchar;
5691da177e4c3f41524e886b7f1b8a0c1fc7321cacLinus Torvalds
5701da177e4c3f41524e886b7f1b8a0c1fc7321cacLinus Torvalds		/*
5711da177e4c3f41524e886b7f1b8a0c1fc7321cacLinus Torvalds		 * These cannot be implemented on any machine that implements
5721da177e4c3f41524e886b7f1b8a0c1fc7321cacLinus Torvalds		 * ioperm() in user level (such as Alpha PCs) or not at all.
5731da177e4c3f41524e886b7f1b8a0c1fc7321cacLinus Torvalds		 *
5741da177e4c3f41524e886b7f1b8a0c1fc7321cacLinus Torvalds		 * XXX: you should never use these, just call ioperm directly..
5751da177e4c3f41524e886b7f1b8a0c1fc7321cacLinus Torvalds		 */
5761da177e4c3f41524e886b7f1b8a0c1fc7321cacLinus Torvalds#ifdef CONFIG_X86
5771da177e4c3f41524e886b7f1b8a0c1fc7321cacLinus Torvalds	case KDADDIO:
5781da177e4c3f41524e886b7f1b8a0c1fc7321cacLinus Torvalds	case KDDELIO:
5791da177e4c3f41524e886b7f1b8a0c1fc7321cacLinus Torvalds		/*
5801da177e4c3f41524e886b7f1b8a0c1fc7321cacLinus Torvalds		 * KDADDIO and KDDELIO may be able to add ports beyond what
5811da177e4c3f41524e886b7f1b8a0c1fc7321cacLinus Torvalds		 * we reject here, but to be safe...
5821da177e4c3f41524e886b7f1b8a0c1fc7321cacLinus Torvalds		 */
5839cc3c22bf017f33612748aeb466fdc3695fb1e1dAlan Cox		if (arg < GPFIRST || arg > GPLAST) {
5849cc3c22bf017f33612748aeb466fdc3695fb1e1dAlan Cox			ret = -EINVAL;
5859cc3c22bf017f33612748aeb466fdc3695fb1e1dAlan Cox			break;
5869cc3c22bf017f33612748aeb466fdc3695fb1e1dAlan Cox		}
5879cc3c22bf017f33612748aeb466fdc3695fb1e1dAlan Cox		ret = sys_ioperm(arg, 1, (cmd == KDADDIO)) ? -ENXIO : 0;
5889cc3c22bf017f33612748aeb466fdc3695fb1e1dAlan Cox		break;
5891da177e4c3f41524e886b7f1b8a0c1fc7321cacLinus Torvalds
5901da177e4c3f41524e886b7f1b8a0c1fc7321cacLinus Torvalds	case KDENABIO:
5911da177e4c3f41524e886b7f1b8a0c1fc7321cacLinus Torvalds	case KDDISABIO:
5929cc3c22bf017f33612748aeb466fdc3695fb1e1dAlan Cox		ret = sys_ioperm(GPFIRST, GPNUM,
5931da177e4c3f41524e886b7f1b8a0c1fc7321cacLinus Torvalds				  (cmd == KDENABIO)) ? -ENXIO : 0;
5949cc3c22bf017f33612748aeb466fdc3695fb1e1dAlan Cox		break;
5951da177e4c3f41524e886b7f1b8a0c1fc7321cacLinus Torvalds#endif
5961da177e4c3f41524e886b7f1b8a0c1fc7321cacLinus Torvalds
5971da177e4c3f41524e886b7f1b8a0c1fc7321cacLinus Torvalds	/* Linux m68k/i386 interface for setting the keyboard delay/repeat rate */
5981da177e4c3f41524e886b7f1b8a0c1fc7321cacLinus Torvalds
5991da177e4c3f41524e886b7f1b8a0c1fc7321cacLinus Torvalds	case KDKBDREP:
6001da177e4c3f41524e886b7f1b8a0c1fc7321cacLinus Torvalds	{
6011da177e4c3f41524e886b7f1b8a0c1fc7321cacLinus Torvalds		struct kbd_repeat kbrep;
6021da177e4c3f41524e886b7f1b8a0c1fc7321cacLinus Torvalds
6031da177e4c3f41524e886b7f1b8a0c1fc7321cacLinus Torvalds		if (!capable(CAP_SYS_TTY_CONFIG))
6049cc3c22bf017f33612748aeb466fdc3695fb1e1dAlan Cox			goto eperm;
6051da177e4c3f41524e886b7f1b8a0c1fc7321cacLinus Torvalds
6069cc3c22bf017f33612748aeb466fdc3695fb1e1dAlan Cox		if (copy_from_user(&kbrep, up, sizeof(struct kbd_repeat))) {
6079cc3c22bf017f33612748aeb466fdc3695fb1e1dAlan Cox			ret =  -EFAULT;
6089cc3c22bf017f33612748aeb466fdc3695fb1e1dAlan Cox			break;
6099cc3c22bf017f33612748aeb466fdc3695fb1e1dAlan Cox		}
6109cc3c22bf017f33612748aeb466fdc3695fb1e1dAlan Cox		ret = kbd_rate(&kbrep);
6119cc3c22bf017f33612748aeb466fdc3695fb1e1dAlan Cox		if (ret)
6129cc3c22bf017f33612748aeb466fdc3695fb1e1dAlan Cox			break;
6131da177e4c3f41524e886b7f1b8a0c1fc7321cacLinus Torvalds		if (copy_to_user(up, &kbrep, sizeof(struct kbd_repeat)))
6149cc3c22bf017f33612748aeb466fdc3695fb1e1dAlan Cox			ret = -EFAULT;
6159cc3c22bf017f33612748aeb466fdc3695fb1e1dAlan Cox		break;
6161da177e4c3f41524e886b7f1b8a0c1fc7321cacLinus Torvalds	}
6171da177e4c3f41524e886b7f1b8a0c1fc7321cacLinus Torvalds
6181da177e4c3f41524e886b7f1b8a0c1fc7321cacLinus Torvalds	case KDSETMODE:
6191da177e4c3f41524e886b7f1b8a0c1fc7321cacLinus Torvalds		/*
6201da177e4c3f41524e886b7f1b8a0c1fc7321cacLinus Torvalds		 * currently, setting the mode from KD_TEXT to KD_GRAPHICS
6211da177e4c3f41524e886b7f1b8a0c1fc7321cacLinus Torvalds		 * doesn't do a whole lot. i'm not sure if it should do any
6221da177e4c3f41524e886b7f1b8a0c1fc7321cacLinus Torvalds		 * restoration of modes or what...
6231da177e4c3f41524e886b7f1b8a0c1fc7321cacLinus Torvalds		 *
6241da177e4c3f41524e886b7f1b8a0c1fc7321cacLinus Torvalds		 * XXX It should at least call into the driver, fbdev's definitely
6251da177e4c3f41524e886b7f1b8a0c1fc7321cacLinus Torvalds		 * need to restore their engine state. --BenH
6261da177e4c3f41524e886b7f1b8a0c1fc7321cacLinus Torvalds		 */
6271da177e4c3f41524e886b7f1b8a0c1fc7321cacLinus Torvalds		if (!perm)
6289cc3c22bf017f33612748aeb466fdc3695fb1e1dAlan Cox			goto eperm;
6291da177e4c3f41524e886b7f1b8a0c1fc7321cacLinus Torvalds		switch (arg) {
6301da177e4c3f41524e886b7f1b8a0c1fc7321cacLinus Torvalds		case KD_GRAPHICS:
6311da177e4c3f41524e886b7f1b8a0c1fc7321cacLinus Torvalds			break;
6321da177e4c3f41524e886b7f1b8a0c1fc7321cacLinus Torvalds		case KD_TEXT0:
6331da177e4c3f41524e886b7f1b8a0c1fc7321cacLinus Torvalds		case KD_TEXT1:
6341da177e4c3f41524e886b7f1b8a0c1fc7321cacLinus Torvalds			arg = KD_TEXT;
6351da177e4c3f41524e886b7f1b8a0c1fc7321cacLinus Torvalds		case KD_TEXT:
6361da177e4c3f41524e886b7f1b8a0c1fc7321cacLinus Torvalds			break;
6371da177e4c3f41524e886b7f1b8a0c1fc7321cacLinus Torvalds		default:
6389cc3c22bf017f33612748aeb466fdc3695fb1e1dAlan Cox			ret = -EINVAL;
6399cc3c22bf017f33612748aeb466fdc3695fb1e1dAlan Cox			goto out;
6401da177e4c3f41524e886b7f1b8a0c1fc7321cacLinus Torvalds		}
6411da177e4c3f41524e886b7f1b8a0c1fc7321cacLinus Torvalds		if (vc->vc_mode == (unsigned char) arg)
6429cc3c22bf017f33612748aeb466fdc3695fb1e1dAlan Cox			break;
6431da177e4c3f41524e886b7f1b8a0c1fc7321cacLinus Torvalds		vc->vc_mode = (unsigned char) arg;
6441da177e4c3f41524e886b7f1b8a0c1fc7321cacLinus Torvalds		if (console != fg_console)
6459cc3c22bf017f33612748aeb466fdc3695fb1e1dAlan Cox			break;
6461da177e4c3f41524e886b7f1b8a0c1fc7321cacLinus Torvalds		/*
6471da177e4c3f41524e886b7f1b8a0c1fc7321cacLinus Torvalds		 * explicitly blank/unblank the screen if switching modes
6481da177e4c3f41524e886b7f1b8a0c1fc7321cacLinus Torvalds		 */
649ac751efa6a0d70f2c9daef5c7e3a92270f5c2dffTorben Hohn		console_lock();
6501da177e4c3f41524e886b7f1b8a0c1fc7321cacLinus Torvalds		if (arg == KD_TEXT)
6511da177e4c3f41524e886b7f1b8a0c1fc7321cacLinus Torvalds			do_unblank_screen(1);
6521da177e4c3f41524e886b7f1b8a0c1fc7321cacLinus Torvalds		else
6531da177e4c3f41524e886b7f1b8a0c1fc7321cacLinus Torvalds			do_blank_screen(1);
654ac751efa6a0d70f2c9daef5c7e3a92270f5c2dffTorben Hohn		console_unlock();
6559cc3c22bf017f33612748aeb466fdc3695fb1e1dAlan Cox		break;
6561da177e4c3f41524e886b7f1b8a0c1fc7321cacLinus Torvalds
6571da177e4c3f41524e886b7f1b8a0c1fc7321cacLinus Torvalds	case KDGETMODE:
6581e0ad2881d50becaeea70ec696a80afeadf944d2Graham Gower		uival = vc->vc_mode;
6591da177e4c3f41524e886b7f1b8a0c1fc7321cacLinus Torvalds		goto setint;
6601da177e4c3f41524e886b7f1b8a0c1fc7321cacLinus Torvalds
6611da177e4c3f41524e886b7f1b8a0c1fc7321cacLinus Torvalds	case KDMAPDISP:
6621da177e4c3f41524e886b7f1b8a0c1fc7321cacLinus Torvalds	case KDUNMAPDISP:
6631da177e4c3f41524e886b7f1b8a0c1fc7321cacLinus Torvalds		/*
6641da177e4c3f41524e886b7f1b8a0c1fc7321cacLinus Torvalds		 * these work like a combination of mmap and KDENABIO.
6651da177e4c3f41524e886b7f1b8a0c1fc7321cacLinus Torvalds		 * this could be easily finished.
6661da177e4c3f41524e886b7f1b8a0c1fc7321cacLinus Torvalds		 */
6679cc3c22bf017f33612748aeb466fdc3695fb1e1dAlan Cox		ret = -EINVAL;
6689cc3c22bf017f33612748aeb466fdc3695fb1e1dAlan Cox		break;
6691da177e4c3f41524e886b7f1b8a0c1fc7321cacLinus Torvalds
6701da177e4c3f41524e886b7f1b8a0c1fc7321cacLinus Torvalds	case KDSKBMODE:
6711da177e4c3f41524e886b7f1b8a0c1fc7321cacLinus Torvalds		if (!perm)
6729cc3c22bf017f33612748aeb466fdc3695fb1e1dAlan Cox			goto eperm;
6731da177e4c3f41524e886b7f1b8a0c1fc7321cacLinus Torvalds		switch(arg) {
6741da177e4c3f41524e886b7f1b8a0c1fc7321cacLinus Torvalds		  case K_RAW:
6751da177e4c3f41524e886b7f1b8a0c1fc7321cacLinus Torvalds			kbd->kbdmode = VC_RAW;
6761da177e4c3f41524e886b7f1b8a0c1fc7321cacLinus Torvalds			break;
6771da177e4c3f41524e886b7f1b8a0c1fc7321cacLinus Torvalds		  case K_MEDIUMRAW:
6781da177e4c3f41524e886b7f1b8a0c1fc7321cacLinus Torvalds			kbd->kbdmode = VC_MEDIUMRAW;
6791da177e4c3f41524e886b7f1b8a0c1fc7321cacLinus Torvalds			break;
6801da177e4c3f41524e886b7f1b8a0c1fc7321cacLinus Torvalds		  case K_XLATE:
6811da177e4c3f41524e886b7f1b8a0c1fc7321cacLinus Torvalds			kbd->kbdmode = VC_XLATE;
6821da177e4c3f41524e886b7f1b8a0c1fc7321cacLinus Torvalds			compute_shiftstate();
6831da177e4c3f41524e886b7f1b8a0c1fc7321cacLinus Torvalds			break;
6841da177e4c3f41524e886b7f1b8a0c1fc7321cacLinus Torvalds		  case K_UNICODE:
6851da177e4c3f41524e886b7f1b8a0c1fc7321cacLinus Torvalds			kbd->kbdmode = VC_UNICODE;
6861da177e4c3f41524e886b7f1b8a0c1fc7321cacLinus Torvalds			compute_shiftstate();
6871da177e4c3f41524e886b7f1b8a0c1fc7321cacLinus Torvalds			break;
6889fc3de9c83565fcaa23df74c2fc414bb6e7efb0aArthur Taylor		  case K_OFF:
6899fc3de9c83565fcaa23df74c2fc414bb6e7efb0aArthur Taylor			kbd->kbdmode = VC_OFF;
6909fc3de9c83565fcaa23df74c2fc414bb6e7efb0aArthur Taylor			break;
6911da177e4c3f41524e886b7f1b8a0c1fc7321cacLinus Torvalds		  default:
6929cc3c22bf017f33612748aeb466fdc3695fb1e1dAlan Cox			ret = -EINVAL;
6939cc3c22bf017f33612748aeb466fdc3695fb1e1dAlan Cox			goto out;
6941da177e4c3f41524e886b7f1b8a0c1fc7321cacLinus Torvalds		}
6951da177e4c3f41524e886b7f1b8a0c1fc7321cacLinus Torvalds		tty_ldisc_flush(tty);
6969cc3c22bf017f33612748aeb466fdc3695fb1e1dAlan Cox		break;
6971da177e4c3f41524e886b7f1b8a0c1fc7321cacLinus Torvalds
6981da177e4c3f41524e886b7f1b8a0c1fc7321cacLinus Torvalds	case KDGKBMODE:
6996da9e95f7381fa27bc9c66c9840b11adde778618Andrew Morton		switch (kbd->kbdmode) {
7006da9e95f7381fa27bc9c66c9840b11adde778618Andrew Morton		case VC_RAW:
7016da9e95f7381fa27bc9c66c9840b11adde778618Andrew Morton			uival = K_RAW;
7026da9e95f7381fa27bc9c66c9840b11adde778618Andrew Morton			break;
7036da9e95f7381fa27bc9c66c9840b11adde778618Andrew Morton		case VC_MEDIUMRAW:
7046da9e95f7381fa27bc9c66c9840b11adde778618Andrew Morton			uival = K_MEDIUMRAW;
7056da9e95f7381fa27bc9c66c9840b11adde778618Andrew Morton			break;
7066da9e95f7381fa27bc9c66c9840b11adde778618Andrew Morton		case VC_UNICODE:
7076da9e95f7381fa27bc9c66c9840b11adde778618Andrew Morton			uival = K_UNICODE;
7086da9e95f7381fa27bc9c66c9840b11adde778618Andrew Morton			break;
7096da9e95f7381fa27bc9c66c9840b11adde778618Andrew Morton		case VC_OFF:
7106da9e95f7381fa27bc9c66c9840b11adde778618Andrew Morton			uival = K_OFF;
7116da9e95f7381fa27bc9c66c9840b11adde778618Andrew Morton			break;
7126da9e95f7381fa27bc9c66c9840b11adde778618Andrew Morton		default:
7136da9e95f7381fa27bc9c66c9840b11adde778618Andrew Morton			uival = K_XLATE;
7146da9e95f7381fa27bc9c66c9840b11adde778618Andrew Morton			break;
7156da9e95f7381fa27bc9c66c9840b11adde778618Andrew Morton		}
7161da177e4c3f41524e886b7f1b8a0c1fc7321cacLinus Torvalds		goto setint;
7171da177e4c3f41524e886b7f1b8a0c1fc7321cacLinus Torvalds
7181da177e4c3f41524e886b7f1b8a0c1fc7321cacLinus Torvalds	/* this could be folded into KDSKBMODE, but for compatibility
7191da177e4c3f41524e886b7f1b8a0c1fc7321cacLinus Torvalds	   reasons it is not so easy to fold KDGKBMETA into KDGKBMODE */
7201da177e4c3f41524e886b7f1b8a0c1fc7321cacLinus Torvalds	case KDSKBMETA:
7211da177e4c3f41524e886b7f1b8a0c1fc7321cacLinus Torvalds		switch(arg) {
7221da177e4c3f41524e886b7f1b8a0c1fc7321cacLinus Torvalds		  case K_METABIT:
7231da177e4c3f41524e886b7f1b8a0c1fc7321cacLinus Torvalds			clr_vc_kbd_mode(kbd, VC_META);
7241da177e4c3f41524e886b7f1b8a0c1fc7321cacLinus Torvalds			break;
7251da177e4c3f41524e886b7f1b8a0c1fc7321cacLinus Torvalds		  case K_ESCPREFIX:
7261da177e4c3f41524e886b7f1b8a0c1fc7321cacLinus Torvalds			set_vc_kbd_mode(kbd, VC_META);
7271da177e4c3f41524e886b7f1b8a0c1fc7321cacLinus Torvalds			break;
7281da177e4c3f41524e886b7f1b8a0c1fc7321cacLinus Torvalds		  default:
7299cc3c22bf017f33612748aeb466fdc3695fb1e1dAlan Cox			ret = -EINVAL;
7301da177e4c3f41524e886b7f1b8a0c1fc7321cacLinus Torvalds		}
7319cc3c22bf017f33612748aeb466fdc3695fb1e1dAlan Cox		break;
7321da177e4c3f41524e886b7f1b8a0c1fc7321cacLinus Torvalds
7331da177e4c3f41524e886b7f1b8a0c1fc7321cacLinus Torvalds	case KDGKBMETA:
7341e0ad2881d50becaeea70ec696a80afeadf944d2Graham Gower		uival = (vc_kbd_mode(kbd, VC_META) ? K_ESCPREFIX : K_METABIT);
7351da177e4c3f41524e886b7f1b8a0c1fc7321cacLinus Torvalds	setint:
7361e0ad2881d50becaeea70ec696a80afeadf944d2Graham Gower		ret = put_user(uival, (int __user *)arg);
7379cc3c22bf017f33612748aeb466fdc3695fb1e1dAlan Cox		break;
7381da177e4c3f41524e886b7f1b8a0c1fc7321cacLinus Torvalds
7391da177e4c3f41524e886b7f1b8a0c1fc7321cacLinus Torvalds	case KDGETKEYCODE:
7401da177e4c3f41524e886b7f1b8a0c1fc7321cacLinus Torvalds	case KDSETKEYCODE:
7411da177e4c3f41524e886b7f1b8a0c1fc7321cacLinus Torvalds		if(!capable(CAP_SYS_TTY_CONFIG))
7429cc3c22bf017f33612748aeb466fdc3695fb1e1dAlan Cox			perm = 0;
7439cc3c22bf017f33612748aeb466fdc3695fb1e1dAlan Cox		ret = do_kbkeycode_ioctl(cmd, up, perm);
7449cc3c22bf017f33612748aeb466fdc3695fb1e1dAlan Cox		break;
7451da177e4c3f41524e886b7f1b8a0c1fc7321cacLinus Torvalds
7461da177e4c3f41524e886b7f1b8a0c1fc7321cacLinus Torvalds	case KDGKBENT:
7471da177e4c3f41524e886b7f1b8a0c1fc7321cacLinus Torvalds	case KDSKBENT:
7489cc3c22bf017f33612748aeb466fdc3695fb1e1dAlan Cox		ret = do_kdsk_ioctl(cmd, up, perm, kbd);
7499cc3c22bf017f33612748aeb466fdc3695fb1e1dAlan Cox		break;
7501da177e4c3f41524e886b7f1b8a0c1fc7321cacLinus Torvalds
7511da177e4c3f41524e886b7f1b8a0c1fc7321cacLinus Torvalds	case KDGKBSENT:
7521da177e4c3f41524e886b7f1b8a0c1fc7321cacLinus Torvalds	case KDSKBSENT:
7539cc3c22bf017f33612748aeb466fdc3695fb1e1dAlan Cox		ret = do_kdgkb_ioctl(cmd, up, perm);
7549cc3c22bf017f33612748aeb466fdc3695fb1e1dAlan Cox		break;
7551da177e4c3f41524e886b7f1b8a0c1fc7321cacLinus Torvalds
756247ff8e610cb63c015de19191db9666754c2ed79Alan Cox	/* Diacritical processing. Handled in keyboard.c as it has
757247ff8e610cb63c015de19191db9666754c2ed79Alan Cox	   to operate on the keyboard locks and structures */
7581da177e4c3f41524e886b7f1b8a0c1fc7321cacLinus Torvalds	case KDGKBDIACR:
75904c71976500352d02f60616d2b960267d8c5fe24Samuel Thibault	case KDGKBDIACRUC:
7601da177e4c3f41524e886b7f1b8a0c1fc7321cacLinus Torvalds	case KDSKBDIACR:
76104c71976500352d02f60616d2b960267d8c5fe24Samuel Thibault	case KDSKBDIACRUC:
762247ff8e610cb63c015de19191db9666754c2ed79Alan Cox		ret = vt_do_diacrit(cmd, up, perm);
7639cc3c22bf017f33612748aeb466fdc3695fb1e1dAlan Cox		break;
7641da177e4c3f41524e886b7f1b8a0c1fc7321cacLinus Torvalds
7651da177e4c3f41524e886b7f1b8a0c1fc7321cacLinus Torvalds	/* the ioctls below read/set the flags usually shown in the leds */
7661da177e4c3f41524e886b7f1b8a0c1fc7321cacLinus Torvalds	/* don't use them - they will go away without warning */
7671da177e4c3f41524e886b7f1b8a0c1fc7321cacLinus Torvalds	case KDGKBLED:
7681da177e4c3f41524e886b7f1b8a0c1fc7321cacLinus Torvalds		ucval = kbd->ledflagstate | (kbd->default_ledflagstate << 4);
7691da177e4c3f41524e886b7f1b8a0c1fc7321cacLinus Torvalds		goto setchar;
7701da177e4c3f41524e886b7f1b8a0c1fc7321cacLinus Torvalds
7711da177e4c3f41524e886b7f1b8a0c1fc7321cacLinus Torvalds	case KDSKBLED:
7721da177e4c3f41524e886b7f1b8a0c1fc7321cacLinus Torvalds		if (!perm)
7739cc3c22bf017f33612748aeb466fdc3695fb1e1dAlan Cox			goto eperm;
7749cc3c22bf017f33612748aeb466fdc3695fb1e1dAlan Cox		if (arg & ~0x77) {
7759cc3c22bf017f33612748aeb466fdc3695fb1e1dAlan Cox			ret = -EINVAL;
7769cc3c22bf017f33612748aeb466fdc3695fb1e1dAlan Cox			break;
7779cc3c22bf017f33612748aeb466fdc3695fb1e1dAlan Cox		}
7781da177e4c3f41524e886b7f1b8a0c1fc7321cacLinus Torvalds		kbd->ledflagstate = (arg & 7);
7791da177e4c3f41524e886b7f1b8a0c1fc7321cacLinus Torvalds		kbd->default_ledflagstate = ((arg >> 4) & 7);
7801da177e4c3f41524e886b7f1b8a0c1fc7321cacLinus Torvalds		set_leds();
7819cc3c22bf017f33612748aeb466fdc3695fb1e1dAlan Cox		break;
7821da177e4c3f41524e886b7f1b8a0c1fc7321cacLinus Torvalds
7831da177e4c3f41524e886b7f1b8a0c1fc7321cacLinus Torvalds	/* the ioctls below only set the lights, not the functions */
7841da177e4c3f41524e886b7f1b8a0c1fc7321cacLinus Torvalds	/* for those, see KDGKBLED and KDSKBLED above */
7851da177e4c3f41524e886b7f1b8a0c1fc7321cacLinus Torvalds	case KDGETLED:
7861da177e4c3f41524e886b7f1b8a0c1fc7321cacLinus Torvalds		ucval = getledstate();
7871da177e4c3f41524e886b7f1b8a0c1fc7321cacLinus Torvalds	setchar:
7889cc3c22bf017f33612748aeb466fdc3695fb1e1dAlan Cox		ret = put_user(ucval, (char __user *)arg);
7899cc3c22bf017f33612748aeb466fdc3695fb1e1dAlan Cox		break;
7901da177e4c3f41524e886b7f1b8a0c1fc7321cacLinus Torvalds
7911da177e4c3f41524e886b7f1b8a0c1fc7321cacLinus Torvalds	case KDSETLED:
7921da177e4c3f41524e886b7f1b8a0c1fc7321cacLinus Torvalds		if (!perm)
7939cc3c22bf017f33612748aeb466fdc3695fb1e1dAlan Cox			goto eperm;
7941da177e4c3f41524e886b7f1b8a0c1fc7321cacLinus Torvalds		setledstate(kbd, arg);
7959cc3c22bf017f33612748aeb466fdc3695fb1e1dAlan Cox		break;
7961da177e4c3f41524e886b7f1b8a0c1fc7321cacLinus Torvalds
7971da177e4c3f41524e886b7f1b8a0c1fc7321cacLinus Torvalds	/*
7981da177e4c3f41524e886b7f1b8a0c1fc7321cacLinus Torvalds	 * A process can indicate its willingness to accept signals
7991da177e4c3f41524e886b7f1b8a0c1fc7321cacLinus Torvalds	 * generated by pressing an appropriate key combination.
8001da177e4c3f41524e886b7f1b8a0c1fc7321cacLinus Torvalds	 * Thus, one can have a daemon that e.g. spawns a new console
8011da177e4c3f41524e886b7f1b8a0c1fc7321cacLinus Torvalds	 * upon a keypress and then changes to it.
8021da177e4c3f41524e886b7f1b8a0c1fc7321cacLinus Torvalds	 * See also the kbrequest field of inittab(5).
8031da177e4c3f41524e886b7f1b8a0c1fc7321cacLinus Torvalds	 */
8041da177e4c3f41524e886b7f1b8a0c1fc7321cacLinus Torvalds	case KDSIGACCEPT:
8051da177e4c3f41524e886b7f1b8a0c1fc7321cacLinus Torvalds	{
8061da177e4c3f41524e886b7f1b8a0c1fc7321cacLinus Torvalds		if (!perm || !capable(CAP_KILL))
8079cc3c22bf017f33612748aeb466fdc3695fb1e1dAlan Cox			goto eperm;
8087ed20e1ad521b5f5df61bf6559ae60738e393741Jesper Juhl		if (!valid_signal(arg) || arg < 1 || arg == SIGKILL)
8099cc3c22bf017f33612748aeb466fdc3695fb1e1dAlan Cox			ret = -EINVAL;
8109cc3c22bf017f33612748aeb466fdc3695fb1e1dAlan Cox		else {
8119cc3c22bf017f33612748aeb466fdc3695fb1e1dAlan Cox			spin_lock_irq(&vt_spawn_con.lock);
8129cc3c22bf017f33612748aeb466fdc3695fb1e1dAlan Cox			put_pid(vt_spawn_con.pid);
8139cc3c22bf017f33612748aeb466fdc3695fb1e1dAlan Cox			vt_spawn_con.pid = get_pid(task_pid(current));
8149cc3c22bf017f33612748aeb466fdc3695fb1e1dAlan Cox			vt_spawn_con.sig = arg;
8159cc3c22bf017f33612748aeb466fdc3695fb1e1dAlan Cox			spin_unlock_irq(&vt_spawn_con.lock);
8169cc3c22bf017f33612748aeb466fdc3695fb1e1dAlan Cox		}
8179cc3c22bf017f33612748aeb466fdc3695fb1e1dAlan Cox		break;
8181da177e4c3f41524e886b7f1b8a0c1fc7321cacLinus Torvalds	}
8191da177e4c3f41524e886b7f1b8a0c1fc7321cacLinus Torvalds
8201da177e4c3f41524e886b7f1b8a0c1fc7321cacLinus Torvalds	case VT_SETMODE:
8211da177e4c3f41524e886b7f1b8a0c1fc7321cacLinus Torvalds	{
8221da177e4c3f41524e886b7f1b8a0c1fc7321cacLinus Torvalds		struct vt_mode tmp;
8231da177e4c3f41524e886b7f1b8a0c1fc7321cacLinus Torvalds
8241da177e4c3f41524e886b7f1b8a0c1fc7321cacLinus Torvalds		if (!perm)
8259cc3c22bf017f33612748aeb466fdc3695fb1e1dAlan Cox			goto eperm;
8269cc3c22bf017f33612748aeb466fdc3695fb1e1dAlan Cox		if (copy_from_user(&tmp, up, sizeof(struct vt_mode))) {
8279cc3c22bf017f33612748aeb466fdc3695fb1e1dAlan Cox			ret = -EFAULT;
8289cc3c22bf017f33612748aeb466fdc3695fb1e1dAlan Cox			goto out;
8299cc3c22bf017f33612748aeb466fdc3695fb1e1dAlan Cox		}
83087a6aca504d65f242589583e04df5e74b5eae1feGreg Kroah-Hartman		if (tmp.mode != VT_AUTO && tmp.mode != VT_PROCESS) {
8319cc3c22bf017f33612748aeb466fdc3695fb1e1dAlan Cox			ret = -EINVAL;
8329cc3c22bf017f33612748aeb466fdc3695fb1e1dAlan Cox			goto out;
8339cc3c22bf017f33612748aeb466fdc3695fb1e1dAlan Cox		}
834ac751efa6a0d70f2c9daef5c7e3a92270f5c2dffTorben Hohn		console_lock();
8351da177e4c3f41524e886b7f1b8a0c1fc7321cacLinus Torvalds		vc->vt_mode = tmp;
8361da177e4c3f41524e886b7f1b8a0c1fc7321cacLinus Torvalds		/* the frsig is ignored, so we set it to 0 */
8371da177e4c3f41524e886b7f1b8a0c1fc7321cacLinus Torvalds		vc->vt_mode.frsig = 0;
8388b6312f4dcc1efe7975731b6c47dd134282bd9acEric W. Biederman		put_pid(vc->vt_pid);
8398b6312f4dcc1efe7975731b6c47dd134282bd9acEric W. Biederman		vc->vt_pid = get_pid(task_pid(current));
8401da177e4c3f41524e886b7f1b8a0c1fc7321cacLinus Torvalds		/* no switch is required -- saw@shade.msu.ru */
8411da177e4c3f41524e886b7f1b8a0c1fc7321cacLinus Torvalds		vc->vt_newvt = -1;
842ac751efa6a0d70f2c9daef5c7e3a92270f5c2dffTorben Hohn		console_unlock();
8439cc3c22bf017f33612748aeb466fdc3695fb1e1dAlan Cox		break;
8441da177e4c3f41524e886b7f1b8a0c1fc7321cacLinus Torvalds	}
8451da177e4c3f41524e886b7f1b8a0c1fc7321cacLinus Torvalds
8461da177e4c3f41524e886b7f1b8a0c1fc7321cacLinus Torvalds	case VT_GETMODE:
8471da177e4c3f41524e886b7f1b8a0c1fc7321cacLinus Torvalds	{
8481da177e4c3f41524e886b7f1b8a0c1fc7321cacLinus Torvalds		struct vt_mode tmp;
8491da177e4c3f41524e886b7f1b8a0c1fc7321cacLinus Torvalds		int rc;
8501da177e4c3f41524e886b7f1b8a0c1fc7321cacLinus Torvalds
851ac751efa6a0d70f2c9daef5c7e3a92270f5c2dffTorben Hohn		console_lock();
8521da177e4c3f41524e886b7f1b8a0c1fc7321cacLinus Torvalds		memcpy(&tmp, &vc->vt_mode, sizeof(struct vt_mode));
853ac751efa6a0d70f2c9daef5c7e3a92270f5c2dffTorben Hohn		console_unlock();
8541da177e4c3f41524e886b7f1b8a0c1fc7321cacLinus Torvalds
8551da177e4c3f41524e886b7f1b8a0c1fc7321cacLinus Torvalds		rc = copy_to_user(up, &tmp, sizeof(struct vt_mode));
8569cc3c22bf017f33612748aeb466fdc3695fb1e1dAlan Cox		if (rc)
8579cc3c22bf017f33612748aeb466fdc3695fb1e1dAlan Cox			ret = -EFAULT;
8589cc3c22bf017f33612748aeb466fdc3695fb1e1dAlan Cox		break;
8591da177e4c3f41524e886b7f1b8a0c1fc7321cacLinus Torvalds	}
8601da177e4c3f41524e886b7f1b8a0c1fc7321cacLinus Torvalds
8611da177e4c3f41524e886b7f1b8a0c1fc7321cacLinus Torvalds	/*
8621da177e4c3f41524e886b7f1b8a0c1fc7321cacLinus Torvalds	 * Returns global vt state. Note that VT 0 is always open, since
8631da177e4c3f41524e886b7f1b8a0c1fc7321cacLinus Torvalds	 * it's an alias for the current VT, and people can't use it here.
8641da177e4c3f41524e886b7f1b8a0c1fc7321cacLinus Torvalds	 * We cannot return state for more than 16 VTs, since v_state is short.
8651da177e4c3f41524e886b7f1b8a0c1fc7321cacLinus Torvalds	 */
8661da177e4c3f41524e886b7f1b8a0c1fc7321cacLinus Torvalds	case VT_GETSTATE:
8671da177e4c3f41524e886b7f1b8a0c1fc7321cacLinus Torvalds	{
8681da177e4c3f41524e886b7f1b8a0c1fc7321cacLinus Torvalds		struct vt_stat __user *vtstat = up;
8691da177e4c3f41524e886b7f1b8a0c1fc7321cacLinus Torvalds		unsigned short state, mask;
8701da177e4c3f41524e886b7f1b8a0c1fc7321cacLinus Torvalds
8711da177e4c3f41524e886b7f1b8a0c1fc7321cacLinus Torvalds		if (put_user(fg_console + 1, &vtstat->v_active))
8729cc3c22bf017f33612748aeb466fdc3695fb1e1dAlan Cox			ret = -EFAULT;
8739cc3c22bf017f33612748aeb466fdc3695fb1e1dAlan Cox		else {
8749cc3c22bf017f33612748aeb466fdc3695fb1e1dAlan Cox			state = 1;	/* /dev/tty0 is always open */
8759cc3c22bf017f33612748aeb466fdc3695fb1e1dAlan Cox			for (i = 0, mask = 2; i < MAX_NR_CONSOLES && mask;
8769cc3c22bf017f33612748aeb466fdc3695fb1e1dAlan Cox							++i, mask <<= 1)
8779cc3c22bf017f33612748aeb466fdc3695fb1e1dAlan Cox				if (VT_IS_IN_USE(i))
8789cc3c22bf017f33612748aeb466fdc3695fb1e1dAlan Cox					state |= mask;
8799cc3c22bf017f33612748aeb466fdc3695fb1e1dAlan Cox			ret = put_user(state, &vtstat->v_state);
8809cc3c22bf017f33612748aeb466fdc3695fb1e1dAlan Cox		}
8819cc3c22bf017f33612748aeb466fdc3695fb1e1dAlan Cox		break;
8821da177e4c3f41524e886b7f1b8a0c1fc7321cacLinus Torvalds	}
8831da177e4c3f41524e886b7f1b8a0c1fc7321cacLinus Torvalds
8841da177e4c3f41524e886b7f1b8a0c1fc7321cacLinus Torvalds	/*
8851da177e4c3f41524e886b7f1b8a0c1fc7321cacLinus Torvalds	 * Returns the first available (non-opened) console.
8861da177e4c3f41524e886b7f1b8a0c1fc7321cacLinus Torvalds	 */
8871da177e4c3f41524e886b7f1b8a0c1fc7321cacLinus Torvalds	case VT_OPENQRY:
8881da177e4c3f41524e886b7f1b8a0c1fc7321cacLinus Torvalds		for (i = 0; i < MAX_NR_CONSOLES; ++i)
8891da177e4c3f41524e886b7f1b8a0c1fc7321cacLinus Torvalds			if (! VT_IS_IN_USE(i))
8901da177e4c3f41524e886b7f1b8a0c1fc7321cacLinus Torvalds				break;
8911e0ad2881d50becaeea70ec696a80afeadf944d2Graham Gower		uival = i < MAX_NR_CONSOLES ? (i+1) : -1;
8921da177e4c3f41524e886b7f1b8a0c1fc7321cacLinus Torvalds		goto setint;
8931da177e4c3f41524e886b7f1b8a0c1fc7321cacLinus Torvalds
8941da177e4c3f41524e886b7f1b8a0c1fc7321cacLinus Torvalds	/*
8951da177e4c3f41524e886b7f1b8a0c1fc7321cacLinus Torvalds	 * ioctl(fd, VT_ACTIVATE, num) will cause us to switch to vt # num,
8961da177e4c3f41524e886b7f1b8a0c1fc7321cacLinus Torvalds	 * with num >= 1 (switches to vt 0, our console, are not allowed, just
8971da177e4c3f41524e886b7f1b8a0c1fc7321cacLinus Torvalds	 * to preserve sanity).
8981da177e4c3f41524e886b7f1b8a0c1fc7321cacLinus Torvalds	 */
8991da177e4c3f41524e886b7f1b8a0c1fc7321cacLinus Torvalds	case VT_ACTIVATE:
9001da177e4c3f41524e886b7f1b8a0c1fc7321cacLinus Torvalds		if (!perm)
9019cc3c22bf017f33612748aeb466fdc3695fb1e1dAlan Cox			goto eperm;
9021da177e4c3f41524e886b7f1b8a0c1fc7321cacLinus Torvalds		if (arg == 0 || arg > MAX_NR_CONSOLES)
9039cc3c22bf017f33612748aeb466fdc3695fb1e1dAlan Cox			ret =  -ENXIO;
9049cc3c22bf017f33612748aeb466fdc3695fb1e1dAlan Cox		else {
9059cc3c22bf017f33612748aeb466fdc3695fb1e1dAlan Cox			arg--;
906ac751efa6a0d70f2c9daef5c7e3a92270f5c2dffTorben Hohn			console_lock();
9079cc3c22bf017f33612748aeb466fdc3695fb1e1dAlan Cox			ret = vc_allocate(arg);
908ac751efa6a0d70f2c9daef5c7e3a92270f5c2dffTorben Hohn			console_unlock();
9099cc3c22bf017f33612748aeb466fdc3695fb1e1dAlan Cox			if (ret)
9109cc3c22bf017f33612748aeb466fdc3695fb1e1dAlan Cox				break;
9119cc3c22bf017f33612748aeb466fdc3695fb1e1dAlan Cox			set_console(arg);
9129cc3c22bf017f33612748aeb466fdc3695fb1e1dAlan Cox		}
9139cc3c22bf017f33612748aeb466fdc3695fb1e1dAlan Cox		break;
9141da177e4c3f41524e886b7f1b8a0c1fc7321cacLinus Torvalds
915d3b5cffcf84a8bdc7073dce4745d67c72629af85Alan Cox	case VT_SETACTIVATE:
916d3b5cffcf84a8bdc7073dce4745d67c72629af85Alan Cox	{
917d3b5cffcf84a8bdc7073dce4745d67c72629af85Alan Cox		struct vt_setactivate vsa;
918d3b5cffcf84a8bdc7073dce4745d67c72629af85Alan Cox
919d3b5cffcf84a8bdc7073dce4745d67c72629af85Alan Cox		if (!perm)
920d3b5cffcf84a8bdc7073dce4745d67c72629af85Alan Cox			goto eperm;
921d3b5cffcf84a8bdc7073dce4745d67c72629af85Alan Cox
922d3b5cffcf84a8bdc7073dce4745d67c72629af85Alan Cox		if (copy_from_user(&vsa, (struct vt_setactivate __user *)arg,
923a09efb07b5025fb75f42e903d31767a3cafede89Jiri Slaby					sizeof(struct vt_setactivate))) {
924a09efb07b5025fb75f42e903d31767a3cafede89Jiri Slaby			ret = -EFAULT;
925a09efb07b5025fb75f42e903d31767a3cafede89Jiri Slaby			goto out;
926a09efb07b5025fb75f42e903d31767a3cafede89Jiri Slaby		}
927d3b5cffcf84a8bdc7073dce4745d67c72629af85Alan Cox		if (vsa.console == 0 || vsa.console > MAX_NR_CONSOLES)
928d3b5cffcf84a8bdc7073dce4745d67c72629af85Alan Cox			ret = -ENXIO;
929d3b5cffcf84a8bdc7073dce4745d67c72629af85Alan Cox		else {
930d3b5cffcf84a8bdc7073dce4745d67c72629af85Alan Cox			vsa.console--;
931ac751efa6a0d70f2c9daef5c7e3a92270f5c2dffTorben Hohn			console_lock();
932d3b5cffcf84a8bdc7073dce4745d67c72629af85Alan Cox			ret = vc_allocate(vsa.console);
933d3b5cffcf84a8bdc7073dce4745d67c72629af85Alan Cox			if (ret == 0) {
934d3b5cffcf84a8bdc7073dce4745d67c72629af85Alan Cox				struct vc_data *nvc;
935d3b5cffcf84a8bdc7073dce4745d67c72629af85Alan Cox				/* This is safe providing we don't drop the
936d3b5cffcf84a8bdc7073dce4745d67c72629af85Alan Cox				   console sem between vc_allocate and
937d3b5cffcf84a8bdc7073dce4745d67c72629af85Alan Cox				   finishing referencing nvc */
938d3b5cffcf84a8bdc7073dce4745d67c72629af85Alan Cox				nvc = vc_cons[vsa.console].d;
939d3b5cffcf84a8bdc7073dce4745d67c72629af85Alan Cox				nvc->vt_mode = vsa.mode;
940d3b5cffcf84a8bdc7073dce4745d67c72629af85Alan Cox				nvc->vt_mode.frsig = 0;
941d3b5cffcf84a8bdc7073dce4745d67c72629af85Alan Cox				put_pid(nvc->vt_pid);
942d3b5cffcf84a8bdc7073dce4745d67c72629af85Alan Cox				nvc->vt_pid = get_pid(task_pid(current));
943d3b5cffcf84a8bdc7073dce4745d67c72629af85Alan Cox			}
944ac751efa6a0d70f2c9daef5c7e3a92270f5c2dffTorben Hohn			console_unlock();
945d3b5cffcf84a8bdc7073dce4745d67c72629af85Alan Cox			if (ret)
946d3b5cffcf84a8bdc7073dce4745d67c72629af85Alan Cox				break;
947d3b5cffcf84a8bdc7073dce4745d67c72629af85Alan Cox			/* Commence switch and lock */
948d637837583163a1a70331ce48097f697cac85e32Jiri Olsa			set_console(vsa.console);
949d3b5cffcf84a8bdc7073dce4745d67c72629af85Alan Cox		}
950d637837583163a1a70331ce48097f697cac85e32Jiri Olsa		break;
951d3b5cffcf84a8bdc7073dce4745d67c72629af85Alan Cox	}
952d3b5cffcf84a8bdc7073dce4745d67c72629af85Alan Cox
9531da177e4c3f41524e886b7f1b8a0c1fc7321cacLinus Torvalds	/*
9541da177e4c3f41524e886b7f1b8a0c1fc7321cacLinus Torvalds	 * wait until the specified VT has been activated
9551da177e4c3f41524e886b7f1b8a0c1fc7321cacLinus Torvalds	 */
9561da177e4c3f41524e886b7f1b8a0c1fc7321cacLinus Torvalds	case VT_WAITACTIVE:
9571da177e4c3f41524e886b7f1b8a0c1fc7321cacLinus Torvalds		if (!perm)
9589cc3c22bf017f33612748aeb466fdc3695fb1e1dAlan Cox			goto eperm;
9591da177e4c3f41524e886b7f1b8a0c1fc7321cacLinus Torvalds		if (arg == 0 || arg > MAX_NR_CONSOLES)
9609cc3c22bf017f33612748aeb466fdc3695fb1e1dAlan Cox			ret = -ENXIO;
9619cc3c22bf017f33612748aeb466fdc3695fb1e1dAlan Cox		else
9628b92e87d39bfd046e7581e1fe0f40eac40f88608Alan Cox			ret = vt_waitactive(arg);
9639cc3c22bf017f33612748aeb466fdc3695fb1e1dAlan Cox		break;
9641da177e4c3f41524e886b7f1b8a0c1fc7321cacLinus Torvalds
9651da177e4c3f41524e886b7f1b8a0c1fc7321cacLinus Torvalds	/*
9661da177e4c3f41524e886b7f1b8a0c1fc7321cacLinus Torvalds	 * If a vt is under process control, the kernel will not switch to it
9671da177e4c3f41524e886b7f1b8a0c1fc7321cacLinus Torvalds	 * immediately, but postpone the operation until the process calls this
9681da177e4c3f41524e886b7f1b8a0c1fc7321cacLinus Torvalds	 * ioctl, allowing the switch to complete.
9691da177e4c3f41524e886b7f1b8a0c1fc7321cacLinus Torvalds	 *
9701da177e4c3f41524e886b7f1b8a0c1fc7321cacLinus Torvalds	 * According to the X sources this is the behavior:
9711da177e4c3f41524e886b7f1b8a0c1fc7321cacLinus Torvalds	 *	0:	pending switch-from not OK
9721da177e4c3f41524e886b7f1b8a0c1fc7321cacLinus Torvalds	 *	1:	pending switch-from OK
9731da177e4c3f41524e886b7f1b8a0c1fc7321cacLinus Torvalds	 *	2:	completed switch-to OK
9741da177e4c3f41524e886b7f1b8a0c1fc7321cacLinus Torvalds	 */
9751da177e4c3f41524e886b7f1b8a0c1fc7321cacLinus Torvalds	case VT_RELDISP:
9761da177e4c3f41524e886b7f1b8a0c1fc7321cacLinus Torvalds		if (!perm)
9779cc3c22bf017f33612748aeb466fdc3695fb1e1dAlan Cox			goto eperm;
9781da177e4c3f41524e886b7f1b8a0c1fc7321cacLinus Torvalds
9799cc3c22bf017f33612748aeb466fdc3695fb1e1dAlan Cox		if (vc->vt_mode.mode != VT_PROCESS) {
9809cc3c22bf017f33612748aeb466fdc3695fb1e1dAlan Cox			ret = -EINVAL;
9819cc3c22bf017f33612748aeb466fdc3695fb1e1dAlan Cox			break;
9829cc3c22bf017f33612748aeb466fdc3695fb1e1dAlan Cox		}
9831da177e4c3f41524e886b7f1b8a0c1fc7321cacLinus Torvalds		/*
9841da177e4c3f41524e886b7f1b8a0c1fc7321cacLinus Torvalds		 * Switching-from response
9851da177e4c3f41524e886b7f1b8a0c1fc7321cacLinus Torvalds		 */
986ac751efa6a0d70f2c9daef5c7e3a92270f5c2dffTorben Hohn		console_lock();
9871da177e4c3f41524e886b7f1b8a0c1fc7321cacLinus Torvalds		if (vc->vt_newvt >= 0) {
9881da177e4c3f41524e886b7f1b8a0c1fc7321cacLinus Torvalds			if (arg == 0)
9891da177e4c3f41524e886b7f1b8a0c1fc7321cacLinus Torvalds				/*
9901da177e4c3f41524e886b7f1b8a0c1fc7321cacLinus Torvalds				 * Switch disallowed, so forget we were trying
9911da177e4c3f41524e886b7f1b8a0c1fc7321cacLinus Torvalds				 * to do it.
9921da177e4c3f41524e886b7f1b8a0c1fc7321cacLinus Torvalds				 */
9931da177e4c3f41524e886b7f1b8a0c1fc7321cacLinus Torvalds				vc->vt_newvt = -1;
9941da177e4c3f41524e886b7f1b8a0c1fc7321cacLinus Torvalds
9951da177e4c3f41524e886b7f1b8a0c1fc7321cacLinus Torvalds			else {
9961da177e4c3f41524e886b7f1b8a0c1fc7321cacLinus Torvalds				/*
9971da177e4c3f41524e886b7f1b8a0c1fc7321cacLinus Torvalds				 * The current vt has been released, so
9981da177e4c3f41524e886b7f1b8a0c1fc7321cacLinus Torvalds				 * complete the switch.
9991da177e4c3f41524e886b7f1b8a0c1fc7321cacLinus Torvalds				 */
10001da177e4c3f41524e886b7f1b8a0c1fc7321cacLinus Torvalds				int newvt;
10011da177e4c3f41524e886b7f1b8a0c1fc7321cacLinus Torvalds				newvt = vc->vt_newvt;
10021da177e4c3f41524e886b7f1b8a0c1fc7321cacLinus Torvalds				vc->vt_newvt = -1;
10039cc3c22bf017f33612748aeb466fdc3695fb1e1dAlan Cox				ret = vc_allocate(newvt);
10049cc3c22bf017f33612748aeb466fdc3695fb1e1dAlan Cox				if (ret) {
1005ac751efa6a0d70f2c9daef5c7e3a92270f5c2dffTorben Hohn					console_unlock();
10069cc3c22bf017f33612748aeb466fdc3695fb1e1dAlan Cox					break;
10071da177e4c3f41524e886b7f1b8a0c1fc7321cacLinus Torvalds				}
10081da177e4c3f41524e886b7f1b8a0c1fc7321cacLinus Torvalds				/*
10091da177e4c3f41524e886b7f1b8a0c1fc7321cacLinus Torvalds				 * When we actually do the console switch,
10101da177e4c3f41524e886b7f1b8a0c1fc7321cacLinus Torvalds				 * make sure we are atomic with respect to
10111da177e4c3f41524e886b7f1b8a0c1fc7321cacLinus Torvalds				 * other console switches..
10121da177e4c3f41524e886b7f1b8a0c1fc7321cacLinus Torvalds				 */
10131da177e4c3f41524e886b7f1b8a0c1fc7321cacLinus Torvalds				complete_change_console(vc_cons[newvt].d);
10141da177e4c3f41524e886b7f1b8a0c1fc7321cacLinus Torvalds			}
10159cc3c22bf017f33612748aeb466fdc3695fb1e1dAlan Cox		} else {
10169cc3c22bf017f33612748aeb466fdc3695fb1e1dAlan Cox			/*
10179cc3c22bf017f33612748aeb466fdc3695fb1e1dAlan Cox			 * Switched-to response
10189cc3c22bf017f33612748aeb466fdc3695fb1e1dAlan Cox			 */
10191da177e4c3f41524e886b7f1b8a0c1fc7321cacLinus Torvalds			/*
10201da177e4c3f41524e886b7f1b8a0c1fc7321cacLinus Torvalds			 * If it's just an ACK, ignore it
10211da177e4c3f41524e886b7f1b8a0c1fc7321cacLinus Torvalds			 */
10229cc3c22bf017f33612748aeb466fdc3695fb1e1dAlan Cox			if (arg != VT_ACKACQ)
10239cc3c22bf017f33612748aeb466fdc3695fb1e1dAlan Cox				ret = -EINVAL;
10241da177e4c3f41524e886b7f1b8a0c1fc7321cacLinus Torvalds		}
1025ac751efa6a0d70f2c9daef5c7e3a92270f5c2dffTorben Hohn		console_unlock();
10269cc3c22bf017f33612748aeb466fdc3695fb1e1dAlan Cox		break;
10271da177e4c3f41524e886b7f1b8a0c1fc7321cacLinus Torvalds
10281da177e4c3f41524e886b7f1b8a0c1fc7321cacLinus Torvalds	 /*
10291da177e4c3f41524e886b7f1b8a0c1fc7321cacLinus Torvalds	  * Disallocate memory associated to VT (but leave VT1)
10301da177e4c3f41524e886b7f1b8a0c1fc7321cacLinus Torvalds	  */
10311da177e4c3f41524e886b7f1b8a0c1fc7321cacLinus Torvalds	 case VT_DISALLOCATE:
10329cc3c22bf017f33612748aeb466fdc3695fb1e1dAlan Cox		if (arg > MAX_NR_CONSOLES) {
10339cc3c22bf017f33612748aeb466fdc3695fb1e1dAlan Cox			ret = -ENXIO;
10349cc3c22bf017f33612748aeb466fdc3695fb1e1dAlan Cox			break;
10359cc3c22bf017f33612748aeb466fdc3695fb1e1dAlan Cox		}
10361da177e4c3f41524e886b7f1b8a0c1fc7321cacLinus Torvalds		if (arg == 0) {
1037ca9bda00b4aafc42cd3d1b9d32934463e2993b4cAlan Cox		    /* deallocate all unused consoles, but leave 0 */
1038ac751efa6a0d70f2c9daef5c7e3a92270f5c2dffTorben Hohn			console_lock();
10391da177e4c3f41524e886b7f1b8a0c1fc7321cacLinus Torvalds			for (i=1; i<MAX_NR_CONSOLES; i++)
10401da177e4c3f41524e886b7f1b8a0c1fc7321cacLinus Torvalds				if (! VT_BUSY(i))
1041ca9bda00b4aafc42cd3d1b9d32934463e2993b4cAlan Cox					vc_deallocate(i);
1042ac751efa6a0d70f2c9daef5c7e3a92270f5c2dffTorben Hohn			console_unlock();
10431da177e4c3f41524e886b7f1b8a0c1fc7321cacLinus Torvalds		} else {
1044ca9bda00b4aafc42cd3d1b9d32934463e2993b4cAlan Cox			/* deallocate a single console, if possible */
10451da177e4c3f41524e886b7f1b8a0c1fc7321cacLinus Torvalds			arg--;
10461da177e4c3f41524e886b7f1b8a0c1fc7321cacLinus Torvalds			if (VT_BUSY(arg))
10479cc3c22bf017f33612748aeb466fdc3695fb1e1dAlan Cox				ret = -EBUSY;
10489cc3c22bf017f33612748aeb466fdc3695fb1e1dAlan Cox			else if (arg) {			      /* leave 0 */
1049ac751efa6a0d70f2c9daef5c7e3a92270f5c2dffTorben Hohn				console_lock();
1050ca9bda00b4aafc42cd3d1b9d32934463e2993b4cAlan Cox				vc_deallocate(arg);
1051ac751efa6a0d70f2c9daef5c7e3a92270f5c2dffTorben Hohn				console_unlock();
10521da177e4c3f41524e886b7f1b8a0c1fc7321cacLinus Torvalds			}
10531da177e4c3f41524e886b7f1b8a0c1fc7321cacLinus Torvalds		}
10549cc3c22bf017f33612748aeb466fdc3695fb1e1dAlan Cox		break;
10551da177e4c3f41524e886b7f1b8a0c1fc7321cacLinus Torvalds
10561da177e4c3f41524e886b7f1b8a0c1fc7321cacLinus Torvalds	case VT_RESIZE:
10571da177e4c3f41524e886b7f1b8a0c1fc7321cacLinus Torvalds	{
10581da177e4c3f41524e886b7f1b8a0c1fc7321cacLinus Torvalds		struct vt_sizes __user *vtsizes = up;
1059e400b6ec4ede4dc0aa8e5640425df5b29796fe0eAntonino A. Daplas		struct vc_data *vc;
1060e400b6ec4ede4dc0aa8e5640425df5b29796fe0eAntonino A. Daplas
10611da177e4c3f41524e886b7f1b8a0c1fc7321cacLinus Torvalds		ushort ll,cc;
10621da177e4c3f41524e886b7f1b8a0c1fc7321cacLinus Torvalds		if (!perm)
10639cc3c22bf017f33612748aeb466fdc3695fb1e1dAlan Cox			goto eperm;
10641da177e4c3f41524e886b7f1b8a0c1fc7321cacLinus Torvalds		if (get_user(ll, &vtsizes->v_rows) ||
10651da177e4c3f41524e886b7f1b8a0c1fc7321cacLinus Torvalds		    get_user(cc, &vtsizes->v_cols))
10669cc3c22bf017f33612748aeb466fdc3695fb1e1dAlan Cox			ret = -EFAULT;
10679cc3c22bf017f33612748aeb466fdc3695fb1e1dAlan Cox		else {
1068ac751efa6a0d70f2c9daef5c7e3a92270f5c2dffTorben Hohn			console_lock();
10699cc3c22bf017f33612748aeb466fdc3695fb1e1dAlan Cox			for (i = 0; i < MAX_NR_CONSOLES; i++) {
10709cc3c22bf017f33612748aeb466fdc3695fb1e1dAlan Cox				vc = vc_cons[i].d;
1071e400b6ec4ede4dc0aa8e5640425df5b29796fe0eAntonino A. Daplas
10729cc3c22bf017f33612748aeb466fdc3695fb1e1dAlan Cox				if (vc) {
10739cc3c22bf017f33612748aeb466fdc3695fb1e1dAlan Cox					vc->vc_resize_user = 1;
10748c9a9dd0fa3a269d380eaae2dc1bee39e865fae1Alan Cox					vc_resize(vc_cons[i].d, cc, ll);
10759cc3c22bf017f33612748aeb466fdc3695fb1e1dAlan Cox				}
1076e400b6ec4ede4dc0aa8e5640425df5b29796fe0eAntonino A. Daplas			}
1077ac751efa6a0d70f2c9daef5c7e3a92270f5c2dffTorben Hohn			console_unlock();
1078e400b6ec4ede4dc0aa8e5640425df5b29796fe0eAntonino A. Daplas		}
10799cc3c22bf017f33612748aeb466fdc3695fb1e1dAlan Cox		break;
10801da177e4c3f41524e886b7f1b8a0c1fc7321cacLinus Torvalds	}
10811da177e4c3f41524e886b7f1b8a0c1fc7321cacLinus Torvalds
10821da177e4c3f41524e886b7f1b8a0c1fc7321cacLinus Torvalds	case VT_RESIZEX:
10831da177e4c3f41524e886b7f1b8a0c1fc7321cacLinus Torvalds	{
10841da177e4c3f41524e886b7f1b8a0c1fc7321cacLinus Torvalds		struct vt_consize __user *vtconsize = up;
10851da177e4c3f41524e886b7f1b8a0c1fc7321cacLinus Torvalds		ushort ll,cc,vlin,clin,vcol,ccol;
10861da177e4c3f41524e886b7f1b8a0c1fc7321cacLinus Torvalds		if (!perm)
10879cc3c22bf017f33612748aeb466fdc3695fb1e1dAlan Cox			goto eperm;
10881da177e4c3f41524e886b7f1b8a0c1fc7321cacLinus Torvalds		if (!access_ok(VERIFY_READ, vtconsize,
10899cc3c22bf017f33612748aeb466fdc3695fb1e1dAlan Cox				sizeof(struct vt_consize))) {
10909cc3c22bf017f33612748aeb466fdc3695fb1e1dAlan Cox			ret = -EFAULT;
10919cc3c22bf017f33612748aeb466fdc3695fb1e1dAlan Cox			break;
10929cc3c22bf017f33612748aeb466fdc3695fb1e1dAlan Cox		}
10939cc3c22bf017f33612748aeb466fdc3695fb1e1dAlan Cox		/* FIXME: Should check the copies properly */
10941da177e4c3f41524e886b7f1b8a0c1fc7321cacLinus Torvalds		__get_user(ll, &vtconsize->v_rows);
10951da177e4c3f41524e886b7f1b8a0c1fc7321cacLinus Torvalds		__get_user(cc, &vtconsize->v_cols);
10961da177e4c3f41524e886b7f1b8a0c1fc7321cacLinus Torvalds		__get_user(vlin, &vtconsize->v_vlin);
10971da177e4c3f41524e886b7f1b8a0c1fc7321cacLinus Torvalds		__get_user(clin, &vtconsize->v_clin);
10981da177e4c3f41524e886b7f1b8a0c1fc7321cacLinus Torvalds		__get_user(vcol, &vtconsize->v_vcol);
10991da177e4c3f41524e886b7f1b8a0c1fc7321cacLinus Torvalds		__get_user(ccol, &vtconsize->v_ccol);
11001da177e4c3f41524e886b7f1b8a0c1fc7321cacLinus Torvalds		vlin = vlin ? vlin : vc->vc_scan_lines;
11011da177e4c3f41524e886b7f1b8a0c1fc7321cacLinus Torvalds		if (clin) {
11021da177e4c3f41524e886b7f1b8a0c1fc7321cacLinus Torvalds			if (ll) {
11039cc3c22bf017f33612748aeb466fdc3695fb1e1dAlan Cox				if (ll != vlin/clin) {
11049cc3c22bf017f33612748aeb466fdc3695fb1e1dAlan Cox					/* Parameters don't add up */
11059cc3c22bf017f33612748aeb466fdc3695fb1e1dAlan Cox					ret = -EINVAL;
11069cc3c22bf017f33612748aeb466fdc3695fb1e1dAlan Cox					break;
11079cc3c22bf017f33612748aeb466fdc3695fb1e1dAlan Cox				}
11081da177e4c3f41524e886b7f1b8a0c1fc7321cacLinus Torvalds			} else
11091da177e4c3f41524e886b7f1b8a0c1fc7321cacLinus Torvalds				ll = vlin/clin;
11101da177e4c3f41524e886b7f1b8a0c1fc7321cacLinus Torvalds		}
11111da177e4c3f41524e886b7f1b8a0c1fc7321cacLinus Torvalds		if (vcol && ccol) {
11121da177e4c3f41524e886b7f1b8a0c1fc7321cacLinus Torvalds			if (cc) {
11139cc3c22bf017f33612748aeb466fdc3695fb1e1dAlan Cox				if (cc != vcol/ccol) {
11149cc3c22bf017f33612748aeb466fdc3695fb1e1dAlan Cox					ret = -EINVAL;
11159cc3c22bf017f33612748aeb466fdc3695fb1e1dAlan Cox					break;
11169cc3c22bf017f33612748aeb466fdc3695fb1e1dAlan Cox				}
11171da177e4c3f41524e886b7f1b8a0c1fc7321cacLinus Torvalds			} else
11181da177e4c3f41524e886b7f1b8a0c1fc7321cacLinus Torvalds				cc = vcol/ccol;
11191da177e4c3f41524e886b7f1b8a0c1fc7321cacLinus Torvalds		}
11201da177e4c3f41524e886b7f1b8a0c1fc7321cacLinus Torvalds
11219cc3c22bf017f33612748aeb466fdc3695fb1e1dAlan Cox		if (clin > 32) {
11229cc3c22bf017f33612748aeb466fdc3695fb1e1dAlan Cox			ret =  -EINVAL;
11239cc3c22bf017f33612748aeb466fdc3695fb1e1dAlan Cox			break;
11249cc3c22bf017f33612748aeb466fdc3695fb1e1dAlan Cox		}
11251da177e4c3f41524e886b7f1b8a0c1fc7321cacLinus Torvalds
11261da177e4c3f41524e886b7f1b8a0c1fc7321cacLinus Torvalds		for (i = 0; i < MAX_NR_CONSOLES; i++) {
11271da177e4c3f41524e886b7f1b8a0c1fc7321cacLinus Torvalds			if (!vc_cons[i].d)
11281da177e4c3f41524e886b7f1b8a0c1fc7321cacLinus Torvalds				continue;
1129ac751efa6a0d70f2c9daef5c7e3a92270f5c2dffTorben Hohn			console_lock();
11301da177e4c3f41524e886b7f1b8a0c1fc7321cacLinus Torvalds			if (vlin)
11311da177e4c3f41524e886b7f1b8a0c1fc7321cacLinus Torvalds				vc_cons[i].d->vc_scan_lines = vlin;
11321da177e4c3f41524e886b7f1b8a0c1fc7321cacLinus Torvalds			if (clin)
11331da177e4c3f41524e886b7f1b8a0c1fc7321cacLinus Torvalds				vc_cons[i].d->vc_font.height = clin;
1134e400b6ec4ede4dc0aa8e5640425df5b29796fe0eAntonino A. Daplas			vc_cons[i].d->vc_resize_user = 1;
11351da177e4c3f41524e886b7f1b8a0c1fc7321cacLinus Torvalds			vc_resize(vc_cons[i].d, cc, ll);
1136ac751efa6a0d70f2c9daef5c7e3a92270f5c2dffTorben Hohn			console_unlock();
11371da177e4c3f41524e886b7f1b8a0c1fc7321cacLinus Torvalds		}
11389cc3c22bf017f33612748aeb466fdc3695fb1e1dAlan Cox		break;
11391da177e4c3f41524e886b7f1b8a0c1fc7321cacLinus Torvalds	}
11401da177e4c3f41524e886b7f1b8a0c1fc7321cacLinus Torvalds
11411da177e4c3f41524e886b7f1b8a0c1fc7321cacLinus Torvalds	case PIO_FONT: {
11421da177e4c3f41524e886b7f1b8a0c1fc7321cacLinus Torvalds		if (!perm)
11439cc3c22bf017f33612748aeb466fdc3695fb1e1dAlan Cox			goto eperm;
11441da177e4c3f41524e886b7f1b8a0c1fc7321cacLinus Torvalds		op.op = KD_FONT_OP_SET;
11451da177e4c3f41524e886b7f1b8a0c1fc7321cacLinus Torvalds		op.flags = KD_FONT_FLAG_OLD | KD_FONT_FLAG_DONT_RECALC;	/* Compatibility */
11461da177e4c3f41524e886b7f1b8a0c1fc7321cacLinus Torvalds		op.width = 8;
11471da177e4c3f41524e886b7f1b8a0c1fc7321cacLinus Torvalds		op.height = 0;
11481da177e4c3f41524e886b7f1b8a0c1fc7321cacLinus Torvalds		op.charcount = 256;
11491da177e4c3f41524e886b7f1b8a0c1fc7321cacLinus Torvalds		op.data = up;
11509cc3c22bf017f33612748aeb466fdc3695fb1e1dAlan Cox		ret = con_font_op(vc_cons[fg_console].d, &op);
11519cc3c22bf017f33612748aeb466fdc3695fb1e1dAlan Cox		break;
11521da177e4c3f41524e886b7f1b8a0c1fc7321cacLinus Torvalds	}
11531da177e4c3f41524e886b7f1b8a0c1fc7321cacLinus Torvalds
11541da177e4c3f41524e886b7f1b8a0c1fc7321cacLinus Torvalds	case GIO_FONT: {
11551da177e4c3f41524e886b7f1b8a0c1fc7321cacLinus Torvalds		op.op = KD_FONT_OP_GET;
11561da177e4c3f41524e886b7f1b8a0c1fc7321cacLinus Torvalds		op.flags = KD_FONT_FLAG_OLD;
11571da177e4c3f41524e886b7f1b8a0c1fc7321cacLinus Torvalds		op.width = 8;
11581da177e4c3f41524e886b7f1b8a0c1fc7321cacLinus Torvalds		op.height = 32;
11591da177e4c3f41524e886b7f1b8a0c1fc7321cacLinus Torvalds		op.charcount = 256;
11601da177e4c3f41524e886b7f1b8a0c1fc7321cacLinus Torvalds		op.data = up;
11619cc3c22bf017f33612748aeb466fdc3695fb1e1dAlan Cox		ret = con_font_op(vc_cons[fg_console].d, &op);
11629cc3c22bf017f33612748aeb466fdc3695fb1e1dAlan Cox		break;
11631da177e4c3f41524e886b7f1b8a0c1fc7321cacLinus Torvalds	}
11641da177e4c3f41524e886b7f1b8a0c1fc7321cacLinus Torvalds
11651da177e4c3f41524e886b7f1b8a0c1fc7321cacLinus Torvalds	case PIO_CMAP:
11661da177e4c3f41524e886b7f1b8a0c1fc7321cacLinus Torvalds                if (!perm)
11679cc3c22bf017f33612748aeb466fdc3695fb1e1dAlan Cox			ret = -EPERM;
11689cc3c22bf017f33612748aeb466fdc3695fb1e1dAlan Cox		else
11699cc3c22bf017f33612748aeb466fdc3695fb1e1dAlan Cox	                ret = con_set_cmap(up);
11709cc3c22bf017f33612748aeb466fdc3695fb1e1dAlan Cox		break;
11711da177e4c3f41524e886b7f1b8a0c1fc7321cacLinus Torvalds
11721da177e4c3f41524e886b7f1b8a0c1fc7321cacLinus Torvalds	case GIO_CMAP:
11739cc3c22bf017f33612748aeb466fdc3695fb1e1dAlan Cox                ret = con_get_cmap(up);
11749cc3c22bf017f33612748aeb466fdc3695fb1e1dAlan Cox		break;
11751da177e4c3f41524e886b7f1b8a0c1fc7321cacLinus Torvalds
11761da177e4c3f41524e886b7f1b8a0c1fc7321cacLinus Torvalds	case PIO_FONTX:
11771da177e4c3f41524e886b7f1b8a0c1fc7321cacLinus Torvalds	case GIO_FONTX:
11789cc3c22bf017f33612748aeb466fdc3695fb1e1dAlan Cox		ret = do_fontx_ioctl(cmd, up, perm, &op);
11799cc3c22bf017f33612748aeb466fdc3695fb1e1dAlan Cox		break;
11801da177e4c3f41524e886b7f1b8a0c1fc7321cacLinus Torvalds
11811da177e4c3f41524e886b7f1b8a0c1fc7321cacLinus Torvalds	case PIO_FONTRESET:
11821da177e4c3f41524e886b7f1b8a0c1fc7321cacLinus Torvalds	{
11831da177e4c3f41524e886b7f1b8a0c1fc7321cacLinus Torvalds		if (!perm)
11849cc3c22bf017f33612748aeb466fdc3695fb1e1dAlan Cox			goto eperm;
11851da177e4c3f41524e886b7f1b8a0c1fc7321cacLinus Torvalds
11861da177e4c3f41524e886b7f1b8a0c1fc7321cacLinus Torvalds#ifdef BROKEN_GRAPHICS_PROGRAMS
11871da177e4c3f41524e886b7f1b8a0c1fc7321cacLinus Torvalds		/* With BROKEN_GRAPHICS_PROGRAMS defined, the default
11881da177e4c3f41524e886b7f1b8a0c1fc7321cacLinus Torvalds		   font is not saved. */
11899cc3c22bf017f33612748aeb466fdc3695fb1e1dAlan Cox		ret = -ENOSYS;
11909cc3c22bf017f33612748aeb466fdc3695fb1e1dAlan Cox		break;
11911da177e4c3f41524e886b7f1b8a0c1fc7321cacLinus Torvalds#else
11921da177e4c3f41524e886b7f1b8a0c1fc7321cacLinus Torvalds		{
11931da177e4c3f41524e886b7f1b8a0c1fc7321cacLinus Torvalds		op.op = KD_FONT_OP_SET_DEFAULT;
11941da177e4c3f41524e886b7f1b8a0c1fc7321cacLinus Torvalds		op.data = NULL;
11959cc3c22bf017f33612748aeb466fdc3695fb1e1dAlan Cox		ret = con_font_op(vc_cons[fg_console].d, &op);
11969cc3c22bf017f33612748aeb466fdc3695fb1e1dAlan Cox		if (ret)
11979cc3c22bf017f33612748aeb466fdc3695fb1e1dAlan Cox			break;
11981da177e4c3f41524e886b7f1b8a0c1fc7321cacLinus Torvalds		con_set_default_unimap(vc_cons[fg_console].d);
11999cc3c22bf017f33612748aeb466fdc3695fb1e1dAlan Cox		break;
12001da177e4c3f41524e886b7f1b8a0c1fc7321cacLinus Torvalds		}
12011da177e4c3f41524e886b7f1b8a0c1fc7321cacLinus Torvalds#endif
12021da177e4c3f41524e886b7f1b8a0c1fc7321cacLinus Torvalds	}
12031da177e4c3f41524e886b7f1b8a0c1fc7321cacLinus Torvalds
12041da177e4c3f41524e886b7f1b8a0c1fc7321cacLinus Torvalds	case KDFONTOP: {
12059cc3c22bf017f33612748aeb466fdc3695fb1e1dAlan Cox		if (copy_from_user(&op, up, sizeof(op))) {
12069cc3c22bf017f33612748aeb466fdc3695fb1e1dAlan Cox			ret = -EFAULT;
12079cc3c22bf017f33612748aeb466fdc3695fb1e1dAlan Cox			break;
12089cc3c22bf017f33612748aeb466fdc3695fb1e1dAlan Cox		}
12091da177e4c3f41524e886b7f1b8a0c1fc7321cacLinus Torvalds		if (!perm && op.op != KD_FONT_OP_GET)
12109cc3c22bf017f33612748aeb466fdc3695fb1e1dAlan Cox			goto eperm;
12119cc3c22bf017f33612748aeb466fdc3695fb1e1dAlan Cox		ret = con_font_op(vc, &op);
12129cc3c22bf017f33612748aeb466fdc3695fb1e1dAlan Cox		if (ret)
12139cc3c22bf017f33612748aeb466fdc3695fb1e1dAlan Cox			break;
12141da177e4c3f41524e886b7f1b8a0c1fc7321cacLinus Torvalds		if (copy_to_user(up, &op, sizeof(op)))
12159cc3c22bf017f33612748aeb466fdc3695fb1e1dAlan Cox			ret = -EFAULT;
12169cc3c22bf017f33612748aeb466fdc3695fb1e1dAlan Cox		break;
12171da177e4c3f41524e886b7f1b8a0c1fc7321cacLinus Torvalds	}
12181da177e4c3f41524e886b7f1b8a0c1fc7321cacLinus Torvalds
12191da177e4c3f41524e886b7f1b8a0c1fc7321cacLinus Torvalds	case PIO_SCRNMAP:
12201da177e4c3f41524e886b7f1b8a0c1fc7321cacLinus Torvalds		if (!perm)
12219cc3c22bf017f33612748aeb466fdc3695fb1e1dAlan Cox			ret = -EPERM;
12229cc3c22bf017f33612748aeb466fdc3695fb1e1dAlan Cox		else
12239cc3c22bf017f33612748aeb466fdc3695fb1e1dAlan Cox			ret = con_set_trans_old(up);
12249cc3c22bf017f33612748aeb466fdc3695fb1e1dAlan Cox		break;
12251da177e4c3f41524e886b7f1b8a0c1fc7321cacLinus Torvalds
12261da177e4c3f41524e886b7f1b8a0c1fc7321cacLinus Torvalds	case GIO_SCRNMAP:
12279cc3c22bf017f33612748aeb466fdc3695fb1e1dAlan Cox		ret = con_get_trans_old(up);
12289cc3c22bf017f33612748aeb466fdc3695fb1e1dAlan Cox		break;
12291da177e4c3f41524e886b7f1b8a0c1fc7321cacLinus Torvalds
12301da177e4c3f41524e886b7f1b8a0c1fc7321cacLinus Torvalds	case PIO_UNISCRNMAP:
12311da177e4c3f41524e886b7f1b8a0c1fc7321cacLinus Torvalds		if (!perm)
12329cc3c22bf017f33612748aeb466fdc3695fb1e1dAlan Cox			ret = -EPERM;
12339cc3c22bf017f33612748aeb466fdc3695fb1e1dAlan Cox		else
12349cc3c22bf017f33612748aeb466fdc3695fb1e1dAlan Cox			ret = con_set_trans_new(up);
12359cc3c22bf017f33612748aeb466fdc3695fb1e1dAlan Cox		break;
12361da177e4c3f41524e886b7f1b8a0c1fc7321cacLinus Torvalds
12371da177e4c3f41524e886b7f1b8a0c1fc7321cacLinus Torvalds	case GIO_UNISCRNMAP:
12389cc3c22bf017f33612748aeb466fdc3695fb1e1dAlan Cox		ret = con_get_trans_new(up);
12399cc3c22bf017f33612748aeb466fdc3695fb1e1dAlan Cox		break;
12401da177e4c3f41524e886b7f1b8a0c1fc7321cacLinus Torvalds
12411da177e4c3f41524e886b7f1b8a0c1fc7321cacLinus Torvalds	case PIO_UNIMAPCLR:
12421da177e4c3f41524e886b7f1b8a0c1fc7321cacLinus Torvalds	      { struct unimapinit ui;
12431da177e4c3f41524e886b7f1b8a0c1fc7321cacLinus Torvalds		if (!perm)
12449cc3c22bf017f33612748aeb466fdc3695fb1e1dAlan Cox			goto eperm;
12459cc3c22bf017f33612748aeb466fdc3695fb1e1dAlan Cox		ret = copy_from_user(&ui, up, sizeof(struct unimapinit));
12463fde85df5421eb01f563fef6f111ba73ab0d120eDan Carpenter		if (ret)
12473fde85df5421eb01f563fef6f111ba73ab0d120eDan Carpenter			ret = -EFAULT;
12483fde85df5421eb01f563fef6f111ba73ab0d120eDan Carpenter		else
12499cc3c22bf017f33612748aeb466fdc3695fb1e1dAlan Cox			con_clear_unimap(vc, &ui);
12509cc3c22bf017f33612748aeb466fdc3695fb1e1dAlan Cox		break;
12511da177e4c3f41524e886b7f1b8a0c1fc7321cacLinus Torvalds	      }
12521da177e4c3f41524e886b7f1b8a0c1fc7321cacLinus Torvalds
12531da177e4c3f41524e886b7f1b8a0c1fc7321cacLinus Torvalds	case PIO_UNIMAP:
12541da177e4c3f41524e886b7f1b8a0c1fc7321cacLinus Torvalds	case GIO_UNIMAP:
12559cc3c22bf017f33612748aeb466fdc3695fb1e1dAlan Cox		ret = do_unimap_ioctl(cmd, up, perm, vc);
12569cc3c22bf017f33612748aeb466fdc3695fb1e1dAlan Cox		break;
12571da177e4c3f41524e886b7f1b8a0c1fc7321cacLinus Torvalds
12581da177e4c3f41524e886b7f1b8a0c1fc7321cacLinus Torvalds	case VT_LOCKSWITCH:
12591da177e4c3f41524e886b7f1b8a0c1fc7321cacLinus Torvalds		if (!capable(CAP_SYS_TTY_CONFIG))
12609cc3c22bf017f33612748aeb466fdc3695fb1e1dAlan Cox			goto eperm;
12611da177e4c3f41524e886b7f1b8a0c1fc7321cacLinus Torvalds		vt_dont_switch = 1;
12629cc3c22bf017f33612748aeb466fdc3695fb1e1dAlan Cox		break;
12631da177e4c3f41524e886b7f1b8a0c1fc7321cacLinus Torvalds	case VT_UNLOCKSWITCH:
12641da177e4c3f41524e886b7f1b8a0c1fc7321cacLinus Torvalds		if (!capable(CAP_SYS_TTY_CONFIG))
12659cc3c22bf017f33612748aeb466fdc3695fb1e1dAlan Cox			goto eperm;
12661da177e4c3f41524e886b7f1b8a0c1fc7321cacLinus Torvalds		vt_dont_switch = 0;
12679cc3c22bf017f33612748aeb466fdc3695fb1e1dAlan Cox		break;
1268533475d3d48eb839be2b57f6b020150abae91063Samuel Thibault	case VT_GETHIFONTMASK:
12699cc3c22bf017f33612748aeb466fdc3695fb1e1dAlan Cox		ret = put_user(vc->vc_hi_font_mask,
12709cc3c22bf017f33612748aeb466fdc3695fb1e1dAlan Cox					(unsigned short __user *)arg);
12719cc3c22bf017f33612748aeb466fdc3695fb1e1dAlan Cox		break;
12728b92e87d39bfd046e7581e1fe0f40eac40f88608Alan Cox	case VT_WAITEVENT:
12738b92e87d39bfd046e7581e1fe0f40eac40f88608Alan Cox		ret = vt_event_wait_ioctl((struct vt_event __user *)arg);
12748b92e87d39bfd046e7581e1fe0f40eac40f88608Alan Cox		break;
12751da177e4c3f41524e886b7f1b8a0c1fc7321cacLinus Torvalds	default:
12769cc3c22bf017f33612748aeb466fdc3695fb1e1dAlan Cox		ret = -ENOIOCTLCMD;
12771da177e4c3f41524e886b7f1b8a0c1fc7321cacLinus Torvalds	}
12789cc3c22bf017f33612748aeb466fdc3695fb1e1dAlan Coxout:
1279ec79d6056de58511d8e46d9ae59d3878f958dc3eArnd Bergmann	tty_unlock();
12809cc3c22bf017f33612748aeb466fdc3695fb1e1dAlan Cox	return ret;
12819cc3c22bf017f33612748aeb466fdc3695fb1e1dAlan Coxeperm:
12829cc3c22bf017f33612748aeb466fdc3695fb1e1dAlan Cox	ret = -EPERM;
12839cc3c22bf017f33612748aeb466fdc3695fb1e1dAlan Cox	goto out;
12841da177e4c3f41524e886b7f1b8a0c1fc7321cacLinus Torvalds}
12851da177e4c3f41524e886b7f1b8a0c1fc7321cacLinus Torvalds
12861da177e4c3f41524e886b7f1b8a0c1fc7321cacLinus Torvaldsvoid reset_vc(struct vc_data *vc)
12871da177e4c3f41524e886b7f1b8a0c1fc7321cacLinus Torvalds{
12881da177e4c3f41524e886b7f1b8a0c1fc7321cacLinus Torvalds	vc->vc_mode = KD_TEXT;
12892e8ecb9db0bcc19e1cc8bb51e9252fe6a86a9863Bill Nottingham	kbd_table[vc->vc_num].kbdmode = default_utf8 ? VC_UNICODE : VC_XLATE;
12901da177e4c3f41524e886b7f1b8a0c1fc7321cacLinus Torvalds	vc->vt_mode.mode = VT_AUTO;
12911da177e4c3f41524e886b7f1b8a0c1fc7321cacLinus Torvalds	vc->vt_mode.waitv = 0;
12921da177e4c3f41524e886b7f1b8a0c1fc7321cacLinus Torvalds	vc->vt_mode.relsig = 0;
12931da177e4c3f41524e886b7f1b8a0c1fc7321cacLinus Torvalds	vc->vt_mode.acqsig = 0;
12941da177e4c3f41524e886b7f1b8a0c1fc7321cacLinus Torvalds	vc->vt_mode.frsig = 0;
12958b6312f4dcc1efe7975731b6c47dd134282bd9acEric W. Biederman	put_pid(vc->vt_pid);
12968b6312f4dcc1efe7975731b6c47dd134282bd9acEric W. Biederman	vc->vt_pid = NULL;
12971da177e4c3f41524e886b7f1b8a0c1fc7321cacLinus Torvalds	vc->vt_newvt = -1;
12981da177e4c3f41524e886b7f1b8a0c1fc7321cacLinus Torvalds	if (!in_interrupt())    /* Via keyboard.c:SAK() - akpm */
12991da177e4c3f41524e886b7f1b8a0c1fc7321cacLinus Torvalds		reset_palette(vc);
13001da177e4c3f41524e886b7f1b8a0c1fc7321cacLinus Torvalds}
13011da177e4c3f41524e886b7f1b8a0c1fc7321cacLinus Torvalds
13028b6312f4dcc1efe7975731b6c47dd134282bd9acEric W. Biedermanvoid vc_SAK(struct work_struct *work)
13038b6312f4dcc1efe7975731b6c47dd134282bd9acEric W. Biederman{
13048b6312f4dcc1efe7975731b6c47dd134282bd9acEric W. Biederman	struct vc *vc_con =
13058b6312f4dcc1efe7975731b6c47dd134282bd9acEric W. Biederman		container_of(work, struct vc, SAK_work);
13068b6312f4dcc1efe7975731b6c47dd134282bd9acEric W. Biederman	struct vc_data *vc;
13078b6312f4dcc1efe7975731b6c47dd134282bd9acEric W. Biederman	struct tty_struct *tty;
13088b6312f4dcc1efe7975731b6c47dd134282bd9acEric W. Biederman
1309ac751efa6a0d70f2c9daef5c7e3a92270f5c2dffTorben Hohn	console_lock();
13108b6312f4dcc1efe7975731b6c47dd134282bd9acEric W. Biederman	vc = vc_con->d;
13118b6312f4dcc1efe7975731b6c47dd134282bd9acEric W. Biederman	if (vc) {
13128ce73264b75be4d5ed480440ac32dfc1f25ff678Alan Cox		tty = vc->port.tty;
13138b6312f4dcc1efe7975731b6c47dd134282bd9acEric W. Biederman		/*
13148b6312f4dcc1efe7975731b6c47dd134282bd9acEric W. Biederman		 * SAK should also work in all raw modes and reset
13158b6312f4dcc1efe7975731b6c47dd134282bd9acEric W. Biederman		 * them properly.
13168b6312f4dcc1efe7975731b6c47dd134282bd9acEric W. Biederman		 */
13178b6312f4dcc1efe7975731b6c47dd134282bd9acEric W. Biederman		if (tty)
13188b6312f4dcc1efe7975731b6c47dd134282bd9acEric W. Biederman			__do_SAK(tty);
13198b6312f4dcc1efe7975731b6c47dd134282bd9acEric W. Biederman		reset_vc(vc);
13208b6312f4dcc1efe7975731b6c47dd134282bd9acEric W. Biederman	}
1321ac751efa6a0d70f2c9daef5c7e3a92270f5c2dffTorben Hohn	console_unlock();
13228b6312f4dcc1efe7975731b6c47dd134282bd9acEric W. Biederman}
13238b6312f4dcc1efe7975731b6c47dd134282bd9acEric W. Biederman
1324e92166517e3ca9bfb416f91e69cf0373b55b6edeArnd Bergmann#ifdef CONFIG_COMPAT
1325e92166517e3ca9bfb416f91e69cf0373b55b6edeArnd Bergmann
1326e92166517e3ca9bfb416f91e69cf0373b55b6edeArnd Bergmannstruct compat_consolefontdesc {
1327e92166517e3ca9bfb416f91e69cf0373b55b6edeArnd Bergmann	unsigned short charcount;       /* characters in font (256 or 512) */
1328e92166517e3ca9bfb416f91e69cf0373b55b6edeArnd Bergmann	unsigned short charheight;      /* scan lines per character (1-32) */
1329e92166517e3ca9bfb416f91e69cf0373b55b6edeArnd Bergmann	compat_caddr_t chardata;	/* font data in expanded form */
1330e92166517e3ca9bfb416f91e69cf0373b55b6edeArnd Bergmann};
1331e92166517e3ca9bfb416f91e69cf0373b55b6edeArnd Bergmann
1332e92166517e3ca9bfb416f91e69cf0373b55b6edeArnd Bergmannstatic inline int
1333e92166517e3ca9bfb416f91e69cf0373b55b6edeArnd Bergmanncompat_fontx_ioctl(int cmd, struct compat_consolefontdesc __user *user_cfd,
1334e92166517e3ca9bfb416f91e69cf0373b55b6edeArnd Bergmann			 int perm, struct console_font_op *op)
1335e92166517e3ca9bfb416f91e69cf0373b55b6edeArnd Bergmann{
1336e92166517e3ca9bfb416f91e69cf0373b55b6edeArnd Bergmann	struct compat_consolefontdesc cfdarg;
1337e92166517e3ca9bfb416f91e69cf0373b55b6edeArnd Bergmann	int i;
1338e92166517e3ca9bfb416f91e69cf0373b55b6edeArnd Bergmann
1339e92166517e3ca9bfb416f91e69cf0373b55b6edeArnd Bergmann	if (copy_from_user(&cfdarg, user_cfd, sizeof(struct compat_consolefontdesc)))
1340e92166517e3ca9bfb416f91e69cf0373b55b6edeArnd Bergmann		return -EFAULT;
1341e92166517e3ca9bfb416f91e69cf0373b55b6edeArnd Bergmann
1342e92166517e3ca9bfb416f91e69cf0373b55b6edeArnd Bergmann	switch (cmd) {
1343e92166517e3ca9bfb416f91e69cf0373b55b6edeArnd Bergmann	case PIO_FONTX:
1344e92166517e3ca9bfb416f91e69cf0373b55b6edeArnd Bergmann		if (!perm)
1345e92166517e3ca9bfb416f91e69cf0373b55b6edeArnd Bergmann			return -EPERM;
1346e92166517e3ca9bfb416f91e69cf0373b55b6edeArnd Bergmann		op->op = KD_FONT_OP_SET;
1347e92166517e3ca9bfb416f91e69cf0373b55b6edeArnd Bergmann		op->flags = KD_FONT_FLAG_OLD;
1348e92166517e3ca9bfb416f91e69cf0373b55b6edeArnd Bergmann		op->width = 8;
1349e92166517e3ca9bfb416f91e69cf0373b55b6edeArnd Bergmann		op->height = cfdarg.charheight;
1350e92166517e3ca9bfb416f91e69cf0373b55b6edeArnd Bergmann		op->charcount = cfdarg.charcount;
1351e92166517e3ca9bfb416f91e69cf0373b55b6edeArnd Bergmann		op->data = compat_ptr(cfdarg.chardata);
1352e92166517e3ca9bfb416f91e69cf0373b55b6edeArnd Bergmann		return con_font_op(vc_cons[fg_console].d, op);
1353e92166517e3ca9bfb416f91e69cf0373b55b6edeArnd Bergmann	case GIO_FONTX:
1354e92166517e3ca9bfb416f91e69cf0373b55b6edeArnd Bergmann		op->op = KD_FONT_OP_GET;
1355e92166517e3ca9bfb416f91e69cf0373b55b6edeArnd Bergmann		op->flags = KD_FONT_FLAG_OLD;
1356e92166517e3ca9bfb416f91e69cf0373b55b6edeArnd Bergmann		op->width = 8;
1357e92166517e3ca9bfb416f91e69cf0373b55b6edeArnd Bergmann		op->height = cfdarg.charheight;
1358e92166517e3ca9bfb416f91e69cf0373b55b6edeArnd Bergmann		op->charcount = cfdarg.charcount;
1359e92166517e3ca9bfb416f91e69cf0373b55b6edeArnd Bergmann		op->data = compat_ptr(cfdarg.chardata);
1360e92166517e3ca9bfb416f91e69cf0373b55b6edeArnd Bergmann		i = con_font_op(vc_cons[fg_console].d, op);
1361e92166517e3ca9bfb416f91e69cf0373b55b6edeArnd Bergmann		if (i)
1362e92166517e3ca9bfb416f91e69cf0373b55b6edeArnd Bergmann			return i;
1363e92166517e3ca9bfb416f91e69cf0373b55b6edeArnd Bergmann		cfdarg.charheight = op->height;
1364e92166517e3ca9bfb416f91e69cf0373b55b6edeArnd Bergmann		cfdarg.charcount = op->charcount;
1365e92166517e3ca9bfb416f91e69cf0373b55b6edeArnd Bergmann		if (copy_to_user(user_cfd, &cfdarg, sizeof(struct compat_consolefontdesc)))
1366e92166517e3ca9bfb416f91e69cf0373b55b6edeArnd Bergmann			return -EFAULT;
1367e92166517e3ca9bfb416f91e69cf0373b55b6edeArnd Bergmann		return 0;
1368e92166517e3ca9bfb416f91e69cf0373b55b6edeArnd Bergmann	}
1369e92166517e3ca9bfb416f91e69cf0373b55b6edeArnd Bergmann	return -EINVAL;
1370e92166517e3ca9bfb416f91e69cf0373b55b6edeArnd Bergmann}
1371e92166517e3ca9bfb416f91e69cf0373b55b6edeArnd Bergmann
1372e92166517e3ca9bfb416f91e69cf0373b55b6edeArnd Bergmannstruct compat_console_font_op {
1373e92166517e3ca9bfb416f91e69cf0373b55b6edeArnd Bergmann	compat_uint_t op;        /* operation code KD_FONT_OP_* */
1374e92166517e3ca9bfb416f91e69cf0373b55b6edeArnd Bergmann	compat_uint_t flags;     /* KD_FONT_FLAG_* */
1375e92166517e3ca9bfb416f91e69cf0373b55b6edeArnd Bergmann	compat_uint_t width, height;     /* font size */
1376e92166517e3ca9bfb416f91e69cf0373b55b6edeArnd Bergmann	compat_uint_t charcount;
1377e92166517e3ca9bfb416f91e69cf0373b55b6edeArnd Bergmann	compat_caddr_t data;    /* font data with height fixed to 32 */
1378e92166517e3ca9bfb416f91e69cf0373b55b6edeArnd Bergmann};
1379e92166517e3ca9bfb416f91e69cf0373b55b6edeArnd Bergmann
1380e92166517e3ca9bfb416f91e69cf0373b55b6edeArnd Bergmannstatic inline int
1381e92166517e3ca9bfb416f91e69cf0373b55b6edeArnd Bergmanncompat_kdfontop_ioctl(struct compat_console_font_op __user *fontop,
1382e92166517e3ca9bfb416f91e69cf0373b55b6edeArnd Bergmann			 int perm, struct console_font_op *op, struct vc_data *vc)
1383e92166517e3ca9bfb416f91e69cf0373b55b6edeArnd Bergmann{
1384e92166517e3ca9bfb416f91e69cf0373b55b6edeArnd Bergmann	int i;
1385e92166517e3ca9bfb416f91e69cf0373b55b6edeArnd Bergmann
1386e92166517e3ca9bfb416f91e69cf0373b55b6edeArnd Bergmann	if (copy_from_user(op, fontop, sizeof(struct compat_console_font_op)))
1387e92166517e3ca9bfb416f91e69cf0373b55b6edeArnd Bergmann		return -EFAULT;
1388e92166517e3ca9bfb416f91e69cf0373b55b6edeArnd Bergmann	if (!perm && op->op != KD_FONT_OP_GET)
1389e92166517e3ca9bfb416f91e69cf0373b55b6edeArnd Bergmann		return -EPERM;
1390e92166517e3ca9bfb416f91e69cf0373b55b6edeArnd Bergmann	op->data = compat_ptr(((struct compat_console_font_op *)op)->data);
1391e92166517e3ca9bfb416f91e69cf0373b55b6edeArnd Bergmann	i = con_font_op(vc, op);
1392e92166517e3ca9bfb416f91e69cf0373b55b6edeArnd Bergmann	if (i)
1393e92166517e3ca9bfb416f91e69cf0373b55b6edeArnd Bergmann		return i;
1394e92166517e3ca9bfb416f91e69cf0373b55b6edeArnd Bergmann	((struct compat_console_font_op *)op)->data = (unsigned long)op->data;
1395e92166517e3ca9bfb416f91e69cf0373b55b6edeArnd Bergmann	if (copy_to_user(fontop, op, sizeof(struct compat_console_font_op)))
1396e92166517e3ca9bfb416f91e69cf0373b55b6edeArnd Bergmann		return -EFAULT;
1397e92166517e3ca9bfb416f91e69cf0373b55b6edeArnd Bergmann	return 0;
1398e92166517e3ca9bfb416f91e69cf0373b55b6edeArnd Bergmann}
1399e92166517e3ca9bfb416f91e69cf0373b55b6edeArnd Bergmann
1400e92166517e3ca9bfb416f91e69cf0373b55b6edeArnd Bergmannstruct compat_unimapdesc {
1401e92166517e3ca9bfb416f91e69cf0373b55b6edeArnd Bergmann	unsigned short entry_ct;
1402e92166517e3ca9bfb416f91e69cf0373b55b6edeArnd Bergmann	compat_caddr_t entries;
1403e92166517e3ca9bfb416f91e69cf0373b55b6edeArnd Bergmann};
1404e92166517e3ca9bfb416f91e69cf0373b55b6edeArnd Bergmann
1405e92166517e3ca9bfb416f91e69cf0373b55b6edeArnd Bergmannstatic inline int
1406e92166517e3ca9bfb416f91e69cf0373b55b6edeArnd Bergmanncompat_unimap_ioctl(unsigned int cmd, struct compat_unimapdesc __user *user_ud,
1407e92166517e3ca9bfb416f91e69cf0373b55b6edeArnd Bergmann			 int perm, struct vc_data *vc)
1408e92166517e3ca9bfb416f91e69cf0373b55b6edeArnd Bergmann{
1409e92166517e3ca9bfb416f91e69cf0373b55b6edeArnd Bergmann	struct compat_unimapdesc tmp;
1410e92166517e3ca9bfb416f91e69cf0373b55b6edeArnd Bergmann	struct unipair __user *tmp_entries;
1411e92166517e3ca9bfb416f91e69cf0373b55b6edeArnd Bergmann
1412e92166517e3ca9bfb416f91e69cf0373b55b6edeArnd Bergmann	if (copy_from_user(&tmp, user_ud, sizeof tmp))
1413e92166517e3ca9bfb416f91e69cf0373b55b6edeArnd Bergmann		return -EFAULT;
1414e92166517e3ca9bfb416f91e69cf0373b55b6edeArnd Bergmann	tmp_entries = compat_ptr(tmp.entries);
1415e92166517e3ca9bfb416f91e69cf0373b55b6edeArnd Bergmann	if (tmp_entries)
1416e92166517e3ca9bfb416f91e69cf0373b55b6edeArnd Bergmann		if (!access_ok(VERIFY_WRITE, tmp_entries,
1417e92166517e3ca9bfb416f91e69cf0373b55b6edeArnd Bergmann				tmp.entry_ct*sizeof(struct unipair)))
1418e92166517e3ca9bfb416f91e69cf0373b55b6edeArnd Bergmann			return -EFAULT;
1419e92166517e3ca9bfb416f91e69cf0373b55b6edeArnd Bergmann	switch (cmd) {
1420e92166517e3ca9bfb416f91e69cf0373b55b6edeArnd Bergmann	case PIO_UNIMAP:
1421e92166517e3ca9bfb416f91e69cf0373b55b6edeArnd Bergmann		if (!perm)
1422e92166517e3ca9bfb416f91e69cf0373b55b6edeArnd Bergmann			return -EPERM;
1423e92166517e3ca9bfb416f91e69cf0373b55b6edeArnd Bergmann		return con_set_unimap(vc, tmp.entry_ct, tmp_entries);
1424e92166517e3ca9bfb416f91e69cf0373b55b6edeArnd Bergmann	case GIO_UNIMAP:
1425e92166517e3ca9bfb416f91e69cf0373b55b6edeArnd Bergmann		if (!perm && fg_console != vc->vc_num)
1426e92166517e3ca9bfb416f91e69cf0373b55b6edeArnd Bergmann			return -EPERM;
1427e92166517e3ca9bfb416f91e69cf0373b55b6edeArnd Bergmann		return con_get_unimap(vc, tmp.entry_ct, &(user_ud->entry_ct), tmp_entries);
1428e92166517e3ca9bfb416f91e69cf0373b55b6edeArnd Bergmann	}
1429e92166517e3ca9bfb416f91e69cf0373b55b6edeArnd Bergmann	return 0;
1430e92166517e3ca9bfb416f91e69cf0373b55b6edeArnd Bergmann}
1431e92166517e3ca9bfb416f91e69cf0373b55b6edeArnd Bergmann
14326caa76b7786891b42b66a0e61e2c2fff2c884620Alan Coxlong vt_compat_ioctl(struct tty_struct *tty,
1433e92166517e3ca9bfb416f91e69cf0373b55b6edeArnd Bergmann	     unsigned int cmd, unsigned long arg)
1434e92166517e3ca9bfb416f91e69cf0373b55b6edeArnd Bergmann{
1435e92166517e3ca9bfb416f91e69cf0373b55b6edeArnd Bergmann	struct vc_data *vc = tty->driver_data;
1436e92166517e3ca9bfb416f91e69cf0373b55b6edeArnd Bergmann	struct console_font_op op;	/* used in multiple places here */
1437e92166517e3ca9bfb416f91e69cf0373b55b6edeArnd Bergmann	unsigned int console;
1438e92166517e3ca9bfb416f91e69cf0373b55b6edeArnd Bergmann	void __user *up = (void __user *)arg;
1439e92166517e3ca9bfb416f91e69cf0373b55b6edeArnd Bergmann	int perm;
1440e92166517e3ca9bfb416f91e69cf0373b55b6edeArnd Bergmann	int ret = 0;
1441e92166517e3ca9bfb416f91e69cf0373b55b6edeArnd Bergmann
1442e92166517e3ca9bfb416f91e69cf0373b55b6edeArnd Bergmann	console = vc->vc_num;
1443e92166517e3ca9bfb416f91e69cf0373b55b6edeArnd Bergmann
1444ec79d6056de58511d8e46d9ae59d3878f958dc3eArnd Bergmann	tty_lock();
1445e92166517e3ca9bfb416f91e69cf0373b55b6edeArnd Bergmann
1446e92166517e3ca9bfb416f91e69cf0373b55b6edeArnd Bergmann	if (!vc_cons_allocated(console)) { 	/* impossible? */
1447e92166517e3ca9bfb416f91e69cf0373b55b6edeArnd Bergmann		ret = -ENOIOCTLCMD;
1448e92166517e3ca9bfb416f91e69cf0373b55b6edeArnd Bergmann		goto out;
1449e92166517e3ca9bfb416f91e69cf0373b55b6edeArnd Bergmann	}
1450e92166517e3ca9bfb416f91e69cf0373b55b6edeArnd Bergmann
1451e92166517e3ca9bfb416f91e69cf0373b55b6edeArnd Bergmann	/*
1452e92166517e3ca9bfb416f91e69cf0373b55b6edeArnd Bergmann	 * To have permissions to do most of the vt ioctls, we either have
1453e92166517e3ca9bfb416f91e69cf0373b55b6edeArnd Bergmann	 * to be the owner of the tty, or have CAP_SYS_TTY_CONFIG.
1454e92166517e3ca9bfb416f91e69cf0373b55b6edeArnd Bergmann	 */
1455e92166517e3ca9bfb416f91e69cf0373b55b6edeArnd Bergmann	perm = 0;
1456e92166517e3ca9bfb416f91e69cf0373b55b6edeArnd Bergmann	if (current->signal->tty == tty || capable(CAP_SYS_TTY_CONFIG))
1457e92166517e3ca9bfb416f91e69cf0373b55b6edeArnd Bergmann		perm = 1;
1458e92166517e3ca9bfb416f91e69cf0373b55b6edeArnd Bergmann
1459e92166517e3ca9bfb416f91e69cf0373b55b6edeArnd Bergmann	switch (cmd) {
1460e92166517e3ca9bfb416f91e69cf0373b55b6edeArnd Bergmann	/*
1461e92166517e3ca9bfb416f91e69cf0373b55b6edeArnd Bergmann	 * these need special handlers for incompatible data structures
1462e92166517e3ca9bfb416f91e69cf0373b55b6edeArnd Bergmann	 */
1463e92166517e3ca9bfb416f91e69cf0373b55b6edeArnd Bergmann	case PIO_FONTX:
1464e92166517e3ca9bfb416f91e69cf0373b55b6edeArnd Bergmann	case GIO_FONTX:
1465e92166517e3ca9bfb416f91e69cf0373b55b6edeArnd Bergmann		ret = compat_fontx_ioctl(cmd, up, perm, &op);
1466e92166517e3ca9bfb416f91e69cf0373b55b6edeArnd Bergmann		break;
1467e92166517e3ca9bfb416f91e69cf0373b55b6edeArnd Bergmann
1468e92166517e3ca9bfb416f91e69cf0373b55b6edeArnd Bergmann	case KDFONTOP:
1469e92166517e3ca9bfb416f91e69cf0373b55b6edeArnd Bergmann		ret = compat_kdfontop_ioctl(up, perm, &op, vc);
1470e92166517e3ca9bfb416f91e69cf0373b55b6edeArnd Bergmann		break;
1471e92166517e3ca9bfb416f91e69cf0373b55b6edeArnd Bergmann
1472e92166517e3ca9bfb416f91e69cf0373b55b6edeArnd Bergmann	case PIO_UNIMAP:
1473e92166517e3ca9bfb416f91e69cf0373b55b6edeArnd Bergmann	case GIO_UNIMAP:
14744b1fe7797270e866adc17fc603bddf8768bc187fAndreas Schwab		ret = compat_unimap_ioctl(cmd, up, perm, vc);
1475e92166517e3ca9bfb416f91e69cf0373b55b6edeArnd Bergmann		break;
1476e92166517e3ca9bfb416f91e69cf0373b55b6edeArnd Bergmann
1477e92166517e3ca9bfb416f91e69cf0373b55b6edeArnd Bergmann	/*
1478e92166517e3ca9bfb416f91e69cf0373b55b6edeArnd Bergmann	 * all these treat 'arg' as an integer
1479e92166517e3ca9bfb416f91e69cf0373b55b6edeArnd Bergmann	 */
1480e92166517e3ca9bfb416f91e69cf0373b55b6edeArnd Bergmann	case KIOCSOUND:
1481e92166517e3ca9bfb416f91e69cf0373b55b6edeArnd Bergmann	case KDMKTONE:
1482e92166517e3ca9bfb416f91e69cf0373b55b6edeArnd Bergmann#ifdef CONFIG_X86
1483e92166517e3ca9bfb416f91e69cf0373b55b6edeArnd Bergmann	case KDADDIO:
1484e92166517e3ca9bfb416f91e69cf0373b55b6edeArnd Bergmann	case KDDELIO:
1485e92166517e3ca9bfb416f91e69cf0373b55b6edeArnd Bergmann#endif
1486e92166517e3ca9bfb416f91e69cf0373b55b6edeArnd Bergmann	case KDSETMODE:
1487e92166517e3ca9bfb416f91e69cf0373b55b6edeArnd Bergmann	case KDMAPDISP:
1488e92166517e3ca9bfb416f91e69cf0373b55b6edeArnd Bergmann	case KDUNMAPDISP:
1489e92166517e3ca9bfb416f91e69cf0373b55b6edeArnd Bergmann	case KDSKBMODE:
1490e92166517e3ca9bfb416f91e69cf0373b55b6edeArnd Bergmann	case KDSKBMETA:
1491e92166517e3ca9bfb416f91e69cf0373b55b6edeArnd Bergmann	case KDSKBLED:
1492e92166517e3ca9bfb416f91e69cf0373b55b6edeArnd Bergmann	case KDSETLED:
1493e92166517e3ca9bfb416f91e69cf0373b55b6edeArnd Bergmann	case KDSIGACCEPT:
1494e92166517e3ca9bfb416f91e69cf0373b55b6edeArnd Bergmann	case VT_ACTIVATE:
1495e92166517e3ca9bfb416f91e69cf0373b55b6edeArnd Bergmann	case VT_WAITACTIVE:
1496e92166517e3ca9bfb416f91e69cf0373b55b6edeArnd Bergmann	case VT_RELDISP:
1497e92166517e3ca9bfb416f91e69cf0373b55b6edeArnd Bergmann	case VT_DISALLOCATE:
1498e92166517e3ca9bfb416f91e69cf0373b55b6edeArnd Bergmann	case VT_RESIZE:
1499e92166517e3ca9bfb416f91e69cf0373b55b6edeArnd Bergmann	case VT_RESIZEX:
1500e92166517e3ca9bfb416f91e69cf0373b55b6edeArnd Bergmann		goto fallback;
1501e92166517e3ca9bfb416f91e69cf0373b55b6edeArnd Bergmann
1502e92166517e3ca9bfb416f91e69cf0373b55b6edeArnd Bergmann	/*
1503e92166517e3ca9bfb416f91e69cf0373b55b6edeArnd Bergmann	 * the rest has a compatible data structure behind arg,
1504e92166517e3ca9bfb416f91e69cf0373b55b6edeArnd Bergmann	 * but we have to convert it to a proper 64 bit pointer.
1505e92166517e3ca9bfb416f91e69cf0373b55b6edeArnd Bergmann	 */
1506e92166517e3ca9bfb416f91e69cf0373b55b6edeArnd Bergmann	default:
1507e92166517e3ca9bfb416f91e69cf0373b55b6edeArnd Bergmann		arg = (unsigned long)compat_ptr(arg);
1508e92166517e3ca9bfb416f91e69cf0373b55b6edeArnd Bergmann		goto fallback;
1509e92166517e3ca9bfb416f91e69cf0373b55b6edeArnd Bergmann	}
1510e92166517e3ca9bfb416f91e69cf0373b55b6edeArnd Bergmannout:
1511ec79d6056de58511d8e46d9ae59d3878f958dc3eArnd Bergmann	tty_unlock();
1512e92166517e3ca9bfb416f91e69cf0373b55b6edeArnd Bergmann	return ret;
1513e92166517e3ca9bfb416f91e69cf0373b55b6edeArnd Bergmann
1514e92166517e3ca9bfb416f91e69cf0373b55b6edeArnd Bergmannfallback:
1515ec79d6056de58511d8e46d9ae59d3878f958dc3eArnd Bergmann	tty_unlock();
15166caa76b7786891b42b66a0e61e2c2fff2c884620Alan Cox	return vt_ioctl(tty, cmd, arg);
1517e92166517e3ca9bfb416f91e69cf0373b55b6edeArnd Bergmann}
1518e92166517e3ca9bfb416f91e69cf0373b55b6edeArnd Bergmann
1519e92166517e3ca9bfb416f91e69cf0373b55b6edeArnd Bergmann
1520e92166517e3ca9bfb416f91e69cf0373b55b6edeArnd Bergmann#endif /* CONFIG_COMPAT */
1521e92166517e3ca9bfb416f91e69cf0373b55b6edeArnd Bergmann
1522e92166517e3ca9bfb416f91e69cf0373b55b6edeArnd Bergmann
15231da177e4c3f41524e886b7f1b8a0c1fc7321cacLinus Torvalds/*
1524d3b5cffcf84a8bdc7073dce4745d67c72629af85Alan Cox * Performs the back end of a vt switch. Called under the console
1525d3b5cffcf84a8bdc7073dce4745d67c72629af85Alan Cox * semaphore.
15261da177e4c3f41524e886b7f1b8a0c1fc7321cacLinus Torvalds */
15271da177e4c3f41524e886b7f1b8a0c1fc7321cacLinus Torvaldsstatic void complete_change_console(struct vc_data *vc)
15281da177e4c3f41524e886b7f1b8a0c1fc7321cacLinus Torvalds{
15291da177e4c3f41524e886b7f1b8a0c1fc7321cacLinus Torvalds	unsigned char old_vc_mode;
15308b92e87d39bfd046e7581e1fe0f40eac40f88608Alan Cox	int old = fg_console;
15311da177e4c3f41524e886b7f1b8a0c1fc7321cacLinus Torvalds
15321da177e4c3f41524e886b7f1b8a0c1fc7321cacLinus Torvalds	last_console = fg_console;
15331da177e4c3f41524e886b7f1b8a0c1fc7321cacLinus Torvalds
15341da177e4c3f41524e886b7f1b8a0c1fc7321cacLinus Torvalds	/*
15351da177e4c3f41524e886b7f1b8a0c1fc7321cacLinus Torvalds	 * If we're switching, we could be going from KD_GRAPHICS to
15361da177e4c3f41524e886b7f1b8a0c1fc7321cacLinus Torvalds	 * KD_TEXT mode or vice versa, which means we need to blank or
15371da177e4c3f41524e886b7f1b8a0c1fc7321cacLinus Torvalds	 * unblank the screen later.
15381da177e4c3f41524e886b7f1b8a0c1fc7321cacLinus Torvalds	 */
15391da177e4c3f41524e886b7f1b8a0c1fc7321cacLinus Torvalds	old_vc_mode = vc_cons[fg_console].d->vc_mode;
15401da177e4c3f41524e886b7f1b8a0c1fc7321cacLinus Torvalds	switch_screen(vc);
15411da177e4c3f41524e886b7f1b8a0c1fc7321cacLinus Torvalds
15421da177e4c3f41524e886b7f1b8a0c1fc7321cacLinus Torvalds	/*
15433dfcaf16135150d0f025047a7525664a41bb2adfEric W. Biederman	 * This can't appear below a successful kill_pid().  If it did,
15441da177e4c3f41524e886b7f1b8a0c1fc7321cacLinus Torvalds	 * then the *blank_screen operation could occur while X, having
15451da177e4c3f41524e886b7f1b8a0c1fc7321cacLinus Torvalds	 * received acqsig, is waking up on another processor.  This
15461da177e4c3f41524e886b7f1b8a0c1fc7321cacLinus Torvalds	 * condition can lead to overlapping accesses to the VGA range
15471da177e4c3f41524e886b7f1b8a0c1fc7321cacLinus Torvalds	 * and the framebuffer (causing system lockups).
15481da177e4c3f41524e886b7f1b8a0c1fc7321cacLinus Torvalds	 *
15491da177e4c3f41524e886b7f1b8a0c1fc7321cacLinus Torvalds	 * To account for this we duplicate this code below only if the
15501da177e4c3f41524e886b7f1b8a0c1fc7321cacLinus Torvalds	 * controlling process is gone and we've called reset_vc.
15511da177e4c3f41524e886b7f1b8a0c1fc7321cacLinus Torvalds	 */
15521da177e4c3f41524e886b7f1b8a0c1fc7321cacLinus Torvalds	if (old_vc_mode != vc->vc_mode) {
15531da177e4c3f41524e886b7f1b8a0c1fc7321cacLinus Torvalds		if (vc->vc_mode == KD_TEXT)
15541da177e4c3f41524e886b7f1b8a0c1fc7321cacLinus Torvalds			do_unblank_screen(1);
15551da177e4c3f41524e886b7f1b8a0c1fc7321cacLinus Torvalds		else
15561da177e4c3f41524e886b7f1b8a0c1fc7321cacLinus Torvalds			do_blank_screen(1);
15571da177e4c3f41524e886b7f1b8a0c1fc7321cacLinus Torvalds	}
15581da177e4c3f41524e886b7f1b8a0c1fc7321cacLinus Torvalds
15591da177e4c3f41524e886b7f1b8a0c1fc7321cacLinus Torvalds	/*
15601da177e4c3f41524e886b7f1b8a0c1fc7321cacLinus Torvalds	 * If this new console is under process control, send it a signal
15611da177e4c3f41524e886b7f1b8a0c1fc7321cacLinus Torvalds	 * telling it that it has acquired. Also check if it has died and
15621da177e4c3f41524e886b7f1b8a0c1fc7321cacLinus Torvalds	 * clean up (similar to logic employed in change_console())
15631da177e4c3f41524e886b7f1b8a0c1fc7321cacLinus Torvalds	 */
156487a6aca504d65f242589583e04df5e74b5eae1feGreg Kroah-Hartman	if (vc->vt_mode.mode == VT_PROCESS) {
15651da177e4c3f41524e886b7f1b8a0c1fc7321cacLinus Torvalds		/*
15663dfcaf16135150d0f025047a7525664a41bb2adfEric W. Biederman		 * Send the signal as privileged - kill_pid() will
15671da177e4c3f41524e886b7f1b8a0c1fc7321cacLinus Torvalds		 * tell us if the process has gone or something else
15681da177e4c3f41524e886b7f1b8a0c1fc7321cacLinus Torvalds		 * is awry
15691da177e4c3f41524e886b7f1b8a0c1fc7321cacLinus Torvalds		 */
1570bde0d2c98bcfc9acc83ac79c33a6ac1335b95a92Eric W. Biederman		if (kill_pid(vc->vt_pid, vc->vt_mode.acqsig, 1) != 0) {
15711da177e4c3f41524e886b7f1b8a0c1fc7321cacLinus Torvalds		/*
15721da177e4c3f41524e886b7f1b8a0c1fc7321cacLinus Torvalds		 * The controlling process has died, so we revert back to
15731da177e4c3f41524e886b7f1b8a0c1fc7321cacLinus Torvalds		 * normal operation. In this case, we'll also change back
15741da177e4c3f41524e886b7f1b8a0c1fc7321cacLinus Torvalds		 * to KD_TEXT mode. I'm not sure if this is strictly correct
15751da177e4c3f41524e886b7f1b8a0c1fc7321cacLinus Torvalds		 * but it saves the agony when the X server dies and the screen
15761da177e4c3f41524e886b7f1b8a0c1fc7321cacLinus Torvalds		 * remains blanked due to KD_GRAPHICS! It would be nice to do
15771da177e4c3f41524e886b7f1b8a0c1fc7321cacLinus Torvalds		 * this outside of VT_PROCESS but there is no single process
15781da177e4c3f41524e886b7f1b8a0c1fc7321cacLinus Torvalds		 * to account for and tracking tty count may be undesirable.
15791da177e4c3f41524e886b7f1b8a0c1fc7321cacLinus Torvalds		 */
15801da177e4c3f41524e886b7f1b8a0c1fc7321cacLinus Torvalds			reset_vc(vc);
15811da177e4c3f41524e886b7f1b8a0c1fc7321cacLinus Torvalds
15821da177e4c3f41524e886b7f1b8a0c1fc7321cacLinus Torvalds			if (old_vc_mode != vc->vc_mode) {
15831da177e4c3f41524e886b7f1b8a0c1fc7321cacLinus Torvalds				if (vc->vc_mode == KD_TEXT)
15841da177e4c3f41524e886b7f1b8a0c1fc7321cacLinus Torvalds					do_unblank_screen(1);
15851da177e4c3f41524e886b7f1b8a0c1fc7321cacLinus Torvalds				else
15861da177e4c3f41524e886b7f1b8a0c1fc7321cacLinus Torvalds					do_blank_screen(1);
15871da177e4c3f41524e886b7f1b8a0c1fc7321cacLinus Torvalds			}
15881da177e4c3f41524e886b7f1b8a0c1fc7321cacLinus Torvalds		}
15891da177e4c3f41524e886b7f1b8a0c1fc7321cacLinus Torvalds	}
15901da177e4c3f41524e886b7f1b8a0c1fc7321cacLinus Torvalds
15911da177e4c3f41524e886b7f1b8a0c1fc7321cacLinus Torvalds	/*
15921da177e4c3f41524e886b7f1b8a0c1fc7321cacLinus Torvalds	 * Wake anyone waiting for their VT to activate
15931da177e4c3f41524e886b7f1b8a0c1fc7321cacLinus Torvalds	 */
15948b92e87d39bfd046e7581e1fe0f40eac40f88608Alan Cox	vt_event_post(VT_EVENT_SWITCH, old, vc->vc_num);
15951da177e4c3f41524e886b7f1b8a0c1fc7321cacLinus Torvalds	return;
15961da177e4c3f41524e886b7f1b8a0c1fc7321cacLinus Torvalds}
15971da177e4c3f41524e886b7f1b8a0c1fc7321cacLinus Torvalds
15981da177e4c3f41524e886b7f1b8a0c1fc7321cacLinus Torvalds/*
15991da177e4c3f41524e886b7f1b8a0c1fc7321cacLinus Torvalds * Performs the front-end of a vt switch
16001da177e4c3f41524e886b7f1b8a0c1fc7321cacLinus Torvalds */
16011da177e4c3f41524e886b7f1b8a0c1fc7321cacLinus Torvaldsvoid change_console(struct vc_data *new_vc)
16021da177e4c3f41524e886b7f1b8a0c1fc7321cacLinus Torvalds{
16031da177e4c3f41524e886b7f1b8a0c1fc7321cacLinus Torvalds	struct vc_data *vc;
16041da177e4c3f41524e886b7f1b8a0c1fc7321cacLinus Torvalds
16051da177e4c3f41524e886b7f1b8a0c1fc7321cacLinus Torvalds	if (!new_vc || new_vc->vc_num == fg_console || vt_dont_switch)
16061da177e4c3f41524e886b7f1b8a0c1fc7321cacLinus Torvalds		return;
16071da177e4c3f41524e886b7f1b8a0c1fc7321cacLinus Torvalds
16081da177e4c3f41524e886b7f1b8a0c1fc7321cacLinus Torvalds	/*
16091da177e4c3f41524e886b7f1b8a0c1fc7321cacLinus Torvalds	 * If this vt is in process mode, then we need to handshake with
16101da177e4c3f41524e886b7f1b8a0c1fc7321cacLinus Torvalds	 * that process before switching. Essentially, we store where that
16111da177e4c3f41524e886b7f1b8a0c1fc7321cacLinus Torvalds	 * vt wants to switch to and wait for it to tell us when it's done
16121da177e4c3f41524e886b7f1b8a0c1fc7321cacLinus Torvalds	 * (via VT_RELDISP ioctl).
16131da177e4c3f41524e886b7f1b8a0c1fc7321cacLinus Torvalds	 *
16141da177e4c3f41524e886b7f1b8a0c1fc7321cacLinus Torvalds	 * We also check to see if the controlling process still exists.
16151da177e4c3f41524e886b7f1b8a0c1fc7321cacLinus Torvalds	 * If it doesn't, we reset this vt to auto mode and continue.
16161da177e4c3f41524e886b7f1b8a0c1fc7321cacLinus Torvalds	 * This is a cheap way to track process control. The worst thing
16171da177e4c3f41524e886b7f1b8a0c1fc7321cacLinus Torvalds	 * that can happen is: we send a signal to a process, it dies, and
16181da177e4c3f41524e886b7f1b8a0c1fc7321cacLinus Torvalds	 * the switch gets "lost" waiting for a response; hopefully, the
16191da177e4c3f41524e886b7f1b8a0c1fc7321cacLinus Torvalds	 * user will try again, we'll detect the process is gone (unless
16201da177e4c3f41524e886b7f1b8a0c1fc7321cacLinus Torvalds	 * the user waits just the right amount of time :-) and revert the
16211da177e4c3f41524e886b7f1b8a0c1fc7321cacLinus Torvalds	 * vt to auto control.
16221da177e4c3f41524e886b7f1b8a0c1fc7321cacLinus Torvalds	 */
16231da177e4c3f41524e886b7f1b8a0c1fc7321cacLinus Torvalds	vc = vc_cons[fg_console].d;
162487a6aca504d65f242589583e04df5e74b5eae1feGreg Kroah-Hartman	if (vc->vt_mode.mode == VT_PROCESS) {
16251da177e4c3f41524e886b7f1b8a0c1fc7321cacLinus Torvalds		/*
16263dfcaf16135150d0f025047a7525664a41bb2adfEric W. Biederman		 * Send the signal as privileged - kill_pid() will
16271da177e4c3f41524e886b7f1b8a0c1fc7321cacLinus Torvalds		 * tell us if the process has gone or something else
1628a64314e62d89562b6fc77593648bec3acc35bf61Jan Lübbe		 * is awry.
1629a64314e62d89562b6fc77593648bec3acc35bf61Jan Lübbe		 *
1630a64314e62d89562b6fc77593648bec3acc35bf61Jan Lübbe		 * We need to set vt_newvt *before* sending the signal or we
1631a64314e62d89562b6fc77593648bec3acc35bf61Jan Lübbe		 * have a race.
16321da177e4c3f41524e886b7f1b8a0c1fc7321cacLinus Torvalds		 */
1633a64314e62d89562b6fc77593648bec3acc35bf61Jan Lübbe		vc->vt_newvt = new_vc->vc_num;
1634bde0d2c98bcfc9acc83ac79c33a6ac1335b95a92Eric W. Biederman		if (kill_pid(vc->vt_pid, vc->vt_mode.relsig, 1) == 0) {
16351da177e4c3f41524e886b7f1b8a0c1fc7321cacLinus Torvalds			/*
163687a6aca504d65f242589583e04df5e74b5eae1feGreg Kroah-Hartman			 * It worked. Mark the vt to switch to and
163787a6aca504d65f242589583e04df5e74b5eae1feGreg Kroah-Hartman			 * return. The process needs to send us a
163887a6aca504d65f242589583e04df5e74b5eae1feGreg Kroah-Hartman			 * VT_RELDISP ioctl to complete the switch.
16391da177e4c3f41524e886b7f1b8a0c1fc7321cacLinus Torvalds			 */
164087a6aca504d65f242589583e04df5e74b5eae1feGreg Kroah-Hartman			return;
16411da177e4c3f41524e886b7f1b8a0c1fc7321cacLinus Torvalds		}
16421da177e4c3f41524e886b7f1b8a0c1fc7321cacLinus Torvalds
16431da177e4c3f41524e886b7f1b8a0c1fc7321cacLinus Torvalds		/*
164487a6aca504d65f242589583e04df5e74b5eae1feGreg Kroah-Hartman		 * The controlling process has died, so we revert back to
164587a6aca504d65f242589583e04df5e74b5eae1feGreg Kroah-Hartman		 * normal operation. In this case, we'll also change back
164687a6aca504d65f242589583e04df5e74b5eae1feGreg Kroah-Hartman		 * to KD_TEXT mode. I'm not sure if this is strictly correct
164787a6aca504d65f242589583e04df5e74b5eae1feGreg Kroah-Hartman		 * but it saves the agony when the X server dies and the screen
164887a6aca504d65f242589583e04df5e74b5eae1feGreg Kroah-Hartman		 * remains blanked due to KD_GRAPHICS! It would be nice to do
164987a6aca504d65f242589583e04df5e74b5eae1feGreg Kroah-Hartman		 * this outside of VT_PROCESS but there is no single process
165087a6aca504d65f242589583e04df5e74b5eae1feGreg Kroah-Hartman		 * to account for and tracking tty count may be undesirable.
165187a6aca504d65f242589583e04df5e74b5eae1feGreg Kroah-Hartman		 */
165287a6aca504d65f242589583e04df5e74b5eae1feGreg Kroah-Hartman		reset_vc(vc);
165387a6aca504d65f242589583e04df5e74b5eae1feGreg Kroah-Hartman
165487a6aca504d65f242589583e04df5e74b5eae1feGreg Kroah-Hartman		/*
165587a6aca504d65f242589583e04df5e74b5eae1feGreg Kroah-Hartman		 * Fall through to normal (VT_AUTO) handling of the switch...
16561da177e4c3f41524e886b7f1b8a0c1fc7321cacLinus Torvalds		 */
16571da177e4c3f41524e886b7f1b8a0c1fc7321cacLinus Torvalds	}
16581da177e4c3f41524e886b7f1b8a0c1fc7321cacLinus Torvalds
16591da177e4c3f41524e886b7f1b8a0c1fc7321cacLinus Torvalds	/*
16601da177e4c3f41524e886b7f1b8a0c1fc7321cacLinus Torvalds	 * Ignore all switches in KD_GRAPHICS+VT_AUTO mode
16611da177e4c3f41524e886b7f1b8a0c1fc7321cacLinus Torvalds	 */
16621da177e4c3f41524e886b7f1b8a0c1fc7321cacLinus Torvalds	if (vc->vc_mode == KD_GRAPHICS)
16631da177e4c3f41524e886b7f1b8a0c1fc7321cacLinus Torvalds		return;
16641da177e4c3f41524e886b7f1b8a0c1fc7321cacLinus Torvalds
16651da177e4c3f41524e886b7f1b8a0c1fc7321cacLinus Torvalds	complete_change_console(new_vc);
16661da177e4c3f41524e886b7f1b8a0c1fc7321cacLinus Torvalds}
16678d233558cd99a888571bb5a88a74970879e0aba4Alan Cox
16688d233558cd99a888571bb5a88a74970879e0aba4Alan Cox/* Perform a kernel triggered VT switch for suspend/resume */
16698d233558cd99a888571bb5a88a74970879e0aba4Alan Cox
16708d233558cd99a888571bb5a88a74970879e0aba4Alan Coxstatic int disable_vt_switch;
16718d233558cd99a888571bb5a88a74970879e0aba4Alan Cox
16728d233558cd99a888571bb5a88a74970879e0aba4Alan Coxint vt_move_to_console(unsigned int vt, int alloc)
16738d233558cd99a888571bb5a88a74970879e0aba4Alan Cox{
16748d233558cd99a888571bb5a88a74970879e0aba4Alan Cox	int prev;
16758d233558cd99a888571bb5a88a74970879e0aba4Alan Cox
1676ac751efa6a0d70f2c9daef5c7e3a92270f5c2dffTorben Hohn	console_lock();
16778d233558cd99a888571bb5a88a74970879e0aba4Alan Cox	/* Graphics mode - up to X */
16788d233558cd99a888571bb5a88a74970879e0aba4Alan Cox	if (disable_vt_switch) {
1679ac751efa6a0d70f2c9daef5c7e3a92270f5c2dffTorben Hohn		console_unlock();
16808d233558cd99a888571bb5a88a74970879e0aba4Alan Cox		return 0;
16818d233558cd99a888571bb5a88a74970879e0aba4Alan Cox	}
16828d233558cd99a888571bb5a88a74970879e0aba4Alan Cox	prev = fg_console;
16838d233558cd99a888571bb5a88a74970879e0aba4Alan Cox
16848d233558cd99a888571bb5a88a74970879e0aba4Alan Cox	if (alloc && vc_allocate(vt)) {
16858d233558cd99a888571bb5a88a74970879e0aba4Alan Cox		/* we can't have a free VC for now. Too bad,
16868d233558cd99a888571bb5a88a74970879e0aba4Alan Cox		 * we don't want to mess the screen for now. */
1687ac751efa6a0d70f2c9daef5c7e3a92270f5c2dffTorben Hohn		console_unlock();
16888d233558cd99a888571bb5a88a74970879e0aba4Alan Cox		return -ENOSPC;
16898d233558cd99a888571bb5a88a74970879e0aba4Alan Cox	}
16908d233558cd99a888571bb5a88a74970879e0aba4Alan Cox
16918d233558cd99a888571bb5a88a74970879e0aba4Alan Cox	if (set_console(vt)) {
16928d233558cd99a888571bb5a88a74970879e0aba4Alan Cox		/*
16938d233558cd99a888571bb5a88a74970879e0aba4Alan Cox		 * We're unable to switch to the SUSPEND_CONSOLE.
16948d233558cd99a888571bb5a88a74970879e0aba4Alan Cox		 * Let the calling function know so it can decide
16958d233558cd99a888571bb5a88a74970879e0aba4Alan Cox		 * what to do.
16968d233558cd99a888571bb5a88a74970879e0aba4Alan Cox		 */
1697ac751efa6a0d70f2c9daef5c7e3a92270f5c2dffTorben Hohn		console_unlock();
16988d233558cd99a888571bb5a88a74970879e0aba4Alan Cox		return -EIO;
16998d233558cd99a888571bb5a88a74970879e0aba4Alan Cox	}
1700ac751efa6a0d70f2c9daef5c7e3a92270f5c2dffTorben Hohn	console_unlock();
1701be1bc2889a4db4961ef69f47fb471ecae9f23adeArnd Bergmann	tty_lock();
1702797938b5e33991dadf4dd9228b932cc69c3e905aJiri Slaby	if (vt_waitactive(vt + 1)) {
17038d233558cd99a888571bb5a88a74970879e0aba4Alan Cox		pr_debug("Suspend: Can't switch VCs.");
1704be1bc2889a4db4961ef69f47fb471ecae9f23adeArnd Bergmann		tty_unlock();
17058d233558cd99a888571bb5a88a74970879e0aba4Alan Cox		return -EINTR;
17068d233558cd99a888571bb5a88a74970879e0aba4Alan Cox	}
1707be1bc2889a4db4961ef69f47fb471ecae9f23adeArnd Bergmann	tty_unlock();
17088d233558cd99a888571bb5a88a74970879e0aba4Alan Cox	return prev;
17098d233558cd99a888571bb5a88a74970879e0aba4Alan Cox}
17108d233558cd99a888571bb5a88a74970879e0aba4Alan Cox
17118d233558cd99a888571bb5a88a74970879e0aba4Alan Cox/*
17128d233558cd99a888571bb5a88a74970879e0aba4Alan Cox * Normally during a suspend, we allocate a new console and switch to it.
17138d233558cd99a888571bb5a88a74970879e0aba4Alan Cox * When we resume, we switch back to the original console.  This switch
17148d233558cd99a888571bb5a88a74970879e0aba4Alan Cox * can be slow, so on systems where the framebuffer can handle restoration
17158d233558cd99a888571bb5a88a74970879e0aba4Alan Cox * of video registers anyways, there's little point in doing the console
17168d233558cd99a888571bb5a88a74970879e0aba4Alan Cox * switch.  This function allows you to disable it by passing it '0'.
17178d233558cd99a888571bb5a88a74970879e0aba4Alan Cox */
17188d233558cd99a888571bb5a88a74970879e0aba4Alan Coxvoid pm_set_vt_switch(int do_switch)
17198d233558cd99a888571bb5a88a74970879e0aba4Alan Cox{
1720ac751efa6a0d70f2c9daef5c7e3a92270f5c2dffTorben Hohn	console_lock();
17218d233558cd99a888571bb5a88a74970879e0aba4Alan Cox	disable_vt_switch = !do_switch;
1722ac751efa6a0d70f2c9daef5c7e3a92270f5c2dffTorben Hohn	console_unlock();
17238d233558cd99a888571bb5a88a74970879e0aba4Alan Cox}
17248d233558cd99a888571bb5a88a74970879e0aba4Alan CoxEXPORT_SYMBOL(pm_set_vt_switch);
1725