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 */
13399cceb4e50cb67720e779f6611476bcb611af6b8Alan Cox	wait_event_interruptible(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
1991da177e4c3f41524e886b7f1b8a0c1fc7321cacLinus Torvalds
2001da177e4c3f41524e886b7f1b8a0c1fc7321cacLinus Torvaldsstatic inline int
2011da177e4c3f41524e886b7f1b8a0c1fc7321cacLinus Torvaldsdo_fontx_ioctl(int cmd, struct consolefontdesc __user *user_cfd, int perm, struct console_font_op *op)
2021da177e4c3f41524e886b7f1b8a0c1fc7321cacLinus Torvalds{
2031da177e4c3f41524e886b7f1b8a0c1fc7321cacLinus Torvalds	struct consolefontdesc cfdarg;
2041da177e4c3f41524e886b7f1b8a0c1fc7321cacLinus Torvalds	int i;
2051da177e4c3f41524e886b7f1b8a0c1fc7321cacLinus Torvalds
2061da177e4c3f41524e886b7f1b8a0c1fc7321cacLinus Torvalds	if (copy_from_user(&cfdarg, user_cfd, sizeof(struct consolefontdesc)))
2071da177e4c3f41524e886b7f1b8a0c1fc7321cacLinus Torvalds		return -EFAULT;
2081da177e4c3f41524e886b7f1b8a0c1fc7321cacLinus Torvalds
2091da177e4c3f41524e886b7f1b8a0c1fc7321cacLinus Torvalds	switch (cmd) {
2101da177e4c3f41524e886b7f1b8a0c1fc7321cacLinus Torvalds	case PIO_FONTX:
2111da177e4c3f41524e886b7f1b8a0c1fc7321cacLinus Torvalds		if (!perm)
2121da177e4c3f41524e886b7f1b8a0c1fc7321cacLinus Torvalds			return -EPERM;
2131da177e4c3f41524e886b7f1b8a0c1fc7321cacLinus Torvalds		op->op = KD_FONT_OP_SET;
2141da177e4c3f41524e886b7f1b8a0c1fc7321cacLinus Torvalds		op->flags = KD_FONT_FLAG_OLD;
2151da177e4c3f41524e886b7f1b8a0c1fc7321cacLinus Torvalds		op->width = 8;
2161da177e4c3f41524e886b7f1b8a0c1fc7321cacLinus Torvalds		op->height = cfdarg.charheight;
2171da177e4c3f41524e886b7f1b8a0c1fc7321cacLinus Torvalds		op->charcount = cfdarg.charcount;
2181da177e4c3f41524e886b7f1b8a0c1fc7321cacLinus Torvalds		op->data = cfdarg.chardata;
2191da177e4c3f41524e886b7f1b8a0c1fc7321cacLinus Torvalds		return con_font_op(vc_cons[fg_console].d, op);
2201da177e4c3f41524e886b7f1b8a0c1fc7321cacLinus Torvalds	case GIO_FONTX: {
2211da177e4c3f41524e886b7f1b8a0c1fc7321cacLinus Torvalds		op->op = KD_FONT_OP_GET;
2221da177e4c3f41524e886b7f1b8a0c1fc7321cacLinus Torvalds		op->flags = KD_FONT_FLAG_OLD;
2231da177e4c3f41524e886b7f1b8a0c1fc7321cacLinus Torvalds		op->width = 8;
2241da177e4c3f41524e886b7f1b8a0c1fc7321cacLinus Torvalds		op->height = cfdarg.charheight;
2251da177e4c3f41524e886b7f1b8a0c1fc7321cacLinus Torvalds		op->charcount = cfdarg.charcount;
2261da177e4c3f41524e886b7f1b8a0c1fc7321cacLinus Torvalds		op->data = cfdarg.chardata;
2271da177e4c3f41524e886b7f1b8a0c1fc7321cacLinus Torvalds		i = con_font_op(vc_cons[fg_console].d, op);
2281da177e4c3f41524e886b7f1b8a0c1fc7321cacLinus Torvalds		if (i)
2291da177e4c3f41524e886b7f1b8a0c1fc7321cacLinus Torvalds			return i;
2301da177e4c3f41524e886b7f1b8a0c1fc7321cacLinus Torvalds		cfdarg.charheight = op->height;
2311da177e4c3f41524e886b7f1b8a0c1fc7321cacLinus Torvalds		cfdarg.charcount = op->charcount;
2321da177e4c3f41524e886b7f1b8a0c1fc7321cacLinus Torvalds		if (copy_to_user(user_cfd, &cfdarg, sizeof(struct consolefontdesc)))
2331da177e4c3f41524e886b7f1b8a0c1fc7321cacLinus Torvalds			return -EFAULT;
2341da177e4c3f41524e886b7f1b8a0c1fc7321cacLinus Torvalds		return 0;
2351da177e4c3f41524e886b7f1b8a0c1fc7321cacLinus Torvalds		}
2361da177e4c3f41524e886b7f1b8a0c1fc7321cacLinus Torvalds	}
2371da177e4c3f41524e886b7f1b8a0c1fc7321cacLinus Torvalds	return -EINVAL;
2381da177e4c3f41524e886b7f1b8a0c1fc7321cacLinus Torvalds}
2391da177e4c3f41524e886b7f1b8a0c1fc7321cacLinus Torvalds
2401da177e4c3f41524e886b7f1b8a0c1fc7321cacLinus Torvaldsstatic inline int
2411da177e4c3f41524e886b7f1b8a0c1fc7321cacLinus Torvaldsdo_unimap_ioctl(int cmd, struct unimapdesc __user *user_ud, int perm, struct vc_data *vc)
2421da177e4c3f41524e886b7f1b8a0c1fc7321cacLinus Torvalds{
2431da177e4c3f41524e886b7f1b8a0c1fc7321cacLinus Torvalds	struct unimapdesc tmp;
2441da177e4c3f41524e886b7f1b8a0c1fc7321cacLinus Torvalds
2451da177e4c3f41524e886b7f1b8a0c1fc7321cacLinus Torvalds	if (copy_from_user(&tmp, user_ud, sizeof tmp))
2461da177e4c3f41524e886b7f1b8a0c1fc7321cacLinus Torvalds		return -EFAULT;
2471da177e4c3f41524e886b7f1b8a0c1fc7321cacLinus Torvalds	if (tmp.entries)
2481da177e4c3f41524e886b7f1b8a0c1fc7321cacLinus Torvalds		if (!access_ok(VERIFY_WRITE, tmp.entries,
2491da177e4c3f41524e886b7f1b8a0c1fc7321cacLinus Torvalds				tmp.entry_ct*sizeof(struct unipair)))
2501da177e4c3f41524e886b7f1b8a0c1fc7321cacLinus Torvalds			return -EFAULT;
2511da177e4c3f41524e886b7f1b8a0c1fc7321cacLinus Torvalds	switch (cmd) {
2521da177e4c3f41524e886b7f1b8a0c1fc7321cacLinus Torvalds	case PIO_UNIMAP:
2531da177e4c3f41524e886b7f1b8a0c1fc7321cacLinus Torvalds		if (!perm)
2541da177e4c3f41524e886b7f1b8a0c1fc7321cacLinus Torvalds			return -EPERM;
2551da177e4c3f41524e886b7f1b8a0c1fc7321cacLinus Torvalds		return con_set_unimap(vc, tmp.entry_ct, tmp.entries);
2561da177e4c3f41524e886b7f1b8a0c1fc7321cacLinus Torvalds	case GIO_UNIMAP:
2571da177e4c3f41524e886b7f1b8a0c1fc7321cacLinus Torvalds		if (!perm && fg_console != vc->vc_num)
2581da177e4c3f41524e886b7f1b8a0c1fc7321cacLinus Torvalds			return -EPERM;
2591da177e4c3f41524e886b7f1b8a0c1fc7321cacLinus Torvalds		return con_get_unimap(vc, tmp.entry_ct, &(user_ud->entry_ct), tmp.entries);
2601da177e4c3f41524e886b7f1b8a0c1fc7321cacLinus Torvalds	}
2611da177e4c3f41524e886b7f1b8a0c1fc7321cacLinus Torvalds	return 0;
2621da177e4c3f41524e886b7f1b8a0c1fc7321cacLinus Torvalds}
2631da177e4c3f41524e886b7f1b8a0c1fc7321cacLinus Torvalds
2648b92e87d39bfd046e7581e1fe0f40eac40f88608Alan Cox
2658b92e87d39bfd046e7581e1fe0f40eac40f88608Alan Cox
2661da177e4c3f41524e886b7f1b8a0c1fc7321cacLinus Torvalds/*
2671da177e4c3f41524e886b7f1b8a0c1fc7321cacLinus Torvalds * We handle the console-specific ioctl's here.  We allow the
2681da177e4c3f41524e886b7f1b8a0c1fc7321cacLinus Torvalds * capability to modify any console, not just the fg_console.
2691da177e4c3f41524e886b7f1b8a0c1fc7321cacLinus Torvalds */
2706caa76b7786891b42b66a0e61e2c2fff2c884620Alan Coxint vt_ioctl(struct tty_struct *tty,
2711da177e4c3f41524e886b7f1b8a0c1fc7321cacLinus Torvalds	     unsigned int cmd, unsigned long arg)
2721da177e4c3f41524e886b7f1b8a0c1fc7321cacLinus Torvalds{
273c9f19e96a2f33cd56c2bd19f87a0c4982d011c2bAlan Cox	struct vc_data *vc = tty->driver_data;
2741da177e4c3f41524e886b7f1b8a0c1fc7321cacLinus Torvalds	struct console_font_op op;	/* used in multiple places here */
2751da177e4c3f41524e886b7f1b8a0c1fc7321cacLinus Torvalds	unsigned int console;
2761da177e4c3f41524e886b7f1b8a0c1fc7321cacLinus Torvalds	unsigned char ucval;
2771e0ad2881d50becaeea70ec696a80afeadf944d2Graham Gower	unsigned int uival;
2781da177e4c3f41524e886b7f1b8a0c1fc7321cacLinus Torvalds	void __user *up = (void __user *)arg;
2791da177e4c3f41524e886b7f1b8a0c1fc7321cacLinus Torvalds	int i, perm;
2809cc3c22bf017f33612748aeb466fdc3695fb1e1dAlan Cox	int ret = 0;
2819cc3c22bf017f33612748aeb466fdc3695fb1e1dAlan Cox
2821da177e4c3f41524e886b7f1b8a0c1fc7321cacLinus Torvalds	console = vc->vc_num;
2831da177e4c3f41524e886b7f1b8a0c1fc7321cacLinus Torvalds
2849cc3c22bf017f33612748aeb466fdc3695fb1e1dAlan Cox
2859cc3c22bf017f33612748aeb466fdc3695fb1e1dAlan Cox	if (!vc_cons_allocated(console)) { 	/* impossible? */
2869cc3c22bf017f33612748aeb466fdc3695fb1e1dAlan Cox		ret = -ENOIOCTLCMD;
2879cc3c22bf017f33612748aeb466fdc3695fb1e1dAlan Cox		goto out;
2889cc3c22bf017f33612748aeb466fdc3695fb1e1dAlan Cox	}
2899cc3c22bf017f33612748aeb466fdc3695fb1e1dAlan Cox
2901da177e4c3f41524e886b7f1b8a0c1fc7321cacLinus Torvalds
2911da177e4c3f41524e886b7f1b8a0c1fc7321cacLinus Torvalds	/*
2921da177e4c3f41524e886b7f1b8a0c1fc7321cacLinus Torvalds	 * To have permissions to do most of the vt ioctls, we either have
2931da177e4c3f41524e886b7f1b8a0c1fc7321cacLinus Torvalds	 * to be the owner of the tty, or have CAP_SYS_TTY_CONFIG.
2941da177e4c3f41524e886b7f1b8a0c1fc7321cacLinus Torvalds	 */
2951da177e4c3f41524e886b7f1b8a0c1fc7321cacLinus Torvalds	perm = 0;
2961da177e4c3f41524e886b7f1b8a0c1fc7321cacLinus Torvalds	if (current->signal->tty == tty || capable(CAP_SYS_TTY_CONFIG))
2971da177e4c3f41524e886b7f1b8a0c1fc7321cacLinus Torvalds		perm = 1;
2981da177e4c3f41524e886b7f1b8a0c1fc7321cacLinus Torvalds
2991da177e4c3f41524e886b7f1b8a0c1fc7321cacLinus Torvalds	switch (cmd) {
300e6885107736a4dd23e7d3bc103fe6d043c63c4deAlan Cox	case TIOCLINUX:
301a115902f67ef51fbbe83e214fb761aaa9734c1ceJiri Slaby		ret = tioclinux(tty, arg);
302a115902f67ef51fbbe83e214fb761aaa9734c1ceJiri Slaby		break;
3031da177e4c3f41524e886b7f1b8a0c1fc7321cacLinus Torvalds	case KIOCSOUND:
3041da177e4c3f41524e886b7f1b8a0c1fc7321cacLinus Torvalds		if (!perm)
3054001d7b7fc271052ebff43f327c26dc64806bbdfAlan Cox			return -EPERM;
3062c4e9671edfef534e9726366707d64e63d44e7e6Arnd Bergmann		/*
3072c4e9671edfef534e9726366707d64e63d44e7e6Arnd Bergmann		 * The use of PIT_TICK_RATE is historic, it used to be
3082c4e9671edfef534e9726366707d64e63d44e7e6Arnd Bergmann		 * the platform-dependent CLOCK_TICK_RATE between 2.6.12
3092c4e9671edfef534e9726366707d64e63d44e7e6Arnd Bergmann		 * and 2.6.36, which was a minor but unfortunate ABI
3104001d7b7fc271052ebff43f327c26dc64806bbdfAlan Cox		 * change. kd_mksound is locked by the input layer.
3112c4e9671edfef534e9726366707d64e63d44e7e6Arnd Bergmann		 */
3121da177e4c3f41524e886b7f1b8a0c1fc7321cacLinus Torvalds		if (arg)
3132c4e9671edfef534e9726366707d64e63d44e7e6Arnd Bergmann			arg = PIT_TICK_RATE / arg;
3141da177e4c3f41524e886b7f1b8a0c1fc7321cacLinus Torvalds		kd_mksound(arg, 0);
3159cc3c22bf017f33612748aeb466fdc3695fb1e1dAlan Cox		break;
3161da177e4c3f41524e886b7f1b8a0c1fc7321cacLinus Torvalds
3171da177e4c3f41524e886b7f1b8a0c1fc7321cacLinus Torvalds	case KDMKTONE:
3181da177e4c3f41524e886b7f1b8a0c1fc7321cacLinus Torvalds		if (!perm)
3194001d7b7fc271052ebff43f327c26dc64806bbdfAlan Cox			return -EPERM;
3201da177e4c3f41524e886b7f1b8a0c1fc7321cacLinus Torvalds	{
3211da177e4c3f41524e886b7f1b8a0c1fc7321cacLinus Torvalds		unsigned int ticks, count;
3221da177e4c3f41524e886b7f1b8a0c1fc7321cacLinus Torvalds
3231da177e4c3f41524e886b7f1b8a0c1fc7321cacLinus Torvalds		/*
3241da177e4c3f41524e886b7f1b8a0c1fc7321cacLinus Torvalds		 * Generate the tone for the appropriate number of ticks.
3251da177e4c3f41524e886b7f1b8a0c1fc7321cacLinus Torvalds		 * If the time is zero, turn off sound ourselves.
3261da177e4c3f41524e886b7f1b8a0c1fc7321cacLinus Torvalds		 */
3271da177e4c3f41524e886b7f1b8a0c1fc7321cacLinus Torvalds		ticks = HZ * ((arg >> 16) & 0xffff) / 1000;
3281da177e4c3f41524e886b7f1b8a0c1fc7321cacLinus Torvalds		count = ticks ? (arg & 0xffff) : 0;
3291da177e4c3f41524e886b7f1b8a0c1fc7321cacLinus Torvalds		if (count)
3302c4e9671edfef534e9726366707d64e63d44e7e6Arnd Bergmann			count = PIT_TICK_RATE / count;
3311da177e4c3f41524e886b7f1b8a0c1fc7321cacLinus Torvalds		kd_mksound(count, ticks);
3329cc3c22bf017f33612748aeb466fdc3695fb1e1dAlan Cox		break;
3331da177e4c3f41524e886b7f1b8a0c1fc7321cacLinus Torvalds	}
3341da177e4c3f41524e886b7f1b8a0c1fc7321cacLinus Torvalds
3351da177e4c3f41524e886b7f1b8a0c1fc7321cacLinus Torvalds	case KDGKBTYPE:
3361da177e4c3f41524e886b7f1b8a0c1fc7321cacLinus Torvalds		/*
3374001d7b7fc271052ebff43f327c26dc64806bbdfAlan Cox		 * this is naïve.
3381da177e4c3f41524e886b7f1b8a0c1fc7321cacLinus Torvalds		 */
3391da177e4c3f41524e886b7f1b8a0c1fc7321cacLinus Torvalds		ucval = KB_101;
340079c9534a96da9a85a2a2f9715851050fbfbf749Alan Cox		ret = put_user(ucval, (char __user *)arg);
341079c9534a96da9a85a2a2f9715851050fbfbf749Alan Cox		break;
3421da177e4c3f41524e886b7f1b8a0c1fc7321cacLinus Torvalds
3431da177e4c3f41524e886b7f1b8a0c1fc7321cacLinus Torvalds		/*
3441da177e4c3f41524e886b7f1b8a0c1fc7321cacLinus Torvalds		 * These cannot be implemented on any machine that implements
3451da177e4c3f41524e886b7f1b8a0c1fc7321cacLinus Torvalds		 * ioperm() in user level (such as Alpha PCs) or not at all.
3461da177e4c3f41524e886b7f1b8a0c1fc7321cacLinus Torvalds		 *
3471da177e4c3f41524e886b7f1b8a0c1fc7321cacLinus Torvalds		 * XXX: you should never use these, just call ioperm directly..
3481da177e4c3f41524e886b7f1b8a0c1fc7321cacLinus Torvalds		 */
3491da177e4c3f41524e886b7f1b8a0c1fc7321cacLinus Torvalds#ifdef CONFIG_X86
3501da177e4c3f41524e886b7f1b8a0c1fc7321cacLinus Torvalds	case KDADDIO:
3511da177e4c3f41524e886b7f1b8a0c1fc7321cacLinus Torvalds	case KDDELIO:
3521da177e4c3f41524e886b7f1b8a0c1fc7321cacLinus Torvalds		/*
3531da177e4c3f41524e886b7f1b8a0c1fc7321cacLinus Torvalds		 * KDADDIO and KDDELIO may be able to add ports beyond what
3541da177e4c3f41524e886b7f1b8a0c1fc7321cacLinus Torvalds		 * we reject here, but to be safe...
3554001d7b7fc271052ebff43f327c26dc64806bbdfAlan Cox		 *
3564001d7b7fc271052ebff43f327c26dc64806bbdfAlan Cox		 * These are locked internally via sys_ioperm
3571da177e4c3f41524e886b7f1b8a0c1fc7321cacLinus Torvalds		 */
3589cc3c22bf017f33612748aeb466fdc3695fb1e1dAlan Cox		if (arg < GPFIRST || arg > GPLAST) {
3599cc3c22bf017f33612748aeb466fdc3695fb1e1dAlan Cox			ret = -EINVAL;
3609cc3c22bf017f33612748aeb466fdc3695fb1e1dAlan Cox			break;
3619cc3c22bf017f33612748aeb466fdc3695fb1e1dAlan Cox		}
3629cc3c22bf017f33612748aeb466fdc3695fb1e1dAlan Cox		ret = sys_ioperm(arg, 1, (cmd == KDADDIO)) ? -ENXIO : 0;
3639cc3c22bf017f33612748aeb466fdc3695fb1e1dAlan Cox		break;
3641da177e4c3f41524e886b7f1b8a0c1fc7321cacLinus Torvalds
3651da177e4c3f41524e886b7f1b8a0c1fc7321cacLinus Torvalds	case KDENABIO:
3661da177e4c3f41524e886b7f1b8a0c1fc7321cacLinus Torvalds	case KDDISABIO:
3679cc3c22bf017f33612748aeb466fdc3695fb1e1dAlan Cox		ret = sys_ioperm(GPFIRST, GPNUM,
3681da177e4c3f41524e886b7f1b8a0c1fc7321cacLinus Torvalds				  (cmd == KDENABIO)) ? -ENXIO : 0;
3699cc3c22bf017f33612748aeb466fdc3695fb1e1dAlan Cox		break;
3701da177e4c3f41524e886b7f1b8a0c1fc7321cacLinus Torvalds#endif
3711da177e4c3f41524e886b7f1b8a0c1fc7321cacLinus Torvalds
3721da177e4c3f41524e886b7f1b8a0c1fc7321cacLinus Torvalds	/* Linux m68k/i386 interface for setting the keyboard delay/repeat rate */
3731da177e4c3f41524e886b7f1b8a0c1fc7321cacLinus Torvalds
3741da177e4c3f41524e886b7f1b8a0c1fc7321cacLinus Torvalds	case KDKBDREP:
3751da177e4c3f41524e886b7f1b8a0c1fc7321cacLinus Torvalds	{
3761da177e4c3f41524e886b7f1b8a0c1fc7321cacLinus Torvalds		struct kbd_repeat kbrep;
3771da177e4c3f41524e886b7f1b8a0c1fc7321cacLinus Torvalds
3781da177e4c3f41524e886b7f1b8a0c1fc7321cacLinus Torvalds		if (!capable(CAP_SYS_TTY_CONFIG))
3794001d7b7fc271052ebff43f327c26dc64806bbdfAlan Cox			return -EPERM;
3801da177e4c3f41524e886b7f1b8a0c1fc7321cacLinus Torvalds
3819cc3c22bf017f33612748aeb466fdc3695fb1e1dAlan Cox		if (copy_from_user(&kbrep, up, sizeof(struct kbd_repeat))) {
3829cc3c22bf017f33612748aeb466fdc3695fb1e1dAlan Cox			ret =  -EFAULT;
3839cc3c22bf017f33612748aeb466fdc3695fb1e1dAlan Cox			break;
3849cc3c22bf017f33612748aeb466fdc3695fb1e1dAlan Cox		}
3859cc3c22bf017f33612748aeb466fdc3695fb1e1dAlan Cox		ret = kbd_rate(&kbrep);
3869cc3c22bf017f33612748aeb466fdc3695fb1e1dAlan Cox		if (ret)
3879cc3c22bf017f33612748aeb466fdc3695fb1e1dAlan Cox			break;
3881da177e4c3f41524e886b7f1b8a0c1fc7321cacLinus Torvalds		if (copy_to_user(up, &kbrep, sizeof(struct kbd_repeat)))
3899cc3c22bf017f33612748aeb466fdc3695fb1e1dAlan Cox			ret = -EFAULT;
3909cc3c22bf017f33612748aeb466fdc3695fb1e1dAlan Cox		break;
3911da177e4c3f41524e886b7f1b8a0c1fc7321cacLinus Torvalds	}
3921da177e4c3f41524e886b7f1b8a0c1fc7321cacLinus Torvalds
3931da177e4c3f41524e886b7f1b8a0c1fc7321cacLinus Torvalds	case KDSETMODE:
3941da177e4c3f41524e886b7f1b8a0c1fc7321cacLinus Torvalds		/*
3951da177e4c3f41524e886b7f1b8a0c1fc7321cacLinus Torvalds		 * currently, setting the mode from KD_TEXT to KD_GRAPHICS
3961da177e4c3f41524e886b7f1b8a0c1fc7321cacLinus Torvalds		 * doesn't do a whole lot. i'm not sure if it should do any
3971da177e4c3f41524e886b7f1b8a0c1fc7321cacLinus Torvalds		 * restoration of modes or what...
3981da177e4c3f41524e886b7f1b8a0c1fc7321cacLinus Torvalds		 *
3991da177e4c3f41524e886b7f1b8a0c1fc7321cacLinus Torvalds		 * XXX It should at least call into the driver, fbdev's definitely
4001da177e4c3f41524e886b7f1b8a0c1fc7321cacLinus Torvalds		 * need to restore their engine state. --BenH
4011da177e4c3f41524e886b7f1b8a0c1fc7321cacLinus Torvalds		 */
4021da177e4c3f41524e886b7f1b8a0c1fc7321cacLinus Torvalds		if (!perm)
4034001d7b7fc271052ebff43f327c26dc64806bbdfAlan Cox			return -EPERM;
4041da177e4c3f41524e886b7f1b8a0c1fc7321cacLinus Torvalds		switch (arg) {
4051da177e4c3f41524e886b7f1b8a0c1fc7321cacLinus Torvalds		case KD_GRAPHICS:
4061da177e4c3f41524e886b7f1b8a0c1fc7321cacLinus Torvalds			break;
4071da177e4c3f41524e886b7f1b8a0c1fc7321cacLinus Torvalds		case KD_TEXT0:
4081da177e4c3f41524e886b7f1b8a0c1fc7321cacLinus Torvalds		case KD_TEXT1:
4091da177e4c3f41524e886b7f1b8a0c1fc7321cacLinus Torvalds			arg = KD_TEXT;
4101da177e4c3f41524e886b7f1b8a0c1fc7321cacLinus Torvalds		case KD_TEXT:
4111da177e4c3f41524e886b7f1b8a0c1fc7321cacLinus Torvalds			break;
4121da177e4c3f41524e886b7f1b8a0c1fc7321cacLinus Torvalds		default:
4139cc3c22bf017f33612748aeb466fdc3695fb1e1dAlan Cox			ret = -EINVAL;
4149cc3c22bf017f33612748aeb466fdc3695fb1e1dAlan Cox			goto out;
4151da177e4c3f41524e886b7f1b8a0c1fc7321cacLinus Torvalds		}
4164001d7b7fc271052ebff43f327c26dc64806bbdfAlan Cox		/* FIXME: this needs the console lock extending */
4171da177e4c3f41524e886b7f1b8a0c1fc7321cacLinus Torvalds		if (vc->vc_mode == (unsigned char) arg)
4189cc3c22bf017f33612748aeb466fdc3695fb1e1dAlan Cox			break;
4191da177e4c3f41524e886b7f1b8a0c1fc7321cacLinus Torvalds		vc->vc_mode = (unsigned char) arg;
4201da177e4c3f41524e886b7f1b8a0c1fc7321cacLinus Torvalds		if (console != fg_console)
4219cc3c22bf017f33612748aeb466fdc3695fb1e1dAlan Cox			break;
4221da177e4c3f41524e886b7f1b8a0c1fc7321cacLinus Torvalds		/*
4231da177e4c3f41524e886b7f1b8a0c1fc7321cacLinus Torvalds		 * explicitly blank/unblank the screen if switching modes
4241da177e4c3f41524e886b7f1b8a0c1fc7321cacLinus Torvalds		 */
425ac751efa6a0d70f2c9daef5c7e3a92270f5c2dffTorben Hohn		console_lock();
4261da177e4c3f41524e886b7f1b8a0c1fc7321cacLinus Torvalds		if (arg == KD_TEXT)
4271da177e4c3f41524e886b7f1b8a0c1fc7321cacLinus Torvalds			do_unblank_screen(1);
4281da177e4c3f41524e886b7f1b8a0c1fc7321cacLinus Torvalds		else
4291da177e4c3f41524e886b7f1b8a0c1fc7321cacLinus Torvalds			do_blank_screen(1);
430ac751efa6a0d70f2c9daef5c7e3a92270f5c2dffTorben Hohn		console_unlock();
4319cc3c22bf017f33612748aeb466fdc3695fb1e1dAlan Cox		break;
4321da177e4c3f41524e886b7f1b8a0c1fc7321cacLinus Torvalds
4331da177e4c3f41524e886b7f1b8a0c1fc7321cacLinus Torvalds	case KDGETMODE:
4341e0ad2881d50becaeea70ec696a80afeadf944d2Graham Gower		uival = vc->vc_mode;
4351da177e4c3f41524e886b7f1b8a0c1fc7321cacLinus Torvalds		goto setint;
4361da177e4c3f41524e886b7f1b8a0c1fc7321cacLinus Torvalds
4371da177e4c3f41524e886b7f1b8a0c1fc7321cacLinus Torvalds	case KDMAPDISP:
4381da177e4c3f41524e886b7f1b8a0c1fc7321cacLinus Torvalds	case KDUNMAPDISP:
4391da177e4c3f41524e886b7f1b8a0c1fc7321cacLinus Torvalds		/*
4401da177e4c3f41524e886b7f1b8a0c1fc7321cacLinus Torvalds		 * these work like a combination of mmap and KDENABIO.
4411da177e4c3f41524e886b7f1b8a0c1fc7321cacLinus Torvalds		 * this could be easily finished.
4421da177e4c3f41524e886b7f1b8a0c1fc7321cacLinus Torvalds		 */
4439cc3c22bf017f33612748aeb466fdc3695fb1e1dAlan Cox		ret = -EINVAL;
4449cc3c22bf017f33612748aeb466fdc3695fb1e1dAlan Cox		break;
4451da177e4c3f41524e886b7f1b8a0c1fc7321cacLinus Torvalds
4461da177e4c3f41524e886b7f1b8a0c1fc7321cacLinus Torvalds	case KDSKBMODE:
4471da177e4c3f41524e886b7f1b8a0c1fc7321cacLinus Torvalds		if (!perm)
4484001d7b7fc271052ebff43f327c26dc64806bbdfAlan Cox			return -EPERM;
449079c9534a96da9a85a2a2f9715851050fbfbf749Alan Cox		ret = vt_do_kdskbmode(console, arg);
450079c9534a96da9a85a2a2f9715851050fbfbf749Alan Cox		if (ret == 0)
451079c9534a96da9a85a2a2f9715851050fbfbf749Alan Cox			tty_ldisc_flush(tty);
4529cc3c22bf017f33612748aeb466fdc3695fb1e1dAlan Cox		break;
4531da177e4c3f41524e886b7f1b8a0c1fc7321cacLinus Torvalds
4541da177e4c3f41524e886b7f1b8a0c1fc7321cacLinus Torvalds	case KDGKBMODE:
455079c9534a96da9a85a2a2f9715851050fbfbf749Alan Cox		uival = vt_do_kdgkbmode(console);
456079c9534a96da9a85a2a2f9715851050fbfbf749Alan Cox		ret = put_user(uival, (int __user *)arg);
457079c9534a96da9a85a2a2f9715851050fbfbf749Alan Cox		break;
4581da177e4c3f41524e886b7f1b8a0c1fc7321cacLinus Torvalds
4591da177e4c3f41524e886b7f1b8a0c1fc7321cacLinus Torvalds	/* this could be folded into KDSKBMODE, but for compatibility
4601da177e4c3f41524e886b7f1b8a0c1fc7321cacLinus Torvalds	   reasons it is not so easy to fold KDGKBMETA into KDGKBMODE */
4611da177e4c3f41524e886b7f1b8a0c1fc7321cacLinus Torvalds	case KDSKBMETA:
462079c9534a96da9a85a2a2f9715851050fbfbf749Alan Cox		ret = vt_do_kdskbmeta(console, arg);
4639cc3c22bf017f33612748aeb466fdc3695fb1e1dAlan Cox		break;
4641da177e4c3f41524e886b7f1b8a0c1fc7321cacLinus Torvalds
4651da177e4c3f41524e886b7f1b8a0c1fc7321cacLinus Torvalds	case KDGKBMETA:
466079c9534a96da9a85a2a2f9715851050fbfbf749Alan Cox		/* FIXME: should review whether this is worth locking */
467079c9534a96da9a85a2a2f9715851050fbfbf749Alan Cox		uival = vt_do_kdgkbmeta(console);
4681da177e4c3f41524e886b7f1b8a0c1fc7321cacLinus Torvalds	setint:
4691e0ad2881d50becaeea70ec696a80afeadf944d2Graham Gower		ret = put_user(uival, (int __user *)arg);
4709cc3c22bf017f33612748aeb466fdc3695fb1e1dAlan Cox		break;
4711da177e4c3f41524e886b7f1b8a0c1fc7321cacLinus Torvalds
4721da177e4c3f41524e886b7f1b8a0c1fc7321cacLinus Torvalds	case KDGETKEYCODE:
4731da177e4c3f41524e886b7f1b8a0c1fc7321cacLinus Torvalds	case KDSETKEYCODE:
4741da177e4c3f41524e886b7f1b8a0c1fc7321cacLinus Torvalds		if(!capable(CAP_SYS_TTY_CONFIG))
4759cc3c22bf017f33612748aeb466fdc3695fb1e1dAlan Cox			perm = 0;
476079c9534a96da9a85a2a2f9715851050fbfbf749Alan Cox		ret = vt_do_kbkeycode_ioctl(cmd, up, perm);
4779cc3c22bf017f33612748aeb466fdc3695fb1e1dAlan Cox		break;
4781da177e4c3f41524e886b7f1b8a0c1fc7321cacLinus Torvalds
4791da177e4c3f41524e886b7f1b8a0c1fc7321cacLinus Torvalds	case KDGKBENT:
4801da177e4c3f41524e886b7f1b8a0c1fc7321cacLinus Torvalds	case KDSKBENT:
481079c9534a96da9a85a2a2f9715851050fbfbf749Alan Cox		ret = vt_do_kdsk_ioctl(cmd, up, perm, console);
4829cc3c22bf017f33612748aeb466fdc3695fb1e1dAlan Cox		break;
4831da177e4c3f41524e886b7f1b8a0c1fc7321cacLinus Torvalds
4841da177e4c3f41524e886b7f1b8a0c1fc7321cacLinus Torvalds	case KDGKBSENT:
4851da177e4c3f41524e886b7f1b8a0c1fc7321cacLinus Torvalds	case KDSKBSENT:
486079c9534a96da9a85a2a2f9715851050fbfbf749Alan Cox		ret = vt_do_kdgkb_ioctl(cmd, up, perm);
4879cc3c22bf017f33612748aeb466fdc3695fb1e1dAlan Cox		break;
4881da177e4c3f41524e886b7f1b8a0c1fc7321cacLinus Torvalds
489247ff8e610cb63c015de19191db9666754c2ed79Alan Cox	/* Diacritical processing. Handled in keyboard.c as it has
490247ff8e610cb63c015de19191db9666754c2ed79Alan Cox	   to operate on the keyboard locks and structures */
4911da177e4c3f41524e886b7f1b8a0c1fc7321cacLinus Torvalds	case KDGKBDIACR:
49204c71976500352d02f60616d2b960267d8c5fe24Samuel Thibault	case KDGKBDIACRUC:
4931da177e4c3f41524e886b7f1b8a0c1fc7321cacLinus Torvalds	case KDSKBDIACR:
49404c71976500352d02f60616d2b960267d8c5fe24Samuel Thibault	case KDSKBDIACRUC:
495247ff8e610cb63c015de19191db9666754c2ed79Alan Cox		ret = vt_do_diacrit(cmd, up, perm);
4969cc3c22bf017f33612748aeb466fdc3695fb1e1dAlan Cox		break;
4971da177e4c3f41524e886b7f1b8a0c1fc7321cacLinus Torvalds
4981da177e4c3f41524e886b7f1b8a0c1fc7321cacLinus Torvalds	/* the ioctls below read/set the flags usually shown in the leds */
4991da177e4c3f41524e886b7f1b8a0c1fc7321cacLinus Torvalds	/* don't use them - they will go away without warning */
5001da177e4c3f41524e886b7f1b8a0c1fc7321cacLinus Torvalds	case KDGKBLED:
5011da177e4c3f41524e886b7f1b8a0c1fc7321cacLinus Torvalds	case KDSKBLED:
5021da177e4c3f41524e886b7f1b8a0c1fc7321cacLinus Torvalds	case KDGETLED:
5031da177e4c3f41524e886b7f1b8a0c1fc7321cacLinus Torvalds	case KDSETLED:
504079c9534a96da9a85a2a2f9715851050fbfbf749Alan Cox		ret = vt_do_kdskled(console, cmd, arg, perm);
5059cc3c22bf017f33612748aeb466fdc3695fb1e1dAlan Cox		break;
5061da177e4c3f41524e886b7f1b8a0c1fc7321cacLinus Torvalds
5071da177e4c3f41524e886b7f1b8a0c1fc7321cacLinus Torvalds	/*
5081da177e4c3f41524e886b7f1b8a0c1fc7321cacLinus Torvalds	 * A process can indicate its willingness to accept signals
5091da177e4c3f41524e886b7f1b8a0c1fc7321cacLinus Torvalds	 * generated by pressing an appropriate key combination.
5101da177e4c3f41524e886b7f1b8a0c1fc7321cacLinus Torvalds	 * Thus, one can have a daemon that e.g. spawns a new console
5111da177e4c3f41524e886b7f1b8a0c1fc7321cacLinus Torvalds	 * upon a keypress and then changes to it.
5121da177e4c3f41524e886b7f1b8a0c1fc7321cacLinus Torvalds	 * See also the kbrequest field of inittab(5).
5131da177e4c3f41524e886b7f1b8a0c1fc7321cacLinus Torvalds	 */
5141da177e4c3f41524e886b7f1b8a0c1fc7321cacLinus Torvalds	case KDSIGACCEPT:
5151da177e4c3f41524e886b7f1b8a0c1fc7321cacLinus Torvalds	{
5161da177e4c3f41524e886b7f1b8a0c1fc7321cacLinus Torvalds		if (!perm || !capable(CAP_KILL))
5174001d7b7fc271052ebff43f327c26dc64806bbdfAlan Cox			return -EPERM;
5187ed20e1ad521b5f5df61bf6559ae60738e393741Jesper Juhl		if (!valid_signal(arg) || arg < 1 || arg == SIGKILL)
5199cc3c22bf017f33612748aeb466fdc3695fb1e1dAlan Cox			ret = -EINVAL;
5209cc3c22bf017f33612748aeb466fdc3695fb1e1dAlan Cox		else {
5219cc3c22bf017f33612748aeb466fdc3695fb1e1dAlan Cox			spin_lock_irq(&vt_spawn_con.lock);
5229cc3c22bf017f33612748aeb466fdc3695fb1e1dAlan Cox			put_pid(vt_spawn_con.pid);
5239cc3c22bf017f33612748aeb466fdc3695fb1e1dAlan Cox			vt_spawn_con.pid = get_pid(task_pid(current));
5249cc3c22bf017f33612748aeb466fdc3695fb1e1dAlan Cox			vt_spawn_con.sig = arg;
5259cc3c22bf017f33612748aeb466fdc3695fb1e1dAlan Cox			spin_unlock_irq(&vt_spawn_con.lock);
5269cc3c22bf017f33612748aeb466fdc3695fb1e1dAlan Cox		}
5279cc3c22bf017f33612748aeb466fdc3695fb1e1dAlan Cox		break;
5281da177e4c3f41524e886b7f1b8a0c1fc7321cacLinus Torvalds	}
5291da177e4c3f41524e886b7f1b8a0c1fc7321cacLinus Torvalds
5301da177e4c3f41524e886b7f1b8a0c1fc7321cacLinus Torvalds	case VT_SETMODE:
5311da177e4c3f41524e886b7f1b8a0c1fc7321cacLinus Torvalds	{
5321da177e4c3f41524e886b7f1b8a0c1fc7321cacLinus Torvalds		struct vt_mode tmp;
5331da177e4c3f41524e886b7f1b8a0c1fc7321cacLinus Torvalds
5341da177e4c3f41524e886b7f1b8a0c1fc7321cacLinus Torvalds		if (!perm)
5354001d7b7fc271052ebff43f327c26dc64806bbdfAlan Cox			return -EPERM;
5369cc3c22bf017f33612748aeb466fdc3695fb1e1dAlan Cox		if (copy_from_user(&tmp, up, sizeof(struct vt_mode))) {
5379cc3c22bf017f33612748aeb466fdc3695fb1e1dAlan Cox			ret = -EFAULT;
5389cc3c22bf017f33612748aeb466fdc3695fb1e1dAlan Cox			goto out;
5399cc3c22bf017f33612748aeb466fdc3695fb1e1dAlan Cox		}
54087a6aca504d65f242589583e04df5e74b5eae1feGreg Kroah-Hartman		if (tmp.mode != VT_AUTO && tmp.mode != VT_PROCESS) {
5419cc3c22bf017f33612748aeb466fdc3695fb1e1dAlan Cox			ret = -EINVAL;
5429cc3c22bf017f33612748aeb466fdc3695fb1e1dAlan Cox			goto out;
5439cc3c22bf017f33612748aeb466fdc3695fb1e1dAlan Cox		}
544ac751efa6a0d70f2c9daef5c7e3a92270f5c2dffTorben Hohn		console_lock();
5451da177e4c3f41524e886b7f1b8a0c1fc7321cacLinus Torvalds		vc->vt_mode = tmp;
5461da177e4c3f41524e886b7f1b8a0c1fc7321cacLinus Torvalds		/* the frsig is ignored, so we set it to 0 */
5471da177e4c3f41524e886b7f1b8a0c1fc7321cacLinus Torvalds		vc->vt_mode.frsig = 0;
5488b6312f4dcc1efe7975731b6c47dd134282bd9acEric W. Biederman		put_pid(vc->vt_pid);
5498b6312f4dcc1efe7975731b6c47dd134282bd9acEric W. Biederman		vc->vt_pid = get_pid(task_pid(current));
5501da177e4c3f41524e886b7f1b8a0c1fc7321cacLinus Torvalds		/* no switch is required -- saw@shade.msu.ru */
5511da177e4c3f41524e886b7f1b8a0c1fc7321cacLinus Torvalds		vc->vt_newvt = -1;
552ac751efa6a0d70f2c9daef5c7e3a92270f5c2dffTorben Hohn		console_unlock();
5539cc3c22bf017f33612748aeb466fdc3695fb1e1dAlan Cox		break;
5541da177e4c3f41524e886b7f1b8a0c1fc7321cacLinus Torvalds	}
5551da177e4c3f41524e886b7f1b8a0c1fc7321cacLinus Torvalds
5561da177e4c3f41524e886b7f1b8a0c1fc7321cacLinus Torvalds	case VT_GETMODE:
5571da177e4c3f41524e886b7f1b8a0c1fc7321cacLinus Torvalds	{
5581da177e4c3f41524e886b7f1b8a0c1fc7321cacLinus Torvalds		struct vt_mode tmp;
5591da177e4c3f41524e886b7f1b8a0c1fc7321cacLinus Torvalds		int rc;
5601da177e4c3f41524e886b7f1b8a0c1fc7321cacLinus Torvalds
561ac751efa6a0d70f2c9daef5c7e3a92270f5c2dffTorben Hohn		console_lock();
5621da177e4c3f41524e886b7f1b8a0c1fc7321cacLinus Torvalds		memcpy(&tmp, &vc->vt_mode, sizeof(struct vt_mode));
563ac751efa6a0d70f2c9daef5c7e3a92270f5c2dffTorben Hohn		console_unlock();
5641da177e4c3f41524e886b7f1b8a0c1fc7321cacLinus Torvalds
5651da177e4c3f41524e886b7f1b8a0c1fc7321cacLinus Torvalds		rc = copy_to_user(up, &tmp, sizeof(struct vt_mode));
5669cc3c22bf017f33612748aeb466fdc3695fb1e1dAlan Cox		if (rc)
5679cc3c22bf017f33612748aeb466fdc3695fb1e1dAlan Cox			ret = -EFAULT;
5689cc3c22bf017f33612748aeb466fdc3695fb1e1dAlan Cox		break;
5691da177e4c3f41524e886b7f1b8a0c1fc7321cacLinus Torvalds	}
5701da177e4c3f41524e886b7f1b8a0c1fc7321cacLinus Torvalds
5711da177e4c3f41524e886b7f1b8a0c1fc7321cacLinus Torvalds	/*
5721da177e4c3f41524e886b7f1b8a0c1fc7321cacLinus Torvalds	 * Returns global vt state. Note that VT 0 is always open, since
5731da177e4c3f41524e886b7f1b8a0c1fc7321cacLinus Torvalds	 * it's an alias for the current VT, and people can't use it here.
5741da177e4c3f41524e886b7f1b8a0c1fc7321cacLinus Torvalds	 * We cannot return state for more than 16 VTs, since v_state is short.
5751da177e4c3f41524e886b7f1b8a0c1fc7321cacLinus Torvalds	 */
5761da177e4c3f41524e886b7f1b8a0c1fc7321cacLinus Torvalds	case VT_GETSTATE:
5771da177e4c3f41524e886b7f1b8a0c1fc7321cacLinus Torvalds	{
5781da177e4c3f41524e886b7f1b8a0c1fc7321cacLinus Torvalds		struct vt_stat __user *vtstat = up;
5791da177e4c3f41524e886b7f1b8a0c1fc7321cacLinus Torvalds		unsigned short state, mask;
5801da177e4c3f41524e886b7f1b8a0c1fc7321cacLinus Torvalds
5814001d7b7fc271052ebff43f327c26dc64806bbdfAlan Cox		/* Review: FIXME: Console lock ? */
5821da177e4c3f41524e886b7f1b8a0c1fc7321cacLinus Torvalds		if (put_user(fg_console + 1, &vtstat->v_active))
5839cc3c22bf017f33612748aeb466fdc3695fb1e1dAlan Cox			ret = -EFAULT;
5849cc3c22bf017f33612748aeb466fdc3695fb1e1dAlan Cox		else {
5859cc3c22bf017f33612748aeb466fdc3695fb1e1dAlan Cox			state = 1;	/* /dev/tty0 is always open */
5869cc3c22bf017f33612748aeb466fdc3695fb1e1dAlan Cox			for (i = 0, mask = 2; i < MAX_NR_CONSOLES && mask;
5879cc3c22bf017f33612748aeb466fdc3695fb1e1dAlan Cox							++i, mask <<= 1)
5889cc3c22bf017f33612748aeb466fdc3695fb1e1dAlan Cox				if (VT_IS_IN_USE(i))
5899cc3c22bf017f33612748aeb466fdc3695fb1e1dAlan Cox					state |= mask;
5909cc3c22bf017f33612748aeb466fdc3695fb1e1dAlan Cox			ret = put_user(state, &vtstat->v_state);
5919cc3c22bf017f33612748aeb466fdc3695fb1e1dAlan Cox		}
5929cc3c22bf017f33612748aeb466fdc3695fb1e1dAlan Cox		break;
5931da177e4c3f41524e886b7f1b8a0c1fc7321cacLinus Torvalds	}
5941da177e4c3f41524e886b7f1b8a0c1fc7321cacLinus Torvalds
5951da177e4c3f41524e886b7f1b8a0c1fc7321cacLinus Torvalds	/*
5961da177e4c3f41524e886b7f1b8a0c1fc7321cacLinus Torvalds	 * Returns the first available (non-opened) console.
5971da177e4c3f41524e886b7f1b8a0c1fc7321cacLinus Torvalds	 */
5981da177e4c3f41524e886b7f1b8a0c1fc7321cacLinus Torvalds	case VT_OPENQRY:
5994001d7b7fc271052ebff43f327c26dc64806bbdfAlan Cox		/* FIXME: locking ? - but then this is a stupid API */
6001da177e4c3f41524e886b7f1b8a0c1fc7321cacLinus Torvalds		for (i = 0; i < MAX_NR_CONSOLES; ++i)
6011da177e4c3f41524e886b7f1b8a0c1fc7321cacLinus Torvalds			if (! VT_IS_IN_USE(i))
6021da177e4c3f41524e886b7f1b8a0c1fc7321cacLinus Torvalds				break;
6031e0ad2881d50becaeea70ec696a80afeadf944d2Graham Gower		uival = i < MAX_NR_CONSOLES ? (i+1) : -1;
6041da177e4c3f41524e886b7f1b8a0c1fc7321cacLinus Torvalds		goto setint;
6051da177e4c3f41524e886b7f1b8a0c1fc7321cacLinus Torvalds
6061da177e4c3f41524e886b7f1b8a0c1fc7321cacLinus Torvalds	/*
6071da177e4c3f41524e886b7f1b8a0c1fc7321cacLinus Torvalds	 * ioctl(fd, VT_ACTIVATE, num) will cause us to switch to vt # num,
6081da177e4c3f41524e886b7f1b8a0c1fc7321cacLinus Torvalds	 * with num >= 1 (switches to vt 0, our console, are not allowed, just
6091da177e4c3f41524e886b7f1b8a0c1fc7321cacLinus Torvalds	 * to preserve sanity).
6101da177e4c3f41524e886b7f1b8a0c1fc7321cacLinus Torvalds	 */
6111da177e4c3f41524e886b7f1b8a0c1fc7321cacLinus Torvalds	case VT_ACTIVATE:
6121da177e4c3f41524e886b7f1b8a0c1fc7321cacLinus Torvalds		if (!perm)
6134001d7b7fc271052ebff43f327c26dc64806bbdfAlan Cox			return -EPERM;
6141da177e4c3f41524e886b7f1b8a0c1fc7321cacLinus Torvalds		if (arg == 0 || arg > MAX_NR_CONSOLES)
6159cc3c22bf017f33612748aeb466fdc3695fb1e1dAlan Cox			ret =  -ENXIO;
6169cc3c22bf017f33612748aeb466fdc3695fb1e1dAlan Cox		else {
6179cc3c22bf017f33612748aeb466fdc3695fb1e1dAlan Cox			arg--;
618ac751efa6a0d70f2c9daef5c7e3a92270f5c2dffTorben Hohn			console_lock();
6199cc3c22bf017f33612748aeb466fdc3695fb1e1dAlan Cox			ret = vc_allocate(arg);
620ac751efa6a0d70f2c9daef5c7e3a92270f5c2dffTorben Hohn			console_unlock();
6219cc3c22bf017f33612748aeb466fdc3695fb1e1dAlan Cox			if (ret)
6229cc3c22bf017f33612748aeb466fdc3695fb1e1dAlan Cox				break;
6239cc3c22bf017f33612748aeb466fdc3695fb1e1dAlan Cox			set_console(arg);
6249cc3c22bf017f33612748aeb466fdc3695fb1e1dAlan Cox		}
6259cc3c22bf017f33612748aeb466fdc3695fb1e1dAlan Cox		break;
6261da177e4c3f41524e886b7f1b8a0c1fc7321cacLinus Torvalds
627d3b5cffcf84a8bdc7073dce4745d67c72629af85Alan Cox	case VT_SETACTIVATE:
628d3b5cffcf84a8bdc7073dce4745d67c72629af85Alan Cox	{
629d3b5cffcf84a8bdc7073dce4745d67c72629af85Alan Cox		struct vt_setactivate vsa;
630d3b5cffcf84a8bdc7073dce4745d67c72629af85Alan Cox
631d3b5cffcf84a8bdc7073dce4745d67c72629af85Alan Cox		if (!perm)
6324001d7b7fc271052ebff43f327c26dc64806bbdfAlan Cox			return -EPERM;
633d3b5cffcf84a8bdc7073dce4745d67c72629af85Alan Cox
634d3b5cffcf84a8bdc7073dce4745d67c72629af85Alan Cox		if (copy_from_user(&vsa, (struct vt_setactivate __user *)arg,
635a09efb07b5025fb75f42e903d31767a3cafede89Jiri Slaby					sizeof(struct vt_setactivate))) {
636a09efb07b5025fb75f42e903d31767a3cafede89Jiri Slaby			ret = -EFAULT;
637a09efb07b5025fb75f42e903d31767a3cafede89Jiri Slaby			goto out;
638a09efb07b5025fb75f42e903d31767a3cafede89Jiri Slaby		}
639d3b5cffcf84a8bdc7073dce4745d67c72629af85Alan Cox		if (vsa.console == 0 || vsa.console > MAX_NR_CONSOLES)
640d3b5cffcf84a8bdc7073dce4745d67c72629af85Alan Cox			ret = -ENXIO;
641d3b5cffcf84a8bdc7073dce4745d67c72629af85Alan Cox		else {
642d3b5cffcf84a8bdc7073dce4745d67c72629af85Alan Cox			vsa.console--;
643ac751efa6a0d70f2c9daef5c7e3a92270f5c2dffTorben Hohn			console_lock();
644d3b5cffcf84a8bdc7073dce4745d67c72629af85Alan Cox			ret = vc_allocate(vsa.console);
645d3b5cffcf84a8bdc7073dce4745d67c72629af85Alan Cox			if (ret == 0) {
646d3b5cffcf84a8bdc7073dce4745d67c72629af85Alan Cox				struct vc_data *nvc;
647d3b5cffcf84a8bdc7073dce4745d67c72629af85Alan Cox				/* This is safe providing we don't drop the
648d3b5cffcf84a8bdc7073dce4745d67c72629af85Alan Cox				   console sem between vc_allocate and
649d3b5cffcf84a8bdc7073dce4745d67c72629af85Alan Cox				   finishing referencing nvc */
650d3b5cffcf84a8bdc7073dce4745d67c72629af85Alan Cox				nvc = vc_cons[vsa.console].d;
651d3b5cffcf84a8bdc7073dce4745d67c72629af85Alan Cox				nvc->vt_mode = vsa.mode;
652d3b5cffcf84a8bdc7073dce4745d67c72629af85Alan Cox				nvc->vt_mode.frsig = 0;
653d3b5cffcf84a8bdc7073dce4745d67c72629af85Alan Cox				put_pid(nvc->vt_pid);
654d3b5cffcf84a8bdc7073dce4745d67c72629af85Alan Cox				nvc->vt_pid = get_pid(task_pid(current));
655d3b5cffcf84a8bdc7073dce4745d67c72629af85Alan Cox			}
656ac751efa6a0d70f2c9daef5c7e3a92270f5c2dffTorben Hohn			console_unlock();
657d3b5cffcf84a8bdc7073dce4745d67c72629af85Alan Cox			if (ret)
658d3b5cffcf84a8bdc7073dce4745d67c72629af85Alan Cox				break;
659d3b5cffcf84a8bdc7073dce4745d67c72629af85Alan Cox			/* Commence switch and lock */
6604001d7b7fc271052ebff43f327c26dc64806bbdfAlan Cox			/* Review set_console locks */
661d637837583163a1a70331ce48097f697cac85e32Jiri Olsa			set_console(vsa.console);
662d3b5cffcf84a8bdc7073dce4745d67c72629af85Alan Cox		}
663d637837583163a1a70331ce48097f697cac85e32Jiri Olsa		break;
664d3b5cffcf84a8bdc7073dce4745d67c72629af85Alan Cox	}
665d3b5cffcf84a8bdc7073dce4745d67c72629af85Alan Cox
6661da177e4c3f41524e886b7f1b8a0c1fc7321cacLinus Torvalds	/*
6671da177e4c3f41524e886b7f1b8a0c1fc7321cacLinus Torvalds	 * wait until the specified VT has been activated
6681da177e4c3f41524e886b7f1b8a0c1fc7321cacLinus Torvalds	 */
6691da177e4c3f41524e886b7f1b8a0c1fc7321cacLinus Torvalds	case VT_WAITACTIVE:
6701da177e4c3f41524e886b7f1b8a0c1fc7321cacLinus Torvalds		if (!perm)
6714001d7b7fc271052ebff43f327c26dc64806bbdfAlan Cox			return -EPERM;
6721da177e4c3f41524e886b7f1b8a0c1fc7321cacLinus Torvalds		if (arg == 0 || arg > MAX_NR_CONSOLES)
6739cc3c22bf017f33612748aeb466fdc3695fb1e1dAlan Cox			ret = -ENXIO;
67499cceb4e50cb67720e779f6611476bcb611af6b8Alan Cox		else
6758b92e87d39bfd046e7581e1fe0f40eac40f88608Alan Cox			ret = vt_waitactive(arg);
6769cc3c22bf017f33612748aeb466fdc3695fb1e1dAlan Cox		break;
6771da177e4c3f41524e886b7f1b8a0c1fc7321cacLinus Torvalds
6781da177e4c3f41524e886b7f1b8a0c1fc7321cacLinus Torvalds	/*
6791da177e4c3f41524e886b7f1b8a0c1fc7321cacLinus Torvalds	 * If a vt is under process control, the kernel will not switch to it
6801da177e4c3f41524e886b7f1b8a0c1fc7321cacLinus Torvalds	 * immediately, but postpone the operation until the process calls this
6811da177e4c3f41524e886b7f1b8a0c1fc7321cacLinus Torvalds	 * ioctl, allowing the switch to complete.
6821da177e4c3f41524e886b7f1b8a0c1fc7321cacLinus Torvalds	 *
6831da177e4c3f41524e886b7f1b8a0c1fc7321cacLinus Torvalds	 * According to the X sources this is the behavior:
6841da177e4c3f41524e886b7f1b8a0c1fc7321cacLinus Torvalds	 *	0:	pending switch-from not OK
6851da177e4c3f41524e886b7f1b8a0c1fc7321cacLinus Torvalds	 *	1:	pending switch-from OK
6861da177e4c3f41524e886b7f1b8a0c1fc7321cacLinus Torvalds	 *	2:	completed switch-to OK
6871da177e4c3f41524e886b7f1b8a0c1fc7321cacLinus Torvalds	 */
6881da177e4c3f41524e886b7f1b8a0c1fc7321cacLinus Torvalds	case VT_RELDISP:
6891da177e4c3f41524e886b7f1b8a0c1fc7321cacLinus Torvalds		if (!perm)
6904001d7b7fc271052ebff43f327c26dc64806bbdfAlan Cox			return -EPERM;
6911da177e4c3f41524e886b7f1b8a0c1fc7321cacLinus Torvalds
6924001d7b7fc271052ebff43f327c26dc64806bbdfAlan Cox		console_lock();
6939cc3c22bf017f33612748aeb466fdc3695fb1e1dAlan Cox		if (vc->vt_mode.mode != VT_PROCESS) {
6944001d7b7fc271052ebff43f327c26dc64806bbdfAlan Cox			console_unlock();
6959cc3c22bf017f33612748aeb466fdc3695fb1e1dAlan Cox			ret = -EINVAL;
6969cc3c22bf017f33612748aeb466fdc3695fb1e1dAlan Cox			break;
6979cc3c22bf017f33612748aeb466fdc3695fb1e1dAlan Cox		}
6981da177e4c3f41524e886b7f1b8a0c1fc7321cacLinus Torvalds		/*
6991da177e4c3f41524e886b7f1b8a0c1fc7321cacLinus Torvalds		 * Switching-from response
7001da177e4c3f41524e886b7f1b8a0c1fc7321cacLinus Torvalds		 */
7011da177e4c3f41524e886b7f1b8a0c1fc7321cacLinus Torvalds		if (vc->vt_newvt >= 0) {
7021da177e4c3f41524e886b7f1b8a0c1fc7321cacLinus Torvalds			if (arg == 0)
7031da177e4c3f41524e886b7f1b8a0c1fc7321cacLinus Torvalds				/*
7041da177e4c3f41524e886b7f1b8a0c1fc7321cacLinus Torvalds				 * Switch disallowed, so forget we were trying
7051da177e4c3f41524e886b7f1b8a0c1fc7321cacLinus Torvalds				 * to do it.
7061da177e4c3f41524e886b7f1b8a0c1fc7321cacLinus Torvalds				 */
7071da177e4c3f41524e886b7f1b8a0c1fc7321cacLinus Torvalds				vc->vt_newvt = -1;
7081da177e4c3f41524e886b7f1b8a0c1fc7321cacLinus Torvalds
7091da177e4c3f41524e886b7f1b8a0c1fc7321cacLinus Torvalds			else {
7101da177e4c3f41524e886b7f1b8a0c1fc7321cacLinus Torvalds				/*
7111da177e4c3f41524e886b7f1b8a0c1fc7321cacLinus Torvalds				 * The current vt has been released, so
7121da177e4c3f41524e886b7f1b8a0c1fc7321cacLinus Torvalds				 * complete the switch.
7131da177e4c3f41524e886b7f1b8a0c1fc7321cacLinus Torvalds				 */
7141da177e4c3f41524e886b7f1b8a0c1fc7321cacLinus Torvalds				int newvt;
7151da177e4c3f41524e886b7f1b8a0c1fc7321cacLinus Torvalds				newvt = vc->vt_newvt;
7161da177e4c3f41524e886b7f1b8a0c1fc7321cacLinus Torvalds				vc->vt_newvt = -1;
7179cc3c22bf017f33612748aeb466fdc3695fb1e1dAlan Cox				ret = vc_allocate(newvt);
7189cc3c22bf017f33612748aeb466fdc3695fb1e1dAlan Cox				if (ret) {
719ac751efa6a0d70f2c9daef5c7e3a92270f5c2dffTorben Hohn					console_unlock();
7209cc3c22bf017f33612748aeb466fdc3695fb1e1dAlan Cox					break;
7211da177e4c3f41524e886b7f1b8a0c1fc7321cacLinus Torvalds				}
7221da177e4c3f41524e886b7f1b8a0c1fc7321cacLinus Torvalds				/*
7231da177e4c3f41524e886b7f1b8a0c1fc7321cacLinus Torvalds				 * When we actually do the console switch,
7241da177e4c3f41524e886b7f1b8a0c1fc7321cacLinus Torvalds				 * make sure we are atomic with respect to
7251da177e4c3f41524e886b7f1b8a0c1fc7321cacLinus Torvalds				 * other console switches..
7261da177e4c3f41524e886b7f1b8a0c1fc7321cacLinus Torvalds				 */
7271da177e4c3f41524e886b7f1b8a0c1fc7321cacLinus Torvalds				complete_change_console(vc_cons[newvt].d);
7281da177e4c3f41524e886b7f1b8a0c1fc7321cacLinus Torvalds			}
7299cc3c22bf017f33612748aeb466fdc3695fb1e1dAlan Cox		} else {
7309cc3c22bf017f33612748aeb466fdc3695fb1e1dAlan Cox			/*
7319cc3c22bf017f33612748aeb466fdc3695fb1e1dAlan Cox			 * Switched-to response
7329cc3c22bf017f33612748aeb466fdc3695fb1e1dAlan Cox			 */
7331da177e4c3f41524e886b7f1b8a0c1fc7321cacLinus Torvalds			/*
7341da177e4c3f41524e886b7f1b8a0c1fc7321cacLinus Torvalds			 * If it's just an ACK, ignore it
7351da177e4c3f41524e886b7f1b8a0c1fc7321cacLinus Torvalds			 */
7369cc3c22bf017f33612748aeb466fdc3695fb1e1dAlan Cox			if (arg != VT_ACKACQ)
7379cc3c22bf017f33612748aeb466fdc3695fb1e1dAlan Cox				ret = -EINVAL;
7381da177e4c3f41524e886b7f1b8a0c1fc7321cacLinus Torvalds		}
739ac751efa6a0d70f2c9daef5c7e3a92270f5c2dffTorben Hohn		console_unlock();
7409cc3c22bf017f33612748aeb466fdc3695fb1e1dAlan Cox		break;
7411da177e4c3f41524e886b7f1b8a0c1fc7321cacLinus Torvalds
7421da177e4c3f41524e886b7f1b8a0c1fc7321cacLinus Torvalds	 /*
7431da177e4c3f41524e886b7f1b8a0c1fc7321cacLinus Torvalds	  * Disallocate memory associated to VT (but leave VT1)
7441da177e4c3f41524e886b7f1b8a0c1fc7321cacLinus Torvalds	  */
7451da177e4c3f41524e886b7f1b8a0c1fc7321cacLinus Torvalds	 case VT_DISALLOCATE:
7469cc3c22bf017f33612748aeb466fdc3695fb1e1dAlan Cox		if (arg > MAX_NR_CONSOLES) {
7479cc3c22bf017f33612748aeb466fdc3695fb1e1dAlan Cox			ret = -ENXIO;
7489cc3c22bf017f33612748aeb466fdc3695fb1e1dAlan Cox			break;
7499cc3c22bf017f33612748aeb466fdc3695fb1e1dAlan Cox		}
7501da177e4c3f41524e886b7f1b8a0c1fc7321cacLinus Torvalds		if (arg == 0) {
751ca9bda00b4aafc42cd3d1b9d32934463e2993b4cAlan Cox		    /* deallocate all unused consoles, but leave 0 */
752ac751efa6a0d70f2c9daef5c7e3a92270f5c2dffTorben Hohn			console_lock();
7531da177e4c3f41524e886b7f1b8a0c1fc7321cacLinus Torvalds			for (i=1; i<MAX_NR_CONSOLES; i++)
7541da177e4c3f41524e886b7f1b8a0c1fc7321cacLinus Torvalds				if (! VT_BUSY(i))
755ca9bda00b4aafc42cd3d1b9d32934463e2993b4cAlan Cox					vc_deallocate(i);
756ac751efa6a0d70f2c9daef5c7e3a92270f5c2dffTorben Hohn			console_unlock();
7571da177e4c3f41524e886b7f1b8a0c1fc7321cacLinus Torvalds		} else {
758ca9bda00b4aafc42cd3d1b9d32934463e2993b4cAlan Cox			/* deallocate a single console, if possible */
7591da177e4c3f41524e886b7f1b8a0c1fc7321cacLinus Torvalds			arg--;
7601da177e4c3f41524e886b7f1b8a0c1fc7321cacLinus Torvalds			if (VT_BUSY(arg))
7619cc3c22bf017f33612748aeb466fdc3695fb1e1dAlan Cox				ret = -EBUSY;
7629cc3c22bf017f33612748aeb466fdc3695fb1e1dAlan Cox			else if (arg) {			      /* leave 0 */
763ac751efa6a0d70f2c9daef5c7e3a92270f5c2dffTorben Hohn				console_lock();
764ca9bda00b4aafc42cd3d1b9d32934463e2993b4cAlan Cox				vc_deallocate(arg);
765ac751efa6a0d70f2c9daef5c7e3a92270f5c2dffTorben Hohn				console_unlock();
7661da177e4c3f41524e886b7f1b8a0c1fc7321cacLinus Torvalds			}
7671da177e4c3f41524e886b7f1b8a0c1fc7321cacLinus Torvalds		}
7689cc3c22bf017f33612748aeb466fdc3695fb1e1dAlan Cox		break;
7691da177e4c3f41524e886b7f1b8a0c1fc7321cacLinus Torvalds
7701da177e4c3f41524e886b7f1b8a0c1fc7321cacLinus Torvalds	case VT_RESIZE:
7711da177e4c3f41524e886b7f1b8a0c1fc7321cacLinus Torvalds	{
7721da177e4c3f41524e886b7f1b8a0c1fc7321cacLinus Torvalds		struct vt_sizes __user *vtsizes = up;
773e400b6ec4ede4dc0aa8e5640425df5b29796fe0eAntonino A. Daplas		struct vc_data *vc;
774e400b6ec4ede4dc0aa8e5640425df5b29796fe0eAntonino A. Daplas
7751da177e4c3f41524e886b7f1b8a0c1fc7321cacLinus Torvalds		ushort ll,cc;
7761da177e4c3f41524e886b7f1b8a0c1fc7321cacLinus Torvalds		if (!perm)
7774001d7b7fc271052ebff43f327c26dc64806bbdfAlan Cox			return -EPERM;
7781da177e4c3f41524e886b7f1b8a0c1fc7321cacLinus Torvalds		if (get_user(ll, &vtsizes->v_rows) ||
7791da177e4c3f41524e886b7f1b8a0c1fc7321cacLinus Torvalds		    get_user(cc, &vtsizes->v_cols))
7809cc3c22bf017f33612748aeb466fdc3695fb1e1dAlan Cox			ret = -EFAULT;
7819cc3c22bf017f33612748aeb466fdc3695fb1e1dAlan Cox		else {
782ac751efa6a0d70f2c9daef5c7e3a92270f5c2dffTorben Hohn			console_lock();
7839cc3c22bf017f33612748aeb466fdc3695fb1e1dAlan Cox			for (i = 0; i < MAX_NR_CONSOLES; i++) {
7849cc3c22bf017f33612748aeb466fdc3695fb1e1dAlan Cox				vc = vc_cons[i].d;
785e400b6ec4ede4dc0aa8e5640425df5b29796fe0eAntonino A. Daplas
7869cc3c22bf017f33612748aeb466fdc3695fb1e1dAlan Cox				if (vc) {
7879cc3c22bf017f33612748aeb466fdc3695fb1e1dAlan Cox					vc->vc_resize_user = 1;
7884001d7b7fc271052ebff43f327c26dc64806bbdfAlan Cox					/* FIXME: review v tty lock */
7898c9a9dd0fa3a269d380eaae2dc1bee39e865fae1Alan Cox					vc_resize(vc_cons[i].d, cc, ll);
7909cc3c22bf017f33612748aeb466fdc3695fb1e1dAlan Cox				}
791e400b6ec4ede4dc0aa8e5640425df5b29796fe0eAntonino A. Daplas			}
792ac751efa6a0d70f2c9daef5c7e3a92270f5c2dffTorben Hohn			console_unlock();
793e400b6ec4ede4dc0aa8e5640425df5b29796fe0eAntonino A. Daplas		}
7949cc3c22bf017f33612748aeb466fdc3695fb1e1dAlan Cox		break;
7951da177e4c3f41524e886b7f1b8a0c1fc7321cacLinus Torvalds	}
7961da177e4c3f41524e886b7f1b8a0c1fc7321cacLinus Torvalds
7971da177e4c3f41524e886b7f1b8a0c1fc7321cacLinus Torvalds	case VT_RESIZEX:
7981da177e4c3f41524e886b7f1b8a0c1fc7321cacLinus Torvalds	{
7991da177e4c3f41524e886b7f1b8a0c1fc7321cacLinus Torvalds		struct vt_consize __user *vtconsize = up;
8001da177e4c3f41524e886b7f1b8a0c1fc7321cacLinus Torvalds		ushort ll,cc,vlin,clin,vcol,ccol;
8011da177e4c3f41524e886b7f1b8a0c1fc7321cacLinus Torvalds		if (!perm)
8024001d7b7fc271052ebff43f327c26dc64806bbdfAlan Cox			return -EPERM;
8031da177e4c3f41524e886b7f1b8a0c1fc7321cacLinus Torvalds		if (!access_ok(VERIFY_READ, vtconsize,
8049cc3c22bf017f33612748aeb466fdc3695fb1e1dAlan Cox				sizeof(struct vt_consize))) {
8059cc3c22bf017f33612748aeb466fdc3695fb1e1dAlan Cox			ret = -EFAULT;
8069cc3c22bf017f33612748aeb466fdc3695fb1e1dAlan Cox			break;
8079cc3c22bf017f33612748aeb466fdc3695fb1e1dAlan Cox		}
8089cc3c22bf017f33612748aeb466fdc3695fb1e1dAlan Cox		/* FIXME: Should check the copies properly */
8091da177e4c3f41524e886b7f1b8a0c1fc7321cacLinus Torvalds		__get_user(ll, &vtconsize->v_rows);
8101da177e4c3f41524e886b7f1b8a0c1fc7321cacLinus Torvalds		__get_user(cc, &vtconsize->v_cols);
8111da177e4c3f41524e886b7f1b8a0c1fc7321cacLinus Torvalds		__get_user(vlin, &vtconsize->v_vlin);
8121da177e4c3f41524e886b7f1b8a0c1fc7321cacLinus Torvalds		__get_user(clin, &vtconsize->v_clin);
8131da177e4c3f41524e886b7f1b8a0c1fc7321cacLinus Torvalds		__get_user(vcol, &vtconsize->v_vcol);
8141da177e4c3f41524e886b7f1b8a0c1fc7321cacLinus Torvalds		__get_user(ccol, &vtconsize->v_ccol);
8151da177e4c3f41524e886b7f1b8a0c1fc7321cacLinus Torvalds		vlin = vlin ? vlin : vc->vc_scan_lines;
8161da177e4c3f41524e886b7f1b8a0c1fc7321cacLinus Torvalds		if (clin) {
8171da177e4c3f41524e886b7f1b8a0c1fc7321cacLinus Torvalds			if (ll) {
8189cc3c22bf017f33612748aeb466fdc3695fb1e1dAlan Cox				if (ll != vlin/clin) {
8199cc3c22bf017f33612748aeb466fdc3695fb1e1dAlan Cox					/* Parameters don't add up */
8209cc3c22bf017f33612748aeb466fdc3695fb1e1dAlan Cox					ret = -EINVAL;
8219cc3c22bf017f33612748aeb466fdc3695fb1e1dAlan Cox					break;
8229cc3c22bf017f33612748aeb466fdc3695fb1e1dAlan Cox				}
8231da177e4c3f41524e886b7f1b8a0c1fc7321cacLinus Torvalds			} else
8241da177e4c3f41524e886b7f1b8a0c1fc7321cacLinus Torvalds				ll = vlin/clin;
8251da177e4c3f41524e886b7f1b8a0c1fc7321cacLinus Torvalds		}
8261da177e4c3f41524e886b7f1b8a0c1fc7321cacLinus Torvalds		if (vcol && ccol) {
8271da177e4c3f41524e886b7f1b8a0c1fc7321cacLinus Torvalds			if (cc) {
8289cc3c22bf017f33612748aeb466fdc3695fb1e1dAlan Cox				if (cc != vcol/ccol) {
8299cc3c22bf017f33612748aeb466fdc3695fb1e1dAlan Cox					ret = -EINVAL;
8309cc3c22bf017f33612748aeb466fdc3695fb1e1dAlan Cox					break;
8319cc3c22bf017f33612748aeb466fdc3695fb1e1dAlan Cox				}
8321da177e4c3f41524e886b7f1b8a0c1fc7321cacLinus Torvalds			} else
8331da177e4c3f41524e886b7f1b8a0c1fc7321cacLinus Torvalds				cc = vcol/ccol;
8341da177e4c3f41524e886b7f1b8a0c1fc7321cacLinus Torvalds		}
8351da177e4c3f41524e886b7f1b8a0c1fc7321cacLinus Torvalds
8369cc3c22bf017f33612748aeb466fdc3695fb1e1dAlan Cox		if (clin > 32) {
8379cc3c22bf017f33612748aeb466fdc3695fb1e1dAlan Cox			ret =  -EINVAL;
8389cc3c22bf017f33612748aeb466fdc3695fb1e1dAlan Cox			break;
8399cc3c22bf017f33612748aeb466fdc3695fb1e1dAlan Cox		}
8401da177e4c3f41524e886b7f1b8a0c1fc7321cacLinus Torvalds
8411da177e4c3f41524e886b7f1b8a0c1fc7321cacLinus Torvalds		for (i = 0; i < MAX_NR_CONSOLES; i++) {
8421da177e4c3f41524e886b7f1b8a0c1fc7321cacLinus Torvalds			if (!vc_cons[i].d)
8431da177e4c3f41524e886b7f1b8a0c1fc7321cacLinus Torvalds				continue;
844ac751efa6a0d70f2c9daef5c7e3a92270f5c2dffTorben Hohn			console_lock();
8451da177e4c3f41524e886b7f1b8a0c1fc7321cacLinus Torvalds			if (vlin)
8461da177e4c3f41524e886b7f1b8a0c1fc7321cacLinus Torvalds				vc_cons[i].d->vc_scan_lines = vlin;
8471da177e4c3f41524e886b7f1b8a0c1fc7321cacLinus Torvalds			if (clin)
8481da177e4c3f41524e886b7f1b8a0c1fc7321cacLinus Torvalds				vc_cons[i].d->vc_font.height = clin;
849e400b6ec4ede4dc0aa8e5640425df5b29796fe0eAntonino A. Daplas			vc_cons[i].d->vc_resize_user = 1;
8501da177e4c3f41524e886b7f1b8a0c1fc7321cacLinus Torvalds			vc_resize(vc_cons[i].d, cc, ll);
851ac751efa6a0d70f2c9daef5c7e3a92270f5c2dffTorben Hohn			console_unlock();
8521da177e4c3f41524e886b7f1b8a0c1fc7321cacLinus Torvalds		}
8539cc3c22bf017f33612748aeb466fdc3695fb1e1dAlan Cox		break;
8541da177e4c3f41524e886b7f1b8a0c1fc7321cacLinus Torvalds	}
8551da177e4c3f41524e886b7f1b8a0c1fc7321cacLinus Torvalds
8561da177e4c3f41524e886b7f1b8a0c1fc7321cacLinus Torvalds	case PIO_FONT: {
8571da177e4c3f41524e886b7f1b8a0c1fc7321cacLinus Torvalds		if (!perm)
8584001d7b7fc271052ebff43f327c26dc64806bbdfAlan Cox			return -EPERM;
8591da177e4c3f41524e886b7f1b8a0c1fc7321cacLinus Torvalds		op.op = KD_FONT_OP_SET;
8601da177e4c3f41524e886b7f1b8a0c1fc7321cacLinus Torvalds		op.flags = KD_FONT_FLAG_OLD | KD_FONT_FLAG_DONT_RECALC;	/* Compatibility */
8611da177e4c3f41524e886b7f1b8a0c1fc7321cacLinus Torvalds		op.width = 8;
8621da177e4c3f41524e886b7f1b8a0c1fc7321cacLinus Torvalds		op.height = 0;
8631da177e4c3f41524e886b7f1b8a0c1fc7321cacLinus Torvalds		op.charcount = 256;
8641da177e4c3f41524e886b7f1b8a0c1fc7321cacLinus Torvalds		op.data = up;
8659cc3c22bf017f33612748aeb466fdc3695fb1e1dAlan Cox		ret = con_font_op(vc_cons[fg_console].d, &op);
8669cc3c22bf017f33612748aeb466fdc3695fb1e1dAlan Cox		break;
8671da177e4c3f41524e886b7f1b8a0c1fc7321cacLinus Torvalds	}
8681da177e4c3f41524e886b7f1b8a0c1fc7321cacLinus Torvalds
8691da177e4c3f41524e886b7f1b8a0c1fc7321cacLinus Torvalds	case GIO_FONT: {
8701da177e4c3f41524e886b7f1b8a0c1fc7321cacLinus Torvalds		op.op = KD_FONT_OP_GET;
8711da177e4c3f41524e886b7f1b8a0c1fc7321cacLinus Torvalds		op.flags = KD_FONT_FLAG_OLD;
8721da177e4c3f41524e886b7f1b8a0c1fc7321cacLinus Torvalds		op.width = 8;
8731da177e4c3f41524e886b7f1b8a0c1fc7321cacLinus Torvalds		op.height = 32;
8741da177e4c3f41524e886b7f1b8a0c1fc7321cacLinus Torvalds		op.charcount = 256;
8751da177e4c3f41524e886b7f1b8a0c1fc7321cacLinus Torvalds		op.data = up;
8769cc3c22bf017f33612748aeb466fdc3695fb1e1dAlan Cox		ret = con_font_op(vc_cons[fg_console].d, &op);
8779cc3c22bf017f33612748aeb466fdc3695fb1e1dAlan Cox		break;
8781da177e4c3f41524e886b7f1b8a0c1fc7321cacLinus Torvalds	}
8791da177e4c3f41524e886b7f1b8a0c1fc7321cacLinus Torvalds
8801da177e4c3f41524e886b7f1b8a0c1fc7321cacLinus Torvalds	case PIO_CMAP:
8811da177e4c3f41524e886b7f1b8a0c1fc7321cacLinus Torvalds                if (!perm)
8829cc3c22bf017f33612748aeb466fdc3695fb1e1dAlan Cox			ret = -EPERM;
8839cc3c22bf017f33612748aeb466fdc3695fb1e1dAlan Cox		else
8849cc3c22bf017f33612748aeb466fdc3695fb1e1dAlan Cox	                ret = con_set_cmap(up);
8859cc3c22bf017f33612748aeb466fdc3695fb1e1dAlan Cox		break;
8861da177e4c3f41524e886b7f1b8a0c1fc7321cacLinus Torvalds
8871da177e4c3f41524e886b7f1b8a0c1fc7321cacLinus Torvalds	case GIO_CMAP:
8889cc3c22bf017f33612748aeb466fdc3695fb1e1dAlan Cox                ret = con_get_cmap(up);
8899cc3c22bf017f33612748aeb466fdc3695fb1e1dAlan Cox		break;
8901da177e4c3f41524e886b7f1b8a0c1fc7321cacLinus Torvalds
8911da177e4c3f41524e886b7f1b8a0c1fc7321cacLinus Torvalds	case PIO_FONTX:
8921da177e4c3f41524e886b7f1b8a0c1fc7321cacLinus Torvalds	case GIO_FONTX:
8939cc3c22bf017f33612748aeb466fdc3695fb1e1dAlan Cox		ret = do_fontx_ioctl(cmd, up, perm, &op);
8949cc3c22bf017f33612748aeb466fdc3695fb1e1dAlan Cox		break;
8951da177e4c3f41524e886b7f1b8a0c1fc7321cacLinus Torvalds
8961da177e4c3f41524e886b7f1b8a0c1fc7321cacLinus Torvalds	case PIO_FONTRESET:
8971da177e4c3f41524e886b7f1b8a0c1fc7321cacLinus Torvalds	{
8981da177e4c3f41524e886b7f1b8a0c1fc7321cacLinus Torvalds		if (!perm)
8994001d7b7fc271052ebff43f327c26dc64806bbdfAlan Cox			return -EPERM;
9001da177e4c3f41524e886b7f1b8a0c1fc7321cacLinus Torvalds
9011da177e4c3f41524e886b7f1b8a0c1fc7321cacLinus Torvalds#ifdef BROKEN_GRAPHICS_PROGRAMS
9021da177e4c3f41524e886b7f1b8a0c1fc7321cacLinus Torvalds		/* With BROKEN_GRAPHICS_PROGRAMS defined, the default
9031da177e4c3f41524e886b7f1b8a0c1fc7321cacLinus Torvalds		   font is not saved. */
9049cc3c22bf017f33612748aeb466fdc3695fb1e1dAlan Cox		ret = -ENOSYS;
9059cc3c22bf017f33612748aeb466fdc3695fb1e1dAlan Cox		break;
9061da177e4c3f41524e886b7f1b8a0c1fc7321cacLinus Torvalds#else
9071da177e4c3f41524e886b7f1b8a0c1fc7321cacLinus Torvalds		{
9081da177e4c3f41524e886b7f1b8a0c1fc7321cacLinus Torvalds		op.op = KD_FONT_OP_SET_DEFAULT;
9091da177e4c3f41524e886b7f1b8a0c1fc7321cacLinus Torvalds		op.data = NULL;
9109cc3c22bf017f33612748aeb466fdc3695fb1e1dAlan Cox		ret = con_font_op(vc_cons[fg_console].d, &op);
9119cc3c22bf017f33612748aeb466fdc3695fb1e1dAlan Cox		if (ret)
9129cc3c22bf017f33612748aeb466fdc3695fb1e1dAlan Cox			break;
9131da177e4c3f41524e886b7f1b8a0c1fc7321cacLinus Torvalds		con_set_default_unimap(vc_cons[fg_console].d);
9149cc3c22bf017f33612748aeb466fdc3695fb1e1dAlan Cox		break;
9151da177e4c3f41524e886b7f1b8a0c1fc7321cacLinus Torvalds		}
9161da177e4c3f41524e886b7f1b8a0c1fc7321cacLinus Torvalds#endif
9171da177e4c3f41524e886b7f1b8a0c1fc7321cacLinus Torvalds	}
9181da177e4c3f41524e886b7f1b8a0c1fc7321cacLinus Torvalds
9191da177e4c3f41524e886b7f1b8a0c1fc7321cacLinus Torvalds	case KDFONTOP: {
9209cc3c22bf017f33612748aeb466fdc3695fb1e1dAlan Cox		if (copy_from_user(&op, up, sizeof(op))) {
9219cc3c22bf017f33612748aeb466fdc3695fb1e1dAlan Cox			ret = -EFAULT;
9229cc3c22bf017f33612748aeb466fdc3695fb1e1dAlan Cox			break;
9239cc3c22bf017f33612748aeb466fdc3695fb1e1dAlan Cox		}
9241da177e4c3f41524e886b7f1b8a0c1fc7321cacLinus Torvalds		if (!perm && op.op != KD_FONT_OP_GET)
9254001d7b7fc271052ebff43f327c26dc64806bbdfAlan Cox			return -EPERM;
9269cc3c22bf017f33612748aeb466fdc3695fb1e1dAlan Cox		ret = con_font_op(vc, &op);
9279cc3c22bf017f33612748aeb466fdc3695fb1e1dAlan Cox		if (ret)
9289cc3c22bf017f33612748aeb466fdc3695fb1e1dAlan Cox			break;
9291da177e4c3f41524e886b7f1b8a0c1fc7321cacLinus Torvalds		if (copy_to_user(up, &op, sizeof(op)))
9309cc3c22bf017f33612748aeb466fdc3695fb1e1dAlan Cox			ret = -EFAULT;
9319cc3c22bf017f33612748aeb466fdc3695fb1e1dAlan Cox		break;
9321da177e4c3f41524e886b7f1b8a0c1fc7321cacLinus Torvalds	}
9331da177e4c3f41524e886b7f1b8a0c1fc7321cacLinus Torvalds
9341da177e4c3f41524e886b7f1b8a0c1fc7321cacLinus Torvalds	case PIO_SCRNMAP:
9351da177e4c3f41524e886b7f1b8a0c1fc7321cacLinus Torvalds		if (!perm)
9369cc3c22bf017f33612748aeb466fdc3695fb1e1dAlan Cox			ret = -EPERM;
9374001d7b7fc271052ebff43f327c26dc64806bbdfAlan Cox		else {
9384001d7b7fc271052ebff43f327c26dc64806bbdfAlan Cox			tty_lock();
9399cc3c22bf017f33612748aeb466fdc3695fb1e1dAlan Cox			ret = con_set_trans_old(up);
9404001d7b7fc271052ebff43f327c26dc64806bbdfAlan Cox			tty_unlock();
9414001d7b7fc271052ebff43f327c26dc64806bbdfAlan Cox		}
9429cc3c22bf017f33612748aeb466fdc3695fb1e1dAlan Cox		break;
9431da177e4c3f41524e886b7f1b8a0c1fc7321cacLinus Torvalds
9441da177e4c3f41524e886b7f1b8a0c1fc7321cacLinus Torvalds	case GIO_SCRNMAP:
9454001d7b7fc271052ebff43f327c26dc64806bbdfAlan Cox		tty_lock();
9469cc3c22bf017f33612748aeb466fdc3695fb1e1dAlan Cox		ret = con_get_trans_old(up);
9474001d7b7fc271052ebff43f327c26dc64806bbdfAlan Cox		tty_unlock();
9489cc3c22bf017f33612748aeb466fdc3695fb1e1dAlan Cox		break;
9491da177e4c3f41524e886b7f1b8a0c1fc7321cacLinus Torvalds
9501da177e4c3f41524e886b7f1b8a0c1fc7321cacLinus Torvalds	case PIO_UNISCRNMAP:
9511da177e4c3f41524e886b7f1b8a0c1fc7321cacLinus Torvalds		if (!perm)
9529cc3c22bf017f33612748aeb466fdc3695fb1e1dAlan Cox			ret = -EPERM;
9534001d7b7fc271052ebff43f327c26dc64806bbdfAlan Cox		else {
9544001d7b7fc271052ebff43f327c26dc64806bbdfAlan Cox			tty_lock();
9559cc3c22bf017f33612748aeb466fdc3695fb1e1dAlan Cox			ret = con_set_trans_new(up);
9564001d7b7fc271052ebff43f327c26dc64806bbdfAlan Cox			tty_unlock();
9574001d7b7fc271052ebff43f327c26dc64806bbdfAlan Cox		}
9589cc3c22bf017f33612748aeb466fdc3695fb1e1dAlan Cox		break;
9591da177e4c3f41524e886b7f1b8a0c1fc7321cacLinus Torvalds
9601da177e4c3f41524e886b7f1b8a0c1fc7321cacLinus Torvalds	case GIO_UNISCRNMAP:
9614001d7b7fc271052ebff43f327c26dc64806bbdfAlan Cox		tty_lock();
9629cc3c22bf017f33612748aeb466fdc3695fb1e1dAlan Cox		ret = con_get_trans_new(up);
9634001d7b7fc271052ebff43f327c26dc64806bbdfAlan Cox		tty_unlock();
9649cc3c22bf017f33612748aeb466fdc3695fb1e1dAlan Cox		break;
9651da177e4c3f41524e886b7f1b8a0c1fc7321cacLinus Torvalds
9661da177e4c3f41524e886b7f1b8a0c1fc7321cacLinus Torvalds	case PIO_UNIMAPCLR:
9671da177e4c3f41524e886b7f1b8a0c1fc7321cacLinus Torvalds	      { struct unimapinit ui;
9681da177e4c3f41524e886b7f1b8a0c1fc7321cacLinus Torvalds		if (!perm)
9694001d7b7fc271052ebff43f327c26dc64806bbdfAlan Cox			return -EPERM;
9709cc3c22bf017f33612748aeb466fdc3695fb1e1dAlan Cox		ret = copy_from_user(&ui, up, sizeof(struct unimapinit));
9713fde85df5421eb01f563fef6f111ba73ab0d120eDan Carpenter		if (ret)
9723fde85df5421eb01f563fef6f111ba73ab0d120eDan Carpenter			ret = -EFAULT;
9734001d7b7fc271052ebff43f327c26dc64806bbdfAlan Cox		else {
9744001d7b7fc271052ebff43f327c26dc64806bbdfAlan Cox			tty_lock();
9759cc3c22bf017f33612748aeb466fdc3695fb1e1dAlan Cox			con_clear_unimap(vc, &ui);
9764001d7b7fc271052ebff43f327c26dc64806bbdfAlan Cox			tty_unlock();
9774001d7b7fc271052ebff43f327c26dc64806bbdfAlan Cox		}
9789cc3c22bf017f33612748aeb466fdc3695fb1e1dAlan Cox		break;
9791da177e4c3f41524e886b7f1b8a0c1fc7321cacLinus Torvalds	      }
9801da177e4c3f41524e886b7f1b8a0c1fc7321cacLinus Torvalds
9811da177e4c3f41524e886b7f1b8a0c1fc7321cacLinus Torvalds	case PIO_UNIMAP:
9821da177e4c3f41524e886b7f1b8a0c1fc7321cacLinus Torvalds	case GIO_UNIMAP:
9834001d7b7fc271052ebff43f327c26dc64806bbdfAlan Cox		tty_lock();
9849cc3c22bf017f33612748aeb466fdc3695fb1e1dAlan Cox		ret = do_unimap_ioctl(cmd, up, perm, vc);
9854001d7b7fc271052ebff43f327c26dc64806bbdfAlan Cox		tty_unlock();
9869cc3c22bf017f33612748aeb466fdc3695fb1e1dAlan Cox		break;
9871da177e4c3f41524e886b7f1b8a0c1fc7321cacLinus Torvalds
9881da177e4c3f41524e886b7f1b8a0c1fc7321cacLinus Torvalds	case VT_LOCKSWITCH:
9891da177e4c3f41524e886b7f1b8a0c1fc7321cacLinus Torvalds		if (!capable(CAP_SYS_TTY_CONFIG))
9904001d7b7fc271052ebff43f327c26dc64806bbdfAlan Cox			return -EPERM;
9911da177e4c3f41524e886b7f1b8a0c1fc7321cacLinus Torvalds		vt_dont_switch = 1;
9929cc3c22bf017f33612748aeb466fdc3695fb1e1dAlan Cox		break;
9931da177e4c3f41524e886b7f1b8a0c1fc7321cacLinus Torvalds	case VT_UNLOCKSWITCH:
9941da177e4c3f41524e886b7f1b8a0c1fc7321cacLinus Torvalds		if (!capable(CAP_SYS_TTY_CONFIG))
9954001d7b7fc271052ebff43f327c26dc64806bbdfAlan Cox			return -EPERM;
9961da177e4c3f41524e886b7f1b8a0c1fc7321cacLinus Torvalds		vt_dont_switch = 0;
9979cc3c22bf017f33612748aeb466fdc3695fb1e1dAlan Cox		break;
998533475d3d48eb839be2b57f6b020150abae91063Samuel Thibault	case VT_GETHIFONTMASK:
9999cc3c22bf017f33612748aeb466fdc3695fb1e1dAlan Cox		ret = put_user(vc->vc_hi_font_mask,
10009cc3c22bf017f33612748aeb466fdc3695fb1e1dAlan Cox					(unsigned short __user *)arg);
10019cc3c22bf017f33612748aeb466fdc3695fb1e1dAlan Cox		break;
10028b92e87d39bfd046e7581e1fe0f40eac40f88608Alan Cox	case VT_WAITEVENT:
10038b92e87d39bfd046e7581e1fe0f40eac40f88608Alan Cox		ret = vt_event_wait_ioctl((struct vt_event __user *)arg);
10048b92e87d39bfd046e7581e1fe0f40eac40f88608Alan Cox		break;
10051da177e4c3f41524e886b7f1b8a0c1fc7321cacLinus Torvalds	default:
10069cc3c22bf017f33612748aeb466fdc3695fb1e1dAlan Cox		ret = -ENOIOCTLCMD;
10071da177e4c3f41524e886b7f1b8a0c1fc7321cacLinus Torvalds	}
10089cc3c22bf017f33612748aeb466fdc3695fb1e1dAlan Coxout:
10099cc3c22bf017f33612748aeb466fdc3695fb1e1dAlan Cox	return ret;
10101da177e4c3f41524e886b7f1b8a0c1fc7321cacLinus Torvalds}
10111da177e4c3f41524e886b7f1b8a0c1fc7321cacLinus Torvalds
10121da177e4c3f41524e886b7f1b8a0c1fc7321cacLinus Torvaldsvoid reset_vc(struct vc_data *vc)
10131da177e4c3f41524e886b7f1b8a0c1fc7321cacLinus Torvalds{
10141da177e4c3f41524e886b7f1b8a0c1fc7321cacLinus Torvalds	vc->vc_mode = KD_TEXT;
1015079c9534a96da9a85a2a2f9715851050fbfbf749Alan Cox	vt_reset_unicode(vc->vc_num);
10161da177e4c3f41524e886b7f1b8a0c1fc7321cacLinus Torvalds	vc->vt_mode.mode = VT_AUTO;
10171da177e4c3f41524e886b7f1b8a0c1fc7321cacLinus Torvalds	vc->vt_mode.waitv = 0;
10181da177e4c3f41524e886b7f1b8a0c1fc7321cacLinus Torvalds	vc->vt_mode.relsig = 0;
10191da177e4c3f41524e886b7f1b8a0c1fc7321cacLinus Torvalds	vc->vt_mode.acqsig = 0;
10201da177e4c3f41524e886b7f1b8a0c1fc7321cacLinus Torvalds	vc->vt_mode.frsig = 0;
10218b6312f4dcc1efe7975731b6c47dd134282bd9acEric W. Biederman	put_pid(vc->vt_pid);
10228b6312f4dcc1efe7975731b6c47dd134282bd9acEric W. Biederman	vc->vt_pid = NULL;
10231da177e4c3f41524e886b7f1b8a0c1fc7321cacLinus Torvalds	vc->vt_newvt = -1;
10241da177e4c3f41524e886b7f1b8a0c1fc7321cacLinus Torvalds	if (!in_interrupt())    /* Via keyboard.c:SAK() - akpm */
10251da177e4c3f41524e886b7f1b8a0c1fc7321cacLinus Torvalds		reset_palette(vc);
10261da177e4c3f41524e886b7f1b8a0c1fc7321cacLinus Torvalds}
10271da177e4c3f41524e886b7f1b8a0c1fc7321cacLinus Torvalds
10288b6312f4dcc1efe7975731b6c47dd134282bd9acEric W. Biedermanvoid vc_SAK(struct work_struct *work)
10298b6312f4dcc1efe7975731b6c47dd134282bd9acEric W. Biederman{
10308b6312f4dcc1efe7975731b6c47dd134282bd9acEric W. Biederman	struct vc *vc_con =
10318b6312f4dcc1efe7975731b6c47dd134282bd9acEric W. Biederman		container_of(work, struct vc, SAK_work);
10328b6312f4dcc1efe7975731b6c47dd134282bd9acEric W. Biederman	struct vc_data *vc;
10338b6312f4dcc1efe7975731b6c47dd134282bd9acEric W. Biederman	struct tty_struct *tty;
10348b6312f4dcc1efe7975731b6c47dd134282bd9acEric W. Biederman
1035ac751efa6a0d70f2c9daef5c7e3a92270f5c2dffTorben Hohn	console_lock();
10368b6312f4dcc1efe7975731b6c47dd134282bd9acEric W. Biederman	vc = vc_con->d;
10378b6312f4dcc1efe7975731b6c47dd134282bd9acEric W. Biederman	if (vc) {
1038079c9534a96da9a85a2a2f9715851050fbfbf749Alan Cox		/* FIXME: review tty ref counting */
10398ce73264b75be4d5ed480440ac32dfc1f25ff678Alan Cox		tty = vc->port.tty;
10408b6312f4dcc1efe7975731b6c47dd134282bd9acEric W. Biederman		/*
10418b6312f4dcc1efe7975731b6c47dd134282bd9acEric W. Biederman		 * SAK should also work in all raw modes and reset
10428b6312f4dcc1efe7975731b6c47dd134282bd9acEric W. Biederman		 * them properly.
10438b6312f4dcc1efe7975731b6c47dd134282bd9acEric W. Biederman		 */
10448b6312f4dcc1efe7975731b6c47dd134282bd9acEric W. Biederman		if (tty)
10458b6312f4dcc1efe7975731b6c47dd134282bd9acEric W. Biederman			__do_SAK(tty);
10468b6312f4dcc1efe7975731b6c47dd134282bd9acEric W. Biederman		reset_vc(vc);
10478b6312f4dcc1efe7975731b6c47dd134282bd9acEric W. Biederman	}
1048ac751efa6a0d70f2c9daef5c7e3a92270f5c2dffTorben Hohn	console_unlock();
10498b6312f4dcc1efe7975731b6c47dd134282bd9acEric W. Biederman}
10508b6312f4dcc1efe7975731b6c47dd134282bd9acEric W. Biederman
1051e92166517e3ca9bfb416f91e69cf0373b55b6edeArnd Bergmann#ifdef CONFIG_COMPAT
1052e92166517e3ca9bfb416f91e69cf0373b55b6edeArnd Bergmann
1053e92166517e3ca9bfb416f91e69cf0373b55b6edeArnd Bergmannstruct compat_consolefontdesc {
1054e92166517e3ca9bfb416f91e69cf0373b55b6edeArnd Bergmann	unsigned short charcount;       /* characters in font (256 or 512) */
1055e92166517e3ca9bfb416f91e69cf0373b55b6edeArnd Bergmann	unsigned short charheight;      /* scan lines per character (1-32) */
1056e92166517e3ca9bfb416f91e69cf0373b55b6edeArnd Bergmann	compat_caddr_t chardata;	/* font data in expanded form */
1057e92166517e3ca9bfb416f91e69cf0373b55b6edeArnd Bergmann};
1058e92166517e3ca9bfb416f91e69cf0373b55b6edeArnd Bergmann
1059e92166517e3ca9bfb416f91e69cf0373b55b6edeArnd Bergmannstatic inline int
1060e92166517e3ca9bfb416f91e69cf0373b55b6edeArnd Bergmanncompat_fontx_ioctl(int cmd, struct compat_consolefontdesc __user *user_cfd,
1061e92166517e3ca9bfb416f91e69cf0373b55b6edeArnd Bergmann			 int perm, struct console_font_op *op)
1062e92166517e3ca9bfb416f91e69cf0373b55b6edeArnd Bergmann{
1063e92166517e3ca9bfb416f91e69cf0373b55b6edeArnd Bergmann	struct compat_consolefontdesc cfdarg;
1064e92166517e3ca9bfb416f91e69cf0373b55b6edeArnd Bergmann	int i;
1065e92166517e3ca9bfb416f91e69cf0373b55b6edeArnd Bergmann
1066e92166517e3ca9bfb416f91e69cf0373b55b6edeArnd Bergmann	if (copy_from_user(&cfdarg, user_cfd, sizeof(struct compat_consolefontdesc)))
1067e92166517e3ca9bfb416f91e69cf0373b55b6edeArnd Bergmann		return -EFAULT;
1068e92166517e3ca9bfb416f91e69cf0373b55b6edeArnd Bergmann
1069e92166517e3ca9bfb416f91e69cf0373b55b6edeArnd Bergmann	switch (cmd) {
1070e92166517e3ca9bfb416f91e69cf0373b55b6edeArnd Bergmann	case PIO_FONTX:
1071e92166517e3ca9bfb416f91e69cf0373b55b6edeArnd Bergmann		if (!perm)
1072e92166517e3ca9bfb416f91e69cf0373b55b6edeArnd Bergmann			return -EPERM;
1073e92166517e3ca9bfb416f91e69cf0373b55b6edeArnd Bergmann		op->op = KD_FONT_OP_SET;
1074e92166517e3ca9bfb416f91e69cf0373b55b6edeArnd Bergmann		op->flags = KD_FONT_FLAG_OLD;
1075e92166517e3ca9bfb416f91e69cf0373b55b6edeArnd Bergmann		op->width = 8;
1076e92166517e3ca9bfb416f91e69cf0373b55b6edeArnd Bergmann		op->height = cfdarg.charheight;
1077e92166517e3ca9bfb416f91e69cf0373b55b6edeArnd Bergmann		op->charcount = cfdarg.charcount;
1078e92166517e3ca9bfb416f91e69cf0373b55b6edeArnd Bergmann		op->data = compat_ptr(cfdarg.chardata);
1079e92166517e3ca9bfb416f91e69cf0373b55b6edeArnd Bergmann		return con_font_op(vc_cons[fg_console].d, op);
1080e92166517e3ca9bfb416f91e69cf0373b55b6edeArnd Bergmann	case GIO_FONTX:
1081e92166517e3ca9bfb416f91e69cf0373b55b6edeArnd Bergmann		op->op = KD_FONT_OP_GET;
1082e92166517e3ca9bfb416f91e69cf0373b55b6edeArnd Bergmann		op->flags = KD_FONT_FLAG_OLD;
1083e92166517e3ca9bfb416f91e69cf0373b55b6edeArnd Bergmann		op->width = 8;
1084e92166517e3ca9bfb416f91e69cf0373b55b6edeArnd Bergmann		op->height = cfdarg.charheight;
1085e92166517e3ca9bfb416f91e69cf0373b55b6edeArnd Bergmann		op->charcount = cfdarg.charcount;
1086e92166517e3ca9bfb416f91e69cf0373b55b6edeArnd Bergmann		op->data = compat_ptr(cfdarg.chardata);
1087e92166517e3ca9bfb416f91e69cf0373b55b6edeArnd Bergmann		i = con_font_op(vc_cons[fg_console].d, op);
1088e92166517e3ca9bfb416f91e69cf0373b55b6edeArnd Bergmann		if (i)
1089e92166517e3ca9bfb416f91e69cf0373b55b6edeArnd Bergmann			return i;
1090e92166517e3ca9bfb416f91e69cf0373b55b6edeArnd Bergmann		cfdarg.charheight = op->height;
1091e92166517e3ca9bfb416f91e69cf0373b55b6edeArnd Bergmann		cfdarg.charcount = op->charcount;
1092e92166517e3ca9bfb416f91e69cf0373b55b6edeArnd Bergmann		if (copy_to_user(user_cfd, &cfdarg, sizeof(struct compat_consolefontdesc)))
1093e92166517e3ca9bfb416f91e69cf0373b55b6edeArnd Bergmann			return -EFAULT;
1094e92166517e3ca9bfb416f91e69cf0373b55b6edeArnd Bergmann		return 0;
1095e92166517e3ca9bfb416f91e69cf0373b55b6edeArnd Bergmann	}
1096e92166517e3ca9bfb416f91e69cf0373b55b6edeArnd Bergmann	return -EINVAL;
1097e92166517e3ca9bfb416f91e69cf0373b55b6edeArnd Bergmann}
1098e92166517e3ca9bfb416f91e69cf0373b55b6edeArnd Bergmann
1099e92166517e3ca9bfb416f91e69cf0373b55b6edeArnd Bergmannstruct compat_console_font_op {
1100e92166517e3ca9bfb416f91e69cf0373b55b6edeArnd Bergmann	compat_uint_t op;        /* operation code KD_FONT_OP_* */
1101e92166517e3ca9bfb416f91e69cf0373b55b6edeArnd Bergmann	compat_uint_t flags;     /* KD_FONT_FLAG_* */
1102e92166517e3ca9bfb416f91e69cf0373b55b6edeArnd Bergmann	compat_uint_t width, height;     /* font size */
1103e92166517e3ca9bfb416f91e69cf0373b55b6edeArnd Bergmann	compat_uint_t charcount;
1104e92166517e3ca9bfb416f91e69cf0373b55b6edeArnd Bergmann	compat_caddr_t data;    /* font data with height fixed to 32 */
1105e92166517e3ca9bfb416f91e69cf0373b55b6edeArnd Bergmann};
1106e92166517e3ca9bfb416f91e69cf0373b55b6edeArnd Bergmann
1107e92166517e3ca9bfb416f91e69cf0373b55b6edeArnd Bergmannstatic inline int
1108e92166517e3ca9bfb416f91e69cf0373b55b6edeArnd Bergmanncompat_kdfontop_ioctl(struct compat_console_font_op __user *fontop,
1109e92166517e3ca9bfb416f91e69cf0373b55b6edeArnd Bergmann			 int perm, struct console_font_op *op, struct vc_data *vc)
1110e92166517e3ca9bfb416f91e69cf0373b55b6edeArnd Bergmann{
1111e92166517e3ca9bfb416f91e69cf0373b55b6edeArnd Bergmann	int i;
1112e92166517e3ca9bfb416f91e69cf0373b55b6edeArnd Bergmann
1113e92166517e3ca9bfb416f91e69cf0373b55b6edeArnd Bergmann	if (copy_from_user(op, fontop, sizeof(struct compat_console_font_op)))
1114e92166517e3ca9bfb416f91e69cf0373b55b6edeArnd Bergmann		return -EFAULT;
1115e92166517e3ca9bfb416f91e69cf0373b55b6edeArnd Bergmann	if (!perm && op->op != KD_FONT_OP_GET)
1116e92166517e3ca9bfb416f91e69cf0373b55b6edeArnd Bergmann		return -EPERM;
1117e92166517e3ca9bfb416f91e69cf0373b55b6edeArnd Bergmann	op->data = compat_ptr(((struct compat_console_font_op *)op)->data);
1118e92166517e3ca9bfb416f91e69cf0373b55b6edeArnd Bergmann	i = con_font_op(vc, op);
1119e92166517e3ca9bfb416f91e69cf0373b55b6edeArnd Bergmann	if (i)
1120e92166517e3ca9bfb416f91e69cf0373b55b6edeArnd Bergmann		return i;
1121e92166517e3ca9bfb416f91e69cf0373b55b6edeArnd Bergmann	((struct compat_console_font_op *)op)->data = (unsigned long)op->data;
1122e92166517e3ca9bfb416f91e69cf0373b55b6edeArnd Bergmann	if (copy_to_user(fontop, op, sizeof(struct compat_console_font_op)))
1123e92166517e3ca9bfb416f91e69cf0373b55b6edeArnd Bergmann		return -EFAULT;
1124e92166517e3ca9bfb416f91e69cf0373b55b6edeArnd Bergmann	return 0;
1125e92166517e3ca9bfb416f91e69cf0373b55b6edeArnd Bergmann}
1126e92166517e3ca9bfb416f91e69cf0373b55b6edeArnd Bergmann
1127e92166517e3ca9bfb416f91e69cf0373b55b6edeArnd Bergmannstruct compat_unimapdesc {
1128e92166517e3ca9bfb416f91e69cf0373b55b6edeArnd Bergmann	unsigned short entry_ct;
1129e92166517e3ca9bfb416f91e69cf0373b55b6edeArnd Bergmann	compat_caddr_t entries;
1130e92166517e3ca9bfb416f91e69cf0373b55b6edeArnd Bergmann};
1131e92166517e3ca9bfb416f91e69cf0373b55b6edeArnd Bergmann
1132e92166517e3ca9bfb416f91e69cf0373b55b6edeArnd Bergmannstatic inline int
1133e92166517e3ca9bfb416f91e69cf0373b55b6edeArnd Bergmanncompat_unimap_ioctl(unsigned int cmd, struct compat_unimapdesc __user *user_ud,
1134e92166517e3ca9bfb416f91e69cf0373b55b6edeArnd Bergmann			 int perm, struct vc_data *vc)
1135e92166517e3ca9bfb416f91e69cf0373b55b6edeArnd Bergmann{
1136e92166517e3ca9bfb416f91e69cf0373b55b6edeArnd Bergmann	struct compat_unimapdesc tmp;
1137e92166517e3ca9bfb416f91e69cf0373b55b6edeArnd Bergmann	struct unipair __user *tmp_entries;
1138e92166517e3ca9bfb416f91e69cf0373b55b6edeArnd Bergmann
1139e92166517e3ca9bfb416f91e69cf0373b55b6edeArnd Bergmann	if (copy_from_user(&tmp, user_ud, sizeof tmp))
1140e92166517e3ca9bfb416f91e69cf0373b55b6edeArnd Bergmann		return -EFAULT;
1141e92166517e3ca9bfb416f91e69cf0373b55b6edeArnd Bergmann	tmp_entries = compat_ptr(tmp.entries);
1142e92166517e3ca9bfb416f91e69cf0373b55b6edeArnd Bergmann	if (tmp_entries)
1143e92166517e3ca9bfb416f91e69cf0373b55b6edeArnd Bergmann		if (!access_ok(VERIFY_WRITE, tmp_entries,
1144e92166517e3ca9bfb416f91e69cf0373b55b6edeArnd Bergmann				tmp.entry_ct*sizeof(struct unipair)))
1145e92166517e3ca9bfb416f91e69cf0373b55b6edeArnd Bergmann			return -EFAULT;
1146e92166517e3ca9bfb416f91e69cf0373b55b6edeArnd Bergmann	switch (cmd) {
1147e92166517e3ca9bfb416f91e69cf0373b55b6edeArnd Bergmann	case PIO_UNIMAP:
1148e92166517e3ca9bfb416f91e69cf0373b55b6edeArnd Bergmann		if (!perm)
1149e92166517e3ca9bfb416f91e69cf0373b55b6edeArnd Bergmann			return -EPERM;
1150e92166517e3ca9bfb416f91e69cf0373b55b6edeArnd Bergmann		return con_set_unimap(vc, tmp.entry_ct, tmp_entries);
1151e92166517e3ca9bfb416f91e69cf0373b55b6edeArnd Bergmann	case GIO_UNIMAP:
1152e92166517e3ca9bfb416f91e69cf0373b55b6edeArnd Bergmann		if (!perm && fg_console != vc->vc_num)
1153e92166517e3ca9bfb416f91e69cf0373b55b6edeArnd Bergmann			return -EPERM;
1154e92166517e3ca9bfb416f91e69cf0373b55b6edeArnd Bergmann		return con_get_unimap(vc, tmp.entry_ct, &(user_ud->entry_ct), tmp_entries);
1155e92166517e3ca9bfb416f91e69cf0373b55b6edeArnd Bergmann	}
1156e92166517e3ca9bfb416f91e69cf0373b55b6edeArnd Bergmann	return 0;
1157e92166517e3ca9bfb416f91e69cf0373b55b6edeArnd Bergmann}
1158e92166517e3ca9bfb416f91e69cf0373b55b6edeArnd Bergmann
11596caa76b7786891b42b66a0e61e2c2fff2c884620Alan Coxlong vt_compat_ioctl(struct tty_struct *tty,
1160e92166517e3ca9bfb416f91e69cf0373b55b6edeArnd Bergmann	     unsigned int cmd, unsigned long arg)
1161e92166517e3ca9bfb416f91e69cf0373b55b6edeArnd Bergmann{
1162e92166517e3ca9bfb416f91e69cf0373b55b6edeArnd Bergmann	struct vc_data *vc = tty->driver_data;
1163e92166517e3ca9bfb416f91e69cf0373b55b6edeArnd Bergmann	struct console_font_op op;	/* used in multiple places here */
1164e92166517e3ca9bfb416f91e69cf0373b55b6edeArnd Bergmann	unsigned int console;
1165e92166517e3ca9bfb416f91e69cf0373b55b6edeArnd Bergmann	void __user *up = (void __user *)arg;
1166e92166517e3ca9bfb416f91e69cf0373b55b6edeArnd Bergmann	int perm;
1167e92166517e3ca9bfb416f91e69cf0373b55b6edeArnd Bergmann	int ret = 0;
1168e92166517e3ca9bfb416f91e69cf0373b55b6edeArnd Bergmann
1169e92166517e3ca9bfb416f91e69cf0373b55b6edeArnd Bergmann	console = vc->vc_num;
1170e92166517e3ca9bfb416f91e69cf0373b55b6edeArnd Bergmann
1171e92166517e3ca9bfb416f91e69cf0373b55b6edeArnd Bergmann	if (!vc_cons_allocated(console)) { 	/* impossible? */
1172e92166517e3ca9bfb416f91e69cf0373b55b6edeArnd Bergmann		ret = -ENOIOCTLCMD;
1173e92166517e3ca9bfb416f91e69cf0373b55b6edeArnd Bergmann		goto out;
1174e92166517e3ca9bfb416f91e69cf0373b55b6edeArnd Bergmann	}
1175e92166517e3ca9bfb416f91e69cf0373b55b6edeArnd Bergmann
1176e92166517e3ca9bfb416f91e69cf0373b55b6edeArnd Bergmann	/*
1177e92166517e3ca9bfb416f91e69cf0373b55b6edeArnd Bergmann	 * To have permissions to do most of the vt ioctls, we either have
1178e92166517e3ca9bfb416f91e69cf0373b55b6edeArnd Bergmann	 * to be the owner of the tty, or have CAP_SYS_TTY_CONFIG.
1179e92166517e3ca9bfb416f91e69cf0373b55b6edeArnd Bergmann	 */
1180e92166517e3ca9bfb416f91e69cf0373b55b6edeArnd Bergmann	perm = 0;
1181e92166517e3ca9bfb416f91e69cf0373b55b6edeArnd Bergmann	if (current->signal->tty == tty || capable(CAP_SYS_TTY_CONFIG))
1182e92166517e3ca9bfb416f91e69cf0373b55b6edeArnd Bergmann		perm = 1;
1183e92166517e3ca9bfb416f91e69cf0373b55b6edeArnd Bergmann
1184e92166517e3ca9bfb416f91e69cf0373b55b6edeArnd Bergmann	switch (cmd) {
1185e92166517e3ca9bfb416f91e69cf0373b55b6edeArnd Bergmann	/*
1186e92166517e3ca9bfb416f91e69cf0373b55b6edeArnd Bergmann	 * these need special handlers for incompatible data structures
1187e92166517e3ca9bfb416f91e69cf0373b55b6edeArnd Bergmann	 */
1188e92166517e3ca9bfb416f91e69cf0373b55b6edeArnd Bergmann	case PIO_FONTX:
1189e92166517e3ca9bfb416f91e69cf0373b55b6edeArnd Bergmann	case GIO_FONTX:
1190e92166517e3ca9bfb416f91e69cf0373b55b6edeArnd Bergmann		ret = compat_fontx_ioctl(cmd, up, perm, &op);
1191e92166517e3ca9bfb416f91e69cf0373b55b6edeArnd Bergmann		break;
1192e92166517e3ca9bfb416f91e69cf0373b55b6edeArnd Bergmann
1193e92166517e3ca9bfb416f91e69cf0373b55b6edeArnd Bergmann	case KDFONTOP:
1194e92166517e3ca9bfb416f91e69cf0373b55b6edeArnd Bergmann		ret = compat_kdfontop_ioctl(up, perm, &op, vc);
1195e92166517e3ca9bfb416f91e69cf0373b55b6edeArnd Bergmann		break;
1196e92166517e3ca9bfb416f91e69cf0373b55b6edeArnd Bergmann
1197e92166517e3ca9bfb416f91e69cf0373b55b6edeArnd Bergmann	case PIO_UNIMAP:
1198e92166517e3ca9bfb416f91e69cf0373b55b6edeArnd Bergmann	case GIO_UNIMAP:
11994001d7b7fc271052ebff43f327c26dc64806bbdfAlan Cox		tty_lock();
12004b1fe7797270e866adc17fc603bddf8768bc187fAndreas Schwab		ret = compat_unimap_ioctl(cmd, up, perm, vc);
12014001d7b7fc271052ebff43f327c26dc64806bbdfAlan Cox		tty_unlock();
1202e92166517e3ca9bfb416f91e69cf0373b55b6edeArnd Bergmann		break;
1203e92166517e3ca9bfb416f91e69cf0373b55b6edeArnd Bergmann
1204e92166517e3ca9bfb416f91e69cf0373b55b6edeArnd Bergmann	/*
1205e92166517e3ca9bfb416f91e69cf0373b55b6edeArnd Bergmann	 * all these treat 'arg' as an integer
1206e92166517e3ca9bfb416f91e69cf0373b55b6edeArnd Bergmann	 */
1207e92166517e3ca9bfb416f91e69cf0373b55b6edeArnd Bergmann	case KIOCSOUND:
1208e92166517e3ca9bfb416f91e69cf0373b55b6edeArnd Bergmann	case KDMKTONE:
1209e92166517e3ca9bfb416f91e69cf0373b55b6edeArnd Bergmann#ifdef CONFIG_X86
1210e92166517e3ca9bfb416f91e69cf0373b55b6edeArnd Bergmann	case KDADDIO:
1211e92166517e3ca9bfb416f91e69cf0373b55b6edeArnd Bergmann	case KDDELIO:
1212e92166517e3ca9bfb416f91e69cf0373b55b6edeArnd Bergmann#endif
1213e92166517e3ca9bfb416f91e69cf0373b55b6edeArnd Bergmann	case KDSETMODE:
1214e92166517e3ca9bfb416f91e69cf0373b55b6edeArnd Bergmann	case KDMAPDISP:
1215e92166517e3ca9bfb416f91e69cf0373b55b6edeArnd Bergmann	case KDUNMAPDISP:
1216e92166517e3ca9bfb416f91e69cf0373b55b6edeArnd Bergmann	case KDSKBMODE:
1217e92166517e3ca9bfb416f91e69cf0373b55b6edeArnd Bergmann	case KDSKBMETA:
1218e92166517e3ca9bfb416f91e69cf0373b55b6edeArnd Bergmann	case KDSKBLED:
1219e92166517e3ca9bfb416f91e69cf0373b55b6edeArnd Bergmann	case KDSETLED:
1220e92166517e3ca9bfb416f91e69cf0373b55b6edeArnd Bergmann	case KDSIGACCEPT:
1221e92166517e3ca9bfb416f91e69cf0373b55b6edeArnd Bergmann	case VT_ACTIVATE:
1222e92166517e3ca9bfb416f91e69cf0373b55b6edeArnd Bergmann	case VT_WAITACTIVE:
1223e92166517e3ca9bfb416f91e69cf0373b55b6edeArnd Bergmann	case VT_RELDISP:
1224e92166517e3ca9bfb416f91e69cf0373b55b6edeArnd Bergmann	case VT_DISALLOCATE:
1225e92166517e3ca9bfb416f91e69cf0373b55b6edeArnd Bergmann	case VT_RESIZE:
1226e92166517e3ca9bfb416f91e69cf0373b55b6edeArnd Bergmann	case VT_RESIZEX:
1227e92166517e3ca9bfb416f91e69cf0373b55b6edeArnd Bergmann		goto fallback;
1228e92166517e3ca9bfb416f91e69cf0373b55b6edeArnd Bergmann
1229e92166517e3ca9bfb416f91e69cf0373b55b6edeArnd Bergmann	/*
1230e92166517e3ca9bfb416f91e69cf0373b55b6edeArnd Bergmann	 * the rest has a compatible data structure behind arg,
1231e92166517e3ca9bfb416f91e69cf0373b55b6edeArnd Bergmann	 * but we have to convert it to a proper 64 bit pointer.
1232e92166517e3ca9bfb416f91e69cf0373b55b6edeArnd Bergmann	 */
1233e92166517e3ca9bfb416f91e69cf0373b55b6edeArnd Bergmann	default:
1234e92166517e3ca9bfb416f91e69cf0373b55b6edeArnd Bergmann		arg = (unsigned long)compat_ptr(arg);
1235e92166517e3ca9bfb416f91e69cf0373b55b6edeArnd Bergmann		goto fallback;
1236e92166517e3ca9bfb416f91e69cf0373b55b6edeArnd Bergmann	}
1237e92166517e3ca9bfb416f91e69cf0373b55b6edeArnd Bergmannout:
1238e92166517e3ca9bfb416f91e69cf0373b55b6edeArnd Bergmann	return ret;
1239e92166517e3ca9bfb416f91e69cf0373b55b6edeArnd Bergmann
1240e92166517e3ca9bfb416f91e69cf0373b55b6edeArnd Bergmannfallback:
12416caa76b7786891b42b66a0e61e2c2fff2c884620Alan Cox	return vt_ioctl(tty, cmd, arg);
1242e92166517e3ca9bfb416f91e69cf0373b55b6edeArnd Bergmann}
1243e92166517e3ca9bfb416f91e69cf0373b55b6edeArnd Bergmann
1244e92166517e3ca9bfb416f91e69cf0373b55b6edeArnd Bergmann
1245e92166517e3ca9bfb416f91e69cf0373b55b6edeArnd Bergmann#endif /* CONFIG_COMPAT */
1246e92166517e3ca9bfb416f91e69cf0373b55b6edeArnd Bergmann
1247e92166517e3ca9bfb416f91e69cf0373b55b6edeArnd Bergmann
12481da177e4c3f41524e886b7f1b8a0c1fc7321cacLinus Torvalds/*
1249d3b5cffcf84a8bdc7073dce4745d67c72629af85Alan Cox * Performs the back end of a vt switch. Called under the console
1250d3b5cffcf84a8bdc7073dce4745d67c72629af85Alan Cox * semaphore.
12511da177e4c3f41524e886b7f1b8a0c1fc7321cacLinus Torvalds */
12521da177e4c3f41524e886b7f1b8a0c1fc7321cacLinus Torvaldsstatic void complete_change_console(struct vc_data *vc)
12531da177e4c3f41524e886b7f1b8a0c1fc7321cacLinus Torvalds{
12541da177e4c3f41524e886b7f1b8a0c1fc7321cacLinus Torvalds	unsigned char old_vc_mode;
12558b92e87d39bfd046e7581e1fe0f40eac40f88608Alan Cox	int old = fg_console;
12561da177e4c3f41524e886b7f1b8a0c1fc7321cacLinus Torvalds
12571da177e4c3f41524e886b7f1b8a0c1fc7321cacLinus Torvalds	last_console = fg_console;
12581da177e4c3f41524e886b7f1b8a0c1fc7321cacLinus Torvalds
12591da177e4c3f41524e886b7f1b8a0c1fc7321cacLinus Torvalds	/*
12601da177e4c3f41524e886b7f1b8a0c1fc7321cacLinus Torvalds	 * If we're switching, we could be going from KD_GRAPHICS to
12611da177e4c3f41524e886b7f1b8a0c1fc7321cacLinus Torvalds	 * KD_TEXT mode or vice versa, which means we need to blank or
12621da177e4c3f41524e886b7f1b8a0c1fc7321cacLinus Torvalds	 * unblank the screen later.
12631da177e4c3f41524e886b7f1b8a0c1fc7321cacLinus Torvalds	 */
12641da177e4c3f41524e886b7f1b8a0c1fc7321cacLinus Torvalds	old_vc_mode = vc_cons[fg_console].d->vc_mode;
12651da177e4c3f41524e886b7f1b8a0c1fc7321cacLinus Torvalds	switch_screen(vc);
12661da177e4c3f41524e886b7f1b8a0c1fc7321cacLinus Torvalds
12671da177e4c3f41524e886b7f1b8a0c1fc7321cacLinus Torvalds	/*
12683dfcaf16135150d0f025047a7525664a41bb2adfEric W. Biederman	 * This can't appear below a successful kill_pid().  If it did,
12691da177e4c3f41524e886b7f1b8a0c1fc7321cacLinus Torvalds	 * then the *blank_screen operation could occur while X, having
12701da177e4c3f41524e886b7f1b8a0c1fc7321cacLinus Torvalds	 * received acqsig, is waking up on another processor.  This
12711da177e4c3f41524e886b7f1b8a0c1fc7321cacLinus Torvalds	 * condition can lead to overlapping accesses to the VGA range
12721da177e4c3f41524e886b7f1b8a0c1fc7321cacLinus Torvalds	 * and the framebuffer (causing system lockups).
12731da177e4c3f41524e886b7f1b8a0c1fc7321cacLinus Torvalds	 *
12741da177e4c3f41524e886b7f1b8a0c1fc7321cacLinus Torvalds	 * To account for this we duplicate this code below only if the
12751da177e4c3f41524e886b7f1b8a0c1fc7321cacLinus Torvalds	 * controlling process is gone and we've called reset_vc.
12761da177e4c3f41524e886b7f1b8a0c1fc7321cacLinus Torvalds	 */
12771da177e4c3f41524e886b7f1b8a0c1fc7321cacLinus Torvalds	if (old_vc_mode != vc->vc_mode) {
12781da177e4c3f41524e886b7f1b8a0c1fc7321cacLinus Torvalds		if (vc->vc_mode == KD_TEXT)
12791da177e4c3f41524e886b7f1b8a0c1fc7321cacLinus Torvalds			do_unblank_screen(1);
12801da177e4c3f41524e886b7f1b8a0c1fc7321cacLinus Torvalds		else
12811da177e4c3f41524e886b7f1b8a0c1fc7321cacLinus Torvalds			do_blank_screen(1);
12821da177e4c3f41524e886b7f1b8a0c1fc7321cacLinus Torvalds	}
12831da177e4c3f41524e886b7f1b8a0c1fc7321cacLinus Torvalds
12841da177e4c3f41524e886b7f1b8a0c1fc7321cacLinus Torvalds	/*
12851da177e4c3f41524e886b7f1b8a0c1fc7321cacLinus Torvalds	 * If this new console is under process control, send it a signal
12861da177e4c3f41524e886b7f1b8a0c1fc7321cacLinus Torvalds	 * telling it that it has acquired. Also check if it has died and
12871da177e4c3f41524e886b7f1b8a0c1fc7321cacLinus Torvalds	 * clean up (similar to logic employed in change_console())
12881da177e4c3f41524e886b7f1b8a0c1fc7321cacLinus Torvalds	 */
128987a6aca504d65f242589583e04df5e74b5eae1feGreg Kroah-Hartman	if (vc->vt_mode.mode == VT_PROCESS) {
12901da177e4c3f41524e886b7f1b8a0c1fc7321cacLinus Torvalds		/*
12913dfcaf16135150d0f025047a7525664a41bb2adfEric W. Biederman		 * Send the signal as privileged - kill_pid() will
12921da177e4c3f41524e886b7f1b8a0c1fc7321cacLinus Torvalds		 * tell us if the process has gone or something else
12931da177e4c3f41524e886b7f1b8a0c1fc7321cacLinus Torvalds		 * is awry
12941da177e4c3f41524e886b7f1b8a0c1fc7321cacLinus Torvalds		 */
1295bde0d2c98bcfc9acc83ac79c33a6ac1335b95a92Eric W. Biederman		if (kill_pid(vc->vt_pid, vc->vt_mode.acqsig, 1) != 0) {
12961da177e4c3f41524e886b7f1b8a0c1fc7321cacLinus Torvalds		/*
12971da177e4c3f41524e886b7f1b8a0c1fc7321cacLinus Torvalds		 * The controlling process has died, so we revert back to
12981da177e4c3f41524e886b7f1b8a0c1fc7321cacLinus Torvalds		 * normal operation. In this case, we'll also change back
12991da177e4c3f41524e886b7f1b8a0c1fc7321cacLinus Torvalds		 * to KD_TEXT mode. I'm not sure if this is strictly correct
13001da177e4c3f41524e886b7f1b8a0c1fc7321cacLinus Torvalds		 * but it saves the agony when the X server dies and the screen
13011da177e4c3f41524e886b7f1b8a0c1fc7321cacLinus Torvalds		 * remains blanked due to KD_GRAPHICS! It would be nice to do
13021da177e4c3f41524e886b7f1b8a0c1fc7321cacLinus Torvalds		 * this outside of VT_PROCESS but there is no single process
13031da177e4c3f41524e886b7f1b8a0c1fc7321cacLinus Torvalds		 * to account for and tracking tty count may be undesirable.
13041da177e4c3f41524e886b7f1b8a0c1fc7321cacLinus Torvalds		 */
13051da177e4c3f41524e886b7f1b8a0c1fc7321cacLinus Torvalds			reset_vc(vc);
13061da177e4c3f41524e886b7f1b8a0c1fc7321cacLinus Torvalds
13071da177e4c3f41524e886b7f1b8a0c1fc7321cacLinus Torvalds			if (old_vc_mode != vc->vc_mode) {
13081da177e4c3f41524e886b7f1b8a0c1fc7321cacLinus Torvalds				if (vc->vc_mode == KD_TEXT)
13091da177e4c3f41524e886b7f1b8a0c1fc7321cacLinus Torvalds					do_unblank_screen(1);
13101da177e4c3f41524e886b7f1b8a0c1fc7321cacLinus Torvalds				else
13111da177e4c3f41524e886b7f1b8a0c1fc7321cacLinus Torvalds					do_blank_screen(1);
13121da177e4c3f41524e886b7f1b8a0c1fc7321cacLinus Torvalds			}
13131da177e4c3f41524e886b7f1b8a0c1fc7321cacLinus Torvalds		}
13141da177e4c3f41524e886b7f1b8a0c1fc7321cacLinus Torvalds	}
13151da177e4c3f41524e886b7f1b8a0c1fc7321cacLinus Torvalds
13161da177e4c3f41524e886b7f1b8a0c1fc7321cacLinus Torvalds	/*
13171da177e4c3f41524e886b7f1b8a0c1fc7321cacLinus Torvalds	 * Wake anyone waiting for their VT to activate
13181da177e4c3f41524e886b7f1b8a0c1fc7321cacLinus Torvalds	 */
13198b92e87d39bfd046e7581e1fe0f40eac40f88608Alan Cox	vt_event_post(VT_EVENT_SWITCH, old, vc->vc_num);
13201da177e4c3f41524e886b7f1b8a0c1fc7321cacLinus Torvalds	return;
13211da177e4c3f41524e886b7f1b8a0c1fc7321cacLinus Torvalds}
13221da177e4c3f41524e886b7f1b8a0c1fc7321cacLinus Torvalds
13231da177e4c3f41524e886b7f1b8a0c1fc7321cacLinus Torvalds/*
13241da177e4c3f41524e886b7f1b8a0c1fc7321cacLinus Torvalds * Performs the front-end of a vt switch
13251da177e4c3f41524e886b7f1b8a0c1fc7321cacLinus Torvalds */
13261da177e4c3f41524e886b7f1b8a0c1fc7321cacLinus Torvaldsvoid change_console(struct vc_data *new_vc)
13271da177e4c3f41524e886b7f1b8a0c1fc7321cacLinus Torvalds{
13281da177e4c3f41524e886b7f1b8a0c1fc7321cacLinus Torvalds	struct vc_data *vc;
13291da177e4c3f41524e886b7f1b8a0c1fc7321cacLinus Torvalds
13301da177e4c3f41524e886b7f1b8a0c1fc7321cacLinus Torvalds	if (!new_vc || new_vc->vc_num == fg_console || vt_dont_switch)
13311da177e4c3f41524e886b7f1b8a0c1fc7321cacLinus Torvalds		return;
13321da177e4c3f41524e886b7f1b8a0c1fc7321cacLinus Torvalds
13331da177e4c3f41524e886b7f1b8a0c1fc7321cacLinus Torvalds	/*
13341da177e4c3f41524e886b7f1b8a0c1fc7321cacLinus Torvalds	 * If this vt is in process mode, then we need to handshake with
13351da177e4c3f41524e886b7f1b8a0c1fc7321cacLinus Torvalds	 * that process before switching. Essentially, we store where that
13361da177e4c3f41524e886b7f1b8a0c1fc7321cacLinus Torvalds	 * vt wants to switch to and wait for it to tell us when it's done
13371da177e4c3f41524e886b7f1b8a0c1fc7321cacLinus Torvalds	 * (via VT_RELDISP ioctl).
13381da177e4c3f41524e886b7f1b8a0c1fc7321cacLinus Torvalds	 *
13391da177e4c3f41524e886b7f1b8a0c1fc7321cacLinus Torvalds	 * We also check to see if the controlling process still exists.
13401da177e4c3f41524e886b7f1b8a0c1fc7321cacLinus Torvalds	 * If it doesn't, we reset this vt to auto mode and continue.
13411da177e4c3f41524e886b7f1b8a0c1fc7321cacLinus Torvalds	 * This is a cheap way to track process control. The worst thing
13421da177e4c3f41524e886b7f1b8a0c1fc7321cacLinus Torvalds	 * that can happen is: we send a signal to a process, it dies, and
13431da177e4c3f41524e886b7f1b8a0c1fc7321cacLinus Torvalds	 * the switch gets "lost" waiting for a response; hopefully, the
13441da177e4c3f41524e886b7f1b8a0c1fc7321cacLinus Torvalds	 * user will try again, we'll detect the process is gone (unless
13451da177e4c3f41524e886b7f1b8a0c1fc7321cacLinus Torvalds	 * the user waits just the right amount of time :-) and revert the
13461da177e4c3f41524e886b7f1b8a0c1fc7321cacLinus Torvalds	 * vt to auto control.
13471da177e4c3f41524e886b7f1b8a0c1fc7321cacLinus Torvalds	 */
13481da177e4c3f41524e886b7f1b8a0c1fc7321cacLinus Torvalds	vc = vc_cons[fg_console].d;
134987a6aca504d65f242589583e04df5e74b5eae1feGreg Kroah-Hartman	if (vc->vt_mode.mode == VT_PROCESS) {
13501da177e4c3f41524e886b7f1b8a0c1fc7321cacLinus Torvalds		/*
13513dfcaf16135150d0f025047a7525664a41bb2adfEric W. Biederman		 * Send the signal as privileged - kill_pid() will
13521da177e4c3f41524e886b7f1b8a0c1fc7321cacLinus Torvalds		 * tell us if the process has gone or something else
1353a64314e62d89562b6fc77593648bec3acc35bf61Jan Lübbe		 * is awry.
1354a64314e62d89562b6fc77593648bec3acc35bf61Jan Lübbe		 *
1355a64314e62d89562b6fc77593648bec3acc35bf61Jan Lübbe		 * We need to set vt_newvt *before* sending the signal or we
1356a64314e62d89562b6fc77593648bec3acc35bf61Jan Lübbe		 * have a race.
13571da177e4c3f41524e886b7f1b8a0c1fc7321cacLinus Torvalds		 */
1358a64314e62d89562b6fc77593648bec3acc35bf61Jan Lübbe		vc->vt_newvt = new_vc->vc_num;
1359bde0d2c98bcfc9acc83ac79c33a6ac1335b95a92Eric W. Biederman		if (kill_pid(vc->vt_pid, vc->vt_mode.relsig, 1) == 0) {
13601da177e4c3f41524e886b7f1b8a0c1fc7321cacLinus Torvalds			/*
136187a6aca504d65f242589583e04df5e74b5eae1feGreg Kroah-Hartman			 * It worked. Mark the vt to switch to and
136287a6aca504d65f242589583e04df5e74b5eae1feGreg Kroah-Hartman			 * return. The process needs to send us a
136387a6aca504d65f242589583e04df5e74b5eae1feGreg Kroah-Hartman			 * VT_RELDISP ioctl to complete the switch.
13641da177e4c3f41524e886b7f1b8a0c1fc7321cacLinus Torvalds			 */
136587a6aca504d65f242589583e04df5e74b5eae1feGreg Kroah-Hartman			return;
13661da177e4c3f41524e886b7f1b8a0c1fc7321cacLinus Torvalds		}
13671da177e4c3f41524e886b7f1b8a0c1fc7321cacLinus Torvalds
13681da177e4c3f41524e886b7f1b8a0c1fc7321cacLinus Torvalds		/*
136987a6aca504d65f242589583e04df5e74b5eae1feGreg Kroah-Hartman		 * The controlling process has died, so we revert back to
137087a6aca504d65f242589583e04df5e74b5eae1feGreg Kroah-Hartman		 * normal operation. In this case, we'll also change back
137187a6aca504d65f242589583e04df5e74b5eae1feGreg Kroah-Hartman		 * to KD_TEXT mode. I'm not sure if this is strictly correct
137287a6aca504d65f242589583e04df5e74b5eae1feGreg Kroah-Hartman		 * but it saves the agony when the X server dies and the screen
137387a6aca504d65f242589583e04df5e74b5eae1feGreg Kroah-Hartman		 * remains blanked due to KD_GRAPHICS! It would be nice to do
137487a6aca504d65f242589583e04df5e74b5eae1feGreg Kroah-Hartman		 * this outside of VT_PROCESS but there is no single process
137587a6aca504d65f242589583e04df5e74b5eae1feGreg Kroah-Hartman		 * to account for and tracking tty count may be undesirable.
137687a6aca504d65f242589583e04df5e74b5eae1feGreg Kroah-Hartman		 */
137787a6aca504d65f242589583e04df5e74b5eae1feGreg Kroah-Hartman		reset_vc(vc);
137887a6aca504d65f242589583e04df5e74b5eae1feGreg Kroah-Hartman
137987a6aca504d65f242589583e04df5e74b5eae1feGreg Kroah-Hartman		/*
138087a6aca504d65f242589583e04df5e74b5eae1feGreg Kroah-Hartman		 * Fall through to normal (VT_AUTO) handling of the switch...
13811da177e4c3f41524e886b7f1b8a0c1fc7321cacLinus Torvalds		 */
13821da177e4c3f41524e886b7f1b8a0c1fc7321cacLinus Torvalds	}
13831da177e4c3f41524e886b7f1b8a0c1fc7321cacLinus Torvalds
13841da177e4c3f41524e886b7f1b8a0c1fc7321cacLinus Torvalds	/*
13851da177e4c3f41524e886b7f1b8a0c1fc7321cacLinus Torvalds	 * Ignore all switches in KD_GRAPHICS+VT_AUTO mode
13861da177e4c3f41524e886b7f1b8a0c1fc7321cacLinus Torvalds	 */
13871da177e4c3f41524e886b7f1b8a0c1fc7321cacLinus Torvalds	if (vc->vc_mode == KD_GRAPHICS)
13881da177e4c3f41524e886b7f1b8a0c1fc7321cacLinus Torvalds		return;
13891da177e4c3f41524e886b7f1b8a0c1fc7321cacLinus Torvalds
13901da177e4c3f41524e886b7f1b8a0c1fc7321cacLinus Torvalds	complete_change_console(new_vc);
13911da177e4c3f41524e886b7f1b8a0c1fc7321cacLinus Torvalds}
13928d233558cd99a888571bb5a88a74970879e0aba4Alan Cox
13938d233558cd99a888571bb5a88a74970879e0aba4Alan Cox/* Perform a kernel triggered VT switch for suspend/resume */
13948d233558cd99a888571bb5a88a74970879e0aba4Alan Cox
13958d233558cd99a888571bb5a88a74970879e0aba4Alan Coxstatic int disable_vt_switch;
13968d233558cd99a888571bb5a88a74970879e0aba4Alan Cox
13978d233558cd99a888571bb5a88a74970879e0aba4Alan Coxint vt_move_to_console(unsigned int vt, int alloc)
13988d233558cd99a888571bb5a88a74970879e0aba4Alan Cox{
13998d233558cd99a888571bb5a88a74970879e0aba4Alan Cox	int prev;
14008d233558cd99a888571bb5a88a74970879e0aba4Alan Cox
1401ac751efa6a0d70f2c9daef5c7e3a92270f5c2dffTorben Hohn	console_lock();
14028d233558cd99a888571bb5a88a74970879e0aba4Alan Cox	/* Graphics mode - up to X */
14038d233558cd99a888571bb5a88a74970879e0aba4Alan Cox	if (disable_vt_switch) {
1404ac751efa6a0d70f2c9daef5c7e3a92270f5c2dffTorben Hohn		console_unlock();
14058d233558cd99a888571bb5a88a74970879e0aba4Alan Cox		return 0;
14068d233558cd99a888571bb5a88a74970879e0aba4Alan Cox	}
14078d233558cd99a888571bb5a88a74970879e0aba4Alan Cox	prev = fg_console;
14088d233558cd99a888571bb5a88a74970879e0aba4Alan Cox
14098d233558cd99a888571bb5a88a74970879e0aba4Alan Cox	if (alloc && vc_allocate(vt)) {
14108d233558cd99a888571bb5a88a74970879e0aba4Alan Cox		/* we can't have a free VC for now. Too bad,
14118d233558cd99a888571bb5a88a74970879e0aba4Alan Cox		 * we don't want to mess the screen for now. */
1412ac751efa6a0d70f2c9daef5c7e3a92270f5c2dffTorben Hohn		console_unlock();
14138d233558cd99a888571bb5a88a74970879e0aba4Alan Cox		return -ENOSPC;
14148d233558cd99a888571bb5a88a74970879e0aba4Alan Cox	}
14158d233558cd99a888571bb5a88a74970879e0aba4Alan Cox
14168d233558cd99a888571bb5a88a74970879e0aba4Alan Cox	if (set_console(vt)) {
14178d233558cd99a888571bb5a88a74970879e0aba4Alan Cox		/*
14188d233558cd99a888571bb5a88a74970879e0aba4Alan Cox		 * We're unable to switch to the SUSPEND_CONSOLE.
14198d233558cd99a888571bb5a88a74970879e0aba4Alan Cox		 * Let the calling function know so it can decide
14208d233558cd99a888571bb5a88a74970879e0aba4Alan Cox		 * what to do.
14218d233558cd99a888571bb5a88a74970879e0aba4Alan Cox		 */
1422ac751efa6a0d70f2c9daef5c7e3a92270f5c2dffTorben Hohn		console_unlock();
14238d233558cd99a888571bb5a88a74970879e0aba4Alan Cox		return -EIO;
14248d233558cd99a888571bb5a88a74970879e0aba4Alan Cox	}
1425ac751efa6a0d70f2c9daef5c7e3a92270f5c2dffTorben Hohn	console_unlock();
1426797938b5e33991dadf4dd9228b932cc69c3e905aJiri Slaby	if (vt_waitactive(vt + 1)) {
14278d233558cd99a888571bb5a88a74970879e0aba4Alan Cox		pr_debug("Suspend: Can't switch VCs.");
14288d233558cd99a888571bb5a88a74970879e0aba4Alan Cox		return -EINTR;
14298d233558cd99a888571bb5a88a74970879e0aba4Alan Cox	}
14308d233558cd99a888571bb5a88a74970879e0aba4Alan Cox	return prev;
14318d233558cd99a888571bb5a88a74970879e0aba4Alan Cox}
14328d233558cd99a888571bb5a88a74970879e0aba4Alan Cox
14338d233558cd99a888571bb5a88a74970879e0aba4Alan Cox/*
14348d233558cd99a888571bb5a88a74970879e0aba4Alan Cox * Normally during a suspend, we allocate a new console and switch to it.
14358d233558cd99a888571bb5a88a74970879e0aba4Alan Cox * When we resume, we switch back to the original console.  This switch
14368d233558cd99a888571bb5a88a74970879e0aba4Alan Cox * can be slow, so on systems where the framebuffer can handle restoration
14378d233558cd99a888571bb5a88a74970879e0aba4Alan Cox * of video registers anyways, there's little point in doing the console
14388d233558cd99a888571bb5a88a74970879e0aba4Alan Cox * switch.  This function allows you to disable it by passing it '0'.
14398d233558cd99a888571bb5a88a74970879e0aba4Alan Cox */
14408d233558cd99a888571bb5a88a74970879e0aba4Alan Coxvoid pm_set_vt_switch(int do_switch)
14418d233558cd99a888571bb5a88a74970879e0aba4Alan Cox{
1442ac751efa6a0d70f2c9daef5c7e3a92270f5c2dffTorben Hohn	console_lock();
14438d233558cd99a888571bb5a88a74970879e0aba4Alan Cox	disable_vt_switch = !do_switch;
1444ac751efa6a0d70f2c9daef5c7e3a92270f5c2dffTorben Hohn	console_unlock();
14458d233558cd99a888571bb5a88a74970879e0aba4Alan Cox}
14468d233558cd99a888571bb5a88a74970879e0aba4Alan CoxEXPORT_SYMBOL(pm_set_vt_switch);
1447