1/* 2 * Copyright 2006, Ingo Weinhold <bonefish@cs.tu-berlin.de>. 3 * Copyright 2019-2020, Adrien Destugues, pulkomandy@pulkomandy.tk. 4 * All rights reserved. Distributed under the terms of the MIT License. 5 */ 6 7#include <arch_platform.h> 8 9#include <new> 10 11#include <KernelExport.h> 12 13#include <arch/generic/debug_uart.h> 14#include <boot/kernel_args.h> 15#include <platform/openfirmware/openfirmware.h> 16#include <real_time_clock.h> 17#include <util/kernel_cpp.h> 18 19 20static SparcPlatform *sSparcPlatform; 21 22 23// constructor 24SparcPlatform::SparcPlatform(sparc_platform_type platformType) 25 : fPlatformType(platformType) 26{ 27} 28 29// destructor 30SparcPlatform::~SparcPlatform() 31{ 32} 33 34// Default 35SparcPlatform * 36SparcPlatform::Default() 37{ 38 return sSparcPlatform; 39} 40 41 42// #pragma mark - Open Firmware 43 44 45namespace BPrivate { 46 47class SparcOpenFirmware : public SparcPlatform { 48public: 49 SparcOpenFirmware(); 50 virtual ~SparcOpenFirmware(); 51 52 virtual status_t Init(struct kernel_args *kernelArgs); 53 virtual status_t InitSerialDebug(struct kernel_args *kernelArgs); 54 virtual status_t InitPostVM(struct kernel_args *kernelArgs); 55 virtual status_t InitRTC(struct kernel_args *kernelArgs, 56 struct real_time_data *data); 57 58 virtual char SerialDebugGetChar(); 59 virtual void SerialDebugPutChar(char c); 60 61 virtual void SetHardwareRTC(uint32 seconds); 62 virtual uint32 GetHardwareRTC(); 63 64 virtual void ShutDown(bool reboot); 65 66private: 67 int fInput; 68 int fOutput; 69 int fRTC; 70}; 71 72} // namespace BPrivate 73 74using BPrivate::SparcOpenFirmware; 75 76 77// OF debugger commands 78 79// debug_command_of_exit 80static int 81debug_command_of_exit(int argc, char **argv) 82{ 83 of_exit(); 84 kprintf("of_exit() failed!\n"); 85 return 0; 86} 87 88// debug_command_of_enter 89static int 90debug_command_of_enter(int argc, char **argv) 91{ 92 of_call_client_function("enter", 0, 0); 93 return 0; 94} 95 96 97// constructor 98SparcOpenFirmware::SparcOpenFirmware() 99 : SparcPlatform(SPARC_PLATFORM_OPEN_FIRMWARE), 100 fInput(-1), 101 fOutput(-1), 102 fRTC(-1) 103{ 104} 105 106// destructor 107SparcOpenFirmware::~SparcOpenFirmware() 108{ 109} 110 111// Init 112status_t 113SparcOpenFirmware::Init(struct kernel_args *kernelArgs) 114{ 115 return of_init( 116 (intptr_t(*)(void*))kernelArgs->platform_args.openfirmware_entry); 117} 118 119// InitSerialDebug 120status_t 121SparcOpenFirmware::InitSerialDebug(struct kernel_args *kernelArgs) 122{ 123 if (of_getprop(gChosen, "stdin", &fInput, sizeof(int)) == OF_FAILED) 124 return B_ERROR; 125 if (!kernelArgs->frame_buffer.enabled) { 126 if (of_getprop(gChosen, "stdout", &fOutput, sizeof(int)) == OF_FAILED) 127 return B_ERROR; 128 } 129 130 return B_OK; 131} 132 133// InitPostVM 134status_t 135SparcOpenFirmware::InitPostVM(struct kernel_args *kernelArgs) 136{ 137 add_debugger_command("of_exit", &debug_command_of_exit, 138 "Exit to the Open Firmware prompt. No way to get back into the OS!"); 139 add_debugger_command("of_enter", &debug_command_of_enter, 140 "Enter a subordinate Open Firmware interpreter. Quitting it returns " 141 "to KDL."); 142 143 return B_OK; 144} 145 146// InitRTC 147status_t 148SparcOpenFirmware::InitRTC(struct kernel_args *kernelArgs, 149 struct real_time_data *data) 150{ 151 // open RTC 152 fRTC = of_open(kernelArgs->platform_args.rtc_path); 153 if (fRTC == OF_FAILED) { 154 dprintf("SparcOpenFirmware::InitRTC(): Failed open RTC device!\n"); 155 return B_ERROR; 156 } 157 158 return B_OK; 159} 160 161// DebugSerialGetChar 162char 163SparcOpenFirmware::SerialDebugGetChar() 164{ 165 int key; 166 if (of_interpret("key", 0, 1, &key) == OF_FAILED) 167 return 0; 168 return (char)key; 169} 170 171// DebugSerialPutChar 172void 173SparcOpenFirmware::SerialDebugPutChar(char c) 174{ 175 if (fOutput == -1) 176 return; 177 178 if (c == '\n') 179 of_write((uint32_t)fOutput, "\r\n", 2); 180 else 181 of_write((uint32_t)fOutput, &c, 1); 182} 183 184// SetHardwareRTC 185void 186SparcOpenFirmware::SetHardwareRTC(uint32 seconds) 187{ 188 struct tm t; 189 rtc_secs_to_tm(seconds, &t); 190 191 t.tm_year += RTC_EPOCH_BASE_YEAR; 192 t.tm_mon++; 193 194 if (of_call_method((uint32_t)fRTC, "set-time", 6, 0, t.tm_year, t.tm_mon, t.tm_mday, 195 t.tm_hour, t.tm_min, t.tm_sec) == OF_FAILED) { 196 dprintf("SparcOpenFirmware::SetHardwareRTC(): Failed to set RTC!\n"); 197 } 198} 199 200// GetHardwareRTC 201uint32 202SparcOpenFirmware::GetHardwareRTC() 203{ 204 struct tm t; 205 if (of_call_method((uint32_t)fRTC, "get-time", 0, 6, &t.tm_year, &t.tm_mon, 206 &t.tm_mday, &t.tm_hour, &t.tm_min, &t.tm_sec) == OF_FAILED) { 207 dprintf("SparcOpenFirmware::GetHardwareRTC(): Failed to get RTC!\n"); 208 return 0; 209 } 210 211 t.tm_year -= RTC_EPOCH_BASE_YEAR; 212 t.tm_mon--; 213 214 return rtc_tm_to_secs(&t); 215} 216 217// ShutDown 218void 219SparcOpenFirmware::ShutDown(bool reboot) 220{ 221 if (reboot) { 222 of_interpret("reset-all", 0, 0); 223 } else { 224 // not standardized, so it might fail 225 of_interpret("shut-down", 0, 0); 226 } 227} 228 229 230// # pragma mark - 231 232 233#define PLATFORM_BUFFER_SIZE sizeof(SparcOpenFirmware) 234// static buffer for constructing the actual SparcPlatform 235static char *sSparcPlatformBuffer[PLATFORM_BUFFER_SIZE]; 236 237status_t 238arch_platform_init(struct kernel_args *kernelArgs) 239{ 240 // only OpenFirmware supported for now 241 sSparcPlatform = new(sSparcPlatformBuffer) SparcOpenFirmware; 242 243 return sSparcPlatform->Init(kernelArgs); 244} 245 246 247status_t 248arch_platform_init_post_vm(struct kernel_args *kernelArgs) 249{ 250 return sSparcPlatform->InitPostVM(kernelArgs); 251} 252 253 254status_t 255arch_platform_init_post_thread(struct kernel_args *kernelArgs) 256{ 257 return B_OK; 258} 259