xref: /haiku/src/system/kernel/arch/sparc/arch_platform.cpp (revision 1a76488fc88584bf66b9751d7fb9b6527ac20d87)
1 /*
2  * Copyright 2006, Ingo Weinhold <bonefish@cs.tu-berlin.de>.
3  * Copyright 2019-2020, Adrien Destugues, pulkomandy@pulkomandy.tk.
4  * All rights reserved. Distributed under the terms of the MIT License.
5  */
6 
7 #include <arch_platform.h>
8 
9 #include <new>
10 
11 #include <KernelExport.h>
12 
13 #include <arch/generic/debug_uart.h>
14 #include <boot/kernel_args.h>
15 #include <platform/openfirmware/openfirmware.h>
16 #include <real_time_clock.h>
17 #include <util/kernel_cpp.h>
18 
19 
20 static SparcPlatform *sSparcPlatform;
21 
22 
23 // constructor
24 SparcPlatform::SparcPlatform(sparc_platform_type platformType)
25 	: fPlatformType(platformType)
26 {
27 }
28 
29 // destructor
30 SparcPlatform::~SparcPlatform()
31 {
32 }
33 
34 // Default
35 SparcPlatform *
36 SparcPlatform::Default()
37 {
38 	return sSparcPlatform;
39 }
40 
41 
42 // #pragma mark - Open Firmware
43 
44 
45 namespace BPrivate {
46 
47 class SparcOpenFirmware : public SparcPlatform {
48 public:
49 	SparcOpenFirmware();
50 	virtual ~SparcOpenFirmware();
51 
52 	virtual status_t Init(struct kernel_args *kernelArgs);
53 	virtual status_t InitSerialDebug(struct kernel_args *kernelArgs);
54 	virtual status_t InitPostVM(struct kernel_args *kernelArgs);
55 	virtual status_t InitRTC(struct kernel_args *kernelArgs,
56 		struct real_time_data *data);
57 
58 	virtual char SerialDebugGetChar();
59 	virtual void SerialDebugPutChar(char c);
60 
61 	virtual	void SetHardwareRTC(uint32 seconds);
62 	virtual	uint32 GetHardwareRTC();
63 
64 	virtual	void ShutDown(bool reboot);
65 
66 private:
67 	int	fInput;
68 	int	fOutput;
69 	int	fRTC;
70 };
71 
72 }	// namespace BPrivate
73 
74 using BPrivate::SparcOpenFirmware;
75 
76 
77 // OF debugger commands
78 
79 // debug_command_of_exit
80 static int
81 debug_command_of_exit(int argc, char **argv)
82 {
83 	of_exit();
84 	kprintf("of_exit() failed!\n");
85 	return 0;
86 }
87 
88 // debug_command_of_enter
89 static int
90 debug_command_of_enter(int argc, char **argv)
91 {
92 	of_call_client_function("enter", 0, 0);
93 	return 0;
94 }
95 
96 
97 // constructor
98 SparcOpenFirmware::SparcOpenFirmware()
99 	: SparcPlatform(SPARC_PLATFORM_OPEN_FIRMWARE),
100 	  fInput(-1),
101 	  fOutput(-1),
102 	  fRTC(-1)
103 {
104 }
105 
106 // destructor
107 SparcOpenFirmware::~SparcOpenFirmware()
108 {
109 }
110 
111 // Init
112 status_t
113 SparcOpenFirmware::Init(struct kernel_args *kernelArgs)
114 {
115 	return of_init(
116 		(intptr_t(*)(void*))kernelArgs->platform_args.openfirmware_entry);
117 }
118 
119 // InitSerialDebug
120 status_t
121 SparcOpenFirmware::InitSerialDebug(struct kernel_args *kernelArgs)
122 {
123 	if (of_getprop(gChosen, "stdin", &fInput, sizeof(int)) == OF_FAILED)
124 		return B_ERROR;
125 	if (!kernelArgs->frame_buffer.enabled) {
126 		if (of_getprop(gChosen, "stdout", &fOutput, sizeof(int)) == OF_FAILED)
127 			return B_ERROR;
128 	}
129 
130 	return B_OK;
131 }
132 
133 // InitPostVM
134 status_t
135 SparcOpenFirmware::InitPostVM(struct kernel_args *kernelArgs)
136 {
137 	add_debugger_command("of_exit", &debug_command_of_exit,
138 		"Exit to the Open Firmware prompt. No way to get back into the OS!");
139 	add_debugger_command("of_enter", &debug_command_of_enter,
140 		"Enter a subordinate Open Firmware interpreter. Quitting it returns "
141 		"to KDL.");
142 
143 	return B_OK;
144 }
145 
146 // InitRTC
147 status_t
148 SparcOpenFirmware::InitRTC(struct kernel_args *kernelArgs,
149 	struct real_time_data *data)
150 {
151 	// open RTC
152 	fRTC = of_open(kernelArgs->platform_args.rtc_path);
153 	if (fRTC == OF_FAILED) {
154 		dprintf("SparcOpenFirmware::InitRTC(): Failed open RTC device!\n");
155 		return B_ERROR;
156 	}
157 
158 	return B_OK;
159 }
160 
161 // DebugSerialGetChar
162 char
163 SparcOpenFirmware::SerialDebugGetChar()
164 {
165 	int key;
166 	if (of_interpret("key", 0, 1, &key) == OF_FAILED)
167 		return 0;
168 	return (char)key;
169 }
170 
171 // DebugSerialPutChar
172 void
173 SparcOpenFirmware::SerialDebugPutChar(char c)
174 {
175 	if (fOutput == -1)
176 		return;
177 
178 	if (c == '\n')
179 		of_write((uint32_t)fOutput, "\r\n", 2);
180 	else
181 		of_write((uint32_t)fOutput, &c, 1);
182 }
183 
184 // SetHardwareRTC
185 void
186 SparcOpenFirmware::SetHardwareRTC(uint32 seconds)
187 {
188 	struct tm t;
189 	rtc_secs_to_tm(seconds, &t);
190 
191 	t.tm_year += RTC_EPOCH_BASE_YEAR;
192 	t.tm_mon++;
193 
194 	if (of_call_method((uint32_t)fRTC, "set-time", 6, 0, t.tm_year, t.tm_mon, t.tm_mday,
195 			t.tm_hour, t.tm_min, t.tm_sec) == OF_FAILED) {
196 		dprintf("SparcOpenFirmware::SetHardwareRTC(): Failed to set RTC!\n");
197 	}
198 }
199 
200 // GetHardwareRTC
201 uint32
202 SparcOpenFirmware::GetHardwareRTC()
203 {
204 	struct tm t;
205 	if (of_call_method((uint32_t)fRTC, "get-time", 0, 6, &t.tm_year, &t.tm_mon,
206 			&t.tm_mday, &t.tm_hour, &t.tm_min, &t.tm_sec) == OF_FAILED) {
207 		dprintf("SparcOpenFirmware::GetHardwareRTC(): Failed to get RTC!\n");
208 		return 0;
209 	}
210 
211 	t.tm_year -= RTC_EPOCH_BASE_YEAR;
212 	t.tm_mon--;
213 
214 	return rtc_tm_to_secs(&t);
215 }
216 
217 // ShutDown
218 void
219 SparcOpenFirmware::ShutDown(bool reboot)
220 {
221 	if (reboot) {
222 		of_interpret("reset-all", 0, 0);
223 	} else {
224 		// not standardized, so it might fail
225 		of_interpret("shut-down", 0, 0);
226 	}
227 }
228 
229 
230 // # pragma mark -
231 
232 
233 #define PLATFORM_BUFFER_SIZE sizeof(SparcOpenFirmware)
234 // static buffer for constructing the actual SparcPlatform
235 static char *sSparcPlatformBuffer[PLATFORM_BUFFER_SIZE];
236 
237 status_t
238 arch_platform_init(struct kernel_args *kernelArgs)
239 {
240 	// only OpenFirmware supported for now
241 	sSparcPlatform = new(sSparcPlatformBuffer) SparcOpenFirmware;
242 
243 	return sSparcPlatform->Init(kernelArgs);
244 }
245 
246 
247 status_t
248 arch_platform_init_post_vm(struct kernel_args *kernelArgs)
249 {
250 	return sSparcPlatform->InitPostVM(kernelArgs);
251 }
252 
253 
254 status_t
255 arch_platform_init_post_thread(struct kernel_args *kernelArgs)
256 {
257 	return B_OK;
258 }
259