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:
Axel Dörfler 2004-10-27 01:06:33 +00:00
parent f2ea9af307
commit c9e4e71f10
3 changed files with 105 additions and 1 deletions

View File

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

View File

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

View File

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