1 |
dpavlin |
1 |
/* |
2 |
|
|
* PearPC |
3 |
|
|
* promosi.cc |
4 |
|
|
* |
5 |
|
|
* Copyright (C) 2003, 2004 Sebastian Biallas (sb@biallas.net) |
6 |
|
|
* |
7 |
|
|
* This program is free software; you can redistribute it and/or modify |
8 |
|
|
* it under the terms of the GNU General Public License version 2 as |
9 |
|
|
* published by the Free Software Foundation. |
10 |
|
|
* |
11 |
|
|
* This program is distributed in the hope that it will be useful, |
12 |
|
|
* but WITHOUT ANY WARRANTY; without even the implied warranty of |
13 |
|
|
* MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the |
14 |
|
|
* GNU General Public License for more details. |
15 |
|
|
* |
16 |
|
|
* You should have received a copy of the GNU General Public License |
17 |
|
|
* along with this program; if not, write to the Free Software |
18 |
|
|
* Foundation, Inc., 675 Mass Ave, Cambridge, MA 02139, USA. |
19 |
|
|
*/ |
20 |
|
|
|
21 |
|
|
#include <cstring> |
22 |
|
|
|
23 |
|
|
#include "debug/tracers.h" |
24 |
|
|
#include "system/display.h" |
25 |
|
|
#include "system/arch/sysendian.h" |
26 |
|
|
#include "cpu/cpu.h" |
27 |
|
|
#include "cpu/mem.h" |
28 |
|
|
#include "system/sysclk.h" |
29 |
|
|
#include "promdt.h" |
30 |
|
|
#include "prommem.h" |
31 |
|
|
#include "promosi.h" |
32 |
|
|
|
33 |
|
|
uint32 gPromOSIEntry; |
34 |
|
|
|
35 |
|
|
void prom_service_start_cpu(prom_args *pa) |
36 |
|
|
{ |
37 |
|
|
IO_PROM_ERR("start_cpu()\n"); |
38 |
|
|
} |
39 |
|
|
|
40 |
|
|
void prom_service_quiesce(prom_args *pa) |
41 |
|
|
{ |
42 |
|
|
IO_PROM_TRACE("quiesce()\n"); |
43 |
|
|
prom_mem_done(); |
44 |
|
|
} |
45 |
|
|
|
46 |
|
|
/* |
47 |
|
|
* .65 |
48 |
|
|
* Missing is 0 if the service name exists, and -1 if it does not exist. |
49 |
|
|
*/ |
50 |
|
|
void prom_service_test(prom_args *pa) |
51 |
|
|
{ |
52 |
|
|
//; of_test(const char *name, int *missing) |
53 |
|
|
String name; |
54 |
|
|
prom_get_string(name, pa->args[0]); |
55 |
|
|
IO_PROM_ERR("test('%y')\n", &name); |
56 |
|
|
} |
57 |
|
|
|
58 |
|
|
/* |
59 |
|
|
* .66 |
60 |
|
|
* |
61 |
|
|
*/ |
62 |
|
|
void prom_service_peer(prom_args *pa) |
63 |
|
|
{ |
64 |
|
|
//; of_peer(int phandle, int *sibling_phandle) |
65 |
|
|
uint32 phandle = pa->args[0]; |
66 |
|
|
IO_PROM_TRACE("peer(%08x)\n", phandle); |
67 |
|
|
if (!phandle) { |
68 |
|
|
pa->args[1] = gPromRoot ? gPromRoot->getPHandle() : 0; |
69 |
|
|
} else { |
70 |
|
|
PromNode *p = handleToPackage(phandle); |
71 |
|
|
if (p) { |
72 |
|
|
if (!p->owner) { |
73 |
|
|
pa->args[1] = 0; |
74 |
|
|
} else { |
75 |
|
|
p = p->owner->nextChild(p); |
76 |
|
|
pa->args[1] = p ? p->getPHandle() : 0; |
77 |
|
|
} |
78 |
|
|
} else { |
79 |
|
|
pa->args[1] = 0xffffffff; |
80 |
|
|
} |
81 |
|
|
} |
82 |
|
|
IO_PROM_TRACE("= %08x\n", pa->args[1]); |
83 |
|
|
} |
84 |
|
|
void prom_service_child(prom_args *pa) |
85 |
|
|
{ |
86 |
|
|
//; (int phandle, int *child_phandle) |
87 |
|
|
uint32 phandle = pa->args[0]; |
88 |
|
|
PromNode *p = handleToPackage(phandle); |
89 |
|
|
IO_PROM_TRACE("child(%08x, '%s')\n", phandle, p->name); |
90 |
|
|
PromNode *pn = p ? p->firstChild() : NULL; |
91 |
|
|
if (pn) { |
92 |
|
|
pa->args[1] = pn->getPHandle(); |
93 |
|
|
} else { |
94 |
|
|
pa->args[1] = 0; |
95 |
|
|
} |
96 |
|
|
IO_PROM_TRACE("= %08x\n", pa->args[1]); |
97 |
|
|
} |
98 |
|
|
void prom_service_parent(prom_args *pa) |
99 |
|
|
{ |
100 |
|
|
//; of_parent(int phandle, int *parent_phandle) |
101 |
|
|
uint32 phandle = pa->args[0]; |
102 |
|
|
PromNode *p = handleToPackage(phandle); |
103 |
|
|
IO_PROM_TRACE("parent(%08x)\n", phandle); |
104 |
|
|
PromNode *owner = p ? p->owner : NULL; |
105 |
|
|
pa->args[1] = owner ? owner->getPHandle() : 0; |
106 |
|
|
IO_PROM_TRACE("= %08x\n", pa->args[1]); |
107 |
|
|
} |
108 |
|
|
void prom_service_instance_to_package(prom_args *pa) |
109 |
|
|
{ |
110 |
|
|
//; of_instance_to_package(int ihandle, int *phandle) |
111 |
|
|
uint32 ihandle = pa->args[0]; |
112 |
|
|
IO_PROM_TRACE("instance-to-package(%08x)\n", ihandle); |
113 |
|
|
PromInstance *pi = handleToInstance(ihandle); |
114 |
|
|
if (pi) { |
115 |
|
|
pa->args[1] = pi->getType()->getPHandle(); |
116 |
|
|
} else { |
117 |
|
|
pa->args[1] = 0xffffffff; |
118 |
|
|
} |
119 |
|
|
IO_PROM_TRACE("= %08x\n", pa->args[1]); |
120 |
|
|
} |
121 |
|
|
|
122 |
|
|
void prom_service_finddevice(prom_args *pa) |
123 |
|
|
{ |
124 |
|
|
//; of_finddevice(const char *device_specifier, int *phandle) |
125 |
|
|
String device; |
126 |
|
|
prom_get_string(device, pa->args[0]); |
127 |
|
|
IO_PROM_TRACE("finddevice('%y')\n", &device); |
128 |
|
|
PromNode *node = findDevice(device.contentChar(), FIND_DEVICE_FIND, NULL); |
129 |
|
|
if (node) { |
130 |
|
|
pa->args[1] = node->getPHandle(); |
131 |
|
|
} else { |
132 |
|
|
pa->args[1] = 0xffffffff; |
133 |
|
|
} |
134 |
|
|
IO_PROM_TRACE("= %08x\n", pa->args[1]); |
135 |
|
|
} |
136 |
|
|
void prom_service_getproplen(prom_args *pa) |
137 |
|
|
{ |
138 |
|
|
//; of_getproplen(int phandle, const char *name, int *proplen) |
139 |
|
|
uint32 phandle = pa->args[0]; |
140 |
|
|
PromNode *p = handleToPackage(phandle); |
141 |
|
|
String name; |
142 |
|
|
prom_get_string(name, pa->args[1]); |
143 |
|
|
IO_PROM_TRACE("getproplen(%08x, '%y')\n", phandle, &name); |
144 |
|
|
PromProp *prop = p ? p->findProp(name.contentChar()) : 0; |
145 |
|
|
if (!prop) { |
146 |
|
|
pa->args[2] = 0xffffffff; |
147 |
|
|
} else { |
148 |
|
|
pa->args[2] = prop->getValueLen(); |
149 |
|
|
} |
150 |
|
|
IO_PROM_TRACE("= %08x\n", pa->args[2]); |
151 |
|
|
} |
152 |
|
|
void prom_service_getprop(prom_args *pa) |
153 |
|
|
{ |
154 |
|
|
//; of_getprop(int phandle, const char *name, void *buf, int buflen, int *size) |
155 |
|
|
uint32 phandle = pa->args[0]; |
156 |
|
|
String name; |
157 |
|
|
prom_get_string(name, pa->args[1]); |
158 |
|
|
uint32 buf = pa->args[2]; |
159 |
|
|
uint32 buflen = pa->args[3]; |
160 |
|
|
IO_PROM_TRACE("getprop(%08x, '%y', %08x, %08x)\n", phandle, &name, buf, buflen); |
161 |
|
|
PromNode *p = handleToPackage(phandle); |
162 |
|
|
PromProp *prop = p ? p->findProp(name.contentChar()) : 0; |
163 |
|
|
if (!prop) { |
164 |
|
|
pa->args[4] = 0xffffffff; |
165 |
|
|
} else { |
166 |
|
|
pa->args[4] = prop->getValue(buf, buflen); |
167 |
|
|
} |
168 |
|
|
IO_PROM_TRACE("= %08x\n", pa->args[4]); |
169 |
|
|
} |
170 |
|
|
void prom_service_nextprop(prom_args *pa) |
171 |
|
|
{ |
172 |
|
|
//; of_nextprop(int phandle, const char *previous, void *buf, int *flag) |
173 |
|
|
uint32 phandle = pa->args[0]; |
174 |
|
|
String previous; |
175 |
|
|
prom_get_string(previous, pa->args[1]); |
176 |
|
|
uint32 buf = pa->args[2]; |
177 |
|
|
uint32 *flag = &pa->args[3]; |
178 |
|
|
IO_PROM_TRACE("nextprop(%08x, %08x:'%y', %08x)\n", phandle, pa->args[1], &previous, buf); |
179 |
|
|
PromNode *pn = handleToPackage(phandle); |
180 |
|
|
PromProp *prop = NULL; |
181 |
|
|
if (previous.isEmpty() || !pn) { |
182 |
|
|
prop = pn ? pn->firstProp() : 0; |
183 |
|
|
if (!prop) { |
184 |
|
|
*flag = 0; |
185 |
|
|
} else { |
186 |
|
|
*flag = 1; |
187 |
|
|
} |
188 |
|
|
} else { |
189 |
|
|
prop = pn->findProp(previous.contentChar()); |
190 |
|
|
if (prop) { |
191 |
|
|
prop = pn->nextProp(prop); |
192 |
|
|
if (prop) { |
193 |
|
|
*flag = 1; |
194 |
|
|
} else { |
195 |
|
|
*flag = 0; |
196 |
|
|
} |
197 |
|
|
} else { |
198 |
|
|
*flag = 0xffffffff; |
199 |
|
|
} |
200 |
|
|
} |
201 |
|
|
uint32 phys; |
202 |
|
|
if (ppc_prom_effective_to_physical(phys, buf)) { |
203 |
|
|
if (prop) { |
204 |
|
|
char b[32]; |
205 |
|
|
ht_snprintf(b, sizeof b, "%s", prop->name); |
206 |
|
|
ppc_dma_write(phys, b, strlen(b)+1); |
207 |
|
|
} else { |
208 |
|
|
char b=0; |
209 |
|
|
ppc_dma_write(phys, &b, 1); |
210 |
|
|
} |
211 |
|
|
} else { |
212 |
|
|
IO_PROM_ERR("can't access memory in %s\n", __FUNCTION__); |
213 |
|
|
} |
214 |
|
|
IO_PROM_TRACE("= %08x\n", *flag); |
215 |
|
|
} |
216 |
|
|
void prom_service_setprop(prom_args *pa) |
217 |
|
|
{ |
218 |
|
|
//; of_setprop(int phandle, const char *name, void *buf, int len, int *size) |
219 |
|
|
uint32 phandle = pa->args[0]; |
220 |
|
|
String name; |
221 |
|
|
prom_get_string(name, pa->args[1]); |
222 |
|
|
uint32 buf = pa->args[2]; |
223 |
|
|
String value; |
224 |
|
|
uint32 len = pa->args[3]; |
225 |
|
|
uint32 phys; |
226 |
|
|
if (buf && len && ppc_prom_effective_to_physical(phys, buf)) { |
227 |
|
|
byte *p = (byte *)malloc(len); |
228 |
|
|
if (ppc_dma_read(p, phys, len)) { |
229 |
|
|
value.assign(p, len); |
230 |
|
|
} |
231 |
|
|
free(p); |
232 |
|
|
} |
233 |
|
|
PromNode *p = handleToPackage(phandle); |
234 |
|
|
IO_PROM_TRACE("setprop(%x=='%s', '%y', '%y', %d)\n", phandle, p->name, &name, &value, len); |
235 |
|
|
/* if (phandle == 0xdeadbee1) { |
236 |
|
|
pa->args[4] = len; |
237 |
|
|
// gSinglestep = true; |
238 |
|
|
return; |
239 |
|
|
}*/ |
240 |
|
|
if (p) { |
241 |
|
|
PromProp *prop = p->findProp(name.contentChar()); |
242 |
|
|
if (!prop) { |
243 |
|
|
if (buf) { |
244 |
|
|
p->addProp(new PromPropMemory(name.contentChar(), value.content(), len)); |
245 |
|
|
} else { |
246 |
|
|
p->addProp(new PromPropString(name.contentChar(), "")); |
247 |
|
|
} |
248 |
|
|
pa->args[4] = len; |
249 |
|
|
} else { |
250 |
|
|
//if (!buf && len) IO_PROM_ERR("setprop null bla\n"); |
251 |
|
|
if (buf && len) |
252 |
|
|
pa->args[4] = prop->setValue(buf, len); |
253 |
|
|
else |
254 |
|
|
pa->args[4] = prop->setValue(0, 0); |
255 |
|
|
} |
256 |
|
|
} else { |
257 |
|
|
pa->args[4] = 0; |
258 |
|
|
} |
259 |
|
|
IO_PROM_TRACE("= %08x\n", pa->args[4]); |
260 |
|
|
} |
261 |
|
|
void prom_service_canon(prom_args *pa) |
262 |
|
|
{ |
263 |
|
|
//; of_canon(const char *device_specifier, void *buf, int buflen, int *length) |
264 |
|
|
String device; |
265 |
|
|
prom_get_string(device, pa->args[0]); |
266 |
|
|
uint32 buf = pa->args[1]; |
267 |
|
|
uint32 buflen = pa->args[2]; |
268 |
|
|
IO_PROM_TRACE("canon('%y', %08x, %08x)\n", &device, buf, buflen); |
269 |
|
|
|
270 |
|
|
uint32 phys; |
271 |
|
|
if (ppc_prom_effective_to_physical(phys, buf)) { |
272 |
|
|
if (buflen) buflen--; |
273 |
|
|
device.crop(buflen); |
274 |
|
|
ppc_dma_write(phys, device.contentChar(), device.length()+1); |
275 |
|
|
pa->args[3] = device.length(); |
276 |
|
|
} else { |
277 |
|
|
pa->args[3] = 0; |
278 |
|
|
} |
279 |
|
|
IO_PROM_TRACE("= %08x\n", pa->args[3]); |
280 |
|
|
} |
281 |
|
|
void prom_service_instance_to_path(prom_args *pa) |
282 |
|
|
{ |
283 |
|
|
//; of_instance_to_path(int ihandle, void *buf, int buflen, int *length) |
284 |
|
|
uint32 ihandle = pa->args[0]; |
285 |
|
|
uint32 buf = pa->args[1]; |
286 |
|
|
uint32 buflen = pa->args[2]; |
287 |
|
|
PromInstance *pi = handleToInstance(ihandle); |
288 |
|
|
IO_PROM_TRACE("instance-to-path(%08x, %08x, %08x)\n", ihandle, buf, buflen); |
289 |
|
|
uint32 phys; |
290 |
|
|
if (pi && buflen && ppc_prom_effective_to_physical(phys, buf)) { |
291 |
|
|
PromNode *pn = pi->getType(); |
292 |
|
|
char *s = (char *)malloc(buflen); |
293 |
|
|
pa->args[3] = pn->toPath(s, buflen); |
294 |
|
|
ppc_dma_write(phys, s, pa->args[3]+1); |
295 |
|
|
free(s); |
296 |
|
|
} else { |
297 |
|
|
pa->args[3] = 0; |
298 |
|
|
} |
299 |
|
|
IO_PROM_TRACE("= %08x\n", pa->args[3]); |
300 |
|
|
} |
301 |
|
|
void prom_service_package_to_path(prom_args *pa) |
302 |
|
|
{ |
303 |
|
|
//; of_package_to_path(int phandle, void *buf, int buflen, int *length) |
304 |
|
|
uint32 phandle = pa->args[0]; |
305 |
|
|
uint32 buf = pa->args[1]; |
306 |
|
|
uint32 buflen = pa->args[2]; |
307 |
|
|
PromNode *p = handleToPackage(phandle); |
308 |
|
|
IO_PROM_TRACE("package-to-path(%08x, %08x, %08x)\n", phandle, buf, buflen); |
309 |
|
|
uint32 phys; |
310 |
|
|
if (p && ppc_prom_effective_to_physical(phys, buf)) { |
311 |
|
|
char *s = (char *)malloc(buflen); |
312 |
|
|
pa->args[3] = p->toPath(s, buflen); |
313 |
|
|
ppc_dma_write(phys, s, pa->args[3]+1); |
314 |
|
|
free(s); |
315 |
|
|
} else { |
316 |
|
|
pa->args[3] = 0; |
317 |
|
|
} |
318 |
|
|
// IO_PROM_TRACE("%s\n", prom_ea_string(buf)); |
319 |
|
|
IO_PROM_TRACE("= %08x\n", pa->args[3]); |
320 |
|
|
} |
321 |
|
|
void prom_service_call_method(prom_args *pa) |
322 |
|
|
{ |
323 |
|
|
//; int of_call_method(const char *method, int ihandle, ...); */ |
324 |
|
|
String method; |
325 |
|
|
prom_get_string(method, pa->args[0]); |
326 |
|
|
uint32 ihandle = pa->args[1]; |
327 |
|
|
PromInstance *pi = handleToInstance(ihandle); |
328 |
|
|
IO_PROM_TRACE("call-method('%y', %08x, ...)\n", &method, ihandle); |
329 |
|
|
if (ihandle == 0xdeadbee2) { |
330 |
|
|
if (method == "slw_emit") { |
331 |
|
|
// gDisplay->printf("%c", pa->args[2]); |
332 |
|
|
} else if (method == "slw_cr") { |
333 |
|
|
// gDisplay->print("\n"); |
334 |
|
|
} else if (method == "slw_init_keymap") { |
335 |
|
|
uint32 a = prom_mem_malloc(20); |
336 |
|
|
prom_mem_set(a, 0x00, 20); |
337 |
|
|
pa->args[4] = prom_mem_phys_to_virt(a); |
338 |
|
|
pa->args[3] = 0; |
339 |
|
|
} else if (method == "slw_update_keymap") { |
340 |
|
|
} else if (method == "slw_set_output_level") { |
341 |
|
|
} else if (method == "slw_spin_init") { |
342 |
|
|
} else if (method == "slw_spin") { |
343 |
|
|
} else if (method == "slw_pwd") { |
344 |
|
|
uint32 phandle = pa->args[4]; |
345 |
|
|
uint32 buf = pa->args[3]; |
346 |
|
|
uint32 buflen = pa->args[2]; |
347 |
|
|
PromNode *obj = handleToPackage(phandle); |
348 |
|
|
pa->args[5] = 0; |
349 |
|
|
uint32 phys; |
350 |
|
|
if (obj && ppc_prom_effective_to_physical(phys, buf)) { |
351 |
|
|
char *s = (char *)malloc(buflen); |
352 |
|
|
pa->args[6] = obj->toPath(s, buflen); |
353 |
|
|
ppc_dma_write(phys, s, pa->args[6]+1); |
354 |
|
|
free(s); |
355 |
|
|
} else { |
356 |
|
|
pa->args[6] = 0; |
357 |
|
|
} |
358 |
|
|
} else { |
359 |
|
|
IO_PROM_ERR("slw: %y not impl\n", &method); |
360 |
|
|
} |
361 |
|
|
} else { |
362 |
|
|
if (pi) pi->callMethod(method.contentChar(), pa); |
363 |
|
|
} |
364 |
|
|
} |
365 |
|
|
void prom_service_open(prom_args *pa) |
366 |
|
|
{ |
367 |
|
|
//; of_open(const char *device_specifier, int *ihandle) |
368 |
|
|
String device; |
369 |
|
|
prom_get_string(device, pa->args[0]); |
370 |
|
|
IO_PROM_TRACE("open('%y')\n", &device); |
371 |
|
|
PromInstanceHandle ih; |
372 |
|
|
PromNode *node = findDevice(device.contentChar(), FIND_DEVICE_OPEN, &ih); |
373 |
|
|
if (node) { |
374 |
|
|
pa->args[1] = ih; |
375 |
|
|
} else { |
376 |
|
|
pa->args[1] = 0xffffffff; |
377 |
|
|
} |
378 |
|
|
IO_PROM_TRACE("= %08x\n", pa->args[1]); |
379 |
|
|
} |
380 |
|
|
void prom_service_close(prom_args *pa) |
381 |
|
|
{ |
382 |
|
|
//; of_close(int ihandle) |
383 |
|
|
uint32 ihandle = pa->args[0]; |
384 |
|
|
IO_PROM_TRACE("close(%x)\n", ihandle); |
385 |
|
|
PromInstance *pi = handleToInstance(ihandle); |
386 |
|
|
if (pi) { |
387 |
|
|
pi->getType()->close(ihandle); |
388 |
|
|
} |
389 |
|
|
} |
390 |
|
|
void prom_service_read(prom_args *pa) |
391 |
|
|
{ |
392 |
|
|
//; of_read(int ihandle, void *addr, int len, int *actual) |
393 |
|
|
uint32 ihandle = pa->args[0]; |
394 |
|
|
uint32 addr = pa->args[1]; |
395 |
|
|
uint32 len = pa->args[2]; |
396 |
|
|
IO_PROM_TRACE("read(%08x, %08x, %08x)\n", ihandle, addr, len); |
397 |
|
|
PromInstance *pi = handleToInstance(ihandle); |
398 |
|
|
pa->args[3] = pi ? pi->read(addr, len) : 0; |
399 |
|
|
IO_PROM_TRACE("= %08x\n", pa->args[3]); |
400 |
|
|
} |
401 |
|
|
void prom_service_write(prom_args *pa) |
402 |
|
|
{ |
403 |
|
|
//; of_write(int ihandle, void *addr, int len, int *actual) |
404 |
|
|
uint32 ihandle = pa->args[0]; |
405 |
|
|
uint32 addr = pa->args[1]; |
406 |
|
|
uint32 len = pa->args[2]; |
407 |
|
|
IO_PROM_TRACE("write(%08x, %08x, %08x)\n", ihandle, addr, len); |
408 |
|
|
PromInstance *pi = handleToInstance(ihandle); |
409 |
|
|
pa->args[3] = pi ? pi->write(addr, len) : 0; |
410 |
|
|
IO_PROM_TRACE("= %08x\n", pa->args[3]); |
411 |
|
|
} |
412 |
|
|
void prom_service_seek(prom_args *pa) |
413 |
|
|
{ |
414 |
|
|
//; of_seek(int ihandle, int pos_hi, int pos_lo, int *status) |
415 |
|
|
uint32 ihandle = pa->args[0]; |
416 |
|
|
uint32 pos_hi = pa->args[1]; |
417 |
|
|
uint32 pos_lo = pa->args[2]; |
418 |
|
|
IO_PROM_TRACE("seek(%x, %x%032x)\n", ihandle, pos_hi, pos_lo); |
419 |
|
|
PromInstance *pi = handleToInstance(ihandle); |
420 |
|
|
pa->args[3] = pi ? pi->seek((((uint64)pos_hi) << 32) | pos_lo) : 0; |
421 |
|
|
IO_PROM_TRACE("= %08x\n", pa->args[3]); |
422 |
|
|
} |
423 |
|
|
void prom_service_claim(prom_args *pa) |
424 |
|
|
{ |
425 |
|
|
//; of_claim(void *virt, int size, int align, void **baseaddr) |
426 |
|
|
uint32 virt = pa->args[0]; |
427 |
|
|
uint32 size = pa->args[1]; |
428 |
|
|
uint32 align = pa->args[2]; |
429 |
|
|
IO_PROM_TRACE("claim(%x, %x, %x)\n", virt, size, align); |
430 |
|
|
if (!align) { |
431 |
|
|
pa->args[3] = prom_allocate_mem(size, align, virt); |
432 |
|
|
IO_PROM_TRACE("= %08x\n", pa->args[3]); |
433 |
|
|
} else { |
434 |
|
|
pa->args[3] = prom_allocate_mem(size, align, virt); |
435 |
|
|
IO_PROM_TRACE("= %08x\n", pa->args[3]); |
436 |
|
|
} |
437 |
|
|
} |
438 |
|
|
void prom_service_release(prom_args *pa) |
439 |
|
|
{ |
440 |
|
|
//; of_release(void *virt, int size) |
441 |
|
|
IO_PROM_ERR("release()\n"); |
442 |
|
|
} |
443 |
|
|
void prom_service_boot(prom_args *pa) |
444 |
|
|
{ |
445 |
|
|
//; of_boot(const char *bootspec) |
446 |
|
|
IO_PROM_ERR("boot()\n"); |
447 |
|
|
} |
448 |
|
|
void prom_service_enter(prom_args *pa) |
449 |
|
|
{ |
450 |
|
|
//; of_enter(void) |
451 |
|
|
uint64 start = sys_get_hiresclk_ticks(); |
452 |
|
|
uint64 end = start+(sys_get_hiresclk_ticks_per_second()*3); |
453 |
|
|
while (sys_get_hiresclk_ticks() < end); |
454 |
|
|
//IO_PROM_ERR("enter()\n"); |
455 |
|
|
} |
456 |
|
|
void prom_service_exit(prom_args *pa) |
457 |
|
|
{ |
458 |
|
|
//; of_exit(void) |
459 |
|
|
IO_PROM_ERR("exit()\n"); |
460 |
|
|
/* while (1); |
461 |
|
|
exit(1);*/ |
462 |
|
|
} |
463 |
|
|
void prom_service_chain(prom_args *pa) |
464 |
|
|
{ |
465 |
|
|
//; of_chain(void *virt, int size, void *entry, void *args, int len); |
466 |
|
|
IO_PROM_ERR("chain()\n"); |
467 |
|
|
} |
468 |
|
|
#include "io/graphic/gcard.h" |
469 |
|
|
void prom_service_interpret(prom_args *pa) |
470 |
|
|
{ |
471 |
|
|
//; of_(const char *arg, ...); |
472 |
|
|
String arg; |
473 |
|
|
prom_get_string(arg, pa->args[0]); |
474 |
|
|
IO_PROM_TRACE("interpret(%d, %08x, %08x, %08x, %08x, '%y' ...)\n", arg.length(), pa->args[1], pa->args[2], pa->args[3], pa->args[4], &arg); |
475 |
|
|
switch (arg.length()) { |
476 |
|
|
case 6: { |
477 |
|
|
// " 10 ms" |
478 |
|
|
void prom_service_milliseconds(prom_args *pa); |
479 |
|
|
uint32 start = (prom_service_milliseconds(pa), pa->args[0]); |
480 |
|
|
while ((prom_service_milliseconds(pa),pa->args[0]) < start+10); |
481 |
|
|
break; |
482 |
|
|
} |
483 |
|
|
case 32: { |
484 |
|
|
// GetPackageProperty |
485 |
|
|
uint32 phandle = pa->args[1]; |
486 |
|
|
uint32 proplen UNUSED = pa->args[2]; |
487 |
|
|
uint32 propname = pa->args[3]; |
488 |
|
|
String n; |
489 |
|
|
prom_get_string(n, propname); |
490 |
|
|
PromNode *pn = handleToPackage(phandle); |
491 |
|
|
IO_PROM_TRACE("GetPackageProperty('%y', %08x:%s)\n", &n, phandle, pn->name); |
492 |
|
|
PromProp *prop = pn->findProp(n.contentChar()); |
493 |
|
|
if (!prop) { |
494 |
|
|
pa->args[4] = 0; |
495 |
|
|
pa->args[5] = 0; |
496 |
|
|
pa->args[6] = 0; |
497 |
|
|
} else { |
498 |
|
|
uint32 m = prom_mem_phys_to_virt(prom_mem_malloc(100)); |
499 |
|
|
IO_PROM_TRACE("m = %08x\n", m); |
500 |
|
|
int s = prop->getValue(m, 100); |
501 |
|
|
pa->args[4] = 0; |
502 |
|
|
pa->args[5] = s; |
503 |
|
|
pa->args[6] = m; |
504 |
|
|
} |
505 |
|
|
break; |
506 |
|
|
// IO_PROM_ERR("-1\n"); |
507 |
|
|
} |
508 |
|
|
case 39: |
509 |
|
|
case 81: |
510 |
|
|
case 89: |
511 |
|
|
pa->args[2] = 0; |
512 |
|
|
break; |
513 |
|
|
case 75: { |
514 |
|
|
// InitMemoryMap |
515 |
|
|
PromNode *chosen = (PromNode*)gPromRoot->findNode("chosen"); |
516 |
|
|
PromNode *mm = new PromNode("memory-map"); |
517 |
|
|
chosen->addNode(mm); |
518 |
|
|
pa->args[1] = 0; |
519 |
|
|
pa->args[2] = mm->getPHandle(); |
520 |
|
|
break; |
521 |
|
|
} |
522 |
|
|
case 593: |
523 |
|
|
case 648: |
524 |
|
|
// InitDisplay |
525 |
|
|
pa->args[4] = 0; |
526 |
|
|
pa->args[5] = IO_GCARD_FRAMEBUFFER_PA_START; |
527 |
|
|
// gSinglestep = true; |
528 |
|
|
break; |
529 |
|
|
case 1967: |
530 |
|
|
case 1644: |
531 |
|
|
// Init SLW |
532 |
|
|
pa->args[1] = 0; |
533 |
|
|
pa->args[2] = 0xdeadbee2; |
534 |
|
|
break; |
535 |
|
|
case 1972: // older BootX |
536 |
|
|
pa->args[1] = 0; |
537 |
|
|
pa->args[2] = 0; |
538 |
|
|
pa->args[3] = 0xdeadbee2; |
539 |
|
|
break; |
540 |
|
|
case 47: |
541 |
|
|
case 11: |
542 |
|
|
case 21: |
543 |
|
|
case 36: |
544 |
|
|
case 116: |
545 |
|
|
case 152: |
546 |
|
|
case 10722: |
547 |
|
|
pa->args[1] = 0; |
548 |
|
|
pa->args[2] = 0; |
549 |
|
|
break; |
550 |
|
|
default: |
551 |
|
|
IO_PROM_ERR("unknown interpret size %d\ninterpret: %y\n", arg.length(), &arg); |
552 |
|
|
break; |
553 |
|
|
} |
554 |
|
|
} |
555 |
|
|
void prom_service_set_callback(prom_args *pa) |
556 |
|
|
{ |
557 |
|
|
//; of_set_callback(void *newfunc, void **oldfunc) |
558 |
|
|
IO_PROM_ERR("callback()\n"); |
559 |
|
|
} |
560 |
|
|
void prom_service_set_symbol_lookup(prom_args *pa) |
561 |
|
|
{ |
562 |
|
|
//; of_set_symbol_lookup(void *sym_to_value, void *value_to_sym) |
563 |
|
|
IO_PROM_ERR("symbol-lookup()\n"); |
564 |
|
|
} |
565 |
|
|
void prom_service_milliseconds(prom_args *pa) |
566 |
|
|
{ |
567 |
|
|
static uint32 start = (sys_get_hiresclk_ticks() / (sys_get_hiresclk_ticks_per_second()/1000)); |
568 |
|
|
//; of_milliseconds(int *ms) |
569 |
|
|
uint32 millis = (uint32)(sys_get_hiresclk_ticks() / (sys_get_hiresclk_ticks_per_second()/1000)) - start; |
570 |
|
|
IO_PROM_TRACE("milliseconds()\n"); |
571 |
|
|
pa->args[0] = millis; |
572 |
|
|
IO_PROM_TRACE("= %08x\n", pa->args[0]); |
573 |
|
|
} |
574 |
|
|
|
575 |
|
|
typedef void (*prom_service_function)(prom_args *pa); |
576 |
|
|
|
577 |
|
|
struct prom_service_desc { |
578 |
|
|
const char *name; |
579 |
|
|
prom_service_function f; |
580 |
|
|
}; |
581 |
|
|
|
582 |
|
|
prom_service_desc prom_service_table[] = { |
583 |
|
|
{"start-cpu", &prom_service_start_cpu}, |
584 |
|
|
{"quiesce", &prom_service_quiesce}, |
585 |
|
|
/* 6.3.2.1 Client interface */ |
586 |
|
|
{"test", &prom_service_test}, //; of_test(const char *name, int *missing) |
587 |
|
|
/* 6.3.2.2 Device tree */ |
588 |
|
|
{"peer", &prom_service_peer}, //; of_peer(int phandle, int *sibling_phandle) |
589 |
|
|
{"child", &prom_service_child}, //; (int phandle, int *child_phandle) |
590 |
|
|
{"parent", &prom_service_parent}, //; of_parent(int phandle, int *parent_phandle) |
591 |
|
|
{"instance-to-package", &prom_service_instance_to_package}, //; of_instance_to_package(int ihandle, int *phandle) |
592 |
|
|
{"getproplen", &prom_service_getproplen}, //; of_getproplen(int phandle, const char *name, int *proplen) |
593 |
|
|
{"getprop", &prom_service_getprop}, //; of_getprop(int phandle, const char *name, void *buf, int buflen, int *size) |
594 |
|
|
{"nextprop", &prom_service_nextprop}, //; of_nextprop(int phandle, const char *previous, void *buf, int *flag) |
595 |
|
|
{"setprop", &prom_service_setprop}, //; of_setprop(int phandle, const char *name, void *buf, int len, int *size) |
596 |
|
|
{"canon", &prom_service_canon}, //; of_canon(const char *device_specifier, void *buf, int buflen, int *length) |
597 |
|
|
{"finddevice", &prom_service_finddevice}, //; of_finddevice(const char *device_specifier, int *phandle) |
598 |
|
|
{"instance-to-path", &prom_service_instance_to_path}, //; of_instance_to_path(int ihandle, void *buf, int buflen, int *length) |
599 |
|
|
{"package-to-path", &prom_service_package_to_path}, //; of_package_to_path(int phandle, void *buf, int buflen, int *length) |
600 |
|
|
{"call-method", &prom_service_call_method}, //; int of_call_method(const char *method, int ihandle, ...); */ |
601 |
|
|
/* 6.3.2.3 Device I/O */ |
602 |
|
|
{"open", &prom_service_open}, //; of_open(const char *device_specifier, int *ihandle) |
603 |
|
|
{"close", &prom_service_close}, //; of_close(int ihandle) |
604 |
|
|
{"read", &prom_service_read}, //; of_read(int ihandle, void *addr, int len, int *actual) |
605 |
|
|
{"write", &prom_service_write}, //; of_write(int ihandle, void *addr, int len, int *actual) |
606 |
|
|
{"seek", &prom_service_seek}, //; of_seek(int ihandle, int pos_hi, int pos_lo, int *status) |
607 |
|
|
/* 6.3.2.4 Memory */ |
608 |
|
|
{"claim", &prom_service_claim}, //; of_claim(void *virt, int size, int align, void **baseaddr) |
609 |
|
|
{"release", &prom_service_release}, //; of_release(void *virt, int size) |
610 |
|
|
/* 6.3.2.5 Control transfer */ |
611 |
|
|
{"boot", &prom_service_boot}, //; of_boot(const char *bootspec) |
612 |
|
|
{"enter", &prom_service_enter}, //; of_enter(void) |
613 |
|
|
{"exit", &prom_service_exit}, //; of_exit(void) |
614 |
|
|
{"chain", &prom_service_chain}, //; of_chain(void *virt, int size, void *entry, void *args, int len); |
615 |
|
|
/* 6.3.2.6 User interface */ |
616 |
|
|
{"interpret", &prom_service_interpret}, //; of_(const char *arg, ...); |
617 |
|
|
{"set-callback", &prom_service_set_callback}, //; of_set_callback(void *newfunc, void **oldfunc) |
618 |
|
|
{"set-symbol-lookup", &prom_service_set_symbol_lookup}, //; of_set_symbol_lookup(void *sym_to_value, void *value_to_sym) |
619 |
|
|
/* 6.3.2.7 Time */ |
620 |
|
|
{"milliseconds", &prom_service_milliseconds}, //; of_milliseconds(int *ms) |
621 |
|
|
{"get-msecs", &prom_service_milliseconds}, //; of_milliseconds(int *ms) |
622 |
|
|
{NULL, NULL} |
623 |
|
|
}; |
624 |
|
|
|
625 |
|
|
void call_prom_osi() |
626 |
|
|
{ |
627 |
|
|
prom_args pa; |
628 |
|
|
memset(&pa, 0, sizeof pa); |
629 |
|
|
uint32 pa_s = ppc_cpu_get_gpr(0, 3); |
630 |
|
|
uint32 phys; |
631 |
|
|
if (!ppc_prom_effective_to_physical(phys, pa_s) |
632 |
|
|
|| !ppc_dma_read(&pa.service, phys+0, 4) |
633 |
|
|
|| !ppc_dma_read(&pa.nargs, phys+4, 4) |
634 |
|
|
|| !ppc_dma_read(&pa.nret, phys+8, 4)) { |
635 |
|
|
IO_PROM_ERR("can't read memory at %08x-%08x\n", pa_s+0, pa_s+8); |
636 |
|
|
} |
637 |
|
|
pa.service = ppc_word_from_BE(pa.service); |
638 |
|
|
pa.nargs = ppc_word_from_BE(pa.nargs); |
639 |
|
|
pa.nret = ppc_word_from_BE(pa.nret); |
640 |
|
|
phys += 12; |
641 |
|
|
for (uint i=0; i<pa.nargs; i++) { |
642 |
|
|
if (!ppc_dma_read(&pa.args[i], phys, 4)) { |
643 |
|
|
IO_PROM_ERR("can't read memory at %08x\n", pa.args[i]); |
644 |
|
|
} |
645 |
|
|
pa.args[i] = ppc_word_from_BE(pa.args[i]); |
646 |
|
|
phys += 4; |
647 |
|
|
} |
648 |
|
|
String service; |
649 |
|
|
prom_get_string(service, pa.service); |
650 |
|
|
int i=0; |
651 |
|
|
while (prom_service_table[i].name) { |
652 |
|
|
if (strcmp(prom_service_table[i].name, service.contentChar())==0) { |
653 |
|
|
prom_service_table[i].f(&pa); |
654 |
|
|
goto ok; |
655 |
|
|
} |
656 |
|
|
i++; |
657 |
|
|
} |
658 |
|
|
// error |
659 |
|
|
IO_PROM_ERR("unknown service '%y'\n", &service); |
660 |
|
|
ok: |
661 |
|
|
// write values back |
662 |
|
|
pa_s = ppc_cpu_get_gpr(0, 3); |
663 |
|
|
pa_s += 12; |
664 |
|
|
for (uint i=0; i<(pa.nargs+pa.nret); i++) { |
665 |
|
|
uint32 phys; |
666 |
|
|
if (!ppc_prom_effective_to_physical(phys, pa_s)) { |
667 |
|
|
IO_PROM_ERR("can't write memory at %08x\n", pa.args[i]); |
668 |
|
|
} |
669 |
|
|
uint32 w = ppc_word_to_BE(pa.args[i]); |
670 |
|
|
if (!ppc_dma_write(phys, &w, 4)) { |
671 |
|
|
IO_PROM_ERR("can't write memory at %08x\n", pa.args[i]); |
672 |
|
|
} |
673 |
|
|
pa_s += 4; |
674 |
|
|
} |
675 |
|
|
ppc_cpu_set_gpr(0, 3, 0); |
676 |
|
|
// return |
677 |
|
|
// gCPU.npc = gCPU.lr; |
678 |
|
|
} |