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 (of_getprop(gChosen, "stdout", &fOutput, sizeof(int)) == OF_FAILED) 124 return B_ERROR; 125 126 return B_OK; 127 } 128 129 // InitPostVM 130 status_t 131 PPCOpenFirmware::InitPostVM(struct kernel_args *kernelArgs) 132 { 133 add_debugger_command("of_exit", &debug_command_of_exit, 134 "Exit to the Open Firmware prompt. No way to get back into the OS!"); 135 add_debugger_command("of_enter", &debug_command_of_enter, 136 "Enter a subordinate Open Firmware interpreter. Quitting it returns " 137 "to KDL."); 138 139 return B_OK; 140 } 141 142 // InitRTC 143 status_t 144 PPCOpenFirmware::InitRTC(struct kernel_args *kernelArgs, 145 struct real_time_data *data) 146 { 147 // open RTC 148 fRTC = of_open(kernelArgs->platform_args.rtc_path); 149 if (fRTC == OF_FAILED) { 150 dprintf("PPCOpenFirmware::InitRTC(): Failed open RTC device!\n"); 151 return B_ERROR; 152 } 153 154 return B_OK; 155 } 156 157 // DebugSerialGetChar 158 char 159 PPCOpenFirmware::SerialDebugGetChar() 160 { 161 int key; 162 if (of_interpret("key", 0, 1, &key) == OF_FAILED) 163 return 0; 164 return (char)key; 165 } 166 167 // DebugSerialPutChar 168 void 169 PPCOpenFirmware::SerialDebugPutChar(char c) 170 { 171 if (c == '\n') 172 of_write(fOutput, "\r\n", 2); 173 else 174 of_write(fOutput, &c, 1); 175 } 176 177 // SetHardwareRTC 178 void 179 PPCOpenFirmware::SetHardwareRTC(uint32 seconds) 180 { 181 struct tm t; 182 rtc_secs_to_tm(seconds, &t); 183 184 t.tm_year += RTC_EPOCH_BASE_YEAR; 185 t.tm_mon++; 186 187 if (of_call_method(fRTC, "set-time", 6, 0, t.tm_year, t.tm_mon, t.tm_mday, 188 t.tm_hour, t.tm_min, t.tm_sec) == OF_FAILED) { 189 dprintf("PPCOpenFirmware::SetHardwareRTC(): Failed to set RTC!\n"); 190 } 191 } 192 193 // GetHardwareRTC 194 uint32 195 PPCOpenFirmware::GetHardwareRTC() 196 { 197 struct tm t; 198 if (of_call_method(fRTC, "get-time", 0, 6, &t.tm_year, &t.tm_mon, 199 &t.tm_mday, &t.tm_hour, &t.tm_min, &t.tm_sec) == OF_FAILED) { 200 dprintf("PPCOpenFirmware::GetHardwareRTC(): Failed to get RTC!\n"); 201 return 0; 202 } 203 204 t.tm_year -= RTC_EPOCH_BASE_YEAR; 205 t.tm_mon--; 206 207 return rtc_tm_to_secs(&t); 208 } 209 210 // ShutDown 211 void 212 PPCOpenFirmware::ShutDown(bool reboot) 213 { 214 if (reboot) { 215 of_interpret("reset-all", 0, 0); 216 } else { 217 // not standardized, so it might fail 218 of_interpret("shut-down", 0, 0); 219 } 220 } 221 222 223 // # pragma mark - 224 225 226 // static buffer for constructing the actual PPCPlatform 227 static char *sPPCPlatformBuffer[sizeof(PPCOpenFirmware)]; 228 229 status_t 230 arch_platform_init(struct kernel_args *kernelArgs) 231 { 232 // only OpenFirmware supported for now 233 if (true) 234 sPPCPlatform = new(sPPCPlatformBuffer) PPCOpenFirmware; 235 236 return sPPCPlatform->Init(kernelArgs); 237 } 238 239 240 status_t 241 arch_platform_init_post_vm(struct kernel_args *kernelArgs) 242 { 243 return sPPCPlatform->InitPostVM(kernelArgs); 244 } 245 246 247 status_t 248 arch_platform_init_post_thread(struct kernel_args *kernelArgs) 249 { 250 return B_OK; 251 } 252