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 | | } |
| 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 | } |