* 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
This commit is contained in:
Axel Dörfler 2006-06-12 22:24:53 +00:00
parent 099e443467
commit d51ce54011
4 changed files with 150 additions and 37 deletions

View File

@ -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);

View File

@ -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 <string.h>
void
arch_debug_remove_interrupt_handler(uint32 line)
{
}
void
arch_debug_install_interrupt_handlers(void)
{
}
char
arch_debug_blue_screen_getchar(void)
{

View File

@ -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 <judd@ob-wan.com>
* Copyright 2002, Marcus Overhagen <marcus@overhagen.de>
* Distributed under the terms of the Haiku License.
@ -14,9 +14,9 @@
#include <KernelExport.h>
#include <driver_settings.h>
#include <int.h>
#include <arch/cpu.h>
#include <arch/debug_console.h>
#include <boot/stage2.h>
#include <string.h>
@ -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];
}
}
}

View File

@ -10,8 +10,10 @@
#include <int.h>
#include <smp.h>
#include <util/kqueue.h>
#include <boot/kernel_args.h>
#include <arch/debug_console.h>
#include <arch/int.h>
#include <boot/kernel_args.h>
#include <string.h>
#include <stdio.h>
@ -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;