Root/
Source at commit 1335 created 12 years 10 months ago. By azimutz, Old ati.c changes: - auto switch framebuffer according to OS version (pre/post 10.6.8) - add AtiConfig key, plus verbose messages - small "clean up" | |
---|---|
1 | /*␊ |
2 | * Copyright (c) 2000 Apple Computer, Inc. All rights reserved.␊ |
3 | *␊ |
4 | * @APPLE_LICENSE_HEADER_START@␊ |
5 | * ␊ |
6 | * The contents of this file constitute Original Code as defined in and␊ |
7 | * are subject to the Apple Public Source License Version 1.1 (the␊ |
8 | * "License"). You may not use this file except in compliance with the␊ |
9 | * License. Please obtain a copy of the License at␊ |
10 | * http://www.apple.com/publicsource and read it before using this file.␊ |
11 | * ␊ |
12 | * This Original Code and all software distributed under the License are␊ |
13 | * distributed on an "AS IS" basis, WITHOUT WARRANTY OF ANY KIND, EITHER␊ |
14 | * EXPRESS OR IMPLIED, AND APPLE HEREBY DISCLAIMS ALL SUCH WARRANTIES,␊ |
15 | * INCLUDING WITHOUT LIMITATION, ANY WARRANTIES OF MERCHANTABILITY,␊ |
16 | * FITNESS FOR A PARTICULAR PURPOSE OR NON-INFRINGEMENT. Please see the␊ |
17 | * License for the specific language governing rights and limitations␊ |
18 | * under the License.␊ |
19 | * ␊ |
20 | * @APPLE_LICENSE_HEADER_END@␊ |
21 | */␊ |
22 | /*␊ |
23 | * ci.c - Functions for accessing Open Firmware's Client Interface␊ |
24 | *␊ |
25 | * Copyright (c) 1998-2002 Apple Computer, Inc.␊ |
26 | *␊ |
27 | * DRI: Josh de Cesare␊ |
28 | */␊ |
29 | ␊ |
30 | #include <sl.h>␊ |
31 | ␊ |
32 | static ClientInterfacePtr gCIPtr;␊ |
33 | ␊ |
34 | long InitCI(ClientInterfacePtr ciPtr)␊ |
35 | {␊ |
36 | gCIPtr = ciPtr;␊ |
37 | ␊ |
38 | return 0;␊ |
39 | }␊ |
40 | ␊ |
41 | long CallCI(CIArgs *ciArgsPtr)␊ |
42 | {␊ |
43 | long ret;␊ |
44 | ␊ |
45 | ret = (*gCIPtr)(ciArgsPtr);␊ |
46 | return ret;␊ |
47 | }␊ |
48 | ␊ |
49 | ␊ |
50 | // Device Tree␊ |
51 | ␊ |
52 | // Peer take a phandle and returns the next peer.␊ |
53 | // It returns zero of there are no more peers.␊ |
54 | CICell Peer(CICell phandle)␊ |
55 | {␊ |
56 | CIArgs ciArgs;␊ |
57 | CICell peer_ph;␊ |
58 | long ret;␊ |
59 | ␊ |
60 | ciArgs.service = "peer";␊ |
61 | ciArgs.nArgs = 1;␊ |
62 | ciArgs.nReturns = 1;␊ |
63 | ciArgs.args.peer.phandle = phandle;␊ |
64 | ␊ |
65 | ret = CallCI(&ciArgs);␊ |
66 | if (ret != 0) return kCIError;␊ |
67 | ␊ |
68 | peer_ph = ciArgs.args.peer.peerPhandle;␊ |
69 | ␊ |
70 | return peer_ph;␊ |
71 | }␊ |
72 | ␊ |
73 | // Child take a phandle and returns the first child.␊ |
74 | // It returns zero of there in no child.␊ |
75 | CICell Child(CICell phandle)␊ |
76 | {␊ |
77 | CIArgs ciArgs;␊ |
78 | CICell child_ph;␊ |
79 | long ret;␊ |
80 | ␊ |
81 | ciArgs.service = "child";␊ |
82 | ciArgs.nArgs = 1;␊ |
83 | ciArgs.nReturns = 1;␊ |
84 | ciArgs.args.child.phandle = phandle;␊ |
85 | ␊ |
86 | ret = CallCI(&ciArgs);␊ |
87 | if (ret != 0) return kCIError;␊ |
88 | ␊ |
89 | child_ph = ciArgs.args.child.childPhandle;␊ |
90 | ␊ |
91 | return child_ph;␊ |
92 | }␊ |
93 | ␊ |
94 | // Parent take a phandle and returns the parent node.␊ |
95 | // It returns zero of if the phandle is the root node.␊ |
96 | CICell Parent(CICell phandle)␊ |
97 | {␊ |
98 | CIArgs ciArgs;␊ |
99 | CICell parent_ph;␊ |
100 | long ret;␊ |
101 | ␊ |
102 | ciArgs.service = "parent";␊ |
103 | ciArgs.nArgs = 1;␊ |
104 | ciArgs.nReturns = 1;␊ |
105 | ciArgs.args.parent.childPhandle = phandle;␊ |
106 | ␊ |
107 | ret = CallCI(&ciArgs);␊ |
108 | if (ret != 0) return kCIError;␊ |
109 | ␊ |
110 | parent_ph = ciArgs.args.parent.parentPhandle;␊ |
111 | ␊ |
112 | return parent_ph;␊ |
113 | }␊ |
114 | ␊ |
115 | // FindDevice take a device spec and returns the phandle.␊ |
116 | // It returns zero of if the device was not found.␊ |
117 | CICell FindDevice(char *devSpec)␊ |
118 | {␊ |
119 | CIArgs ciArgs;␊ |
120 | CICell phandle;␊ |
121 | long ret;␊ |
122 | ␊ |
123 | ciArgs.service = "finddevice";␊ |
124 | ciArgs.nArgs = 1;␊ |
125 | ciArgs.nReturns = 1;␊ |
126 | ciArgs.args.finddevice.devSpec = devSpec;␊ |
127 | ␊ |
128 | ret = CallCI(&ciArgs);␊ |
129 | if (ret != 0) return kCIError;␊ |
130 | ␊ |
131 | phandle = ciArgs.args.finddevice.phandle;␊ |
132 | ␊ |
133 | return phandle;␊ |
134 | }␊ |
135 | ␊ |
136 | // InstanceToPath take an ihandle, buf and buflen. Set the device path␊ |
137 | // to the package in buf upto buflen characters and returns the length␊ |
138 | // Length will be -1 if the ihandle is invalid.␊ |
139 | CICell InstanceToPath(CICell ihandle, char *buf, long buflen)␊ |
140 | {␊ |
141 | CIArgs ciArgs;␊ |
142 | CICell length;␊ |
143 | long ret;␊ |
144 | ␊ |
145 | ciArgs.service = "instance-to-path";␊ |
146 | ciArgs.nArgs = 3;␊ |
147 | ciArgs.nReturns = 1;␊ |
148 | ciArgs.args.instanceToPath.ihandle = ihandle;␊ |
149 | ciArgs.args.instanceToPath.buf = buf;␊ |
150 | ciArgs.args.instanceToPath.buflen = buflen;␊ |
151 | ␊ |
152 | ret = CallCI(&ciArgs);␊ |
153 | if (ret != 0) return kCIError;␊ |
154 | ␊ |
155 | length = ciArgs.args.instanceToPath.length;␊ |
156 | ␊ |
157 | return length;␊ |
158 | }␊ |
159 | ␊ |
160 | // InstanceToPackage take an ihandle and returns the phandle for it.␊ |
161 | // returns -1 if the phandle can't be found.␊ |
162 | CICell InstanceToPackage(CICell ihandle)␊ |
163 | {␊ |
164 | CIArgs ciArgs;␊ |
165 | CICell phandle;␊ |
166 | long ret;␊ |
167 | ␊ |
168 | ciArgs.service = "instance-to-package";␊ |
169 | ciArgs.nArgs = 1;␊ |
170 | ciArgs.nReturns = 1;␊ |
171 | ciArgs.args.instanceToPackage.ihandle = ihandle;␊ |
172 | ␊ |
173 | ret = CallCI(&ciArgs);␊ |
174 | if (ret != 0) return kCIError;␊ |
175 | ␊ |
176 | phandle = ciArgs.args.instanceToPackage.phandle;␊ |
177 | ␊ |
178 | return phandle;␊ |
179 | }␊ |
180 | ␊ |
181 | // InstanceToPackages␊ |
182 | ␊ |
183 | // PackageToPath take a phandle, buf and buflen. Set the device path␊ |
184 | // to the package in buf upto buflen characters and returns the length␊ |
185 | // Length will be -1 if the phandle is invalid.␊ |
186 | CICell PackageToPath(CICell phandle, char *buf, long buflen)␊ |
187 | {␊ |
188 | CIArgs ciArgs;␊ |
189 | CICell length;␊ |
190 | long ret;␊ |
191 | ␊ |
192 | if (gOFVersion >= kOFVersion2x) {␊ |
193 | ciArgs.service = "package-to-path";␊ |
194 | ciArgs.nArgs = 3;␊ |
195 | ciArgs.nReturns = 1;␊ |
196 | ciArgs.args.packageToPath.phandle = phandle;␊ |
197 | ciArgs.args.packageToPath.buf = buf;␊ |
198 | ciArgs.args.packageToPath.buflen = buflen;␊ |
199 | ␊ |
200 | ret = CallCI(&ciArgs);␊ |
201 | if (ret != 0) return kCIError;␊ |
202 | ␊ |
203 | length = ciArgs.args.packageToPath.length;␊ |
204 | } else {␊ |
205 | ret = CallMethod(3, 1, SLWordsIH, "slw_pwd", phandle,␊ |
206 | ␉␉ (CICell)buf, buflen, &length);␊ |
207 | if (ret != 0) return kCIError;␊ |
208 | ␊ |
209 | buf[length] = '\0';␊ |
210 | }␊ |
211 | ␊ |
212 | return length;␊ |
213 | }␊ |
214 | ␊ |
215 | // Canon␊ |
216 | ␊ |
217 | // GetPropLen takes a phandle and prop name␊ |
218 | // and returns the size of the property␊ |
219 | // or -1 if the property is not valid.␊ |
220 | CICell GetPropLen(CICell phandle, char *name)␊ |
221 | {␊ |
222 | CIArgs ciArgs;␊ |
223 | CICell size;␊ |
224 | long ret;␊ |
225 | ␊ |
226 | ciArgs.service = "getproplen";␊ |
227 | ciArgs.nArgs = 2;␊ |
228 | ciArgs.nReturns = 1;␊ |
229 | ciArgs.args.getproplen.phandle = phandle;␊ |
230 | ciArgs.args.getproplen.name = name;␊ |
231 | ␊ |
232 | ret = CallCI(&ciArgs);␊ |
233 | if (ret != 0) return kCIError;␊ |
234 | ␊ |
235 | size = ciArgs.args.getproplen.size;␊ |
236 | ␊ |
237 | return size;␊ |
238 | }␊ |
239 | ␊ |
240 | // GetProp takes a phandle, prop name, buffer and length␊ |
241 | // and copied the property value in to the buffer.␊ |
242 | // returns -1 if the property is not valid.␊ |
243 | CICell GetProp(CICell phandle, char *name, char *buf, long buflen)␊ |
244 | {␊ |
245 | CIArgs ciArgs;␊ |
246 | CICell size;␊ |
247 | long ret;␊ |
248 | ␊ |
249 | ciArgs.service = "getprop";␊ |
250 | ciArgs.nArgs = 4;␊ |
251 | ciArgs.nReturns = 1;␊ |
252 | ciArgs.args.getprop.phandle = phandle;␊ |
253 | ciArgs.args.getprop.name = name;␊ |
254 | ciArgs.args.getprop.buf = buf;␊ |
255 | ciArgs.args.getprop.buflen = buflen;␊ |
256 | ␊ |
257 | ret = CallCI(&ciArgs);␊ |
258 | if (ret != 0) return kCIError;␊ |
259 | ␊ |
260 | size = ciArgs.args.getprop.size;␊ |
261 | ␊ |
262 | return size;␊ |
263 | }␊ |
264 | ␊ |
265 | // NextProp takes a phandle, prev name, and a buffer␊ |
266 | // and copied the next property name in to the buffer.␊ |
267 | // returns -1 if the property is not valid.␊ |
268 | // returns 0 if the prev was the last property.␊ |
269 | // returns 1 otherwise.␊ |
270 | CICell NextProp(CICell phandle, char *previous, char *buf)␊ |
271 | {␊ |
272 | CIArgs ciArgs;␊ |
273 | CICell flag;␊ |
274 | long ret;␊ |
275 | ␊ |
276 | ciArgs.service = "nextprop";␊ |
277 | ciArgs.nArgs = 3;␊ |
278 | ciArgs.nReturns = 1;␊ |
279 | ciArgs.args.nextprop.phandle = phandle;␊ |
280 | ciArgs.args.nextprop.previous = previous;␊ |
281 | ciArgs.args.nextprop.buf = buf;␊ |
282 | ␊ |
283 | ret = CallCI(&ciArgs);␊ |
284 | if (ret != 0) return kCIError;␊ |
285 | ␊ |
286 | flag = ciArgs.args.nextprop.flag;␊ |
287 | ␊ |
288 | return flag;␊ |
289 | }␊ |
290 | ␊ |
291 | // SetProp takes a phandle, prop name, buffer and length␊ |
292 | // and copied the buffer in to the property value.␊ |
293 | // returns -1 if the property could not be set or created.␊ |
294 | CICell SetProp(CICell phandle, char *name, char *buf, long buflen)␊ |
295 | {␊ |
296 | CIArgs ciArgs;␊ |
297 | CICell size;␊ |
298 | long ret;␊ |
299 | ␊ |
300 | ciArgs.service = "setprop";␊ |
301 | ciArgs.nArgs = 4;␊ |
302 | ciArgs.nReturns = 1;␊ |
303 | ciArgs.args.setprop.phandle = phandle;␊ |
304 | ciArgs.args.setprop.name = name;␊ |
305 | ciArgs.args.setprop.buf = buf;␊ |
306 | ciArgs.args.setprop.buflen = buflen;␊ |
307 | ␊ |
308 | ret = CallCI(&ciArgs);␊ |
309 | if (ret != 0) return kCIError;␊ |
310 | ␊ |
311 | size = ciArgs.args.setprop.size;␊ |
312 | ␊ |
313 | return size;␊ |
314 | }␊ |
315 | ␊ |
316 | ␊ |
317 | // Device I/O␊ |
318 | ␊ |
319 | // Open takes a device specifier and returns an iHandle␊ |
320 | // It returns zero if the device can not be found or opened.␊ |
321 | CICell Open(char *devSpec)␊ |
322 | {␊ |
323 | CIArgs ciArgs;␊ |
324 | CICell ihandle;␊ |
325 | long ret;␊ |
326 | ␊ |
327 | ciArgs.service = "open";␊ |
328 | ciArgs.nArgs = 1;␊ |
329 | ciArgs.nReturns = 1;␊ |
330 | ciArgs.args.open.devSpec = devSpec;␊ |
331 | ␊ |
332 | ret = CallCI(&ciArgs);␊ |
333 | if (ret != 0) return 0;␊ |
334 | ␊ |
335 | ihandle = ciArgs.args.open.ihandle;␊ |
336 | ␊ |
337 | return ihandle;␊ |
338 | }␊ |
339 | ␊ |
340 | // Close takes an iHandle and closes the device.␊ |
341 | void Close(CICell ihandle)␊ |
342 | {␊ |
343 | CIArgs ciArgs;␊ |
344 | ␊ |
345 | ciArgs.service = "close";␊ |
346 | ciArgs.nArgs = 1;␊ |
347 | ciArgs.nReturns = 0;␊ |
348 | ciArgs.args.close.ihandle = ihandle;␊ |
349 | ␊ |
350 | CallCI(&ciArgs);␊ |
351 | }␊ |
352 | ␊ |
353 | // Read takes an iHandle, an address and a length and return the actual␊ |
354 | // Length read. Returns -1 if the operaction failed.␊ |
355 | CICell Read(CICell ihandle, long addr, long length)␊ |
356 | {␊ |
357 | CIArgs ciArgs;␊ |
358 | long actual;␊ |
359 | long ret;␊ |
360 | ␊ |
361 | ciArgs.service = "read";␊ |
362 | ciArgs.nArgs = 3;␊ |
363 | ciArgs.nReturns = 1;␊ |
364 | ciArgs.args.read.ihandle = ihandle;␊ |
365 | ciArgs.args.read.addr = addr;␊ |
366 | ciArgs.args.read.length = length;␊ |
367 | ␊ |
368 | ret = CallCI(&ciArgs);␊ |
369 | if (ret != 0) return kCIError;␊ |
370 | ␊ |
371 | actual = ciArgs.args.read.actual;␊ |
372 | ␊ |
373 | // Spin the wait cursor.␊ |
374 | Spin();␊ |
375 | ␊ |
376 | return actual;␊ |
377 | }␊ |
378 | ␊ |
379 | // Write takes an iHandle, an address and a length and return the actual␊ |
380 | // Length written. Returns -1 if the operaction failed.␊ |
381 | CICell Write(CICell ihandle, long addr, long length)␊ |
382 | {␊ |
383 | CIArgs ciArgs;␊ |
384 | long actual;␊ |
385 | long ret;␊ |
386 | ␊ |
387 | ciArgs.service = "write";␊ |
388 | ciArgs.nArgs = 3;␊ |
389 | ciArgs.nReturns = 1;␊ |
390 | ciArgs.args.write.ihandle = ihandle;␊ |
391 | ciArgs.args.write.addr = addr;␊ |
392 | ciArgs.args.write.length = length;␊ |
393 | ␊ |
394 | ret = CallCI(&ciArgs);␊ |
395 | if (ret != 0) return kCIError;␊ |
396 | ␊ |
397 | actual = ciArgs.args.write.actual;␊ |
398 | ␊ |
399 | return actual;␊ |
400 | }␊ |
401 | ␊ |
402 | // Seek takes an iHandle, and a 64 bit position␊ |
403 | // and moves to that address in file.␊ |
404 | // returns seeks result, or -1 if seek is not supported.␊ |
405 | CICell Seek(CICell ihandle, long long position)␊ |
406 | {␊ |
407 | CIArgs ciArgs;␊ |
408 | long ret;␊ |
409 | ␊ |
410 | ciArgs.service = "seek";␊ |
411 | ciArgs.nArgs = 3;␊ |
412 | ciArgs.nReturns = 1;␊ |
413 | ciArgs.args.seek.ihandle = ihandle;␊ |
414 | ciArgs.args.seek.pos_high = position >> 32;␊ |
415 | ciArgs.args.seek.pos_low = position & 0x00000000FFFFFFFFULL;␊ |
416 | ␊ |
417 | ret = CallCI(&ciArgs);␊ |
418 | if (ret != 0) return kCIError;␊ |
419 | ␊ |
420 | ret = ciArgs.args.seek.result;␊ |
421 | ␊ |
422 | return ret;␊ |
423 | }␊ |
424 | ␊ |
425 | ␊ |
426 | // Other Device Method Invocation␊ |
427 | ␊ |
428 | // Call the specified method on the given iHandle with the listed arguments.␊ |
429 | long CallMethod(long args, long rets, CICell iHandle, const char *method, ...)␊ |
430 | {␊ |
431 | va_list argList;␊ |
432 | CIArgs ciArgs;␊ |
433 | long ret, cnt, error = kCINoError;␊ |
434 | ␊ |
435 | va_start(argList, method);␊ |
436 | ␊ |
437 | ciArgs.service = "call-method";␊ |
438 | ciArgs.nArgs = args + 2;␊ |
439 | ciArgs.nReturns = rets + 1;␊ |
440 | ciArgs.args.callMethod.iHandle = iHandle;␊ |
441 | ciArgs.args.callMethod.method = method;␊ |
442 | ␊ |
443 | for (cnt = 0; cnt < args; cnt++) {␊ |
444 | ciArgs.args.callMethod.cells[args - cnt - 1] = va_arg(argList, CICell);␊ |
445 | }␊ |
446 | ␊ |
447 | ret = CallCI(&ciArgs);␊ |
448 | if (ret != 0) error = kCIError;␊ |
449 | else if (ciArgs.args.callMethod.cells[args] != 0) error = kCICatch;␊ |
450 | ␊ |
451 | if (error == kCINoError) {␊ |
452 | for (cnt = 0; cnt < rets; cnt++) {␊ |
453 | *(va_arg(argList, CICell *)) =␊ |
454 | ␉ciArgs.args.callMethod.cells[args + rets - cnt];␊ |
455 | }␊ |
456 | }␊ |
457 | ␊ |
458 | va_end(argList);␊ |
459 | ␊ |
460 | return error;␊ |
461 | }␊ |
462 | ␊ |
463 | ␊ |
464 | // Memory␊ |
465 | ␊ |
466 | // Claim takes a virt address, a size, and an alignment.␊ |
467 | // It return baseaddr or -1 for claim failed.␊ |
468 | CICell Claim(CICell virt, CICell size, CICell align)␊ |
469 | {␊ |
470 | CIArgs ciArgs;␊ |
471 | CICell baseaddr;␊ |
472 | long ret;␊ |
473 | ␊ |
474 | if (gOFVersion >= kOFVersion2x) {␊ |
475 | // Claim actually works, so use it.␊ |
476 | ciArgs.service = "claim";␊ |
477 | ciArgs.nArgs = 3;␊ |
478 | ciArgs.nReturns = 1;␊ |
479 | ciArgs.args.claim.virt = virt;␊ |
480 | ciArgs.args.claim.size = size;␊ |
481 | ciArgs.args.claim.align = align;␊ |
482 | ␊ |
483 | ret = CallCI(&ciArgs);␊ |
484 | if (ret != 0) return kCIError;␊ |
485 | ␊ |
486 | baseaddr = ciArgs.args.claim.baseaddr;␊ |
487 | } else {␊ |
488 | // Claim does not work. Do it by hand.␊ |
489 | if ((gMMUIH == 0) || (gMMUIH == 0)) return kCIError;␊ |
490 | ␊ |
491 | // Get the physical memory␊ |
492 | ret = CallMethod(3, 1, gMemoryIH, "claim", virt, size, 0, &baseaddr);␊ |
493 | if ((ret != kCINoError) || (virt != baseaddr)) return kCIError;␊ |
494 | ␊ |
495 | // Get the logical memory␊ |
496 | ret = CallMethod(3, 1, gMMUIH, "claim", virt, size, 0, &baseaddr);␊ |
497 | if ((ret != kCINoError) || (virt != baseaddr)) return kCIError;␊ |
498 | ␊ |
499 | // Map them together.␊ |
500 | ret = CallMethod(4, 0, gMMUIH, "map", virt, virt, size, 0);␊ |
501 | if (ret != kCINoError) return kCIError;␊ |
502 | }␊ |
503 | ␊ |
504 | return baseaddr;␊ |
505 | }␊ |
506 | ␊ |
507 | // Release takes a virt address, a size␊ |
508 | void Release(CICell virt, CICell size)␊ |
509 | {␊ |
510 | CIArgs ciArgs;␊ |
511 | ␊ |
512 | ciArgs.service = "release";␊ |
513 | ciArgs.nArgs = 2;␊ |
514 | ciArgs.nReturns = 0;␊ |
515 | ciArgs.args.claim.virt = virt;␊ |
516 | ciArgs.args.claim.size = size;␊ |
517 | ␊ |
518 | CallCI(&ciArgs);␊ |
519 | }␊ |
520 | ␊ |
521 | ␊ |
522 | // Control Transfer␊ |
523 | ␊ |
524 | // Boot trys to boot the bootspec␊ |
525 | void Boot(char *bootspec)␊ |
526 | {␊ |
527 | CIArgs ciArgs;␊ |
528 | ␊ |
529 | ciArgs.service = "boot";␊ |
530 | ciArgs.nArgs = 1;␊ |
531 | ciArgs.nReturns = 0;␊ |
532 | ciArgs.args.boot.bootspec = bootspec;␊ |
533 | ␊ |
534 | CallCI(&ciArgs);␊ |
535 | }␊ |
536 | ␊ |
537 | // Enter the user interface.␊ |
538 | // Executing the 'go' command returns to the client.␊ |
539 | void Enter(void)␊ |
540 | {␊ |
541 | CIArgs ciArgs;␊ |
542 | ␊ |
543 | ciArgs.service = "enter";␊ |
544 | ciArgs.nArgs = 0;␊ |
545 | ciArgs.nReturns = 0;␊ |
546 | ␊ |
547 | CallCI(&ciArgs);␊ |
548 | }␊ |
549 | ␊ |
550 | // Exit the client program.␊ |
551 | void Exit(void)␊ |
552 | {␊ |
553 | CIArgs ciArgs;␊ |
554 | ␊ |
555 | ciArgs.service = "exit";␊ |
556 | ciArgs.nArgs = 0;␊ |
557 | ciArgs.nReturns = 0;␊ |
558 | ␊ |
559 | CallCI(&ciArgs);␊ |
560 | }␊ |
561 | ␊ |
562 | // Clain␊ |
563 | ␊ |
564 | // Quiesce stops any async tasks in Open Firmware.␊ |
565 | void Quiesce(void)␊ |
566 | {␊ |
567 | CIArgs ciArgs;␊ |
568 | ␊ |
569 | ciArgs.service = "quiesce";␊ |
570 | ciArgs.nArgs = 0;␊ |
571 | ciArgs.nReturns = 0;␊ |
572 | ␊ |
573 | CallCI(&ciArgs);␊ |
574 | }␊ |
575 | ␊ |
576 | ␊ |
577 | // User Interface␊ |
578 | ␊ |
579 | // Interpret the given forth string with the listed arguments.␊ |
580 | long Interpret(long args, long rets, const char *forthString, ...)␊ |
581 | {␊ |
582 | va_list argList;␊ |
583 | CIArgs ciArgs;␊ |
584 | long ret, cnt, error = kCINoError;␊ |
585 | ␊ |
586 | va_start(argList, forthString);␊ |
587 | ␊ |
588 | ciArgs.service = "interpret";␊ |
589 | ciArgs.nArgs = args + 1;␊ |
590 | ciArgs.nReturns = rets + 1;␊ |
591 | ciArgs.args.interpret.forth = forthString;␊ |
592 | ␊ |
593 | for (cnt = 0; cnt < args; cnt++) {␊ |
594 | ciArgs.args.interpret.cells[args - cnt - 1] = va_arg(argList, CICell);␊ |
595 | }␊ |
596 | ␊ |
597 | ret = CallCI(&ciArgs);␊ |
598 | if (ret != 0) error = kCIError;␊ |
599 | else if (ciArgs.args.interpret.cells[args] != 0) error = kCICatch;␊ |
600 | ␊ |
601 | if (error == kCINoError) {␊ |
602 | for (cnt = 0; cnt < rets; cnt++) {␊ |
603 | *(va_arg(argList, CICell *)) =␊ |
604 | ␉ciArgs.args.interpret.cells[args + rets - cnt];␊ |
605 | }␊ |
606 | }␊ |
607 | ␊ |
608 | va_end(argList);␊ |
609 | ␊ |
610 | return error;␊ |
611 | }␊ |
612 |