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 20 static SparcPlatform *sSparcPlatform; 21 22 23 // constructor 24 SparcPlatform::SparcPlatform(sparc_platform_type platformType) 25 : fPlatformType(platformType) 26 { 27 } 28 29 // destructor 30 SparcPlatform::~SparcPlatform() 31 { 32 } 33 34 // Default 35 SparcPlatform * 36 SparcPlatform::Default() 37 { 38 return sSparcPlatform; 39 } 40 41 42 // #pragma mark - Open Firmware 43 44 45 namespace BPrivate { 46 47 class SparcOpenFirmware : public SparcPlatform { 48 public: 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 66 private: 67 int fInput; 68 int fOutput; 69 int fRTC; 70 }; 71 72 } // namespace BPrivate 73 74 using BPrivate::SparcOpenFirmware; 75 76 77 // OF debugger commands 78 79 // debug_command_of_exit 80 static int 81 debug_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 89 static int 90 debug_command_of_enter(int argc, char **argv) 91 { 92 of_call_client_function("enter", 0, 0); 93 return 0; 94 } 95 96 97 // constructor 98 SparcOpenFirmware::SparcOpenFirmware() 99 : SparcPlatform(SPARC_PLATFORM_OPEN_FIRMWARE), 100 fInput(-1), 101 fOutput(-1), 102 fRTC(-1) 103 { 104 } 105 106 // destructor 107 SparcOpenFirmware::~SparcOpenFirmware() 108 { 109 } 110 111 // Init 112 status_t 113 SparcOpenFirmware::Init(struct kernel_args *kernelArgs) 114 { 115 return of_init( 116 (intptr_t(*)(void*))kernelArgs->platform_args.openfirmware_entry); 117 } 118 119 // InitSerialDebug 120 status_t 121 SparcOpenFirmware::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 134 status_t 135 SparcOpenFirmware::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 147 status_t 148 SparcOpenFirmware::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 162 char 163 SparcOpenFirmware::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 172 void 173 SparcOpenFirmware::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 185 void 186 SparcOpenFirmware::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 201 uint32 202 SparcOpenFirmware::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 218 void 219 SparcOpenFirmware::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 235 static char *sSparcPlatformBuffer[PLATFORM_BUFFER_SIZE]; 236 237 status_t 238 arch_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 247 status_t 248 arch_platform_init_post_vm(struct kernel_args *kernelArgs) 249 { 250 return sSparcPlatform->InitPostVM(kernelArgs); 251 } 252 253 254 status_t 255 arch_platform_init_post_thread(struct kernel_args *kernelArgs) 256 { 257 return B_OK; 258 } 259