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