xref: /haiku/src/system/kernel/arch/ppc/arch_platform.cpp (revision a906d0a031e721e2f2ec9d95274103e74a3a774f)
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