From d51ce54011529fc882785a87e85b44fc5e19a650 Mon Sep 17 00:00:00 2001 From: =?UTF-8?q?Axel=20D=C3=B6rfler?= Date: Mon, 12 Jun 2006 22:24:53 +0000 Subject: [PATCH] * Added the opportunity to add temporary debug interrupt handlers for arch dependent code (they will be removed as soon as someone else asks for these interrupt lines). * Added an interrupt driven keyboard handler to the kernel that uses this technique. As a result, you can now press F12 to enter the kernel debugger before the input_server has been started, and Control-Alt-Delete should reboot the system (actually I did not test the latter yet). git-svn-id: file:///srv/svn/repos/haiku/haiku/trunk@17806 a95241bf-73f2-0310-859d-f6bbb57e9c96 --- headers/private/kernel/arch/debug_console.h | 5 +- .../kernel/arch/ppc/arch_debug_console.cpp | 14 +- .../kernel/arch/x86/arch_debug_console.c | 158 ++++++++++++++---- src/system/kernel/int.c | 10 +- 4 files changed, 150 insertions(+), 37 deletions(-) diff --git a/headers/private/kernel/arch/debug_console.h b/headers/private/kernel/arch/debug_console.h index 387808ca24..470c9ef1b2 100644 --- a/headers/private/kernel/arch/debug_console.h +++ b/headers/private/kernel/arch/debug_console.h @@ -1,5 +1,5 @@ /* - * Copyright 2002-2005, Axel Dörfler, axeld@pinc-software.de + * Copyright 2002-2006, Axel Dörfler, axeld@pinc-software.de * Distributed under the terms of the MIT License. * * Copyright 2001-2002, Travis Geiselbrecht. All rights reserved. @@ -24,6 +24,9 @@ void arch_debug_serial_putchar(char c); void arch_debug_serial_puts(const char *s); void arch_debug_serial_early_boot_message(const char *string); +void arch_debug_remove_interrupt_handler(uint32 line); +void arch_debug_install_interrupt_handlers(void); + status_t arch_debug_console_init(struct kernel_args *args); status_t arch_debug_console_init_settings(struct kernel_args *args); diff --git a/src/system/kernel/arch/ppc/arch_debug_console.cpp b/src/system/kernel/arch/ppc/arch_debug_console.cpp index 1fd042a208..d60d7a1742 100644 --- a/src/system/kernel/arch/ppc/arch_debug_console.cpp +++ b/src/system/kernel/arch/ppc/arch_debug_console.cpp @@ -1,5 +1,5 @@ /* - * Copyright 2003-2005, Axel Dörfler, axeld@pinc-software.de. + * Copyright 2003-2006, Axel Dörfler, axeld@pinc-software.de. * Distributed under the terms of the MIT License. * * Copyright 2001, Travis Geiselbrecht. All rights reserved. @@ -16,6 +16,18 @@ #include +void +arch_debug_remove_interrupt_handler(uint32 line) +{ +} + + +void +arch_debug_install_interrupt_handlers(void) +{ +} + + char arch_debug_blue_screen_getchar(void) { diff --git a/src/system/kernel/arch/x86/arch_debug_console.c b/src/system/kernel/arch/x86/arch_debug_console.c index 7773ca2e85..359d02cdfd 100644 --- a/src/system/kernel/arch/x86/arch_debug_console.c +++ b/src/system/kernel/arch/x86/arch_debug_console.c @@ -1,5 +1,5 @@ /* - * Copyright 2002-2005, Axel Dörfler, axeld@pinc-software.de + * Copyright 2002-2006, Axel Dörfler, axeld@pinc-software.de * Copyright 2001, Rob Judd * Copyright 2002, Marcus Overhagen * Distributed under the terms of the Haiku License. @@ -14,9 +14,9 @@ #include #include #include + #include #include - #include #include @@ -45,11 +45,54 @@ enum serial_register_offsets { SERIAL_MODEM_STATUS = 6, }; +enum keycodes { + LEFT_SHIFT = 42, + RIGHT_SHIFT = 54, + + LEFT_CONTROL = 29, + RIGHT_CONTROL = 157, + + LEFT_ALT = 56, + RIGHT_ALT = 184, + + CURSOR_LEFT = 75, + CURSOR_RIGHT = 77, + CURSOR_UP = 72, + CURSOR_DOWN = 80, + + BREAK = 198, + DELETE = 201, + F12 = 88, +}; + +static const char kUnshiftedKeymap[128] = { + 0, 27, '1', '2', '3', '4', '5', '6', '7', '8', '9', '0', '-', '=', 8, '\t', + 'q', 'w', 'e', 'r', 't', 'y', 'u', 'i', 'o', 'p', '[', ']', '\n', 0, 'a', 's', + 'd', 'f', 'g', 'h', 'j', 'k', 'l', ';', '\'', '`', 0, '\\', 'z', 'x', 'c', 'v', + 'b', 'n', 'm', ',', '.', '/', 0, '*', 0, ' ', 0, 0, 0, 0, 0, 0, + 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, + '\\', 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, + 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, + 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0 +}; + +static const char kShiftedKeymap[128] = { + 0, 27, '!', '@', '#', '$', '%', '^', '&', '*', '(', ')', '_', '+', 8, '\t', + 'Q', 'W', 'E', 'R', 'T', 'Y', 'U', 'I', 'O', 'P', '{', '}', '\n', 0, 'A', 'S', + 'D', 'F', 'G', 'H', 'J', 'K', 'L', ':', '"', '~', 0, '|', 'Z', 'X', 'C', 'V', + 'B', 'N', 'M', '<', '>', '?', 0, '*', 0, ' ', 0, 0, 0, 0, 0, 0, + 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, + 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, + 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, + 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0 +}; + static const uint32 kSerialBaudRate = 115200; static uint16 sSerialBasePort = 0x3f8; // COM1 is the default debug output port +static bool sKeyboardHandlerInstalled = false; #if BOCHS_DEBUG_HACK static bool sBochsOutput = false; #endif @@ -73,43 +116,90 @@ put_char(const char c) } +/** Minimal keyboard handler to be able to get into the debugger and + * reboot the machine before the input_server is up and running. + * It is added as soon as interrupts become available, and removed + * again if anything else requests the interrupt 1. + */ + +static int32 +debug_keyboard_interrupt(void *data) +{ + static bool controlPressed; + static bool altPressed; + uint8 key; + + key = in8(PS2_PORT_DATA); + //dprintf("debug_keyboard_interrupt: key = 0x%x\n", key); + + if (key & 0x80) { + if (key == LEFT_CONTROL) + controlPressed = false; + if (key == LEFT_ALT) + altPressed = false; + + return B_HANDLED_INTERRUPT; + } + + switch (key) { + case LEFT_CONTROL: + controlPressed = true; + break; + + case LEFT_ALT: + altPressed = true; + break; + + case DELETE: + if (controlPressed && altPressed) + arch_cpu_shutdown(true); + break; + + /* the following code has two possibilities because of issues + * with BeBochs & BeOS (all special keys don't map to anything + * useful, and SYS_REQ does a screen dump in BeOS). + * ToDo: remove these key functions some day... + */ + case F12: + case BREAK: + panic("Keyboard Requested Halt\n"); + break; + } + + return B_HANDLED_INTERRUPT; +} + + // #pragma mark - +void +arch_debug_remove_interrupt_handler(uint32 line) +{ + if (line != INT_PS2_KEYBOARD || !sKeyboardHandlerInstalled) + return; + + remove_io_interrupt_handler(INT_PS2_KEYBOARD, &debug_keyboard_interrupt, + NULL); + sKeyboardHandlerInstalled = false; +} + + +void +arch_debug_install_interrupt_handlers(void) +{ + install_io_interrupt_handler(INT_PS2_KEYBOARD, &debug_keyboard_interrupt, + NULL, 0); + sKeyboardHandlerInstalled = true; +} + + char arch_debug_blue_screen_getchar(void) { /* polling the keyboard, similar to code in keyboard * driver, but without using an interrupt */ - static const char unshifted_keymap[128] = { - 0, 27, '1', '2', '3', '4', '5', '6', '7', '8', '9', '0', '-', '=', 8, '\t', - 'q', 'w', 'e', 'r', 't', 'y', 'u', 'i', 'o', 'p', '[', ']', '\n', 0, 'a', 's', - 'd', 'f', 'g', 'h', 'j', 'k', 'l', ';', '\'', '`', 0, '\\', 'z', 'x', 'c', 'v', - 'b', 'n', 'm', ',', '.', '/', 0, '*', 0, ' ', 0, 0, 0, 0, 0, 0, - 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, - '\\', 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, - 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, - 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0 - }; - static const char shifted_keymap[128] = { - 0, 27, '!', '@', '#', '$', '%', '^', '&', '*', '(', ')', '_', '+', 8, '\t', - 'Q', 'W', 'E', 'R', 'T', 'Y', 'U', 'I', 'O', 'P', '{', '}', '\n', 0, 'A', 'S', - 'D', 'F', 'G', 'H', 'J', 'K', 'L', ':', '"', '~', 0, '|', 'Z', 'X', 'C', 'V', - 'B', 'N', 'M', '<', '>', '?', 0, '*', 0, ' ', 0, 0, 0, 0, 0, 0, - 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, - 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, - 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, - 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0 - }; - enum keycodes { - LSHIFT = 42, - RSHIFT = 54, - CURSOR_LEFT = 75, - CURSOR_RIGHT = 77, - CURSOR_UP = 72, - CURSOR_DOWN = 80, - }; static bool shift = false; static uint8 special = 0; uint8 key, ascii = 0; @@ -143,13 +233,13 @@ arch_debug_blue_screen_getchar(void) if (key & 0x80) { // key up - if (key == (0x80 | LSHIFT) || key == (0x80 | RSHIFT)) + if (key == (0x80 | LEFT_SHIFT) || key == (0x80 | RIGHT_SHIFT)) shift = false; } else { // key down switch (key) { - case LSHIFT: - case RSHIFT: + case LEFT_SHIFT: + case RIGHT_SHIFT: shift = true; break; @@ -168,7 +258,7 @@ arch_debug_blue_screen_getchar(void) return '\x1b'; default: - return shift ? shifted_keymap[key] : unshifted_keymap[key]; + return shift ? kShiftedKeymap[key] : kUnshiftedKeymap[key]; } } } diff --git a/src/system/kernel/int.c b/src/system/kernel/int.c index f01eaf0a7c..cb76711752 100644 --- a/src/system/kernel/int.c +++ b/src/system/kernel/int.c @@ -10,8 +10,10 @@ #include #include #include -#include + +#include #include +#include #include #include @@ -129,6 +131,8 @@ int_init_post_vm(kernel_args *args) status_t int_init_post_device_manager(kernel_args *args) { + arch_debug_install_interrupt_handlers(); + return arch_int_init_post_device_manager(args); } @@ -150,6 +154,10 @@ install_io_interrupt_handler(long vector, interrupt_handler handler, void *data, if (io == NULL) return B_NO_MEMORY; + arch_debug_remove_interrupt_handler(vector); + // There might be a temporary debug interrupt installed on this + // vector that should be removed now. + io->func = handler; io->data = data; io->use_enable_counter = (flags & B_NO_ENABLE_COUNTER) == 0;