The BOCHS_DEBUG_HACK definition now only enables support for the bochs

debug output - to activate it, you now have to enable it in the kernel
settings file ("bochs_debug_output true").
Reimplemented the serial output so that it's flexible towards the base
port at run time.
Implemented support for kernel settings "serial_debug_port" (which can
now also be an index in the BIOS provided serial ports list), and
"serial_debug_speed".
That also means that you can finally use the same kernel executable
under BeOS Bochs and on a real system without any restrictions.


git-svn-id: file:///srv/svn/repos/haiku/trunk/current@10642 a95241bf-73f2-0310-859d-f6bbb57e9c96
This commit is contained in:
Axel Dörfler
2005-01-10 07:53:22 +00:00
parent 163338aef6
commit c51144040d
+164 -93
View File
@@ -1,17 +1,16 @@
/* /*
** Copyright 2002-2004, The Haiku Team. All rights reserved. * Copyright 2002-2005, Axel Dörfler, [email protected]
** Distributed under the terms of the Haiku License. * Copyright 2001, Rob Judd <[email protected]>
** * Copyright 2002, Marcus Overhagen <[email protected]>
** Copyright 2001, Travis Geiselbrecht. All rights reserved. * Distributed under the terms of the Haiku License.
** Distributed under the terms of the NewOS License. *
*/ * Copyright 2001, Travis Geiselbrecht. All rights reserved.
* Distributed under the terms of the NewOS License.
*/
/*
** Modified 2001/09/05 by Rob Judd<[email protected]>
** Modified 2002/09/28 by Marcus Overhagen <[email protected]>
*/
#include <kernel.h> #include <KernelExport.h>
#include <driver_settings.h>
#include <int.h> #include <int.h>
#include <arch/cpu.h> #include <arch/cpu.h>
#include <arch/dbg_console.h> #include <arch/dbg_console.h>
@@ -19,95 +18,110 @@
#include <boot/stage2.h> #include <boot/stage2.h>
#include <string.h> #include <string.h>
#include <stdlib.h>
/* define this only if not used as compile parameter
* setting it to 1 will disable serial debug and /* If you've enabled Bochs debug output in the kernel driver
* redirect it to Bochs * settings and has defined this, serial debug output will be
* disabled and redirected to Bochs.
* Define this only if not used as compile parameter.
*/ */
// #define BOCHS_DEBUG_HACK 0 // #define BOCHS_DEBUG_HACK 0
// Select between COM1 and COM2 for debug output
#define USE_COM1 1
static const int dbg_baud_rate = 115200; enum serial_register_offsets {
SERIAL_TRANSMIT_BUFFER = 0,
SERIAL_RECEIVE_BUFFER = 0,
SERIAL_DIVISOR_LATCH_LOW = 0,
SERIAL_DIVISOR_LATCH_HIGH = 1,
SERIAL_FIFO_CONTROL = 2,
SERIAL_LINE_CONTROL = 3,
SERIAL_MODEM_CONTROL = 4,
SERIAL_LINE_STATUS = 5,
SERIAL_MODEM_STATUS = 6,
};
static const uint32 kSerialBaudRate = 115200;
static uint16 sSerialBasePort = 0x3f8;
// COM1 is the default debug output port
#if BOCHS_DEBUG_HACK
static bool sBochsOutput = false;
#endif
char char
arch_dbg_con_read(void) arch_dbg_con_read(void)
{ {
#if BOCHS_DEBUG_HACK #if BOCHS_DEBUG_HACK
/* polling the keyboard, similar to code in keyboard if (sBochsOutput) {
* driver, but without using an interrupt /* 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', static const char unshifted_keymap[128] = {
'q', 'w', 'e', 'r', 't', 'y', 'u', 'i', 'o', 'p', '[', ']', '\n', 0, 'a', 's', 0, 27, '1', '2', '3', '4', '5', '6', '7', '8', '9', '0', '-', '=', 8, '\t',
'd', 'f', 'g', 'h', 'j', 'k', 'l', ';', '\'', '`', 0, '\\', 'z', 'x', 'c', 'v', 'q', 'w', 'e', 'r', 't', 'y', 'u', 'i', 'o', 'p', '[', ']', '\n', 0, 'a', 's',
'b', 'n', 'm', ',', '.', '/', 0, '*', 0, ' ', 0, 0, 0, 0, 0, 0, 'd', 'f', 'g', 'h', 'j', 'k', 'l', ';', '\'', '`', 0, '\\', 'z', 'x', 'c', 'v',
0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, '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, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0,
}; 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0
const char shifted_keymap[128] = { };
0, 27, '!', '@', '#', '$', '%', '^', '&', '*', '(', ')', '_', '+', 8, '\t', const char shifted_keymap[128] = {
'Q', 'W', 'E', 'R', 'T', 'Y', 'U', 'I', 'O', 'P', '{', '}', '\n', 0, 'A', 'S', 0, 27, '!', '@', '#', '$', '%', '^', '&', '*', '(', ')', '_', '+', 8, '\t',
'D', 'F', 'G', 'H', 'J', 'K', 'L', ':', '"', '~', 0, '|', 'Z', 'X', 'C', 'V', 'Q', 'W', 'E', 'R', 'T', 'Y', 'U', 'I', 'O', 'P', '{', '}', '\n', 0, 'A', 'S',
'B', 'N', 'M', '<', '>', '?', 0, '*', 0, ' ', 0, 0, 0, 0, 0, 0, 'D', 'F', 'G', 'H', 'J', 'K', 'L', ':', '"', '~', 0, '|', 'Z', 'X', 'C', 'V',
0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, '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,
0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0 0, 0, 0, 0, 0, 0, 0, 0, 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 bool shift = false; };
static uint8 last = 0; static bool shift = false;
uint8 key, ascii = 0; static uint8 last = 0;
do { uint8 key, ascii = 0;
while ((key = in8(0x60)) == last) do {
; while ((key = in8(0x60)) == last)
last = key; ;
if (key & 0x80) { last = key;
if (key == (0x80 + 42) || key == (54 + 0x80)) if (key & 0x80) {
shift = false; if (key == (0x80 + 42) || key == (54 + 0x80))
} else { shift = false;
if (key == 42 || key == 54) } else {
shift = true; if (key == 42 || key == 54)
else shift = true;
ascii = shift ? shifted_keymap[key] : unshifted_keymap[key]; else
} ascii = shift ? shifted_keymap[key] : unshifted_keymap[key];
} while (!ascii); }
return ascii; } while (!ascii);
return ascii;
}
#endif #endif
#if USE_COM1 while ((in8(sSerialBasePort + SERIAL_LINE_STATUS) & 0x1) == 0)
while ((in8(0x3fd) & 1) == 0)
; ;
return in8(0x3f8);
#else return in8(sSerialBasePort + SERIAL_RECEIVE_BUFFER);
while ((in8(0x2fd) & 1) == 0)
;
return in8(0x2f8);
#endif
} }
static void static void
_arch_dbg_con_putch(const char c) put_char(const char c)
{ {
#if BOCHS_DEBUG_HACK #if BOCHS_DEBUG_HACK
out8(c, 0xe9); if (sBochsOutput) {
return; out8(c, 0xe9);
return;
}
#endif #endif
#if USE_COM1 // wait until the transmitter empty bit is set
while ((in8(0x3fd) & 0x20) == 0) while ((in8(sSerialBasePort + SERIAL_LINE_STATUS) & 0x20) == 0)
; ;
out8(c, 0x3f8);
#else // COM2 out8(c, sSerialBasePort + SERIAL_TRANSMIT_BUFFER);
while ((in8(0x2fd) & 0x20) == 0)
;
out8(c, 0x2f8);
#endif
} }
@@ -115,10 +129,10 @@ char
arch_dbg_con_putch(const char c) arch_dbg_con_putch(const char c)
{ {
if (c == '\n') { if (c == '\n') {
_arch_dbg_con_putch('\r'); put_char('\r');
_arch_dbg_con_putch('\n'); put_char('\n');
} else if (c != '\r') } else if (c != '\r')
_arch_dbg_con_putch(c); put_char(c);
return c; return c;
} }
@@ -147,20 +161,77 @@ arch_dbg_con_early_boot_message(const char *string)
status_t status_t
arch_dbg_con_init(kernel_args *args) arch_dbg_con_init(kernel_args *args)
{ {
short divisor = 115200 / dbg_baud_rate; uint16 divisor = (uint16)(115200 / kSerialBaudRate);
#if USE_COM1 // only use the port if we could find one, else use the standard port
out8(0x80, 0x3fb); /* set up to load divisor latch */ if (args->platform_args.serial_base_ports[0] != 0)
out8(divisor & 0xf, 0x3f8); /* LSB */ sSerialBasePort = args->platform_args.serial_base_ports[0];
out8(divisor >> 8, 0x3f9); /* MSB */
out8(3, 0x3fb); /* 8N1 */
#else // COM2
out8(0x80, 0x2fb); /* set up to load divisor latch */
out8(divisor & 0xf, 0x2f8); /* LSB */
out8(divisor >> 8, 0x2f9); /* MSB */
out8(3, 0x2fb); /* 8N1 */
#endif
return 0; out8(0x80, sSerialBasePort + SERIAL_LINE_CONTROL); /* set divisor latch access bit */
out8(divisor & 0xf, sSerialBasePort + SERIAL_DIVISOR_LATCH_LOW);
out8(divisor >> 8, sSerialBasePort + SERIAL_DIVISOR_LATCH_HIGH);
out8(3, sSerialBasePort + SERIAL_LINE_CONTROL); /* 8N1 */
return B_OK;
} }
status_t
arch_dbg_con_init_settings(kernel_args *args)
{
uint32 baudRate = kSerialBaudRate;
uint16 basePort = sSerialBasePort;
uint16 divisor;
void *handle;
// get debug settings
handle = load_driver_settings("kernel");
if (handle != NULL) {
const char *value;
#ifdef BOCHS_DEBUG_HACK
sBochsOutput = get_driver_boolean_parameter(handle, "bochs_debug_output", false, false);
#endif
value = get_driver_parameter(handle, "serial_debug_port", NULL, NULL);
if (value != NULL) {
int32 number = strtol(value, NULL, 0);
if (number < MAX_SERIAL_PORTS) {
// use as index into port array
if (args->platform_args.serial_base_ports[number] != 0)
basePort = args->platform_args.serial_base_ports[number];
} else {
// use as port number directly
basePort = number;
}
}
value = get_driver_parameter(handle, "serial_debug_speed", NULL, NULL);
if (value != NULL) {
int32 number = strtol(value, NULL, 0);
switch (number) {
case 9600:
case 19200:
case 38400:
case 57600:
case 115200:
//case 230400:
baudRate = number;
}
}
unload_driver_settings(handle);
}
if (sSerialBasePort == basePort && baudRate == kSerialBaudRate)
return B_OK;
sSerialBasePort = basePort;
divisor = (uint16)(115200 / baudRate);
out8(0x80, sSerialBasePort + SERIAL_LINE_CONTROL); /* set divisor latch access bit */
out8(divisor & 0xf, sSerialBasePort + SERIAL_DIVISOR_LATCH_LOW);
out8(divisor >> 8, sSerialBasePort + SERIAL_DIVISOR_LATCH_HIGH);
out8(3, sSerialBasePort + SERIAL_LINE_CONTROL); /* 8N1 */
return B_OK;
}