sparc: add kernel debug output

Mostly the same as PowerPC, using OpenFirmware.

Change-Id: I197cc181e92da92c272ee9cfa20c8ad2d2c63d41
Reviewed-on: https://review.haiku-os.org/c/haiku/+/3579
Reviewed-by: waddlesplash <waddlesplash@gmail.com>
This commit is contained in:
PulkoMandy 2020-12-31 10:12:59 +01:00 committed by waddlesplash
parent 7c2dc33027
commit b992c828cf
3 changed files with 243 additions and 10 deletions

View File

@ -10,7 +10,7 @@
struct real_time_data; struct real_time_data;
enum sparc_platform_type { enum sparc_platform_type {
PPC_PLATFORM_OPEN_FIRMWARE = 0, SPARC_PLATFORM_OPEN_FIRMWARE = 0,
}; };
namespace BPrivate { namespace BPrivate {

View File

@ -7,6 +7,7 @@
*/ */
#include <arch_platform.h>
#include <arch/debug_console.h> #include <arch/debug_console.h>
#include <boot/kernel_args.h> #include <boot/kernel_args.h>
#include <kernel.h> #include <kernel.h>
@ -30,7 +31,8 @@ arch_debug_install_interrupt_handlers(void)
int int
arch_debug_blue_screen_try_getchar(void) arch_debug_blue_screen_try_getchar(void)
{ {
return 0; // TODO: Implement correctly!
return arch_debug_blue_screen_getchar();
} }
@ -52,13 +54,14 @@ arch_debug_serial_try_getchar(void)
char char
arch_debug_serial_getchar(void) arch_debug_serial_getchar(void)
{ {
return 0; return SparcPlatform::Default()->SerialDebugGetChar();
} }
void void
arch_debug_serial_putchar(const char c) arch_debug_serial_putchar(const char c)
{ {
return SparcPlatform::Default()->SerialDebugPutChar(c);
} }
@ -82,7 +85,7 @@ arch_debug_serial_early_boot_message(const char *string)
status_t status_t
arch_debug_console_init(kernel_args *args) arch_debug_console_init(kernel_args *args)
{ {
return B_OK; return SparcPlatform::Default()->InitSerialDebug(args);
} }
@ -92,4 +95,3 @@ arch_debug_console_init_settings(kernel_args *args)
return B_OK; return B_OK;
} }

View File

@ -1,22 +1,253 @@
/* Copyright 2019, Adrien Destugues, pulkomandy@pulkomandy.tk. /*
* Distributed under the terms of the MIT License. * Copyright 2006, Ingo Weinhold <bonefish@cs.tu-berlin.de>.
* Copyright 2019-2020, Adrien Destugues, pulkomandy@pulkomandy.tk.
* All rights reserved. Distributed under the terms of the MIT License.
*/ */
#include <arch_platform.h>
#include <arch/platform.h> #include <new>
#include <KernelExport.h>
#include <arch/generic/debug_uart.h>
#include <boot/kernel_args.h>
#include <platform/openfirmware/openfirmware.h>
#include <real_time_clock.h>
#include <util/kernel_cpp.h>
static SparcPlatform *sSparcPlatform;
// constructor
SparcPlatform::SparcPlatform(sparc_platform_type platformType)
: fPlatformType(platformType)
{
}
// destructor
SparcPlatform::~SparcPlatform()
{
}
// Default
SparcPlatform *
SparcPlatform::Default()
{
return sSparcPlatform;
}
// #pragma mark - Open Firmware
namespace BPrivate {
class SparcOpenFirmware : public SparcPlatform {
public:
SparcOpenFirmware();
virtual ~SparcOpenFirmware();
virtual status_t Init(struct kernel_args *kernelArgs);
virtual status_t InitSerialDebug(struct kernel_args *kernelArgs);
virtual status_t InitPostVM(struct kernel_args *kernelArgs);
virtual status_t InitRTC(struct kernel_args *kernelArgs,
struct real_time_data *data);
virtual char SerialDebugGetChar();
virtual void SerialDebugPutChar(char c);
virtual void SetHardwareRTC(uint32 seconds);
virtual uint32 GetHardwareRTC();
virtual void ShutDown(bool reboot);
private:
int fInput;
int fOutput;
int fRTC;
};
} // namespace BPrivate
using BPrivate::SparcOpenFirmware;
// OF debugger commands
// debug_command_of_exit
static int
debug_command_of_exit(int argc, char **argv)
{
of_exit();
kprintf("of_exit() failed!\n");
return 0;
}
// debug_command_of_enter
static int
debug_command_of_enter(int argc, char **argv)
{
of_call_client_function("enter", 0, 0);
return 0;
}
// constructor
SparcOpenFirmware::SparcOpenFirmware()
: SparcPlatform(SPARC_PLATFORM_OPEN_FIRMWARE),
fInput(-1),
fOutput(-1),
fRTC(-1)
{
}
// destructor
SparcOpenFirmware::~SparcOpenFirmware()
{
}
// Init
status_t
SparcOpenFirmware::Init(struct kernel_args *kernelArgs)
{
return of_init(
(intptr_t(*)(void*))kernelArgs->platform_args.openfirmware_entry);
}
// InitSerialDebug
status_t
SparcOpenFirmware::InitSerialDebug(struct kernel_args *kernelArgs)
{
if (of_getprop(gChosen, "stdin", &fInput, sizeof(int)) == OF_FAILED)
return B_ERROR;
if (!kernelArgs->frame_buffer.enabled) {
if (of_getprop(gChosen, "stdout", &fOutput, sizeof(int)) == OF_FAILED)
return B_ERROR;
}
return B_OK;
}
// InitPostVM
status_t
SparcOpenFirmware::InitPostVM(struct kernel_args *kernelArgs)
{
add_debugger_command("of_exit", &debug_command_of_exit,
"Exit to the Open Firmware prompt. No way to get back into the OS!");
add_debugger_command("of_enter", &debug_command_of_enter,
"Enter a subordinate Open Firmware interpreter. Quitting it returns "
"to KDL.");
return B_OK;
}
// InitRTC
status_t
SparcOpenFirmware::InitRTC(struct kernel_args *kernelArgs,
struct real_time_data *data)
{
// open RTC
fRTC = of_open(kernelArgs->platform_args.rtc_path);
if (fRTC == OF_FAILED) {
dprintf("SparcOpenFirmware::InitRTC(): Failed open RTC device!\n");
return B_ERROR;
}
return B_OK;
}
// DebugSerialGetChar
char
SparcOpenFirmware::SerialDebugGetChar()
{
int key;
if (of_interpret("key", 0, 1, &key) == OF_FAILED)
return 0;
return (char)key;
}
// DebugSerialPutChar
void
SparcOpenFirmware::SerialDebugPutChar(char c)
{
if (fOutput == -1)
return;
if (c == '\n')
of_write((uint32_t)fOutput, "\r\n", 2);
else
of_write((uint32_t)fOutput, &c, 1);
}
// SetHardwareRTC
void
SparcOpenFirmware::SetHardwareRTC(uint32 seconds)
{
struct tm t;
rtc_secs_to_tm(seconds, &t);
t.tm_year += RTC_EPOCH_BASE_YEAR;
t.tm_mon++;
if (of_call_method((uint32_t)fRTC, "set-time", 6, 0, t.tm_year, t.tm_mon, t.tm_mday,
t.tm_hour, t.tm_min, t.tm_sec) == OF_FAILED) {
dprintf("SparcOpenFirmware::SetHardwareRTC(): Failed to set RTC!\n");
}
}
// GetHardwareRTC
uint32
SparcOpenFirmware::GetHardwareRTC()
{
struct tm t;
if (of_call_method((uint32_t)fRTC, "get-time", 0, 6, &t.tm_year, &t.tm_mon,
&t.tm_mday, &t.tm_hour, &t.tm_min, &t.tm_sec) == OF_FAILED) {
dprintf("SparcOpenFirmware::GetHardwareRTC(): Failed to get RTC!\n");
return 0;
}
t.tm_year -= RTC_EPOCH_BASE_YEAR;
t.tm_mon--;
return rtc_tm_to_secs(&t);
}
// ShutDown
void
SparcOpenFirmware::ShutDown(bool reboot)
{
if (reboot) {
of_interpret("reset-all", 0, 0);
} else {
// not standardized, so it might fail
of_interpret("shut-down", 0, 0);
}
}
// # pragma mark -
#define PLATFORM_BUFFER_SIZE sizeof(SparcOpenFirmware)
// static buffer for constructing the actual SparcPlatform
static char *sSparcPlatformBuffer[PLATFORM_BUFFER_SIZE];
status_t status_t
arch_platform_init(struct kernel_args *kernelArgs) arch_platform_init(struct kernel_args *kernelArgs)
{ {
return B_OK; // only OpenFirmware supported for now
sSparcPlatform = new(sSparcPlatformBuffer) SparcOpenFirmware;
return sSparcPlatform->Init(kernelArgs);
} }
status_t status_t
arch_platform_init_post_vm(struct kernel_args *kernelArgs) arch_platform_init_post_vm(struct kernel_args *kernelArgs)
{ {
return B_OK; return sSparcPlatform->InitPostVM(kernelArgs);
} }