Implemented optional additional serial output in the boot loader.
When the debug boot option is set, or ENABLE_SERIAL defined on compile time, the serial port 1 is activated. It will also read the serial base port info from the BIOS data and use that if any ports are reported (will fall back to 0x3f8 if not). Right now, a fixed baud rate of 115200 and 8n1 is used. git-svn-id: file:///srv/svn/repos/haiku/trunk/current@9527 a95241bf-73f2-0310-859d-f6bbb57e9c96
This commit is contained in:
@@ -7,6 +7,7 @@
|
|||||||
#include <SupportDefs.h>
|
#include <SupportDefs.h>
|
||||||
#include <string.h>
|
#include <string.h>
|
||||||
#include <util/kernel_cpp.h>
|
#include <util/kernel_cpp.h>
|
||||||
|
#include <arch/cpu.h>
|
||||||
#include <boot/stage2.h>
|
#include <boot/stage2.h>
|
||||||
|
|
||||||
#include "console.h"
|
#include "console.h"
|
||||||
@@ -20,16 +21,110 @@ class Console : public ConsoleNode {
|
|||||||
virtual ssize_t WriteAt(void *cookie, off_t pos, const void *buffer, size_t bufferSize);
|
virtual ssize_t WriteAt(void *cookie, off_t pos, const void *buffer, size_t bufferSize);
|
||||||
};
|
};
|
||||||
|
|
||||||
|
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 *sScreenBase = (uint16 *)0xb8000;
|
static uint16 *sScreenBase = (uint16 *)0xb8000;
|
||||||
static uint32 sScreenWidth = 80;
|
static uint32 sScreenWidth = 80;
|
||||||
static uint32 sScreenHeight = 24;
|
static uint32 sScreenHeight = 24;
|
||||||
static uint32 sScreenOffset = 0;
|
static uint32 sScreenOffset = 0;
|
||||||
static uint16 sColor = 0x0f00;
|
static uint16 sColor = 0x0f00;
|
||||||
|
|
||||||
|
static int32 sSerialEnabled = 0;
|
||||||
|
static uint16 sSerialBasePort = 0x3f8;
|
||||||
|
|
||||||
static Console sInput, sOutput;
|
static Console sInput, sOutput;
|
||||||
FILE *stdin, *stdout, *stderr;
|
FILE *stdin, *stdout, *stderr;
|
||||||
|
|
||||||
|
|
||||||
|
// serial debug output
|
||||||
|
|
||||||
|
|
||||||
|
static void
|
||||||
|
serial_putc(char c)
|
||||||
|
{
|
||||||
|
// wait until the transmitter empty bit is set
|
||||||
|
while ((in8(sSerialBasePort + SERIAL_LINE_STATUS) & 0x20) == 0)
|
||||||
|
;
|
||||||
|
|
||||||
|
out8(c, sSerialBasePort + SERIAL_TRANSMIT_BUFFER);
|
||||||
|
}
|
||||||
|
|
||||||
|
|
||||||
|
static void
|
||||||
|
serial_puts(const char *string, size_t size)
|
||||||
|
{
|
||||||
|
while (size-- != 0) {
|
||||||
|
char c = string[0];
|
||||||
|
|
||||||
|
if (c == '\n') {
|
||||||
|
serial_putc('\r');
|
||||||
|
serial_putc('\n');
|
||||||
|
} else if (c != '\r')
|
||||||
|
serial_putc(c);
|
||||||
|
|
||||||
|
string++;
|
||||||
|
}
|
||||||
|
}
|
||||||
|
|
||||||
|
|
||||||
|
extern "C" void
|
||||||
|
serial_disable(void)
|
||||||
|
{
|
||||||
|
#if ENABLE_SERIAL
|
||||||
|
sSerialEnabled = 0;
|
||||||
|
#else
|
||||||
|
sSerialEnabled--;
|
||||||
|
#endif
|
||||||
|
}
|
||||||
|
|
||||||
|
|
||||||
|
extern "C" void
|
||||||
|
serial_enable(void)
|
||||||
|
{
|
||||||
|
sSerialEnabled++;
|
||||||
|
}
|
||||||
|
|
||||||
|
|
||||||
|
static void
|
||||||
|
serial_init(void)
|
||||||
|
{
|
||||||
|
// copy the base ports of the optional 4 serial ports to the kernel args
|
||||||
|
// 0x0000:0x0400 is the location of that information in the BIOS data segment
|
||||||
|
uint16 *ports = (uint16 *)0x400;
|
||||||
|
memcpy(gKernelArgs.platform_args.serial_base_ports, ports, sizeof(uint16) * MAX_SERIAL_PORTS);
|
||||||
|
|
||||||
|
// only use the port if we could find one, else use the standard port
|
||||||
|
if (gKernelArgs.platform_args.serial_base_ports[0] != 0)
|
||||||
|
sSerialBasePort = gKernelArgs.platform_args.serial_base_ports[0];
|
||||||
|
|
||||||
|
uint16 divisor = uint16(115200 / kSerialBaudRate);
|
||||||
|
|
||||||
|
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 */
|
||||||
|
|
||||||
|
#ifdef ENABLE_SERIAL
|
||||||
|
serial_enable();
|
||||||
|
#endif
|
||||||
|
}
|
||||||
|
|
||||||
|
|
||||||
|
// #pragma mark -
|
||||||
|
|
||||||
|
|
||||||
static void
|
static void
|
||||||
scroll_up()
|
scroll_up()
|
||||||
{
|
{
|
||||||
@@ -65,6 +160,9 @@ Console::WriteAt(void *cookie, off_t /*pos*/, const void *buffer, size_t bufferS
|
|||||||
{
|
{
|
||||||
const char *string = (const char *)buffer;
|
const char *string = (const char *)buffer;
|
||||||
|
|
||||||
|
if (sSerialEnabled > 0)
|
||||||
|
serial_puts(string, bufferSize);
|
||||||
|
|
||||||
if (gKernelArgs.frame_buffer.enabled)
|
if (gKernelArgs.frame_buffer.enabled)
|
||||||
return bufferSize;
|
return bufferSize;
|
||||||
|
|
||||||
@@ -133,6 +231,7 @@ console_init(void)
|
|||||||
{
|
{
|
||||||
// ToDo: make screen size changeable via stage2_args
|
// ToDo: make screen size changeable via stage2_args
|
||||||
|
|
||||||
|
serial_init();
|
||||||
console_clear_screen();
|
console_clear_screen();
|
||||||
|
|
||||||
// enable stdio functionality
|
// enable stdio functionality
|
||||||
|
|||||||
@@ -1,6 +1,6 @@
|
|||||||
/*
|
/*
|
||||||
** Copyright 2004, Axel Dörfler, [email protected]. All rights reserved.
|
** Copyright 2004, Axel Dörfler, [email protected]. All rights reserved.
|
||||||
** Distributed under the terms of the OpenBeOS License.
|
** Distributed under the terms of the Haiku License.
|
||||||
*/
|
*/
|
||||||
#ifndef CONSOLE_H
|
#ifndef CONSOLE_H
|
||||||
#define CONSOLE_H
|
#define CONSOLE_H
|
||||||
@@ -42,6 +42,9 @@ extern void console_set_color(int32 foreground, int32 background);
|
|||||||
|
|
||||||
extern status_t console_init(void);
|
extern status_t console_init(void);
|
||||||
|
|
||||||
|
extern void serial_disable(void);
|
||||||
|
extern void serial_enable(void);
|
||||||
|
|
||||||
#ifdef __cplusplus
|
#ifdef __cplusplus
|
||||||
}
|
}
|
||||||
#endif
|
#endif
|
||||||
|
|||||||
@@ -123,6 +123,8 @@ _start(void)
|
|||||||
|
|
||||||
// reading the keyboard doesn't seem to work in graphics mode (maybe a bochs problem)
|
// reading the keyboard doesn't seem to work in graphics mode (maybe a bochs problem)
|
||||||
sBootOptions = check_for_boot_keys();
|
sBootOptions = check_for_boot_keys();
|
||||||
|
if (sBootOptions & BOOT_OPTION_DEBUG_OUTPUT)
|
||||||
|
serial_enable();
|
||||||
|
|
||||||
main(&args);
|
main(&args);
|
||||||
}
|
}
|
||||||
|
|||||||
Reference in New Issue
Block a user