diff --git a/headers/private/kernel/arch/sparc/arch_platform.h b/headers/private/kernel/arch/sparc/arch_platform.h index 24e774eb2f..edee3859c2 100644 --- a/headers/private/kernel/arch/sparc/arch_platform.h +++ b/headers/private/kernel/arch/sparc/arch_platform.h @@ -10,7 +10,7 @@ struct real_time_data; enum sparc_platform_type { - PPC_PLATFORM_OPEN_FIRMWARE = 0, + SPARC_PLATFORM_OPEN_FIRMWARE = 0, }; namespace BPrivate { diff --git a/src/system/kernel/arch/sparc/arch_debug_console.cpp b/src/system/kernel/arch/sparc/arch_debug_console.cpp index 32eaa295fe..1b5f336284 100644 --- a/src/system/kernel/arch/sparc/arch_debug_console.cpp +++ b/src/system/kernel/arch/sparc/arch_debug_console.cpp @@ -7,6 +7,7 @@ */ +#include #include #include #include @@ -30,7 +31,8 @@ arch_debug_install_interrupt_handlers(void) int 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 arch_debug_serial_getchar(void) { - return 0; + return SparcPlatform::Default()->SerialDebugGetChar(); } void 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 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; } - diff --git a/src/system/kernel/arch/sparc/arch_platform.cpp b/src/system/kernel/arch/sparc/arch_platform.cpp index 30a2394057..88c380dbd0 100644 --- a/src/system/kernel/arch/sparc/arch_platform.cpp +++ b/src/system/kernel/arch/sparc/arch_platform.cpp @@ -1,22 +1,253 @@ -/* Copyright 2019, Adrien Destugues, pulkomandy@pulkomandy.tk. - * Distributed under the terms of the MIT License. +/* + * Copyright 2006, Ingo Weinhold . + * Copyright 2019-2020, Adrien Destugues, pulkomandy@pulkomandy.tk. + * All rights reserved. Distributed under the terms of the MIT License. */ +#include -#include +#include +#include + +#include +#include +#include +#include +#include + + +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 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 arch_platform_init_post_vm(struct kernel_args *kernelArgs) { - return B_OK; + return sSparcPlatform->InitPostVM(kernelArgs); }