--- linux-2.4.11-pre2-stateful_sysrq/kernel/sysctl.c.stateful_sysrq Mon Oct 1 23:13:44 2001 +++ linux-2.4.11-pre2-stateful_sysrq/kernel/sysctl.c Mon Oct 1 23:23:58 2001 @@ -46,7 +46,7 @@ extern int sysctl_overcommit_memory; extern int max_threads; extern int nr_queued_signals, max_queued_signals; -extern int sysrq_enabled; +extern struct sysrq_ctls_struct sysrq_ctls; extern int core_uses_pid; extern int cad_pid; @@ -233,7 +233,9 @@ 0644, NULL, &proc_dointvec}, #endif #ifdef CONFIG_MAGIC_SYSRQ - {KERN_SYSRQ, "sysrq", &sysrq_enabled, sizeof (int), + {KERN_SYSRQ, "sysrq", &sysrq_ctls.enabled, sizeof (int), + 0644, NULL, &proc_dointvec}, + {KERN_SYSRQ, "sysrq-key", &sysrq_ctls.keycode, sizeof (sysrq_ctls.keycode), 0644, NULL, &proc_dointvec}, #endif {KERN_CADPID, "cad_pid", &cad_pid, sizeof (int), --- linux-2.4.11-pre2-stateful_sysrq/include/linux/sysctl.h.stateful_sysrq Mon Oct 1 23:13:44 2001 +++ linux-2.4.11-pre2-stateful_sysrq/include/linux/sysctl.h Mon Oct 1 23:23:58 2001 @@ -106,7 +106,7 @@ KERN_MSGMAX=35, /* int: Maximum size of a messege */ KERN_MSGMNB=36, /* int: Maximum message queue size */ KERN_MSGPOOL=37, /* int: Maximum system message pool size */ - KERN_SYSRQ=38, /* int: Sysreq enable */ + KERN_SYSRQ=38, /* struct: Sysreq enable, Sysreq keycode */ KERN_MAX_THREADS=39, /* int: Maximum nr of threads in the system */ KERN_RANDOM=40, /* Random driver */ KERN_SHMALL=41, /* int: Maximum size of shared memory */ --- linux-2.4.11-pre2-stateful_sysrq/include/linux/sysrq.h.stateful_sysrq Mon Oct 1 23:13:44 2001 +++ linux-2.4.11-pre2-stateful_sysrq/include/linux/sysrq.h Mon Oct 1 23:23:58 2001 @@ -26,6 +26,12 @@ #ifdef CONFIG_MAGIC_SYSRQ +/* sysrq_ctls - controls aspects of the SYSRQ magic key hack*/ +struct sysrq_ctls_struct { + int enabled; + int keycode; +}; + /* Generic SysRq interface -- you may call it from any device driver, supplying * ASCII code of the key, pointer to registers and kbd/tty structs (if they * are available -- else NULL's). --- linux-2.4.11-pre2-stateful_sysrq/drivers/char/keyboard.c.stateful_sysrq Tue Sep 18 16:39:51 2001 +++ linux-2.4.11-pre2-stateful_sysrq/drivers/char/keyboard.c Mon Oct 1 23:23:58 2001 @@ -21,6 +21,12 @@ * * 27-05-97: Added support for the Magic SysRq Key (Martin Mares) * 30-07-98: Dead keys redone, aeb@cwi.nl. + * + * 28-09-2001: Crutcher Dunnavant + * Add stateful sysrq features, based upon work from: + * Mathew Mills + * Norman Murray + * */ #include @@ -157,7 +163,14 @@ struct pt_regs * kbd_pt_regs; #ifdef CONFIG_MAGIC_SYSRQ -static int sysrq_pressed; +static enum { + UP_AND_CLEAR, + DOWN_AND_WAITING, + DOWN_AND_DONE, + UP_AND_WAITING, + DOWN_AND_PASS +} sysrq_state; +extern struct sysrq_ctls_struct sysrq_ctls; #endif static struct pm_dev *pm_kbd; @@ -246,15 +259,69 @@ } else rep = test_and_set_bit(keycode, key_down); -#ifdef CONFIG_MAGIC_SYSRQ /* Handle the SysRq Hack */ - if (keycode == SYSRQ_KEY) { - sysrq_pressed = !up_flag; - goto out; - } else if (sysrq_pressed) { - if (!up_flag) { - handle_sysrq(kbd_sysrq_xlate[keycode], kbd_pt_regs, kbd, tty); - goto out; +#ifdef CONFIG_MAGIC_SYSRQ /* Handle the SysRq Hack */ + /* + Pressing magic + command key acts as a chorded command. + Pressing and releasing magic without a command key acts sticky, + using the next non-magic key as a command key + Pressing magic twice without a command key passes the magic key + through. + */ + + if (sysrq_ctls.enabled) { + if (keycode == sysrq_ctls.keycode) switch(sysrq_state) { + case UP_AND_CLEAR: + sysrq_state = up_flag ? UP_AND_CLEAR : + DOWN_AND_WAITING; + /* consume the key event */ + goto out; + + case DOWN_AND_WAITING: + sysrq_state = up_flag ? UP_AND_WAITING : + DOWN_AND_WAITING; + /* consume the key event */ + goto out; + + case DOWN_AND_DONE: + sysrq_state = up_flag ? UP_AND_CLEAR : + DOWN_AND_DONE; + /* consume the key event */ + goto out; + + case DOWN_AND_PASS: + case UP_AND_WAITING: + sysrq_state = up_flag ? UP_AND_CLEAR : + DOWN_AND_PASS; + /* pass the key event through */ + break; + + } else switch(sysrq_state) { + case UP_AND_WAITING: + case DOWN_AND_WAITING: + case DOWN_AND_DONE: + if (!up_flag) { + handle_sysrq(kbd_sysrq_xlate[keycode], + kbd_pt_regs, kbd, tty); + } + + if (sysrq_state == UP_AND_WAITING) { + sysrq_state = UP_AND_CLEAR; + } else { + sysrq_state = DOWN_AND_DONE; + } + + /* consume the key event */ + goto out; + + + case DOWN_AND_PASS: + case UP_AND_CLEAR: + /* pass the key event through */ + break; + } + } else { + sysrq_state = UP_AND_CLEAR; } #endif --- linux-2.4.11-pre2-stateful_sysrq/drivers/char/sysrq.c.stateful_sysrq Mon Oct 1 23:13:36 2001 +++ linux-2.4.11-pre2-stateful_sysrq/drivers/char/sysrq.c Mon Oct 1 23:23:58 2001 @@ -32,12 +32,21 @@ #include +/* for the SYSRQ_KEY definition */ +#include + extern void reset_vc(unsigned int); extern struct list_head super_blocks; /* Whether we react on sysrq keys or just ignore them */ -int sysrq_enabled = 1; +struct sysrq_ctls_struct sysrq_ctls = { + /* Whether we react on sysrq keys or just ignore them */ + enabled: 1, + /* The keycode for the magic key, referred to as sysrq */ + keycode: SYSRQ_KEY, +}; + /* Machine specific power off function */ void (*sysrq_power_off)(void); @@ -433,7 +442,7 @@ void handle_sysrq(int key, struct pt_regs *pt_regs, struct kbd_struct *kbd, struct tty_struct *tty) { - if (!sysrq_enabled) + if (!sysrq_ctls.enabled) return; __sysrq_lock_table(); @@ -453,7 +462,7 @@ int orig_log_level; int i, j; - if (!sysrq_enabled) + if (!sysrq_ctls.enabled) return; orig_log_level = console_loglevel;