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:
parent
f2ea9af307
commit
c9e4e71f10
@ -7,6 +7,7 @@
|
||||
#include <SupportDefs.h>
|
||||
#include <string.h>
|
||||
#include <util/kernel_cpp.h>
|
||||
#include <arch/cpu.h>
|
||||
#include <boot/stage2.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);
|
||||
};
|
||||
|
||||
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 uint32 sScreenWidth = 80;
|
||||
static uint32 sScreenHeight = 24;
|
||||
static uint32 sScreenOffset = 0;
|
||||
static uint16 sColor = 0x0f00;
|
||||
|
||||
static int32 sSerialEnabled = 0;
|
||||
static uint16 sSerialBasePort = 0x3f8;
|
||||
|
||||
static Console sInput, sOutput;
|
||||
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
|
||||
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;
|
||||
|
||||
if (sSerialEnabled > 0)
|
||||
serial_puts(string, bufferSize);
|
||||
|
||||
if (gKernelArgs.frame_buffer.enabled)
|
||||
return bufferSize;
|
||||
|
||||
@ -133,6 +231,7 @@ console_init(void)
|
||||
{
|
||||
// ToDo: make screen size changeable via stage2_args
|
||||
|
||||
serial_init();
|
||||
console_clear_screen();
|
||||
|
||||
// enable stdio functionality
|
||||
|
@ -1,6 +1,6 @@
|
||||
/*
|
||||
** Copyright 2004, Axel Dörfler, axeld@pinc-software.de. All rights reserved.
|
||||
** Distributed under the terms of the OpenBeOS License.
|
||||
** Distributed under the terms of the Haiku License.
|
||||
*/
|
||||
#ifndef 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 void serial_disable(void);
|
||||
extern void serial_enable(void);
|
||||
|
||||
#ifdef __cplusplus
|
||||
}
|
||||
#endif
|
||||
|
@ -123,6 +123,8 @@ _start(void)
|
||||
|
||||
// reading the keyboard doesn't seem to work in graphics mode (maybe a bochs problem)
|
||||
sBootOptions = check_for_boot_keys();
|
||||
if (sBootOptions & BOOT_OPTION_DEBUG_OUTPUT)
|
||||
serial_enable();
|
||||
|
||||
main(&args);
|
||||
}
|
||||
|
Loading…
Reference in New Issue
Block a user