headers/bsd: Add sys/queue.h.
[haiku.git] / src / system / kernel / arch / ppc / arch_platform.cpp
blobc74a5e7adf395d802b03646976560697ef8f07ca
1 /*
2 * Copyright 2006, Ingo Weinhold <bonefish@cs.tu-berlin.de>.
3 * All rights reserved. Distributed under the terms of the MIT License.
4 */
6 #include <arch_platform.h>
8 #include <new>
10 #include <KernelExport.h>
12 #include <arch/generic/debug_uart.h>
13 #include <boot/kernel_args.h>
14 #include <platform/openfirmware/openfirmware.h>
15 #include <real_time_clock.h>
16 #include <util/kernel_cpp.h>
19 // TODO: declare this in some header
20 extern void *gFDT;
21 extern DebugUART *debug_uart_from_fdt(const void *fdt);
23 static PPCPlatform *sPPCPlatform;
26 // constructor
27 PPCPlatform::PPCPlatform(ppc_platform_type platformType)
28 : fPlatformType(platformType)
32 // destructor
33 PPCPlatform::~PPCPlatform()
37 // Default
38 PPCPlatform *
39 PPCPlatform::Default()
41 return sPPCPlatform;
45 // #pragma mark - Open Firmware
48 namespace BPrivate {
50 class PPCOpenFirmware : public PPCPlatform {
51 public:
52 PPCOpenFirmware();
53 virtual ~PPCOpenFirmware();
55 virtual status_t Init(struct kernel_args *kernelArgs);
56 virtual status_t InitSerialDebug(struct kernel_args *kernelArgs);
57 virtual status_t InitPostVM(struct kernel_args *kernelArgs);
58 virtual status_t InitRTC(struct kernel_args *kernelArgs,
59 struct real_time_data *data);
61 virtual char SerialDebugGetChar();
62 virtual void SerialDebugPutChar(char c);
64 virtual void SetHardwareRTC(uint32 seconds);
65 virtual uint32 GetHardwareRTC();
67 virtual void ShutDown(bool reboot);
69 private:
70 int fInput;
71 int fOutput;
72 int fRTC;
75 } // namespace BPrivate
77 using BPrivate::PPCOpenFirmware;
80 // OF debugger commands
82 // debug_command_of_exit
83 static int
84 debug_command_of_exit(int argc, char **argv)
86 of_exit();
87 kprintf("of_exit() failed!\n");
88 return 0;
91 // debug_command_of_enter
92 static int
93 debug_command_of_enter(int argc, char **argv)
95 of_call_client_function("enter", 0, 0);
96 return 0;
100 // constructor
101 PPCOpenFirmware::PPCOpenFirmware()
102 : PPCPlatform(PPC_PLATFORM_OPEN_FIRMWARE),
103 fInput(-1),
104 fOutput(-1),
105 fRTC(-1)
109 // destructor
110 PPCOpenFirmware::~PPCOpenFirmware()
114 // Init
115 status_t
116 PPCOpenFirmware::Init(struct kernel_args *kernelArgs)
118 return of_init(
119 (int(*)(void*))kernelArgs->platform_args.openfirmware_entry);
122 // InitSerialDebug
123 status_t
124 PPCOpenFirmware::InitSerialDebug(struct kernel_args *kernelArgs)
126 if (of_getprop(gChosen, "stdin", &fInput, sizeof(int)) == OF_FAILED)
127 return B_ERROR;
128 if (!kernelArgs->frame_buffer.enabled) {
129 if (of_getprop(gChosen, "stdout", &fOutput, sizeof(int)) == OF_FAILED)
130 return B_ERROR;
133 return B_OK;
136 // InitPostVM
137 status_t
138 PPCOpenFirmware::InitPostVM(struct kernel_args *kernelArgs)
140 add_debugger_command("of_exit", &debug_command_of_exit,
141 "Exit to the Open Firmware prompt. No way to get back into the OS!");
142 add_debugger_command("of_enter", &debug_command_of_enter,
143 "Enter a subordinate Open Firmware interpreter. Quitting it returns "
144 "to KDL.");
146 return B_OK;
149 // InitRTC
150 status_t
151 PPCOpenFirmware::InitRTC(struct kernel_args *kernelArgs,
152 struct real_time_data *data)
154 // open RTC
155 fRTC = of_open(kernelArgs->platform_args.rtc_path);
156 if (fRTC == OF_FAILED) {
157 dprintf("PPCOpenFirmware::InitRTC(): Failed open RTC device!\n");
158 return B_ERROR;
161 return B_OK;
164 // DebugSerialGetChar
165 char
166 PPCOpenFirmware::SerialDebugGetChar()
168 int key;
169 if (of_interpret("key", 0, 1, &key) == OF_FAILED)
170 return 0;
171 return (char)key;
174 // DebugSerialPutChar
175 void
176 PPCOpenFirmware::SerialDebugPutChar(char c)
178 if (fOutput == -1)
179 return;
181 if (c == '\n')
182 of_write(fOutput, "\r\n", 2);
183 else
184 of_write(fOutput, &c, 1);
187 // SetHardwareRTC
188 void
189 PPCOpenFirmware::SetHardwareRTC(uint32 seconds)
191 struct tm t;
192 rtc_secs_to_tm(seconds, &t);
194 t.tm_year += RTC_EPOCH_BASE_YEAR;
195 t.tm_mon++;
197 if (of_call_method(fRTC, "set-time", 6, 0, t.tm_year, t.tm_mon, t.tm_mday,
198 t.tm_hour, t.tm_min, t.tm_sec) == OF_FAILED) {
199 dprintf("PPCOpenFirmware::SetHardwareRTC(): Failed to set RTC!\n");
203 // GetHardwareRTC
204 uint32
205 PPCOpenFirmware::GetHardwareRTC()
207 struct tm t;
208 if (of_call_method(fRTC, "get-time", 0, 6, &t.tm_year, &t.tm_mon,
209 &t.tm_mday, &t.tm_hour, &t.tm_min, &t.tm_sec) == OF_FAILED) {
210 dprintf("PPCOpenFirmware::GetHardwareRTC(): Failed to get RTC!\n");
211 return 0;
214 t.tm_year -= RTC_EPOCH_BASE_YEAR;
215 t.tm_mon--;
217 return rtc_tm_to_secs(&t);
220 // ShutDown
221 void
222 PPCOpenFirmware::ShutDown(bool reboot)
224 if (reboot) {
225 of_interpret("reset-all", 0, 0);
226 } else {
227 // not standardized, so it might fail
228 of_interpret("shut-down", 0, 0);
233 // #pragma mark - U-Boot + FDT
236 namespace BPrivate {
238 class PPCUBoot : public PPCPlatform {
239 public:
240 PPCUBoot();
241 virtual ~PPCUBoot();
243 virtual status_t Init(struct kernel_args *kernelArgs);
244 virtual status_t InitSerialDebug(struct kernel_args *kernelArgs);
245 virtual status_t InitPostVM(struct kernel_args *kernelArgs);
246 virtual status_t InitRTC(struct kernel_args *kernelArgs,
247 struct real_time_data *data);
249 virtual char SerialDebugGetChar();
250 virtual void SerialDebugPutChar(char c);
252 virtual void SetHardwareRTC(uint32 seconds);
253 virtual uint32 GetHardwareRTC();
255 virtual void ShutDown(bool reboot);
257 private:
258 int fInput;
259 int fOutput;
260 int fRTC;
261 DebugUART *fDebugUART;
264 } // namespace BPrivate
266 using BPrivate::PPCUBoot;
269 // constructor
270 PPCUBoot::PPCUBoot()
271 : PPCPlatform(PPC_PLATFORM_U_BOOT),
272 fInput(-1),
273 fOutput(-1),
274 fRTC(-1),
275 fDebugUART(NULL)
279 // destructor
280 PPCUBoot::~PPCUBoot()
284 // Init
285 status_t
286 PPCUBoot::Init(struct kernel_args *kernelArgs)
288 gFDT = kernelArgs->platform_args.fdt;
289 // XXX: do we error out if no FDT?
290 return B_OK;
293 // InitSerialDebug
294 status_t
295 PPCUBoot::InitSerialDebug(struct kernel_args *kernelArgs)
297 fDebugUART = debug_uart_from_fdt(gFDT);
298 if (fDebugUART == NULL)
299 return B_ERROR;
300 return B_OK;
303 // InitPostVM
304 status_t
305 PPCUBoot::InitPostVM(struct kernel_args *kernelArgs)
307 return B_ERROR;
310 // InitRTC
311 status_t
312 PPCUBoot::InitRTC(struct kernel_args *kernelArgs,
313 struct real_time_data *data)
315 return B_ERROR;
318 // DebugSerialGetChar
319 char
320 PPCUBoot::SerialDebugGetChar()
322 if (fDebugUART)
323 return fDebugUART->GetChar(false);
324 return 0;
327 // DebugSerialPutChar
328 void
329 PPCUBoot::SerialDebugPutChar(char c)
331 if (fDebugUART)
332 fDebugUART->PutChar(c);
335 // SetHardwareRTC
336 void
337 PPCUBoot::SetHardwareRTC(uint32 seconds)
341 // GetHardwareRTC
342 uint32
343 PPCUBoot::GetHardwareRTC()
345 return 0;
348 // ShutDown
349 void
350 PPCUBoot::ShutDown(bool reboot)
355 // # pragma mark -
358 #define PLATFORM_BUFFER_SIZE MAX(sizeof(PPCOpenFirmware),sizeof(PPCUBoot))
359 // static buffer for constructing the actual PPCPlatform
360 static char *sPPCPlatformBuffer[PLATFORM_BUFFER_SIZE];
362 status_t
363 arch_platform_init(struct kernel_args *kernelArgs)
365 // only OpenFirmware supported for now
366 switch (kernelArgs->arch_args.platform) {
367 case PPC_PLATFORM_OPEN_FIRMWARE:
368 sPPCPlatform = new(sPPCPlatformBuffer) PPCOpenFirmware;
369 break;
370 case PPC_PLATFORM_U_BOOT:
371 sPPCPlatform = new(sPPCPlatformBuffer) PPCUBoot;
372 break;
373 default:
374 return B_ERROR;
377 return sPPCPlatform->Init(kernelArgs);
381 status_t
382 arch_platform_init_post_vm(struct kernel_args *kernelArgs)
384 return sPPCPlatform->InitPostVM(kernelArgs);
388 status_t
389 arch_platform_init_post_thread(struct kernel_args *kernelArgs)
391 return B_OK;