initial commit with v2.6.9
[linux-2.6.9-moxart.git] / drivers / char / sysrq.c
blobda52bff37f97dc08c1a2ae79f1a4e9d9dba4aec8
1 /* -*- linux-c -*-
3 * $Id: sysrq.c,v 1.15 1998/08/23 14:56:41 mj Exp $
5 * Linux Magic System Request Key Hacks
7 * (c) 1997 Martin Mares <mj@atrey.karlin.mff.cuni.cz>
8 * based on ideas by Pavel Machek <pavel@atrey.karlin.mff.cuni.cz>
10 * (c) 2000 Crutcher Dunnavant <crutcher+kernel@datastacks.com>
11 * overhauled to use key registration
12 * based upon discusions in irc://irc.openprojects.net/#kernelnewbies
15 #include <linux/config.h>
16 #include <linux/sched.h>
17 #include <linux/interrupt.h>
18 #include <linux/mm.h>
19 #include <linux/fs.h>
20 #include <linux/tty.h>
21 #include <linux/mount.h>
22 #include <linux/kdev_t.h>
23 #include <linux/major.h>
24 #include <linux/reboot.h>
25 #include <linux/sysrq.h>
26 #include <linux/kbd_kern.h>
27 #include <linux/quotaops.h>
28 #include <linux/smp_lock.h>
29 #include <linux/kernel.h>
30 #include <linux/module.h>
31 #include <linux/suspend.h>
32 #include <linux/writeback.h>
33 #include <linux/buffer_head.h> /* for fsync_bdev() */
35 #include <linux/spinlock.h>
37 #include <asm/ptrace.h>
39 extern void reset_vc(unsigned int);
41 /* Whether we react on sysrq keys or just ignore them */
42 int sysrq_enabled = 1;
44 /* Machine specific power off function */
45 void (*sysrq_power_off)(void);
47 /* Loglevel sysrq handler */
48 static void sysrq_handle_loglevel(int key, struct pt_regs *pt_regs,
49 struct tty_struct *tty)
51 int i;
52 i = key - '0';
53 console_loglevel = 7;
54 printk("Loglevel set to %d\n", i);
55 console_loglevel = i;
57 static struct sysrq_key_op sysrq_loglevel_op = {
58 .handler = sysrq_handle_loglevel,
59 .help_msg = "loglevel0-8",
60 .action_msg = "Changing Loglevel",
64 /* SAK sysrq handler */
65 #ifdef CONFIG_VT
66 static void sysrq_handle_SAK(int key, struct pt_regs *pt_regs,
67 struct tty_struct *tty)
69 if (tty)
70 do_SAK(tty);
71 reset_vc(fg_console);
73 static struct sysrq_key_op sysrq_SAK_op = {
74 .handler = sysrq_handle_SAK,
75 .help_msg = "saK",
76 .action_msg = "SAK",
78 #endif
80 #ifdef CONFIG_VT
81 /* unraw sysrq handler */
82 static void sysrq_handle_unraw(int key, struct pt_regs *pt_regs,
83 struct tty_struct *tty)
85 struct kbd_struct *kbd = &kbd_table[fg_console];
87 if (kbd)
88 kbd->kbdmode = VC_XLATE;
90 static struct sysrq_key_op sysrq_unraw_op = {
91 .handler = sysrq_handle_unraw,
92 .help_msg = "unRaw",
93 .action_msg = "Keyboard mode set to XLATE",
95 #endif /* CONFIG_VT */
97 /* reboot sysrq handler */
98 static void sysrq_handle_reboot(int key, struct pt_regs *pt_regs,
99 struct tty_struct *tty)
101 machine_restart(NULL);
104 static struct sysrq_key_op sysrq_reboot_op = {
105 .handler = sysrq_handle_reboot,
106 .help_msg = "reBoot",
107 .action_msg = "Resetting",
110 static void sysrq_handle_sync(int key, struct pt_regs *pt_regs,
111 struct tty_struct *tty)
113 emergency_sync();
116 static struct sysrq_key_op sysrq_sync_op = {
117 .handler = sysrq_handle_sync,
118 .help_msg = "Sync",
119 .action_msg = "Emergency Sync",
122 static void sysrq_handle_mountro(int key, struct pt_regs *pt_regs,
123 struct tty_struct *tty)
125 emergency_remount();
128 static struct sysrq_key_op sysrq_mountro_op = {
129 .handler = sysrq_handle_mountro,
130 .help_msg = "Unmount",
131 .action_msg = "Emergency Remount R/O",
134 /* END SYNC SYSRQ HANDLERS BLOCK */
137 /* SHOW SYSRQ HANDLERS BLOCK */
139 static void sysrq_handle_showregs(int key, struct pt_regs *pt_regs,
140 struct tty_struct *tty)
142 if (pt_regs)
143 show_regs(pt_regs);
145 static struct sysrq_key_op sysrq_showregs_op = {
146 .handler = sysrq_handle_showregs,
147 .help_msg = "showPc",
148 .action_msg = "Show Regs",
152 static void sysrq_handle_showstate(int key, struct pt_regs *pt_regs,
153 struct tty_struct *tty)
155 show_state();
157 static struct sysrq_key_op sysrq_showstate_op = {
158 .handler = sysrq_handle_showstate,
159 .help_msg = "showTasks",
160 .action_msg = "Show State",
164 static void sysrq_handle_showmem(int key, struct pt_regs *pt_regs,
165 struct tty_struct *tty)
167 show_mem();
169 static struct sysrq_key_op sysrq_showmem_op = {
170 .handler = sysrq_handle_showmem,
171 .help_msg = "showMem",
172 .action_msg = "Show Memory",
175 /* SHOW SYSRQ HANDLERS BLOCK */
178 /* SIGNAL SYSRQ HANDLERS BLOCK */
180 /* signal sysrq helper function
181 * Sends a signal to all user processes */
182 static void send_sig_all(int sig)
184 struct task_struct *p;
186 for_each_process(p) {
187 if (p->mm && p->pid != 1)
188 /* Not swapper, init nor kernel thread */
189 force_sig(sig, p);
193 static void sysrq_handle_term(int key, struct pt_regs *pt_regs,
194 struct tty_struct *tty)
196 send_sig_all(SIGTERM);
197 console_loglevel = 8;
199 static struct sysrq_key_op sysrq_term_op = {
200 .handler = sysrq_handle_term,
201 .help_msg = "tErm",
202 .action_msg = "Terminate All Tasks",
205 static void sysrq_handle_kill(int key, struct pt_regs *pt_regs,
206 struct tty_struct *tty)
208 send_sig_all(SIGKILL);
209 console_loglevel = 8;
211 static struct sysrq_key_op sysrq_kill_op = {
212 .handler = sysrq_handle_kill,
213 .help_msg = "kIll",
214 .action_msg = "Kill All Tasks",
217 /* END SIGNAL SYSRQ HANDLERS BLOCK */
220 /* Key Operations table and lock */
221 static spinlock_t sysrq_key_table_lock = SPIN_LOCK_UNLOCKED;
222 #define SYSRQ_KEY_TABLE_LENGTH 36
223 static struct sysrq_key_op *sysrq_key_table[SYSRQ_KEY_TABLE_LENGTH] = {
224 /* 0 */ &sysrq_loglevel_op,
225 /* 1 */ &sysrq_loglevel_op,
226 /* 2 */ &sysrq_loglevel_op,
227 /* 3 */ &sysrq_loglevel_op,
228 /* 4 */ &sysrq_loglevel_op,
229 /* 5 */ &sysrq_loglevel_op,
230 /* 6 */ &sysrq_loglevel_op,
231 /* 7 */ &sysrq_loglevel_op,
232 /* 8 */ &sysrq_loglevel_op,
233 /* 9 */ &sysrq_loglevel_op,
234 /* a */ NULL, /* Don't use for system provided sysrqs,
235 it is handled specially on the sparc
236 and will never arrive */
237 /* b */ &sysrq_reboot_op,
238 /* c */ NULL,
239 /* d */ NULL,
240 /* e */ &sysrq_term_op,
241 /* f */ NULL,
242 /* g */ NULL,
243 /* h */ NULL,
244 /* i */ &sysrq_kill_op,
245 /* j */ NULL,
246 #ifdef CONFIG_VT
247 /* k */ &sysrq_SAK_op,
248 #else
249 /* k */ NULL,
250 #endif
251 /* l */ NULL,
252 /* m */ &sysrq_showmem_op,
253 /* n */ NULL,
254 /* o */ NULL, /* This will often be registered
255 as 'Off' at init time */
256 /* p */ &sysrq_showregs_op,
257 /* q */ NULL,
258 #ifdef CONFIG_VT
259 /* r */ &sysrq_unraw_op,
260 #else
261 /* r */ NULL,
262 #endif
263 /* s */ &sysrq_sync_op,
264 /* t */ &sysrq_showstate_op,
265 /* u */ &sysrq_mountro_op,
266 /* v */ NULL, /* May be assigned at init time by SMP VOYAGER */
267 /* w */ NULL,
268 /* x */ NULL,
269 /* y */ NULL,
270 /* z */ NULL
273 /* key2index calculation, -1 on invalid index */
274 static int sysrq_key_table_key2index(int key) {
275 int retval;
276 if ((key >= '0') && (key <= '9')) {
277 retval = key - '0';
278 } else if ((key >= 'a') && (key <= 'z')) {
279 retval = key + 10 - 'a';
280 } else {
281 retval = -1;
283 return retval;
287 * table lock and unlocking functions, exposed to modules
290 void __sysrq_lock_table (void) { spin_lock(&sysrq_key_table_lock); }
292 void __sysrq_unlock_table (void) { spin_unlock(&sysrq_key_table_lock); }
295 * get and put functions for the table, exposed to modules.
298 struct sysrq_key_op *__sysrq_get_key_op (int key) {
299 struct sysrq_key_op *op_p;
300 int i;
302 i = sysrq_key_table_key2index(key);
303 op_p = (i == -1) ? NULL : sysrq_key_table[i];
304 return op_p;
307 void __sysrq_put_key_op (int key, struct sysrq_key_op *op_p) {
308 int i;
310 i = sysrq_key_table_key2index(key);
311 if (i != -1)
312 sysrq_key_table[i] = op_p;
316 * This is the non-locking version of handle_sysrq
317 * It must/can only be called by sysrq key handlers,
318 * as they are inside of the lock
321 void __handle_sysrq(int key, struct pt_regs *pt_regs, struct tty_struct *tty)
323 struct sysrq_key_op *op_p;
324 int orig_log_level;
325 int i, j;
327 __sysrq_lock_table();
328 orig_log_level = console_loglevel;
329 console_loglevel = 7;
330 printk(KERN_INFO "SysRq : ");
332 op_p = __sysrq_get_key_op(key);
333 if (op_p) {
334 printk ("%s\n", op_p->action_msg);
335 console_loglevel = orig_log_level;
336 op_p->handler(key, pt_regs, tty);
337 } else {
338 printk("HELP : ");
339 /* Only print the help msg once per handler */
340 for (i=0; i<SYSRQ_KEY_TABLE_LENGTH; i++)
341 if (sysrq_key_table[i]) {
342 for (j=0; sysrq_key_table[i] != sysrq_key_table[j]; j++);
343 if (j == i)
344 printk ("%s ", sysrq_key_table[i]->help_msg);
346 printk ("\n");
347 console_loglevel = orig_log_level;
349 __sysrq_unlock_table();
353 * This function is called by the keyboard handler when SysRq is pressed
354 * and any other keycode arrives.
357 void handle_sysrq(int key, struct pt_regs *pt_regs, struct tty_struct *tty)
359 if (!sysrq_enabled)
360 return;
361 __handle_sysrq(key, pt_regs, tty);
364 EXPORT_SYMBOL(handle_sysrq);
365 EXPORT_SYMBOL(__sysrq_lock_table);
366 EXPORT_SYMBOL(__sysrq_unlock_table);
367 EXPORT_SYMBOL(__sysrq_get_key_op);
368 EXPORT_SYMBOL(__sysrq_put_key_op);