Skip to contentSkip to conversation

2.5.59 morse code panics

PATCH In review Tomas Szepe 7 participants 19 messages Jan 30, 2003 – Jan 31, 2003

lore
Share & tools
lore
#0 lore raw

PATCH 1/1 2.5.59 morse code panics

Here's the initial port of Andrew Rodland's morse code panics to 2.5. It's probably got a few issues that need to be sorted out:
at least the acquisition of the atkbd handle is a shameful hack. The original regular blinking code from ac has been removed, because it's no use when we've got morse about. :)

Any comments appreciated, patch against 2.5.59.

Signature · 237 lines
Tomas Szepe <[email protected]>


diff -urN a/drivers/input/keyboard/atkbd.c b/drivers/input/keyboard/atkbd.c
--- a/drivers/input/keyboard/atkbd.c	2002-12-08 20:06:16.000000000 +0100
+++ b/drivers/input/keyboard/atkbd.c	2003-01-30 15:19:50.000000000 +0100
@@ -445,6 +445,23 @@
 	atkbd_command(atkbd, &atkbd->oldset, ATKBD_CMD_SSCANSET);
 }
 
+#ifdef CONFIG_MORSE_PANICS
+static struct atkbd *atkbd_blinkdev = NULL;
+int atkbd_blink(char led) {
+	char param[2] = "\0\0";
+	led = led ? (0x01 | 0x04) : 0x00;
+	*param = led;
+
+	if (atkbd_blinkdev == NULL)
+		return -1;
+
+	if (atkbd_command(atkbd_blinkdev, param, ATKBD_CMD_SETLEDS))
+		return -1;
+
+	return 0;
+}
+#endif
+
 /*
  * atkbd_disconnect() closes and frees.
  */
@@ -543,11 +560,12 @@
 			set_bit(atkbd->keycode[i], atkbd->dev.keybit);
 
 	input_register_device(&atkbd->dev);
-
+#ifdef CONFIG_MORSE_PANICS
+	atkbd_blinkdev = atkbd;
+#endif
 	printk(KERN_INFO "input: %s on %s\n", atkbd->name, serio->phys);
 }
 
-
 static struct serio_dev atkbd_dev = {
 	.interrupt =	atkbd_interrupt,
 	.connect =	atkbd_connect,
diff -urN a/init/Kconfig b/init/Kconfig
--- a/init/Kconfig	2003-01-17 04:27:10.000000000 +0100
+++ b/init/Kconfig	2003-01-30 15:15:56.000000000 +0100
@@ -98,6 +98,17 @@
 		     13 =>  8 KB
 		     12 =>  4 KB
 
+config MORSE_PANICS
+	bool "Morse code panics"
+	depends on KEYBOARD_ATKBD || VT
+	help
+	  When enabled, this code will make a panicking kernel scream for
+	  help in morse code, signalling on the leds of a possibly attached
+	  AT keyboard and/or a bleeper.  You can enable/disable your morse
+	  output devices of choice using the "panicmorse" kernel boot
+	  parameter.
+	  If unsure, say Y.
+
 endmenu
 
 
@@ -159,4 +170,3 @@
 	  in <file:Documentation/kmod.txt>.
 
 endmenu
-
diff -urN a/kernel/panic.c b/kernel/panic.c
--- a/kernel/panic.c	2003-01-09 14:25:40.000000000 +0100
+++ b/kernel/panic.c	2003-01-30 15:46:11.000000000 +0100
@@ -16,6 +16,7 @@
 #include <linux/init.h>
 #include <linux/sysrq.h>
 #include <linux/interrupt.h>
+#include <linux/vt_kern.h>
 
 asmlinkage void sys_sync(void);	/* it's really int */
 
@@ -31,6 +32,142 @@
 
 __setup("panic=", panic_setup);
 
+#ifdef CONFIG_MORSE_PANICS
+
+#ifdef CONFIG_KEYBOARD_ATKBD
+ extern int atkbd_blink(char led);	/* drivers/input/keyboards/atkbd.c */
+ #define do_blink(x) atkbd_blink(x)
+#else
+ #define do_blink(x) 0
+#endif
+
+static int morse_setting = 1;
+
+static const unsigned char morsetable[] = {
+	0122, 0, 0310, 0, 0, 0163,				/* "#$%&' */
+	055, 0155, 0, 0, 0163, 0141, 0152, 0051, 		/* ()*+,-./ */
+	077, 076, 074, 070, 060, 040, 041, 043, 047, 057,	/* 0-9 */
+	0107, 0125, 0, 0061, 0, 0114, 0, 			/* :;<=>?@ */
+	006, 021, 025, 011, 002, 024, 013, 020, 004,		/* A-I */
+	036, 015, 022, 007, 005, 017, 026, 033, 012,		/* J-R */
+	010, 003, 014, 030, 016, 031, 035, 023,			/* S-Z */
+	0, 0, 0, 0, 0154					/* [\]^_ */
+};
+
+static inline unsigned char tomorse(char c) {
+	if (c >= 'a' && c <= 'z')
+		c = c - 'a' + 'A';
+	if (c >= '"' && c <= '_') {
+		return morsetable[c - '"'];
+	} else
+		return 0;
+}
+
+#define DITLEN		(HZ / 5)
+#define DAHLEN		(3 * DITLEN)
+#define SPACELEN	(7 * DITLEN)
+
+#define FREQ 844
+
+/*  Tell the user who may be running in X and not see the console that
+ *  we have panic'd.  This is to distingush panics from "real lockups."
+ *  Could in theory send the panic message as morse, but that is left
+ *  as an exercise for the reader.
+ *
+ *  And now it's done! LED and speaker morse code by Andrew Rodland
+ *  <[email protected]>, with improvements based on suggestions from
+ *  [email protected] and a host of others.
+ *
+ *  Initial 2.5 morsepanics port by Tomas Szepe <[email protected]>,
+ *  January 2003.
+ */
+void panic_morseblink(char *buf)
+{ 
+	static unsigned long next_jiffie = 0;
+	static char * bufpos = 0;
+	static unsigned char morse = 0;
+	static char state = 1;
+	
+	if (!morse_setting) 
+		return;
+
+	if (!buf)
+		buf = "Uh oh, we lost the panic msg.";
+
+	/* Waiting for something? */
+	if (bufpos && time_after(next_jiffie, jiffies))
+		return;
+
+	if (state) {	/* Coming off of a blink. */
+		if (morse_setting & 0x01)
+			do_blink(0);
+
+		state = 0;
+
+		if (morse > 1) {
+			/* Not done yet, just a one-dit pause. */
+			next_jiffie = jiffies + DITLEN;
+		} else {
+			/* Get a new char, figure out how much space. */
+
+			/* First time through */
+			if (!bufpos)
+				bufpos = (char *) buf;
+
+			if (!*bufpos) {
+				/* Repeating */
+				bufpos = (char *) buf;
+				next_jiffie = jiffies + SPACELEN;
+			} else {
+				/* Inter-letter space */
+				next_jiffie = jiffies + DAHLEN; 
+			}
+
+			if (!(morse = tomorse(*bufpos))) {
+				next_jiffie = jiffies + SPACELEN;
+				state = 1;	/* And get us back here */
+			}
+			bufpos++;
+		}
+	} else {
+		/* Starting a new blink.  We have a valid code in morse. */
+		int len;
+
+		len = (morse & 001) ? DAHLEN : DITLEN;
+
+#ifdef CONFIG_VT
+		if (morse_setting & 0x02)
+			kd_mksound(FREQ, len);
+#endif
+
+		next_jiffie = jiffies + len;
+
+		if (morse_setting & 0x01)
+			do_blink(1);
+
+		state = 1;
+		morse >>= 1;
+	}
+}
+
+static int __init panicmorse_setup(char *str)
+{
+	int par;
+	if (get_option(&str, &par)) 
+		morse_setting = par;
+	return 1;
+}
+
+/*  "panicmorse=0" disables the blinking as it caused problems with
+ *  certain console switches.
+ *
+ *  "panicmorse | 1" does the show using kbd leds.
+ *  "panicmorse | 2" throws in bleeping via kd_mksound().
+ */
+__setup("panicmorse=", panicmorse_setup);
+
+#endif /* CONFIG_MORSE_PANICS */
+
 /**
  *	panic - halt the system
  *	@fmt: The text string to print
@@ -95,7 +232,10 @@
         disabled_wait(caller);
 #endif
 	local_irq_enable();
-	for(;;) {
+	for (;;) {
+#if defined(CONFIG_MORSE_PANICS)
+		panic_morseblink(buf);
+#endif
 		CHECK_EMERGENCY_SYNC
 	}
 }
#1 lore raw
Quoted 7 lines · Tomas Szepe

Here's the initial port of Andrew Rodland's morse code panics to 2.5. It's probably got a few issues that need to be sorted out:
at least the acquisition of the atkbd handle is a shameful hack. The original regular blinking code from ac has been removed, because it's no use when we've got morse about. :)

Any comments appreciated, patch against 2.5.59.

I forwarded Linus a copy of Andi Kleens original 'blink leds on panic' patch circa 2.5.3 or so. He rejected it due to not wanting PC-isms in kernel/

As this patch further builds upon the previous one, It'd take a complete change of mind on his part to take this as it is.

Dave

Signature · 2 lines
| Dave Jones.        http://www.codemonkey.org.uk
| SuSE Labs
#2 lore raw
Quoted 3 lines · Dave Jones

As this patch further builds upon the previous one, It'd take a complete change of mind on his part to take this as it is.

If its attached to atkbd then its not a PCism and its now nicely modularised in the atkbd driver. Providing we have a clear split between the core "morse sender" and the platform specific morse output device (do we want morse_ops 8)) it should be clean and you can write morse drivers for pc speaker, for non pc keyboard and even for soundblaster 8)

#3 lore raw
Quoted 8 lines

[[email protected]]

Quoted 3 lines · Dave Jones

As this patch further builds upon the previous one, It'd take a complete change of mind on his part to take this as it is.

Quoted 7 lines

If its attached to atkbd then its not a PCism and its now nicely modularised in the atkbd driver. Providing we have a clear split between the core "morse sender" and the platform specific morse output device (do we want morse_ops 8)) it should be clean and you can write morse drivers for pc speaker, for non pc keyboard and even for soundblaster 8)

Of course we want morseops. :)
v2 follows.

Signature · 284 lines
Tomas Szepe <[email protected]>


 drivers/input/keyboard/atkbd.c |   22 +++++-
 include/linux/morseops.h       |   26 +++++++
 init/Kconfig                   |   14 +++-
 kernel/Makefile                |    1 
 kernel/morse.c                 |  137 +++++++++++++++++++++++++++++++++++++++++
 kernel/panic.c                 |    4 -
 6 files changed, 200 insertions(+), 4 deletions(-)

diff -urN b/drivers/input/keyboard/atkbd.c a/drivers/input/keyboard/atkbd.c
--- b/drivers/input/keyboard/atkbd.c	2002-12-08 20:06:16.000000000 +0100
+++ a/drivers/input/keyboard/atkbd.c	2003-01-31 10:20:56.000000000 +0100
@@ -445,6 +445,23 @@
 	atkbd_command(atkbd, &atkbd->oldset, ATKBD_CMD_SSCANSET);
 }
 
+#ifdef CONFIG_MORSE_PANICS
+static struct atkbd *atkbd_blinkdev = NULL;
+int atkbd_blink(char led) {
+	char param[2] = "\0\0";
+	led = led ? (0x01 | 0x04) : 0x00;
+	*param = led;
+
+	if (atkbd_blinkdev == NULL)
+		return -1;
+
+	if (atkbd_command(atkbd_blinkdev, param, ATKBD_CMD_SETLEDS))
+		return -1;
+
+	return 0;
+}
+#endif
+
 /*
  * atkbd_disconnect() closes and frees.
  */
@@ -543,11 +560,12 @@
 			set_bit(atkbd->keycode[i], atkbd->dev.keybit);
 
 	input_register_device(&atkbd->dev);
-
+#ifdef CONFIG_MORSE_PANICS
+	atkbd_blinkdev = atkbd;
+#endif
 	printk(KERN_INFO "input: %s on %s\n", atkbd->name, serio->phys);
 }
 
-
 static struct serio_dev atkbd_dev = {
 	.interrupt =	atkbd_interrupt,
 	.connect =	atkbd_connect,
diff -urN b/include/linux/morseops.h a/include/linux/morseops.h
--- b/include/linux/morseops.h	1970-01-01 01:00:00.000000000 +0100
+++ a/include/linux/morseops.h	2003-01-31 11:20:05.000000000 +0100
@@ -0,0 +1,26 @@
+/* Yes, it's morse code ops indeed. */
+
+#ifndef _LINUX_MORSEOPS_H
+#define _LINUX_MORSEOPS_H
+
+#include <linux/config.h>
+
+#if defined(CONFIG_MORSE_PANICS)
+
+extern const unsigned char morsetable[];	/* in kernel/morse.c */
+void panic_morseblink(char *buf);		/* in kernel/morse.c */
+
+static inline unsigned char tomorse(char c) {
+	if (c >= 'a' && c <= 'z')
+		c = c - 'a' + 'A';
+	if (c >= '"' && c <= '_') {
+		return morsetable[c - '"'];
+	} else
+		return 0;
+}
+
+#else	/* CONFIG_MORSE_PANICS */
+ #define panic_morseblink(buf)
+#endif	/* CONFIG_MORSE_PANICS */
+
+#endif	/* _LINUX_MORSEOPS_H */
diff -urN b/init/Kconfig a/init/Kconfig
--- b/init/Kconfig	2003-01-17 04:27:43.000000000 +0100
+++ a/init/Kconfig	2003-01-31 11:06:31.000000000 +0100
@@ -98,6 +98,19 @@
 		     13 =>  8 KB
 		     12 =>  4 KB
 
+config MORSE_PANICS
+	bool "Morse code panics"
+	depends on KEYBOARD_ATKBD || VT
+	help
+	  When enabled, this code will make a panicking kernel cry for
+	  help in morse code, signalling on the leds of a possibly attached
+	  AT keyboard and/or a bleeper.  You can enable/disable your morse
+	  output devices of choice using the "panicmorse" kernel boot
+	  parameter.
+
+	  If unsure, say Y.  This feature is very helpful for those who
+	  spend most of their time in X.
+
 endmenu
 
 
@@ -159,4 +172,3 @@
 	  in <file:Documentation/kmod.txt>.
 
 endmenu
-
diff -urN b/kernel/Makefile a/kernel/Makefile
--- b/kernel/Makefile	2003-01-09 10:59:41.000000000 +0100
+++ a/kernel/Makefile	2003-01-31 10:28:04.000000000 +0100
@@ -22,6 +22,7 @@
 obj-$(CONFIG_BSD_PROCESS_ACCT) += acct.o
 obj-$(CONFIG_SOFTWARE_SUSPEND) += suspend.o
 obj-$(CONFIG_COMPAT) += compat.o
+obj-$(CONFIG_MORSE_PANICS) += morse.o
 
 ifneq ($(CONFIG_IA64),y)
 # According to Alan Modra <[email protected]>, the -fno-omit-frame-pointer is
diff -urN b/kernel/morse.c a/kernel/morse.c
--- b/kernel/morse.c	1970-01-01 01:00:00.000000000 +0100
+++ a/kernel/morse.c	2003-01-31 11:19:54.000000000 +0100
@@ -0,0 +1,137 @@
+/*
+ *  kernel/morse.c
+ *
+ *  Copyright (C) 2002 Andrew Rodland <[email protected]>
+ *  Copyright (C) 2003 Tomas Szepe <[email protected]>
+ *
+ *  Tell the user who may be running in X and not see the console that
+ *  we have panic'd.  This is to distingush panics from "real lockups."
+ *  Could in theory send the panic message as morse, but that is left
+ *  as an exercise for the reader.
+ *
+ *  And now it's done! LED and speaker morse code by Andrew Rodland
+ *  <[email protected]>, with improvements based on suggestions from
+ *  [email protected] and a host of others.
+ *
+ *  Initial 2.5 morsepanics port and cleanup by
+ *  Tomas Szepe <[email protected]>, January 2003.
+ */
+
+#include <linux/config.h>
+#include <linux/morseops.h>
+#include <linux/init.h>
+#include <linux/jiffies.h>
+#include <linux/vt_kern.h>
+
+#define DITLEN		(HZ / 5)
+#define DAHLEN		(3 * DITLEN)
+#define SPACELEN	(7 * DITLEN)
+#define FREQ		844
+
+/*  Only blink by default if AT keyboard is available,
+ *  go for beeping if it isn't.
+ */
+#ifdef CONFIG_KEYBOARD_ATKBD
+extern int atkbd_blink(char led);	/* drivers/input/keyboards/atkbd.c */
+#define do_blink(x) atkbd_blink(x)
+static int morse_setting = 1;
+#else
+#define do_blink(x)
+static int morse_setting = 2;
+#endif
+
+const unsigned char morsetable[] = {
+	0122, 0, 0310, 0, 0, 0163,				/* "#$%&' */
+	055, 0155, 0, 0, 0163, 0141, 0152, 0051, 		/* ()*+,-./ */
+	077, 076, 074, 070, 060, 040, 041, 043, 047, 057,	/* 0-9 */
+	0107, 0125, 0, 0061, 0, 0114, 0, 			/* :;<=>?@ */
+	006, 021, 025, 011, 002, 024, 013, 020, 004,		/* A-I */
+	036, 015, 022, 007, 005, 017, 026, 033, 012,		/* J-R */
+	010, 003, 014, 030, 016, 031, 035, 023,			/* S-Z */
+	0, 0, 0, 0, 0154					/* [\]^_ */
+};
+
+void panic_morseblink(char *buf)
+{ 
+	static unsigned long next_jiffie = 0;
+	static char * bufpos = 0;
+	static unsigned char morse = 0;
+	static char state = 1;
+	
+	if (!morse_setting) 
+		return;
+
+	if (!buf)
+		buf = "Uh oh, we lost the panic msg.";
+
+	/* Waiting for something? */
+	if (bufpos && time_after(next_jiffie, jiffies))
+		return;
+
+	if (state) {	/* Coming off of a blink. */
+		if (morse_setting & 0x01)
+			do_blink(0);
+
+		state = 0;
+
+		if (morse > 1) {
+			/* Not done yet, just a one-dit pause. */
+			next_jiffie = jiffies + DITLEN;
+		} else {
+			/* Get a new char, figure out how much space. */
+
+			/* First time through */
+			if (!bufpos)
+				bufpos = (char *) buf;
+
+			if (!*bufpos) {
+				/* Repeating */
+				bufpos = (char *) buf;
+				next_jiffie = jiffies + SPACELEN;
+			} else {
+				/* Inter-letter space */
+				next_jiffie = jiffies + DAHLEN; 
+			}
+
+			if (!(morse = tomorse(*bufpos))) {
+				next_jiffie = jiffies + SPACELEN;
+				state = 1;	/* And get us back here */
+			}
+			bufpos++;
+		}
+	} else {
+		/* Starting a new blink.  We have a valid code in morse. */
+		int len;
+
+		len = (morse & 001) ? DAHLEN : DITLEN;
+
+#ifdef CONFIG_VT
+		if (morse_setting & 0x02)
+			kd_mksound(FREQ, len);
+#endif
+
+		next_jiffie = jiffies + len;
+
+		if (morse_setting & 0x01)
+			do_blink(1);
+
+		state = 1;
+		morse >>= 1;
+	}
+}
+
+static int __init panicmorse_setup(char *str)
+{
+	int par;
+	if (get_option(&str, &par)) 
+		morse_setting = par;
+	return 1;
+}
+
+/*  "panicmorse=0" disables the blinking as it caused problems with
+ *  certain console switches.
+ *
+ *  "panicmorse | 1" does the show using kbd leds.
+ *  "panicmorse | 2" throws in bleeping via kd_mksound().
+ */
+__setup("panicmorse=", panicmorse_setup);
diff -urN b/kernel/panic.c a/kernel/panic.c
--- b/kernel/panic.c	2003-01-09 10:59:41.000000000 +0100
+++ a/kernel/panic.c	2003-01-31 10:36:50.000000000 +0100
@@ -16,6 +16,7 @@
 #include <linux/init.h>
 #include <linux/sysrq.h>
 #include <linux/interrupt.h>
+#include <linux/morseops.h>
 
 asmlinkage void sys_sync(void);	/* it's really int */
 
@@ -95,7 +96,8 @@
         disabled_wait(caller);
 #endif
 	local_irq_enable();
-	for(;;) {
+	for (;;) {
+		panic_morseblink(buf);
 		CHECK_EMERGENCY_SYNC
 	}
 }
#4 lore raw
Quoted 11 lines
Quoted 11 lines
Quoted 3 lines

As this patch further builds upon the previous one, It'd take a complete change of mind on his part to take this as it is.

If its attached to atkbd then its not a PCism and its now nicely modularised in the atkbd driver. Providing we have a clear split between the core "morse sender" and the platform specific morse output device (do we want morse_ops 8)) it should be clean and you can write morse drivers for pc speaker, for non pc keyboard and even for soundblaster 8)

Actually the Soundblaster idea might not be so funny as it originally sounds, (pun intended :-) ), because if you've got another machine nearby, with a microphone, you could actually turn up the volume, and de-code the morse on the other box. The PC speaker may well be too quiet to do that. It should be fairly straightforward to get a simple bleep out of any card that implements the Adlib registers.

John.

#5 lore raw
Quoted 4 lines · John Bradford

Actually the Soundblaster idea might not be so funny as it originally sounds, (pun intended :-) ), because if you've got another machine nearby, with a microphone, you could actually turn up the volume, and de-code the morse on the other box.

Or you could put down the crackpipe and run a serial console between the two boxes. Or even netconsole would make more sense (and be a lot more reliable).

Dave

Signature · 2 lines
| Dave Jones.        http://www.codemonkey.org.uk
| SuSE Labs
#6 lore raw
Quoted 3 lines · Dave Jones

Or you could put down the crackpipe and run a serial console between the two boxes. Or even netconsole would make more sense (and be a lot more reliable).

A lot of newer laptops do not have serial ports. While morse code may be a little silly the general purpose hook it needs to be done cleanly is considerably more useful

#7 lore raw
Quoted 3 lines

A lot of newer laptops do not have serial ports. While morse code may be a little silly the general purpose hook it needs to be done cleanly is considerably more useful

Exactly.

The exact method that a crashed machine, in a rack, in a datacentre, miles away from me, contacts me to let me know something is wrong doesn't matter, but if a member of the datacentre staff can get a detailed message to me, so much the better than just having the box rebooted. On the other hand, I don't actually want to have to listen to ten minutes of morse code over the phone when another box could do it for me.

John.

#8 lore raw
Quoted 7 lines · John Bradford

The exact method that a crashed machine, in a rack, in a datacentre, miles away from me, contacts me to let me know something is wrong doesn't matter, but if a member of the datacentre staff can get a detailed message to me, so much the better than just having the box rebooted. On the other hand, I don't actually want to have to listen to ten minutes of morse code over the phone when another box could do it for me.

That must be a pretty quiet datacentre. And what happens when more than one box starts beeping ?

Dave

Signature · 1 line
| Dave Jones.        http://www.codemonkey.org.uk
#9 lore raw
In reply to Alan Cox
Quoted 1 line · Alan Cox

A lot of newer laptops do not have serial ports.

so use something sensible like a crashdump to floppy.

Quoted 3 lines

While morse code may
be a little silly the general purpose hook it needs to be done cleanly is considerably more useful

sure. things like lkcd,netconsole etc could all use that
infrastructure. The beyond-silly bit was the 'other machine
to decode morse' argument.

Dave

Signature · 1 line
| Dave Jones.        http://www.codemonkey.org.uk
#10 lore raw
Quoted 3 lines
Quoted 1 line

A lot of newer laptops do not have serial ports.

so use something sensible like a crashdump to floppy.

A lot of newer laptops do not have floppy drives :-)

Seriously, though, I agree that morse isn't the most ideal way to get data out of a crashed system.

Quoted 7 lines
Quoted 3 lines

While morse code may
be a little silly the general purpose hook it needs to be done cleanly is considerably more useful

sure. things like lkcd,netconsole etc could all use that
infrastructure. The beyond-silly bit was the 'other machine
to decode morse' argument.

Depends on how good your morse is, I suppose, I wouldn't really want to decode a oops from morse by ear.

Quoted 10 lines
Quoted 7 lines

The exact method that a crashed machine, in a rack, in a datacentre, miles away from me, contacts me to let me know something is wrong doesn't matter, but if a member of the datacentre staff can get a detailed message to me, so much the better than just having the box rebooted. On the other hand, I don't actually want to have to listen to ten minutes of morse code over the phone when another box could do it for me.

That must be a pretty quiet datacentre. And what happens when more than one box starts beeping ?

OK, point taken, that *was* a beyond-silly suggestion :-)

John.

#11 lore raw
In reply to Dave Jones
Quoted 3 lines · Dave Jones

Or you could put down the crackpipe and run a serial console between the two boxes. Or even netconsole would make more sense (and be a lot more reliable).

There's a classic Monty Python skit where John Cleese is organizing an expedition to build a bridge between the two peaks of Mt Kilamanjaro.

I have to do most of my kernel hacking at home, on my own time. So I'm sitting there with a laptop and no second machine. Now, if the intent is to say "Don't bother doing anything that might require debugging unless you can afford 2 machines", that's OK - but let's be open about that requirement. And has been pointed out, some laptops don't even *HAVE* a serial port.

There's a *REASON* that IBM RS/6K boxes have at least a little 3-digit LED display - during boot or a panic, even if you can't trust the console drivers anymore, you can still output *something*.

Signature · 3 lines
				Valdis Kletnieks
				Computer Systems Senior Engineer
				Virginia Tech
#12 lore raw
Quoted 3 lines

There's a *REASON* that IBM RS/6K boxes have at least a little 3-digit LED display - during boot or a panic, even if you can't trust the console drivers anymore, you can still output *something*.

By the way, you can buy cards with LED displays on which monitor port 80h, and tell you how far through the boot process a box is getting. Not much use on a laptop, though :-).

John.

#13 lore raw
In reply to [email protected]
Quoted 5 lines · On Fri, Jan 31, 2003 at 09:40:27AM -0500, [email protected] wrote:

I have to do most of my kernel hacking at home, on my own time. So I'm sitting there with a laptop and no second machine. Now, if the intent is to say "Don't bother doing anything that might require debugging unless you can afford 2 machines", that's OK - but let's be open about that requirement. And has been pointed out, some laptops don't even *HAVE* a serial port.

So go see Ingo's netconsole. (Which admittedly only supports certain net drivers). Or one of the crashdump facilities. All of which is far more reliable and useful than sitting there with a microphone.

Quoted 3 lines

There's a *REASON* that IBM RS/6K boxes have at least a little 3-digit LED display - during boot or a panic, even if you can't trust the console drivers anymore, you can still output *something*.

There's no reason to trust morse panic output more than console output. If something has scribbled over kernel space memory, you're screwed anyway. It's hit or miss whether your panic-method-de-jour has been stomped on.

Dave

Signature · 1 line
| Dave Jones.        http://www.codemonkey.org.uk
#14 lore raw
Quoted 3 lines · Dave Jones

So go see Ingo's netconsole. (Which admittedly only supports certain net drivers). Or one of the crashdump facilities. All of which is far more reliable and useful than sitting there with a microphone.

If I don't have a second box to run a serial cable to, I probably don't have a second box to run cat5 to, so netconsole probably doesn't do me any good.

crashdump might be usable, I'll have to look...

Quoted 4 lines

There's no reason to trust morse panic output more than console output. If something has scribbled over kernel space memory, you're screwed anyway. It's hit or miss whether your panic-method-de-jour has been stomped on.

The real solution is probably to get Ingo's netconsole, the morse-panic patch, the current serial-console support, and abstract it all into some infrastructure with output hooks - netconsole, serial, morse, whatever.

But we're alledgedly in a feature freeze, so that's a 2.7-ish I guess...

Signature · 3 lines
				Valdis Kletnieks
				Computer Systems Senior Engineer
				Virginia Tech
#15 lore raw
In reply to Dave Jones
Quoted 4 lines · John Bradford
Quoted 4 lines

Actually the Soundblaster idea might not be so funny as it originally sounds, (pun intended :-) ), because if you've got another machine nearby, with a microphone, you could actually turn up the volume, and de-code the morse on the other box.

And Dave Jones replied:

Quoted 3 lines

Or you could put down the crackpipe and run a serial console between the two boxes. Or even netconsole would make more sense (and be a lot more reliable).

Oh, come now, Dave; be nice! This is fun stuff.

A voice synthesizer would be even better than morse code.

"I'm sorry Dave. I can't boot."

Think Hal 9000, from 2001/2010! The kernel could detect a sound card at boot, and then tell us what broke. Very 22nd century, if you ask me.

If sound is broken or nonexistent, we could fall back to Morse! Or electric shocks via a serial connection! The possibilities are endless.

...Scott (Who thinks people here are much too serious sometimes)

#16 lore raw
In reply to Alan Cox
Quoted 5 lines · Alan Cox
Quoted 3 lines · Dave Jones

As this patch further builds upon the previous one, It'd take a complete change of mind on his part to take this as it is.

Quoted 7 lines

If its attached to atkbd then its not a PCism and its now nicely modularised in the atkbd driver. Providing we have a clear split between the core "morse sender" and the platform specific morse output device (do we want morse_ops 8)) it should be clean and you can write morse drivers for pc speaker, for non pc keyboard and even for soundblaster 8)

It should be in the keyboard.c file, using input_event() to blink the LEDs. This way it'll work on all archs in 2.5.

I will not accept it as a patch for atkbd.c, unless there is a strong reason to do it there.

Signature · 2 lines
Vojtech Pavlik
SuSE Labs
#17 lore raw
Quoted 4 lines

[[email protected]]

It should be in the keyboard.c file, using input_event() to blink the LEDs. This way it'll work on all archs in 2.5.

Oh, thanks for pointing this out, Vojtech, I'll certainly fix it.

Signature · 1 line
Tomas Szepe <[email protected]>
#18 lore raw
In reply to Vojtech Pavlik
Quoted 4 lines

[[email protected]]

It should be in the keyboard.c file, using input_event() to blink the LEDs. This way it'll work on all archs in 2.5.

This change
a) allows for other cleanups, too.
b) probably makes the gazillion leds on sparc keyboards blink. EVIL!!

So here's v3.

Signature · 273 lines
Tomas Szepe <[email protected]>


 drivers/char/keyboard.c  |   21 +++++++
 include/linux/morseops.h |   26 +++++++++
 include/linux/vt_kern.h  |    3 +
 init/Kconfig             |   15 +++++
 kernel/Makefile          |    1 
 kernel/morse.c           |  125 +++++++++++++++++++++++++++++++++++++++++++++++
 kernel/panic.c           |    4 +
 7 files changed, 194 insertions(+), 1 deletion(-)

diff -urN a/drivers/char/keyboard.c b/drivers/char/keyboard.c
--- a/drivers/char/keyboard.c	2002-12-16 07:01:47.000000000 +0100
+++ b/drivers/char/keyboard.c	2003-01-31 20:24:33.000000000 +0100
@@ -262,6 +262,27 @@
 }
 
 /*
+ * Turn all possible leds on or off.
+ */
+void kd_turn_all_leds(int on_or_off)
+{
+	struct list_head *node;
+	on_or_off = on_or_off ? 1 : 0;
+
+	list_for_each(node, &kbd_handler.h_list) {
+		struct input_handle *handle = to_handle_h(node);
+		if (test_bit(EV_LED, handle->dev->evbit)) {
+			int led;
+			for (led = 0; led <= LED_MAX; led++) {
+				if (test_bit(led, handle->dev->ledbit))
+					input_event(handle->dev, EV_LED, led,
+						on_or_off);
+			}
+		}
+	}
+}
+
+/*
  * Setting the keyboard rate.
  */
 static inline unsigned int ms_to_jiffies(unsigned int ms) {
diff -urN a/include/linux/morseops.h b/include/linux/morseops.h
--- a/include/linux/morseops.h	1970-01-01 01:00:00.000000000 +0100
+++ b/include/linux/morseops.h	2003-01-31 20:24:33.000000000 +0100
@@ -0,0 +1,26 @@
+/* Yes, it's morse code ops indeed. */
+
+#ifndef _LINUX_MORSEOPS_H
+#define _LINUX_MORSEOPS_H
+
+#include <linux/config.h>
+
+#if defined(CONFIG_MORSE_PANICS)
+
+extern const unsigned char morsetable[];	/* in kernel/morse.c */
+void panic_morseblink(char *buf);		/* in kernel/morse.c */
+
+static inline unsigned char tomorse(char c) {
+	if (c >= 'a' && c <= 'z')
+		c = c - 'a' + 'A';
+	if (c >= '"' && c <= '_') {
+		return morsetable[c - '"'];
+	} else
+		return 0;
+}
+
+#else	/* CONFIG_MORSE_PANICS */
+ #define panic_morseblink(buf)
+#endif	/* CONFIG_MORSE_PANICS */
+
+#endif	/* _LINUX_MORSEOPS_H */
diff -urN a/include/linux/vt_kern.h b/include/linux/vt_kern.h
--- a/include/linux/vt_kern.h	2002-12-16 07:01:55.000000000 +0100
+++ b/include/linux/vt_kern.h	2003-01-31 20:24:33.000000000 +0100
@@ -33,7 +33,10 @@
 	wait_queue_head_t paste_wait;
 } *vt_cons[MAX_NR_CONSOLES];
 
+/* keyboard.c */
+
 extern void kd_mksound(unsigned int hz, unsigned int ticks);
+extern void kd_turn_all_leds(int on_or_off);
 extern int kbd_rate(struct kbd_repeat *rep);
 
 /* console.c */
diff -urN a/init/Kconfig b/init/Kconfig
--- a/init/Kconfig	2003-01-17 04:27:10.000000000 +0100
+++ b/init/Kconfig	2003-01-31 20:24:33.000000000 +0100
@@ -98,6 +98,21 @@
 		     13 =>  8 KB
 		     12 =>  4 KB
 
+config MORSE_PANICS
+	bool "Morse code panics"
+	depends on VT
+	help
+	  When enabled, this code will make a panicking kernel cry for
+	  help in morse code, signalling on the leds of a possibly attached
+	  keyboard and/or a bleeper.  You can enable/disable your morse
+	  output devices of choice using the "panicmorse" kernel boot
+	  parameter.  Currently, "panicmorse=0" will disable the signalling
+	  completely, "panicmorse=1" (the default) will only blink the leds,
+	  "panicmorse=2" will only beep, and "panicmorse=3" will do both.
+
+	  If unsure, say Y.  This feature is very helpful for those who
+	  spend most of their time in X.
+
 endmenu
 
 
diff -urN a/kernel/Makefile b/kernel/Makefile
--- a/kernel/Makefile	2003-01-09 14:25:40.000000000 +0100
+++ b/kernel/Makefile	2003-01-31 20:24:33.000000000 +0100
@@ -22,6 +22,7 @@
 obj-$(CONFIG_BSD_PROCESS_ACCT) += acct.o
 obj-$(CONFIG_SOFTWARE_SUSPEND) += suspend.o
 obj-$(CONFIG_COMPAT) += compat.o
+obj-$(CONFIG_MORSE_PANICS) += morse.o
 
 ifneq ($(CONFIG_IA64),y)
 # According to Alan Modra <[email protected]>, the -fno-omit-frame-pointer is
diff -urN a/kernel/morse.c b/kernel/morse.c
--- a/kernel/morse.c	1970-01-01 01:00:00.000000000 +0100
+++ b/kernel/morse.c	2003-01-31 20:24:33.000000000 +0100
@@ -0,0 +1,125 @@
+/*
+ *  kernel/morse.c
+ *
+ *  Copyright (C) 2002 Andrew Rodland <[email protected]>
+ *  Copyright (C) 2003 Tomas Szepe <[email protected]>
+ *
+ *  Tell the user who may be running in X and not see the console that
+ *  we have panic'd.  This is to distingush panics from "real lockups."
+ *  Could in theory send the panic message as morse, but that is left
+ *  as an exercise for the reader.
+ *
+ *  And now it's done! LED and speaker morse code by Andrew Rodland
+ *  <[email protected]>, with improvements based on suggestions from
+ *  [email protected] and a host of others.
+ *
+ *  Initial 2.5 morsepanics port and cleanup by
+ *  Tomas Szepe <[email protected]>, January 2003.
+ */
+
+#include <linux/config.h>
+#include <linux/morseops.h>
+#include <linux/init.h>
+#include <linux/jiffies.h>
+#include <linux/vt_kern.h>
+
+#define DITLEN		(HZ / 5)
+#define DAHLEN		(3 * DITLEN)
+#define SPACELEN	(7 * DITLEN)
+#define FREQ		844
+
+static int morse_setting = 1;
+
+const unsigned char morsetable[] = {
+	0122, 0, 0310, 0, 0, 0163,				/* "#$%&' */
+	055, 0155, 0, 0, 0163, 0141, 0152, 0051, 		/* ()*+,-./ */
+	077, 076, 074, 070, 060, 040, 041, 043, 047, 057,	/* 0-9 */
+	0107, 0125, 0, 0061, 0, 0114, 0, 			/* :;<=>?@ */
+	006, 021, 025, 011, 002, 024, 013, 020, 004,		/* A-I */
+	036, 015, 022, 007, 005, 017, 026, 033, 012,		/* J-R */
+	010, 003, 014, 030, 016, 031, 035, 023,			/* S-Z */
+	0, 0, 0, 0, 0154					/* [\]^_ */
+};
+
+void panic_morseblink(char *buf)
+{ 
+	static unsigned long next_jiffie = 0;
+	static char * bufpos = 0;
+	static unsigned char morse = 0;
+	static char state = 1;
+	
+	if (!morse_setting) 
+		return;
+
+	if (!buf)
+		buf = "Uh oh, we lost the panic msg.";
+
+	/* Waiting for something? */
+	if (bufpos && time_after(next_jiffie, jiffies))
+		return;
+
+	if (state) {	/* Coming off of a blink. */
+		if (morse_setting & 0x01)
+			kd_turn_all_leds(0);
+
+		state = 0;
+
+		if (morse > 1) {
+			/* Not done yet, just a one-dit pause. */
+			next_jiffie = jiffies + DITLEN;
+		} else {
+			/* Get a new char, figure out how much space. */
+
+			/* First time through */
+			if (!bufpos)
+				bufpos = (char *) buf;
+
+			if (!*bufpos) {
+				/* Repeating */
+				bufpos = (char *) buf;
+				next_jiffie = jiffies + SPACELEN;
+			} else {
+				/* Inter-letter space */
+				next_jiffie = jiffies + DAHLEN; 
+			}
+
+			if (!(morse = tomorse(*bufpos))) {
+				next_jiffie = jiffies + SPACELEN;
+				state = 1;	/* And get us back here */
+			}
+			bufpos++;
+		}
+	} else {
+		/* Starting a new blink.  We have a valid code in morse. */
+		int len;
+
+		len = (morse & 001) ? DAHLEN : DITLEN;
+
+		if (morse_setting & 0x02)
+			kd_mksound(FREQ, len);
+
+		next_jiffie = jiffies + len;
+
+		if (morse_setting & 0x01)
+			kd_turn_all_leds(1);
+
+		state = 1;
+		morse >>= 1;
+	}
+}
+
+static int __init panicmorse_setup(char *str)
+{
+	int par;
+	if (get_option(&str, &par)) 
+		morse_setting = par;
+	return 1;
+}
+
+/*  "panicmorse=0" disables the blinking as it caused problems with
+ *  certain console switches.
+ *
+ *  "panicmorse | 1" does the show using kbd leds.
+ *  "panicmorse | 2" throws in bleeping via kd_mksound().
+ */
+__setup("panicmorse=", panicmorse_setup);
diff -urN a/kernel/panic.c b/kernel/panic.c
--- a/kernel/panic.c	2003-01-09 14:25:40.000000000 +0100
+++ b/kernel/panic.c	2003-01-31 20:24:33.000000000 +0100
@@ -16,6 +16,7 @@
 #include <linux/init.h>
 #include <linux/sysrq.h>
 #include <linux/interrupt.h>
+#include <linux/morseops.h>
 
 asmlinkage void sys_sync(void);	/* it's really int */
 
@@ -95,7 +96,8 @@
         disabled_wait(caller);
 #endif
 	local_irq_enable();
-	for(;;) {
+	for (;;) {
+		panic_morseblink(buf);
 		CHECK_EMERGENCY_SYNC
 	}
 }