Linux kernel & device driver programming

Cross-Referenced Linux and Device Driver Code

[ source navigation ] [ diff markup ] [ identifier search ] [ freetext search ] [ file search ]
Version: [ 2.6.11.8 ] [ 2.6.25 ] [ 2.6.25.8 ] [ 2.6.31.13 ] Architecture: [ i386 ]
  1 /* -*- linux-c -*-
  2  *
  3  *      $Id: sysrq.c,v 1.15 1998/08/23 14:56:41 mj Exp $
  4  *
  5  *      Linux Magic System Request Key Hacks
  6  *
  7  *      (c) 1997 Martin Mares <mj@atrey.karlin.mff.cuni.cz>
  8  *      based on ideas by Pavel Machek <pavel@atrey.karlin.mff.cuni.cz>
  9  *
 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
 13  */
 14 
 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() */
 34 
 35 #include <linux/spinlock.h>
 36 
 37 #include <asm/ptrace.h>
 38 
 39 extern void reset_vc(unsigned int);
 40 
 41 /* Whether we react on sysrq keys or just ignore them */
 42 int sysrq_enabled = 1;
 43 
 44 /* Machine specific power off function */
 45 void (*sysrq_power_off)(void);
 46 
 47 /* Loglevel sysrq handler */
 48 static void sysrq_handle_loglevel(int key, struct pt_regs *pt_regs,
 49                                   struct tty_struct *tty) 
 50 {
 51         int i;
 52         i = key - '';
 53         console_loglevel = 7;
 54         printk("Loglevel set to %d\n", i);
 55         console_loglevel = i;
 56 }       
 57 static struct sysrq_key_op sysrq_loglevel_op = {
 58         .handler        = sysrq_handle_loglevel,
 59         .help_msg       = "loglevel0-8",
 60         .action_msg     = "Changing Loglevel",
 61 };
 62 
 63 
 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) 
 68 {
 69         if (tty)
 70                 do_SAK(tty);
 71         reset_vc(fg_console);
 72 }
 73 static struct sysrq_key_op sysrq_SAK_op = {
 74         .handler        = sysrq_handle_SAK,
 75         .help_msg       = "saK",
 76         .action_msg     = "SAK",
 77 };
 78 #endif
 79 
 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) 
 84 {
 85         struct kbd_struct *kbd = &kbd_table[fg_console];
 86 
 87         if (kbd)
 88                 kbd->kbdmode = VC_XLATE;
 89 }
 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",
 94 };
 95 #endif /* CONFIG_VT */
 96 
 97 /* reboot sysrq handler */
 98 static void sysrq_handle_reboot(int key, struct pt_regs *pt_regs,
 99                                 struct tty_struct *tty) 
100 {
101         local_irq_enable();
102         machine_restart(NULL);
103 }
104 
105 static struct sysrq_key_op sysrq_reboot_op = {
106         .handler        = sysrq_handle_reboot,
107         .help_msg       = "reBoot",
108         .action_msg     = "Resetting",
109 };
110 
111 static void sysrq_handle_sync(int key, struct pt_regs *pt_regs,
112                               struct tty_struct *tty) 
113 {
114         emergency_sync();
115 }
116 
117 static struct sysrq_key_op sysrq_sync_op = {
118         .handler        = sysrq_handle_sync,
119         .help_msg       = "Sync",
120         .action_msg     = "Emergency Sync",
121 };
122 
123 static void sysrq_handle_mountro(int key, struct pt_regs *pt_regs,
124                                  struct tty_struct *tty) 
125 {
126         emergency_remount();
127 }
128 
129 static struct sysrq_key_op sysrq_mountro_op = {
130         .handler        = sysrq_handle_mountro,
131         .help_msg       = "Unmount",
132         .action_msg     = "Emergency Remount R/O",
133 };
134 
135 /* END SYNC SYSRQ HANDLERS BLOCK */
136 
137 
138 /* SHOW SYSRQ HANDLERS BLOCK */
139 
140 static void sysrq_handle_showregs(int key, struct pt_regs *pt_regs,
141                                   struct tty_struct *tty) 
142 {
143         if (pt_regs)
144                 show_regs(pt_regs);
145 }
146 static struct sysrq_key_op sysrq_showregs_op = {
147         .handler        = sysrq_handle_showregs,
148         .help_msg       = "showPc",
149         .action_msg     = "Show Regs",
150 };
151 
152 
153 static void sysrq_handle_showstate(int key, struct pt_regs *pt_regs,
154                                    struct tty_struct *tty) 
155 {
156         show_state();
157 }
158 static struct sysrq_key_op sysrq_showstate_op = {
159         .handler        = sysrq_handle_showstate,
160         .help_msg       = "showTasks",
161         .action_msg     = "Show State",
162 };
163 
164 
165 static void sysrq_handle_showmem(int key, struct pt_regs *pt_regs,
166                                  struct tty_struct *tty) 
167 {
168         show_mem();
169 }
170 static struct sysrq_key_op sysrq_showmem_op = {
171         .handler        = sysrq_handle_showmem,
172         .help_msg       = "showMem",
173         .action_msg     = "Show Memory",
174 };
175 
176 /* SHOW SYSRQ HANDLERS BLOCK */
177 
178 
179 /* SIGNAL SYSRQ HANDLERS BLOCK */
180 
181 /* signal sysrq helper function
182  * Sends a signal to all user processes */
183 static void send_sig_all(int sig)
184 {
185         struct task_struct *p;
186 
187         for_each_process(p) {
188                 if (p->mm && p->pid != 1)
189                         /* Not swapper, init nor kernel thread */
190                         force_sig(sig, p);
191         }
192 }
193 
194 static void sysrq_handle_term(int key, struct pt_regs *pt_regs,
195                               struct tty_struct *tty) 
196 {
197         send_sig_all(SIGTERM);
198         console_loglevel = 8;
199 }
200 static struct sysrq_key_op sysrq_term_op = {
201         .handler        = sysrq_handle_term,
202         .help_msg       = "tErm",
203         .action_msg     = "Terminate All Tasks",
204 };
205 
206 static void sysrq_handle_kill(int key, struct pt_regs *pt_regs,
207                               struct tty_struct *tty) 
208 {
209         send_sig_all(SIGKILL);
210         console_loglevel = 8;
211 }
212 static struct sysrq_key_op sysrq_kill_op = {
213         .handler        = sysrq_handle_kill,
214         .help_msg       = "kIll",
215         .action_msg     = "Kill All Tasks",
216 };
217 
218 /* END SIGNAL SYSRQ HANDLERS BLOCK */
219 
220 static void sysrq_handle_unrt(int key, struct pt_regs *pt_regs,
221                                 struct tty_struct *tty)
222 {
223         normalize_rt_tasks();
224 }
225 static struct sysrq_key_op sysrq_unrt_op = {
226         .handler        = sysrq_handle_unrt,
227         .help_msg       = "Nice",
228         .action_msg     = "Nice All RT Tasks"
229 };
230 
231 /* Key Operations table and lock */
232 static DEFINE_SPINLOCK(sysrq_key_table_lock);
233 #define SYSRQ_KEY_TABLE_LENGTH 36
234 static struct sysrq_key_op *sysrq_key_table[SYSRQ_KEY_TABLE_LENGTH] = {
235 /* 0 */ &sysrq_loglevel_op,
236 /* 1 */ &sysrq_loglevel_op,
237 /* 2 */ &sysrq_loglevel_op,
238 /* 3 */ &sysrq_loglevel_op,
239 /* 4 */ &sysrq_loglevel_op,
240 /* 5 */ &sysrq_loglevel_op,
241 /* 6 */ &sysrq_loglevel_op,
242 /* 7 */ &sysrq_loglevel_op,
243 /* 8 */ &sysrq_loglevel_op,
244 /* 9 */ &sysrq_loglevel_op,
245 /* a */ NULL, /* Don't use for system provided sysrqs,
246                  it is handled specially on the sparc
247                  and will never arrive */
248 /* b */ &sysrq_reboot_op,
249 /* c */ NULL,
250 /* d */ NULL,
251 /* e */ &sysrq_term_op,
252 /* f */ NULL,
253 /* g */ NULL,
254 /* h */ NULL,
255 /* i */ &sysrq_kill_op,
256 /* j */ NULL,
257 #ifdef CONFIG_VT
258 /* k */ &sysrq_SAK_op,
259 #else
260 /* k */ NULL,
261 #endif
262 /* l */ NULL,
263 /* m */ &sysrq_showmem_op,
264 /* n */ &sysrq_unrt_op,
265 /* o */ NULL, /* This will often be registered
266                  as 'Off' at init time */
267 /* p */ &sysrq_showregs_op,
268 /* q */ NULL,
269 #ifdef CONFIG_VT
270 /* r */ &sysrq_unraw_op,
271 #else
272 /* r */ NULL,
273 #endif
274 /* s */ &sysrq_sync_op,
275 /* t */ &sysrq_showstate_op,
276 /* u */ &sysrq_mountro_op,
277 /* v */ NULL, /* May be assigned at init time by SMP VOYAGER */
278 /* w */ NULL,
279 /* x */ NULL,
280 /* y */ NULL,
281 /* z */ NULL
282 };
283 
284 /* key2index calculation, -1 on invalid index */
285 static int sysrq_key_table_key2index(int key) {
286         int retval;
287         if ((key >= '') && (key <= '9')) {
288                 retval = key - '';
289         } else if ((key >= 'a') && (key <= 'z')) {
290                 retval = key + 10 - 'a';
291         } else {
292                 retval = -1;
293         }
294         return retval;
295 }
296 
297 /*
298  * get and put functions for the table, exposed to modules.
299  */
300 
301 struct sysrq_key_op *__sysrq_get_key_op (int key) {
302         struct sysrq_key_op *op_p;
303         int i;
304         
305         i = sysrq_key_table_key2index(key);
306         op_p = (i == -1) ? NULL : sysrq_key_table[i];
307         return op_p;
308 }
309 
310 void __sysrq_put_key_op (int key, struct sysrq_key_op *op_p) {
311         int i;
312 
313         i = sysrq_key_table_key2index(key);
314         if (i != -1)
315                 sysrq_key_table[i] = op_p;
316 }
317 
318 /*
319  * This is the non-locking version of handle_sysrq
320  * It must/can only be called by sysrq key handlers,
321  * as they are inside of the lock
322  */
323 
324 void __handle_sysrq(int key, struct pt_regs *pt_regs, struct tty_struct *tty)
325 {
326         struct sysrq_key_op *op_p;
327         int orig_log_level;
328         int i, j;
329         unsigned long flags;
330 
331         spin_lock_irqsave(&sysrq_key_table_lock, flags);
332         orig_log_level = console_loglevel;
333         console_loglevel = 7;
334         printk(KERN_INFO "SysRq : ");
335 
336         op_p = __sysrq_get_key_op(key);
337         if (op_p) {
338                 printk ("%s\n", op_p->action_msg);
339                 console_loglevel = orig_log_level;
340                 op_p->handler(key, pt_regs, tty);
341         } else {
342                 printk("HELP : ");
343                 /* Only print the help msg once per handler */
344                 for (i=0; i<SYSRQ_KEY_TABLE_LENGTH; i++) 
345                 if (sysrq_key_table[i]) {
346                         for (j=0; sysrq_key_table[i] != sysrq_key_table[j]; j++);
347                         if (j == i)
348                                 printk ("%s ", sysrq_key_table[i]->help_msg);
349                 }
350                 printk ("\n");
351                 console_loglevel = orig_log_level;
352         }
353         spin_unlock_irqrestore(&sysrq_key_table_lock, flags);
354 }
355 
356 /*
357  * This function is called by the keyboard handler when SysRq is pressed
358  * and any other keycode arrives.
359  */
360 
361 void handle_sysrq(int key, struct pt_regs *pt_regs, struct tty_struct *tty)
362 {
363         if (!sysrq_enabled)
364                 return;
365         __handle_sysrq(key, pt_regs, tty);
366 }
367 
368 int __sysrq_swap_key_ops(int key, struct sysrq_key_op *insert_op_p,
369                                 struct sysrq_key_op *remove_op_p) {
370 
371         int retval;
372         unsigned long flags;
373 
374         spin_lock_irqsave(&sysrq_key_table_lock, flags);
375         if (__sysrq_get_key_op(key) == remove_op_p) {
376                 __sysrq_put_key_op(key, insert_op_p);
377                 retval = 0;
378         } else {
379                 retval = -1;
380         }
381         spin_unlock_irqrestore(&sysrq_key_table_lock, flags);
382 
383         return retval;
384 }
385 
386 int register_sysrq_key(int key, struct sysrq_key_op *op_p)
387 {
388         return __sysrq_swap_key_ops(key, op_p, NULL);
389 }
390 
391 int unregister_sysrq_key(int key, struct sysrq_key_op *op_p)
392 {
393         return __sysrq_swap_key_ops(key, NULL, op_p);
394 }
395 
396 EXPORT_SYMBOL(handle_sysrq);
397 EXPORT_SYMBOL(register_sysrq_key);
398 EXPORT_SYMBOL(unregister_sysrq_key);
399 
  This page was automatically generated by the LXR engine.