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