Messages in this thread Patch in this message |  | | From | "Nicholas J. Leon" <> | Subject | Serial console patch for 2.0.23 | Date | Sun, 10 Nov 1996 18:39:23 -0500 (EST) |
| |
Someone asked about a patch that applies cleanly to 2.0.25? Well, I don't know about .25, but this one goes against .23 perfectly. 'Been using it on 3 servers for over 3 weeks with no problem.
diff -ruN linux-2.0.20.orig/Documentation/serial-console.txt linux-2.0.20/Documentation/serial-console.txt --- linux-2.0.20.orig/Documentation/serial-console.txt Thu Jan 1 01:00:00 1970 +++ linux-2.0.20/Documentation/serial-console.txt Sat Sep 21 14:55:52 1996 @@ -0,0 +1,75 @@ + Linux Serial Console + +These examples are valid if you want to use /dev/ttyS1 (COM2) +as the serial console. Replace as needed. + +1. Tell LILO to use the serial port. + In lilo.conf (global section): + + serial = 1,9600n8 (ttyS1, 9600 bd, no parity, 8 bits) + +2. Adjust to kernel flags for the new kernel, + again in lilo.conf (kernel section) + + append = "console=1,9600n8" + +3. Link /dev/console to the serial port. + + Your probably want to save your old /dev/console (the "master" virtual + console). Check if it is a symbolic link first. If not, `mv' it to + `/dev/tty0': + + ls -l /dev/console + mv /dev/console /dev/tty0 + + Now link the serial port you are going to use as the console to + /dev/console, for example ttyS1: + + ln -s /dev/ttyS1 /dev/console + + On some systems you might want to edit your bootup scripts to make sure + they don't reset this arrangement on boot. (On Debian, check + /etc/rc.boot/console and /etc/default/console). You probably also want + to put a getty on either /dev/console or /dev/ttyS1. + +4. Init and /dev/console. + Sysvinit will open /dev/console on boot. If this does not point + to the serial console device, the startup messages will be printed + to the wrong device. The kernel also passes the environment variable + "CONSOLE" to the init program. sysvinit-2.64 reckognizes this, and + opens that device instead. Boot scripts as mentioned in (3) can + also check this variable to see what device the system console is. + If CONSOLE is not set you can assume the console is /dev/tty0. + + Sysvinit remembers its stty settings in a file in /etc, called + `/etc/ioctl.save'. REMOVE THIS FILE before using the serial + console for the first time, because otherwise init will probably + set the baudrate to 38400 (baudrate of the virtual console). + +5. /dev/console and X + Programs that want to do something with the virtual console usually + open /dev/console. XF86 does this, and probably SVGALIB as well. + IMO this is wrong; they should open /dev/tty0. + I have binary patched /usr/bin/X11/XF86_SVGA to use "tty0" + instead of "console". + +6. Notes. + + If you compile the next little program, you will be able + to really "halt" the system. It will enter a little + monitor :) + + main() { reboot(0xfee1dead, 672274793, 0xCDEF0123); } + + This is just a call to the new "halt" function that later + kernels have. This is included the "halt" command of + the recent sysvinit versions. + + The monitor will also be entered at a kernel panic, or + when you press "break". That last function does not + work at the moment I think, but it would be useful for + kernel debugging. You don't have alt-scrollock on a serial + console to find out the current EIP... + +Miquel van Smoorenburg <miquels@cistron.nl>, 21-Jun-1996 + diff -ruN linux-2.0.20.orig/drivers/char/Config.in linux-2.0.20/drivers/char/Config.in --- linux-2.0.20.orig/drivers/char/Config.in Sat Aug 10 20:44:18 1996 +++ linux-2.0.20/drivers/char/Config.in Sat Sep 21 14:38:17 1996 @@ -5,6 +5,9 @@ comment 'Character devices' tristate 'Standard/generic serial support' CONFIG_SERIAL +if [ "$CONFIG_SERIAL" = y ]; then + bool 'Serial console support' CONFIG_SERIAL_CONSOLE +fi bool 'Digiboard PC/Xx Support' CONFIG_DIGI tristate 'Cyclades async mux support' CONFIG_CYCLADES bool 'Stallion multiport serial support' CONFIG_STALDRV diff -ruN linux-2.0.20.orig/drivers/char/console.c linux-2.0.20/drivers/char/console.c --- linux-2.0.20.orig/drivers/char/console.c Fri Sep 13 23:54:29 1996 +++ linux-2.0.20/drivers/char/console.c Sat Sep 21 14:38:17 1996 @@ -118,6 +118,10 @@ #define MIN(a,b) ((a) < (b) ? (a) : (b)) #endif +#ifdef CONFIG_SERIAL_CONSOLE +extern int serial_console; +#endif + struct tty_driver console_driver; static int console_refcount; static struct tty_struct *console_table[MAX_NR_CONSOLES]; @@ -2104,8 +2108,13 @@ * initialization and register_console() event from * within the bus probing code... :-( */ +#ifdef CONFIG_SERIAL_CONSOLE + if (!serial_console && video_type != VIDEO_TYPE_TGAC) + register_console(console_print); +#else if (video_type != VIDEO_TYPE_TGAC) register_console(console_print); +#endif init_bh(CONSOLE_BH, console_bh); return kmem_start; diff -ruN linux-2.0.20.orig/drivers/char/serial.c linux-2.0.20/drivers/char/serial.c --- linux-2.0.20.orig/drivers/char/serial.c Sat Jul 6 19:50:35 1996 +++ linux-2.0.20/drivers/char/serial.c Sat Sep 21 14:38:17 1996 @@ -42,11 +42,17 @@ #include <linux/ptrace.h> #include <linux/ioport.h> #include <linux/mm.h> +#ifdef CONFIG_SERIAL_CONSOLE +#include <linux/kmon.h> +#endif #include <asm/system.h> #include <asm/io.h> #include <asm/segment.h> #include <asm/bitops.h> +#ifdef CONFIG_SERIAL_CONSOLE +#include <asm/irq.h> +#endif static char *serial_name = "Serial driver"; static char *serial_version = "4.13"; @@ -56,6 +62,19 @@ struct tty_driver serial_driver, callout_driver; static int serial_refcount; +#ifdef CONFIG_SERIAL_CONSOLE +extern void register_console(void (*proc)(const char *)); + +static void serial_print(const char *); +static void init_serial_console(struct async_struct *, unsigned int); +static void register_serial_monio(void); + +static struct async_struct *serial_console_info = NULL; +static unsigned int serial_console_cflag = 0; +static int serial_console_int_disabled = 0; +int serial_console = 0; +#endif + /* serial subtype definitions */ #define SERIAL_TYPE_NORMAL 1 #define SERIAL_TYPE_CALLOUT 2 @@ -392,7 +411,8 @@ } static _INLINE_ void receive_chars(struct async_struct *info, - int *status) + int *status, + struct pt_regs * regs) { struct tty_struct *tty = info->tty; unsigned char ch; @@ -412,6 +432,10 @@ #ifdef SERIAL_DEBUG_INTR printk("handling break...."); #endif +#ifdef CONFIG_SERIAL_CONSOLE + if (info == serial_console_info) + kernel_monitor(regs, "break", NULL); +#endif *tty->flip.flag_buf_ptr++ = TTY_BREAK; if (info->flags & ASYNC_SAK) do_SAK(tty); @@ -574,7 +598,7 @@ printk("status = %x...", status); #endif if (status & UART_LSR_DR) - receive_chars(info, &status); + receive_chars(info, &status, regs); check_modem_status(info); if (status & UART_LSR_THRE) transmit_chars(info, 0); @@ -629,7 +653,7 @@ printk("status = %x...", status); #endif if (status & UART_LSR_DR) - receive_chars(info, &status); + receive_chars(info, &status, regs); check_modem_status(info); if (status & UART_LSR_THRE) transmit_chars(info, 0); @@ -688,7 +712,7 @@ printk("status = %x...", status); #endif if (status & UART_LSR_DR) - receive_chars(info, &status); + receive_chars(info, &status, regs); check_modem_status(info); if (status & UART_LSR_THRE) transmit_chars(info, 0); @@ -2852,6 +2876,13 @@ } } register_symtab(&serial_syms); +#ifdef CONFIG_SERIAL_CONSOLE + if (serial_console) { + init_serial_console(serial_console_info, serial_console_cflag); + register_console(serial_print); + register_serial_monio(); + } +#endif return 0; } @@ -2928,6 +2959,296 @@ printk(KERN_INFO "tty%02d unloaded\n", info->line); restore_flags(flags); } + +#ifdef CONFIG_SERIAL_CONSOLE + +/* + * This is here to set the speed etc. for a non-initialized + * line. We also ALWAYS disable FIFO processing for simplicity. + * It will get enabled as soon as some process does an open() + * on the serial device. + * We have no termios struct yet, so we just pass "cflag". + */ +static void init_serial_console(struct async_struct *info, unsigned int cflag) +{ + unsigned short port; + unsigned cval,fcr; + int i; + int quot = 0; + unsigned long flags; + + /* Calculate speed divisor. */ + if (!(port = info->port)) + return; + + info->normal_termios.c_cflag = cflag; + + i = cflag & CBAUD; + if (i & CBAUDEX) { + i &= ~CBAUDEX; + if (i == 1 || i == 2) i += 15; + } + /* We do not support baudrates of 0. */ + if (!baud_table[i]) i = 13; /* 9600 */ + + if (baud_table[i] == 134) + quot = (2*info->baud_base / 269); + else + quot = info->baud_base / baud_table[i]; + + /* byte size and parity */ + cval = cflag & (CSIZE | CSTOPB); + cval >>= 4; + if (cflag & PARENB) + cval |= UART_LCR_PARITY; + if (!(cflag & PARODD)) + cval |= UART_LCR_EPAR; + + /* We do not support FIFO mode, so clear the buffers. */ + if (info->type == PORT_16650 || info->type == PORT_16550A) + fcr = UART_FCR_CLEAR_RCVR | UART_FCR_CLEAR_XMIT; + else + fcr = 0; + + /* Right, program the UART. */ + save_flags(flags); cli(); + + /* Clear ports to be sure. */ + (void) serial_inp(info, UART_LSR); + (void) serial_inp(info, UART_RX); + (void) serial_inp(info, UART_IIR); + (void) serial_inp(info, UART_MSR); + + /* Disable UART interrupts. */ + serial_out(info, UART_IER, 0); + + /* Set DTR and RTS high. */ + serial_out(info, UART_MCR, UART_MCR_DTR | UART_MCR_RTS); + + /* And set speed. */ + serial_outp(info, UART_LCR, cval | UART_LCR_DLAB); /* set DLAB */ + serial_outp(info, UART_DLL, quot & 0xff); /* LS of divisor */ + serial_outp(info, UART_DLM, quot >> 8); /* MS of divisor */ + serial_outp(info, UART_LCR, cval); /* reset DLAB */ + serial_outp(info, UART_FCR, fcr); /* set fcr */ + + (void)serial_in(info, UART_RX); /* read data port to reset things */ + + restore_flags(flags); +} + +/* Serial console setup. Called from linux/init/main.c */ +void serial_setup(char *str, int *ints) +{ + char *s; + int baud, bits, parity; + int cflag = CREAD | HUPCL | CLOCAL; + + /* Sanity check. */ + if (ints[0] > 3 || ints[1] > 3) return; + + /* Get baud, bits and parity */ + baud = 2400; + bits = 8; + parity = 'n'; + if (ints[2]) baud = ints[2]; + if ((s = strchr(str, ','))) { + do { + s++; + } while(*s >= '0' && *s <= '9'); + if (*s) parity = *s++; + if (*s) bits = *s - '0'; + } + + /* Now construct a cflag setting. */ + switch(baud) { + case 1200: + cflag |= B1200; + break; + case 4800: + cflag |= B4800; + break; + case 9600: + cflag |= B9600; + break; + case 19200: + cflag |= B19200; + break; + case 38400: + cflag |= B38400; + break; + case 2400: + default: + cflag |= B2400; + break; + } + switch(bits) { + case 7: + cflag |= CS7; + break; + default: + case 8: + cflag |= CS8; + break; + } + switch(parity) { + case 'o': case 'O': + cflag |= PARODD; + break; + case 'e': case 'E': + cflag |= PARENB; + break; + } + + serial_console_info = &rs_table[ints[1]]; + serial_console_cflag = cflag; + serial_console = ints[1] + 64; /*callout_driver.minor_start*/ +} + +/* Stop interrupts. */ +static void serial_console_int_disable(void) +{ + if (serial_console_int_disabled) return; + + /* First turn off interrupt on the controller. */ + if (serial_console_info->tty && serial_console_info->irq) + disable_irq(serial_console_info->irq); + + /* Now turn off interrupts on the UART. */ + serial_out(serial_console_info, UART_IER, 0); + + (void)serial_in(serial_console_info, UART_RX); /* read data port to reset */ + serial_console_int_disabled = 1; +} + +/* Retart interrupts. */ +static void serial_console_int_enable(void) +{ + if (!serial_console_int_disabled) return; + + /* First turn on interrupts on the UART. */ + serial_out(serial_console_info, UART_IER, serial_console_info->IER); + + /* Now turn on interrupt on the controller. */ + if (serial_console_info->tty && serial_console_info->irq) + enable_irq(serial_console_info->irq); + + serial_console_int_disabled = 0; +} + +/* Wait for transmitter register to empty. */ +static int serial_wait_thre(void) +{ + unsigned int tmout = 1000000; + + while(!(serial_inp(serial_console_info, UART_LSR) & UART_LSR_THRE)) + if (--tmout == 0) break; + return(tmout ? 0 : -1); +} + +/* Send one character. */ +static int serial_send_one(unsigned char c) +{ + /* Wait for transmit register to empty. */ + if (serial_wait_thre() < 0) return(-1); + + serial_outp(serial_console_info, UART_TX, c); + + return(0); +} + +/* Send string. */ +static void serial_send_str(const char *b) +{ + unsigned char *ptr = (unsigned char *)b; + + for(; *ptr; ptr++) { + /* Send CR if needed. */ + if (*ptr == '\n') serial_send_one('\r'); + + /* And output one character. */ + if (serial_send_one(*ptr) < 0) break; + } + (void) serial_wait_thre(); +} + +/* + * Serial console output. + * This one is used by printk(). + */ +void serial_print(const char *b) +{ + unsigned char *ptr; + + ptr = (unsigned char *)b; + + /* Sanity check. */ + if (serial_console_info->port == 0) return; + + /* Turn off interrupts etc. */ + serial_console_int_disable(); + + /* Print the data. */ + serial_send_str(ptr); + + /* And re-init serial port. */ + serial_console_int_enable(); +} + +/* Read one line from the input. */ +static void serial_gets(char *s, int len) +{ + int ch, cnt = 0; + + while(1) { + /* Get character. */ + while(!(serial_inp(serial_console_info, UART_LSR) & UART_LSR_DR)) + ; + ch = serial_inp(serial_console_info, UART_RX); + + /* Check for backspace. */ + if (ch == 8 || ch == 127) { + if (cnt == 0) { + serial_send_one('\007'); + continue; + } + cnt--; + serial_send_str("\010 \010"); + continue; + } + + /* Check for enter. */ + if (ch == 10 || ch == 13) break; + + /* See if line is too long. */ + if (cnt >= len + 1) { + serial_send_one(7); + cnt--; + continue; + } + + /* Store and echo character. */ + s[cnt++] = ch; + serial_send_one(ch); + } + /* Print enter. */ + serial_send_str("\r\n"); + s[cnt] = 0; +} + +static void register_serial_monio(void) +{ + struct kmon_struct km; + + km.cons_gets = serial_gets; + km.cons_puts = serial_send_str; + km.cons_enable = serial_console_int_disable; + km.cons_disable = serial_console_int_enable; + + register_monitor_io(&km); +} + +#endif /* CONFIG_SERIAL_CONSOLE */ #ifdef MODULE int init_module(void) diff -ruN linux-2.0.20.orig/drivers/char/tga.c linux-2.0.20/drivers/char/tga.c --- linux-2.0.20.orig/drivers/char/tga.c Tue Jun 4 21:52:30 1996 +++ linux-2.0.20/drivers/char/tga.c Sat Sep 21 14:38:17 1996 @@ -25,6 +25,7 @@ #include <linux/ioport.h> #include <linux/bios32.h> #include <linux/pci.h> +#include <linux/config.h> #include <asm/io.h> #include <asm/system.h> @@ -39,6 +40,9 @@ extern void register_console(void (*proc)(const char *)); extern void console_print(const char *); +#ifdef CONFIG_SERIAL_CONSOLE +extern int serial_console; +#endif /* TGA hardware description (minimal) */ /* @@ -480,7 +484,12 @@ /* * FINALLY, we can register TGA as console (whew!) */ +#ifdef CONFIG_SERIAL_CONSOLE + if (!serial_console) + register_console(console_print); +#else register_console(console_print); +#endif } unsigned char PLLbits[7] = { 0x80, 0x04, 0x00, 0x24, 0x44, 0x80, 0xb8 }; diff -ruN linux-2.0.20.orig/include/linux/kmon.h linux-2.0.20/include/linux/kmon.h --- linux-2.0.20.orig/include/linux/kmon.h Thu Jan 1 01:00:00 1970 +++ linux-2.0.20/include/linux/kmon.h Sat Sep 21 14:38:17 1996 @@ -0,0 +1,23 @@ +#ifndef _LINUX_KMON_H +#define _LINUX_KMON_H + +/* + * 'kmon.h' contains the dispatch structure for the + * kernel monitor. + */ + +struct kmon_struct { + void (*cons_gets)(char *s, int len); + void (*cons_puts)(const char *); + void (*cons_enable)(void); + void (*cons_disable)(void); + int (*kmonitor)(struct pt_regs *); +}; + +extern struct kmon_struct kmonitor; + +extern void register_monitor_io(struct kmon_struct *); +int (*register_monitor(int (*newmon)(struct pt_regs *)))(struct pt_regs *); +extern int kernel_monitor(struct pt_regs *, char *prompt, char *pmsg); + +#endif diff -ruN linux-2.0.20.orig/init/main.c linux-2.0.20/init/main.c --- linux-2.0.20.orig/init/main.c Fri Sep 13 23:54:42 1996 +++ linux-2.0.20/init/main.c Sat Sep 21 14:45:58 1996 @@ -177,6 +177,13 @@ extern void ipc_init(void); #endif +#ifdef CONFIG_SERIAL_CONSOLE +extern void serial_setup(char *str, int *ints); +extern int serial_console; +static char console_env[] = "CONSOLE=/dev/ttySx"; +static char *console_dev = console_env + 8; +#endif + /* * Boot command-line arguments */ @@ -413,6 +420,9 @@ #ifdef CONFIG_BAYCOM { "baycom=", baycom_setup }, #endif +#ifdef CONFIG_SERIAL_CONSOLE + { "console=", serial_setup }, +#endif { 0, 0 } }; @@ -639,6 +649,7 @@ } if (checksetup(line)) continue; + /* * Then check if it's an environment variable or * an option. @@ -653,6 +664,13 @@ argv_init[++args] = line; } } +#ifdef CONFIG_SERIAL_CONSOLE + if (serial_console) { + console_env[17] = serial_console - 64 + '0'; + if (envs < MAX_INIT_ENVS) + envp_init[++envs] = console_env; + } +#endif argv_init[args+1] = NULL; envp_init[envs+1] = NULL; } @@ -852,6 +870,31 @@ cpu_idle(NULL); } +/* + * Open the console device. + */ +static int open_console(void) +{ + int i; + +#ifdef CONFIG_SERIAL_CONSOLE + if (serial_console && (i = open(console_dev,O_RDWR,0)) >= 0) + return i; +#endif + + /* + * This keeps serial console MUCH cleaner, but does assume + * the console driver checks there really is a video device + * attached (Sparc effectively does). + */ + + if ((i = open("/dev/tty1",O_RDWR,0)) < 0 && + (i = open("/dev/ttyS0",O_RDWR,0)) < 0) + printk("Unable to open an initial console.\n"); + + return i; +} + static int printf(const char *fmt, ...) { va_list args; @@ -875,7 +918,7 @@ { close(0);close(1);close(2); setsid(); - (void) open("/dev/tty1",O_RDWR,0); + (void) open_console(); (void) dup(0); (void) dup(0); return execve(shell, argv, envp); @@ -888,7 +931,7 @@ close(0);close(1);close(2); setsid(); - (void) open("/dev/tty1",O_RDWR,0); + (void) open_console(); (void) dup(0); (void) dup(0); return execve(shell, argv, envp_init); @@ -961,16 +1004,7 @@ } #endif - /* - * This keeps serial console MUCH cleaner, but does assume - * the console driver checks there really is a video device - * attached (Sparc effectively does). - */ - - if ((open("/dev/tty1",O_RDWR,0) < 0) && - (open("/dev/ttyS0",O_RDWR,0) < 0)) - printk("Unable to open an initial console.\n"); - + (void) open_console(); (void) dup(0); (void) dup(0); diff -ruN linux-2.0.20.orig/kernel/Makefile linux-2.0.20/kernel/Makefile --- linux-2.0.20.orig/kernel/Makefile Wed Jan 10 08:27:39 1996 +++ linux-2.0.20/kernel/Makefile Sat Sep 21 14:38:18 1996 @@ -19,6 +19,10 @@ OX_OBJS = ksyms.o endif +ifeq ($(CONFIG_SERIAL_CONSOLE),y) +O_OBJS += kmon.o +endif + include $(TOPDIR)/Rules.make sched.o: sched.c diff -ruN linux-2.0.20.orig/kernel/kmon.c linux-2.0.20/kernel/kmon.c --- linux-2.0.20.orig/kernel/kmon.c Thu Jan 1 01:00:00 1970 +++ linux-2.0.20/kernel/kmon.c Sat Sep 21 14:38:18 1996 @@ -0,0 +1,142 @@ +/* + * linux/kernel/kmon.c + * + * Copyright (C) 1995 Miquel van Smoorenburg + * + * These are the basic routines for a simple kernel monitor, + * needed when we use a serial console. + * + * One can register an external monitor with + * register_monitor, it returns a pointer to the previous + * function. The monitor will be called with interrupts + * disabled, and it can use kmonitor.cons_gets and + * kmonitor.cons_puts to do I/O. + * + */ + +#include <asm/segment.h> +#include <asm/system.h> + +#include <linux/errno.h> +#include <linux/sched.h> +#include <linux/kernel.h> +#include <linux/mm.h> +#include <linux/kmon.h> + +#define cputs kmonitor.cons_puts +#define cgets kmonitor.cons_gets + +struct kmon_struct kmonitor = { + NULL, + NULL, + NULL, + NULL, + NULL, +}; + +/* + * Register the drivers for monitor input and output. + */ +void register_monitor_io(struct kmon_struct *km) +{ + kmonitor.cons_gets = km->cons_gets; + kmonitor.cons_puts = km->cons_puts; + kmonitor.cons_enable = km->cons_enable; + kmonitor.cons_disable = km->cons_disable; +} + +/* + * Register the kernel monitor itself. + */ +int (*register_monitor(int (*newmon)(struct pt_regs *)))(struct pt_regs *) +{ + int (*omon)(struct pt_regs *); + + omon = kmonitor.kmonitor; + kmonitor.kmonitor = newmon; + + return omon; +} + +/* + * Help for the "monitor". + */ +static void kernel_monitor_help(void) +{ + cputs("Linux serial monitor v0.1\n"); + cputs("b boot\n"); + cputs("c continue\n"); + cputs("m show memory\n"); + cputs("p show panic message\n"); + cputs("s show state\n"); + cputs("r show registers\n"); +} + +/* + * This is the kernel monitor. + */ +int kernel_monitor(struct pt_regs * regs, char *prompt, char *pmsg) +{ + unsigned long flags; + char s[64]; + extern void hard_reset_now(void); + extern void show_mem(void); + extern void show_state(void); + extern void show_regs(struct pt_regs *); + + /* Sanity check. */ + if (cgets == NULL || cputs == NULL) + return -1; + + /* Enable special console puts/gets code. */ + if (kmonitor.cons_enable) + (*kmonitor.cons_enable)(); + + /* Turn off interrupts. */ + save_flags(flags); cli(); + + /* See if another monitor has been registered. */ + if (kmonitor.kmonitor) { + (*kmonitor.kmonitor)(regs); + } else { + + /* Say hello to the crowd. */ + cputs("Linux serial monitor v0.1\n"); + + while(1) { + if (prompt) cputs(prompt); + cputs("> "); + cgets(s, 64); + if (*s == 0) continue; + if (strcmp(s, "c") == 0) + break; + else if (strcmp(s, "b") == 0) + hard_reset_now(); + else if (strcmp(s, "m") == 0) + show_mem(); + else if (strcmp(s, "s") == 0) + show_state(); + else if (strcmp(s, "r") == 0) { + if (regs) + show_regs(regs); + else + cputs("No register data available\n"); + } else if (strcmp(s, "p") == 0) { + if (pmsg) + cputs(pmsg); + else + cputs("No panic message available\n"); + } else + kernel_monitor_help(); + } + } + + /* Turn on interrupts. */ + restore_flags(flags); + + /* Disable special console puts/gets code. */ + if (kmonitor.cons_disable) + (*kmonitor.cons_disable)(); + + return 0; +} diff -ruN linux-2.0.20.orig/kernel/panic.c linux-2.0.20/kernel/panic.c --- linux-2.0.20.orig/kernel/panic.c Sat Apr 13 16:40:51 1996 +++ linux-2.0.20/kernel/panic.c Sat Sep 21 14:38:18 1996 @@ -13,6 +13,10 @@ #include <linux/kernel.h> #include <linux/sched.h> #include <linux/delay.h> +#include <linux/config.h> +#ifdef CONFIG_SERIAL_CONSOLE +#include <linux/kmon.h> +#endif asmlinkage void sys_sync(void); /* it's really int */ extern void hard_reset_now(void); @@ -55,7 +59,12 @@ udelay(1000); hard_reset_now(); } - for(;;); +#ifdef CONFIG_SERIAL_CONSOLE + for(;;) + kernel_monitor(NULL, "panic", buf); +#else + for(;;); +#endif } /* diff -ruN linux-2.0.20.orig/kernel/sys.c linux-2.0.20/kernel/sys.c --- linux-2.0.20.orig/kernel/sys.c Sat Jul 20 12:32:05 1996 +++ linux-2.0.20/kernel/sys.c Sat Sep 21 14:38:18 1996 @@ -24,6 +24,9 @@ #if defined(CONFIG_APM) && defined(CONFIG_APM_POWER_OFF) #include <linux/apm_bios.h> #endif +#ifdef CONFIG_SERIAL_CONSOLE +#include <linux/kmon.h> +#endif #include <asm/segment.h> #include <asm/io.h> @@ -193,6 +196,10 @@ else if (!flag) C_A_D = 0; else if (flag == 0xCDEF0123) { +#ifdef CONFIG_SERIAL_CONSOLE + if (kernel_monitor(NULL, "halt", NULL) == 0) + return(0); +#endif printk(KERN_EMERG "System halted\n"); sys_kill(-1, SIGKILL); #if defined(CONFIG_APM) && defined(CONFIG_APM_POWER_OFF)
N! ------------------------------------------------------------------------------ Nicholas J. Leon nicholas@binary9.net "Elegance through Simplicity" http://www.binary9.net/nicholas Under NO circumstances buy a Packard Bell. They are substandard pieces of shit.
|  |