xref: /haiku/src/system/kernel/arch/ppc/arch_platform.cpp (revision 1e60bdeab63fa7a57bc9a55b032052e95a18bd2c)
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 <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>
17 
18 #include "fdt_serial.h"
19 
20 void *gFDT;
21 static PPCPlatform *sPPCPlatform;
22 
23 
24 // constructor
25 PPCPlatform::PPCPlatform(ppc_platform_type platformType)
26 	: fPlatformType(platformType)
27 {
28 }
29 
30 // destructor
31 PPCPlatform::~PPCPlatform()
32 {
33 }
34 
35 // Default
36 PPCPlatform *
37 PPCPlatform::Default()
38 {
39 	return sPPCPlatform;
40 }
41 
42 
43 // #pragma mark - Open Firmware
44 
45 
46 namespace BPrivate {
47 
48 class PPCOpenFirmware : public PPCPlatform {
49 public:
50 	PPCOpenFirmware();
51 	virtual ~PPCOpenFirmware();
52 
53 	virtual status_t Init(struct kernel_args *kernelArgs);
54 	virtual status_t InitSerialDebug(struct kernel_args *kernelArgs);
55 	virtual status_t InitPostVM(struct kernel_args *kernelArgs);
56 	virtual status_t InitRTC(struct kernel_args *kernelArgs,
57 		struct real_time_data *data);
58 
59 	virtual char SerialDebugGetChar();
60 	virtual void SerialDebugPutChar(char c);
61 
62 	virtual	void SetHardwareRTC(uint32 seconds);
63 	virtual	uint32 GetHardwareRTC();
64 
65 	virtual	void ShutDown(bool reboot);
66 
67 private:
68 	int	fInput;
69 	int	fOutput;
70 	int	fRTC;
71 };
72 
73 }	// namespace BPrivate
74 
75 using BPrivate::PPCOpenFirmware;
76 
77 
78 // OF debugger commands
79 
80 // debug_command_of_exit
81 static int
82 debug_command_of_exit(int argc, char **argv)
83 {
84 	of_exit();
85 	kprintf("of_exit() failed!\n");
86 	return 0;
87 }
88 
89 // debug_command_of_enter
90 static int
91 debug_command_of_enter(int argc, char **argv)
92 {
93 	of_call_client_function("enter", 0, 0);
94 	return 0;
95 }
96 
97 
98 // constructor
99 PPCOpenFirmware::PPCOpenFirmware()
100 	: PPCPlatform(PPC_PLATFORM_OPEN_FIRMWARE),
101 	  fInput(-1),
102 	  fOutput(-1),
103 	  fRTC(-1)
104 {
105 }
106 
107 // destructor
108 PPCOpenFirmware::~PPCOpenFirmware()
109 {
110 }
111 
112 // Init
113 status_t
114 PPCOpenFirmware::Init(struct kernel_args *kernelArgs)
115 {
116 	return of_init(
117 		(int(*)(void*))kernelArgs->platform_args.openfirmware_entry);
118 }
119 
120 // InitSerialDebug
121 status_t
122 PPCOpenFirmware::InitSerialDebug(struct kernel_args *kernelArgs)
123 {
124 	if (of_getprop(gChosen, "stdin", &fInput, sizeof(int)) == OF_FAILED)
125 		return B_ERROR;
126 	if (!kernelArgs->frame_buffer.enabled) {
127 		if (of_getprop(gChosen, "stdout", &fOutput, sizeof(int)) == OF_FAILED)
128 			return B_ERROR;
129 	}
130 
131 	return B_OK;
132 }
133 
134 // InitPostVM
135 status_t
136 PPCOpenFirmware::InitPostVM(struct kernel_args *kernelArgs)
137 {
138 	add_debugger_command("of_exit", &debug_command_of_exit,
139 		"Exit to the Open Firmware prompt. No way to get back into the OS!");
140 	add_debugger_command("of_enter", &debug_command_of_enter,
141 		"Enter a subordinate Open Firmware interpreter. Quitting it returns "
142 		"to KDL.");
143 
144 	return B_OK;
145 }
146 
147 // InitRTC
148 status_t
149 PPCOpenFirmware::InitRTC(struct kernel_args *kernelArgs,
150 	struct real_time_data *data)
151 {
152 	// open RTC
153 	fRTC = of_open(kernelArgs->platform_args.rtc_path);
154 	if (fRTC == OF_FAILED) {
155 		dprintf("PPCOpenFirmware::InitRTC(): Failed open RTC device!\n");
156 		return B_ERROR;
157 	}
158 
159 	return B_OK;
160 }
161 
162 // DebugSerialGetChar
163 char
164 PPCOpenFirmware::SerialDebugGetChar()
165 {
166 	int key;
167 	if (of_interpret("key", 0, 1, &key) == OF_FAILED)
168 		return 0;
169 	return (char)key;
170 }
171 
172 // DebugSerialPutChar
173 void
174 PPCOpenFirmware::SerialDebugPutChar(char c)
175 {
176 	if (fOutput == -1)
177 		return;
178 
179 	if (c == '\n')
180 		of_write(fOutput, "\r\n", 2);
181 	else
182 		of_write(fOutput, &c, 1);
183 }
184 
185 // SetHardwareRTC
186 void
187 PPCOpenFirmware::SetHardwareRTC(uint32 seconds)
188 {
189 	struct tm t;
190 	rtc_secs_to_tm(seconds, &t);
191 
192 	t.tm_year += RTC_EPOCH_BASE_YEAR;
193 	t.tm_mon++;
194 
195 	if (of_call_method(fRTC, "set-time", 6, 0, t.tm_year, t.tm_mon, t.tm_mday,
196 			t.tm_hour, t.tm_min, t.tm_sec) == OF_FAILED) {
197 		dprintf("PPCOpenFirmware::SetHardwareRTC(): Failed to set RTC!\n");
198 	}
199 }
200 
201 // GetHardwareRTC
202 uint32
203 PPCOpenFirmware::GetHardwareRTC()
204 {
205 	struct tm t;
206 	if (of_call_method(fRTC, "get-time", 0, 6, &t.tm_year, &t.tm_mon,
207 			&t.tm_mday, &t.tm_hour, &t.tm_min, &t.tm_sec) == OF_FAILED) {
208 		dprintf("PPCOpenFirmware::GetHardwareRTC(): Failed to get RTC!\n");
209 		return 0;
210 	}
211 
212 	t.tm_year -= RTC_EPOCH_BASE_YEAR;
213 	t.tm_mon--;
214 
215 	return rtc_tm_to_secs(&t);
216 }
217 
218 // ShutDown
219 void
220 PPCOpenFirmware::ShutDown(bool reboot)
221 {
222 	if (reboot) {
223 		of_interpret("reset-all", 0, 0);
224 	} else {
225 		// not standardized, so it might fail
226 		of_interpret("shut-down", 0, 0);
227 	}
228 }
229 
230 
231 // #pragma mark - U-Boot + FDT
232 
233 
234 namespace BPrivate {
235 
236 class PPCUBoot : public PPCPlatform {
237 public:
238 	PPCUBoot();
239 	virtual ~PPCUBoot();
240 
241 	virtual status_t Init(struct kernel_args *kernelArgs);
242 	virtual status_t InitSerialDebug(struct kernel_args *kernelArgs);
243 	virtual status_t InitPostVM(struct kernel_args *kernelArgs);
244 	virtual status_t InitRTC(struct kernel_args *kernelArgs,
245 		struct real_time_data *data);
246 
247 	virtual char SerialDebugGetChar();
248 	virtual void SerialDebugPutChar(char c);
249 
250 	virtual	void SetHardwareRTC(uint32 seconds);
251 	virtual	uint32 GetHardwareRTC();
252 
253 	virtual	void ShutDown(bool reboot);
254 
255 private:
256 	int	fInput;
257 	int	fOutput;
258 	int	fRTC;
259 	DebugUART *fDebugUART;
260 };
261 
262 }	// namespace BPrivate
263 
264 using BPrivate::PPCUBoot;
265 
266 
267 // constructor
268 PPCUBoot::PPCUBoot()
269 	: PPCPlatform(PPC_PLATFORM_U_BOOT),
270 	  fInput(-1),
271 	  fOutput(-1),
272 	  fRTC(-1),
273 	  fDebugUART(NULL)
274 {
275 }
276 
277 // destructor
278 PPCUBoot::~PPCUBoot()
279 {
280 }
281 
282 // Init
283 status_t
284 PPCUBoot::Init(struct kernel_args *kernelArgs)
285 {
286 	gFDT = kernelArgs->platform_args.fdt;
287 	// XXX: do we error out if no FDT?
288 	return B_OK;
289 }
290 
291 // InitSerialDebug
292 status_t
293 PPCUBoot::InitSerialDebug(struct kernel_args *kernelArgs)
294 {
295 	fDebugUART = debug_uart_from_fdt(gFDT);
296 	if (fDebugUART == NULL)
297 		return B_ERROR;
298 	return B_OK;
299 }
300 
301 // InitPostVM
302 status_t
303 PPCUBoot::InitPostVM(struct kernel_args *kernelArgs)
304 {
305 	return B_ERROR;
306 }
307 
308 // InitRTC
309 status_t
310 PPCUBoot::InitRTC(struct kernel_args *kernelArgs,
311 	struct real_time_data *data)
312 {
313 	return B_ERROR;
314 }
315 
316 // DebugSerialGetChar
317 char
318 PPCUBoot::SerialDebugGetChar()
319 {
320 	if (fDebugUART)
321 		return fDebugUART->GetChar(false);
322 	return 0;
323 }
324 
325 // DebugSerialPutChar
326 void
327 PPCUBoot::SerialDebugPutChar(char c)
328 {
329 	if (fDebugUART)
330 		fDebugUART->PutChar(c);
331 }
332 
333 // SetHardwareRTC
334 void
335 PPCUBoot::SetHardwareRTC(uint32 seconds)
336 {
337 }
338 
339 // GetHardwareRTC
340 uint32
341 PPCUBoot::GetHardwareRTC()
342 {
343 	return 0;
344 }
345 
346 // ShutDown
347 void
348 PPCUBoot::ShutDown(bool reboot)
349 {
350 }
351 
352 
353 // # pragma mark -
354 
355 
356 #define PLATFORM_BUFFER_SIZE MAX(sizeof(PPCOpenFirmware),sizeof(PPCUBoot))
357 // static buffer for constructing the actual PPCPlatform
358 static char *sPPCPlatformBuffer[PLATFORM_BUFFER_SIZE];
359 
360 status_t
361 arch_platform_init(struct kernel_args *kernelArgs)
362 {
363 	// only OpenFirmware supported for now
364 	switch (kernelArgs->arch_args.platform) {
365 		case PPC_PLATFORM_OPEN_FIRMWARE:
366 			sPPCPlatform = new(sPPCPlatformBuffer) PPCOpenFirmware;
367 			break;
368 		case PPC_PLATFORM_U_BOOT:
369 			sPPCPlatform = new(sPPCPlatformBuffer) PPCUBoot;
370 			break;
371 		default:
372 			return B_ERROR;
373 	}
374 
375 	return sPPCPlatform->Init(kernelArgs);
376 }
377 
378 
379 status_t
380 arch_platform_init_post_vm(struct kernel_args *kernelArgs)
381 {
382 	return sPPCPlatform->InitPostVM(kernelArgs);
383 }
384 
385 
386 status_t
387 arch_platform_init_post_thread(struct kernel_args *kernelArgs)
388 {
389 	return B_OK;
390 }
391