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
SparcPlatform(sparc_platform_type platformType)24 SparcPlatform::SparcPlatform(sparc_platform_type platformType)
25 : fPlatformType(platformType)
26 {
27 }
28
29 // destructor
~SparcPlatform()30 SparcPlatform::~SparcPlatform()
31 {
32 }
33
34 // Default
35 SparcPlatform *
Default()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
debug_command_of_exit(int argc,char ** argv)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
debug_command_of_enter(int argc,char ** argv)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
SparcOpenFirmware()98 SparcOpenFirmware::SparcOpenFirmware()
99 : SparcPlatform(SPARC_PLATFORM_OPEN_FIRMWARE),
100 fInput(-1),
101 fOutput(-1),
102 fRTC(-1)
103 {
104 }
105
106 // destructor
~SparcOpenFirmware()107 SparcOpenFirmware::~SparcOpenFirmware()
108 {
109 }
110
111 // Init
112 status_t
Init(struct kernel_args * kernelArgs)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
InitSerialDebug(struct kernel_args * kernelArgs)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
InitPostVM(struct kernel_args * kernelArgs)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
InitRTC(struct kernel_args * kernelArgs,struct real_time_data * data)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
SerialDebugGetChar()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
SerialDebugPutChar(char c)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
SetHardwareRTC(uint32 seconds)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
GetHardwareRTC()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
ShutDown(bool reboot)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
arch_platform_init(struct kernel_args * kernelArgs)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
arch_platform_init_post_vm(struct kernel_args * kernelArgs)248 arch_platform_init_post_vm(struct kernel_args *kernelArgs)
249 {
250 return sSparcPlatform->InitPostVM(kernelArgs);
251 }
252
253
254 status_t
arch_platform_init_post_thread(struct kernel_args * kernelArgs)255 arch_platform_init_post_thread(struct kernel_args *kernelArgs)
256 {
257 return B_OK;
258 }
259