/[gxemul]/trunk/src/promemul/of.c
This is repository of my old source code which isn't updated any more. Go to git.rot13.org for current projects!
ViewVC logotype

Annotation of /trunk/src/promemul/of.c

Parent Directory Parent Directory | Revision Log Revision Log


Revision 22 - (hide annotations)
Mon Oct 8 16:19:37 2007 UTC (16 years, 7 months ago) by dpavlin
File MIME type: text/plain
File size: 30626 byte(s)
++ trunk/HISTORY	(local)
$Id: HISTORY,v 1.1121 2006/02/18 21:03:08 debug Exp $
20051126	Cobalt and PReP now work with the 21143 NIC.
		Continuing on Alpha dyntrans things.
		Fixing some more left-shift-by-24 to unsigned.
20051127	Working on OpenFirmware emulation; major cleanup/redesign.
		Progress on MacPPC emulation: NetBSD detects two CPUs (when
		running with -n 2), framebuffer output (for text) works.
		Adding quick-hack Bandit PCI controller and "gc" interrupt
		controller for MacPPC.
20051128	Changing from a Bandit to a Uni-North controller for macppc.
		Continuing on OpenFirmware and MacPPC emulation in general
		(obio controller, and wdc attached to the obio seems to work).
20051129	More work on MacPPC emulation (adding a dummy ADB controller).
		Continuing the PCI bus cleanup (endianness and tag composition)
		and rewriting all PCI controllers' access functions.
20051130	Various minor PPC dyntrans optimizations.
		Manually inlining some parts of the framebuffer redraw routine.
		Slowly beginning the conversion of the old MIPS emulation into
		dyntrans (but this will take quite some time to get right).
		Generalizing quick_pc_to_pointers.
20051201	Documentation update (David Muse has made available a kernel
		which simplifies Debian/DECstation installation).
		Continuing on the ADB bus controller.
20051202	Beginning a rewrite of the Zilog serial controller (dev_zs).
20051203	Continuing on the zs rewrite (now called dev_z8530); conversion
		to devinit style.
		Reworking some of the input-only vs output-only vs input-output
		details of src/console.c, better warning messages, and adding
		a debug dump.
		Removing the concept of "device state"; it wasn't really used.
		Changing some debug output (-vv should now be used to show all
		details about devices and busses; not shown during normal
		startup anymore).
		Beginning on some SPARC instruction disassembly support.
20051204	Minor PPC updates (WALNUT skeleton stuff).
		Continuing on the MIPS dyntrans rewrite.
		More progress on the ADB controller (a keyboard is "detected"
		by NetBSD and OpenBSD).
		Downgrading OpenBSD/arc as a guest OS from "working" to
		"almost working" in the documentation.
		Progress on Algor emulation ("v3" PCI controller).
20051205	Minor updates.
20051207	Sorting devices according to address; this reduces complexity
		of device lookups from O(n) to O(log n) in memory_rw (but no
		real performance increase (yet) in experiments).
20051210	Beginning the work on native dyntrans backends (by making a
		simple skeleton; so far only for Alpha hosts).
20051211	Some very minor SPARC updates.
20051215	Fixing a bug in the MIPS mul (note: not mult) instruction,
		so it also works with non-64-bit emulation. (Thanks to Alec
		Voropay for noticing the problem.)
20051216	More work on the fake/empty/simple/skeleton/whatever backend;
		performance doesn't increase, so this isn't really worth it,
		but it was probably worth it to prepare for a real backend
		later.
20051219	More instr call statistics gathering and analysis stuff.
20051220	Another fix for MIPS 'mul'. Also converting mul and {d,}cl{o,z}
		to dyntrans.
		memory_ppc.c syntax error fix (noticed by Peter Valchev).
		Beginning to move out machines from src/machine.c into
		individual files in src/machines (in a way similar to the
		autodev system for devices).
20051222	Updating the documentation regarding NetBSD/pmax 3.0.
20051223	- " - NetBSD/cats 3.0.
20051225	- " - NetBSD/hpcmips 3.0.
20051226	Continuing on the machine registry redesign.
		Adding support for ARM rrx (33-bit rotate).
		Fixing some signed/unsigned issues (exposed by gcc -W).
20051227	Fixing the bug which prevented a NetBSD/prep 3.0 install kernel
		from starting (triggered when an mtmsr was the last instruction
		on a page). Unfortunately not enough to get the kernel to run
		as well as the 2.1 kernels did.
20051230	Some dyntrans refactoring.
20051231	Continuing on the machine registry redesign.
20060101-10	Continuing... moving more machines. Moving MD interrupt stuff
		from machine.c into a new src/machines/interrupts.c.
20060114	Adding various mvmeppc machine skeletons.
20060115	Continuing on mvme* stuff. NetBSD/mvmeppc prints boot messages
		(for MVME1600) and reaches the root device prompt, but no
		specific hardware devices are emulated yet.
20060116	Minor updates to the mvme1600 emulation mode; the Eagle PCI bus
		seems to work without much modification, and a 21143 can be
		detected, interrupts might work (but untested so far).
		Adding a fake MK48Txx (mkclock) device, for NetBSD/mvmeppc.
20060121	Adding an aux control register for ARM. (A BIG thank you to
		Olivier Houchard for tracking down this bug.)
20060122	Adding more ARM instructions (smulXY), and dev_iq80321_7seg.
20060124	Adding disassembly of more ARM instructions (mia*, mra/mar),
		and some semi-bogus XScale and i80321 registers.
20060201-02	Various minor updates. Moving the last machines out of
		machine.c.
20060204	Adding a -c command line option, for running debugger commands
		before the simulation starts, but after all files have been
		loaded.
		Minor iq80321-related updates.
20060209	Minor hacks (DEVINIT macro, etc).
		Preparing for the generalization of the 64-bit dyntrans address
		translation subsystem.
20060216	Adding ARM ldrd (double-register load).
20060217	Continuing on various ARM-related stuff.
20060218	More progress on the ATA/wdc emulation for NetBSD/iq80321.
		NetBSD/evbarm can now be installed :-)  Updating the docs, etc.
		Continuing on Algor emulation.

==============  RELEASE 0.3.8  ==============


1 dpavlin 14 /*
2 dpavlin 22 * Copyright (C) 2005-2006 Anders Gavare. All rights reserved.
3 dpavlin 14 *
4     * Redistribution and use in source and binary forms, with or without
5     * modification, are permitted provided that the following conditions are met:
6     *
7     * 1. Redistributions of source code must retain the above copyright
8     * notice, this list of conditions and the following disclaimer.
9     * 2. Redistributions in binary form must reproduce the above copyright
10     * notice, this list of conditions and the following disclaimer in the
11     * documentation and/or other materials provided with the distribution.
12     * 3. The name of the author may not be used to endorse or promote products
13     * derived from this software without specific prior written permission.
14     *
15     * THIS SOFTWARE IS PROVIDED BY THE AUTHOR AND CONTRIBUTORS ``AS IS'' AND
16     * ANY EXPRESS OR IMPLIED WARRANTIES, INCLUDING, BUT NOT LIMITED TO, THE
17     * IMPLIED WARRANTIES OF MERCHANTABILITY AND FITNESS FOR A PARTICULAR PURPOSE
18     * ARE DISCLAIMED. IN NO EVENT SHALL THE AUTHOR OR CONTRIBUTORS BE LIABLE
19     * FOR ANY DIRECT, INDIRECT, INCIDENTAL, SPECIAL, EXEMPLARY, OR CONSEQUENTIAL
20     * DAMAGES (INCLUDING, BUT NOT LIMITED TO, PROCUREMENT OF SUBSTITUTE GOODS
21     * OR SERVICES; LOSS OF USE, DATA, OR PROFITS; OR BUSINESS INTERRUPTION)
22     * HOWEVER CAUSED AND ON ANY THEORY OF LIABILITY, WHETHER IN CONTRACT, STRICT
23     * LIABILITY, OR TORT (INCLUDING NEGLIGENCE OR OTHERWISE) ARISING IN ANY WAY
24     * OUT OF THE USE OF THIS SOFTWARE, EVEN IF ADVISED OF THE POSSIBILITY OF
25     * SUCH DAMAGE.
26     *
27     *
28 dpavlin 22 * $Id: of.c,v 1.18 2006/02/16 05:57:10 debug Exp $
29 dpavlin 14 *
30     * OpenFirmware emulation.
31     *
32 dpavlin 22 * NOTE: OpenFirmware is used on quite a variety of different hardware archs,
33     * at least POWER/PowerPC, ARM, and SPARC, so the code in this module
34     * must always remain architecture agnostic.
35     *
36     * NOTE: Some things, e.g. 32-bit integers as returned by the "getprop"
37     * service, are always fixed to big-endian. (According to the standard.)
38     *
39     * TODO: o) 64-bit OpenFirmware?
40     * o) More devices...
41 dpavlin 14 */
42    
43     #include <stdio.h>
44     #include <stdlib.h>
45     #include <string.h>
46     #include <sys/types.h>
47    
48 dpavlin 22 #define OF_C
49    
50 dpavlin 14 #include "console.h"
51     #include "cpu.h"
52 dpavlin 22 #include "device.h"
53     #include "devices.h"
54     #include "diskimage.h"
55 dpavlin 14 #include "machine.h"
56     #include "memory.h"
57     #include "misc.h"
58 dpavlin 22 #include "of.h"
59 dpavlin 14
60    
61 dpavlin 22 /* #define debug fatal */
62 dpavlin 14
63     extern int quiet_mode;
64 dpavlin 22 extern int verbose;
65 dpavlin 14
66    
67     /*
68     * readstr():
69     *
70     * Helper function to read a string from emulated memory.
71     */
72     static void readstr(struct cpu *cpu, uint64_t addr, char *strbuf,
73     int bufsize)
74     {
75     int i;
76     for (i=0; i<bufsize; i++) {
77     unsigned char ch;
78     cpu->memory_rw(cpu, cpu->mem, addr + i,
79     &ch, sizeof(ch), MEM_READ, CACHE_DATA | NO_EXCEPTIONS);
80     strbuf[i] = '\0';
81     if (ch >= 1 && ch < 32)
82     ch = 0;
83     strbuf[i] = ch;
84     if (strbuf[i] == '\0')
85     break;
86     }
87    
88     strbuf[bufsize - 1] = '\0';
89     }
90    
91    
92     /*
93 dpavlin 22 * of_store_32bit_in_host():
94     *
95     * Store big-endian. OpenFirmware properties returned by getprop etc are
96     * always big-endian, even on little-endian machines.
97     */
98     static void of_store_32bit_in_host(unsigned char *d, uint32_t x)
99     {
100     d[0] = x >> 24; d[1] = x >> 16;
101     d[2] = x >> 8; d[3] = x;
102     }
103    
104    
105     /*
106     * find_device_handle():
107     *
108     * name may consist of multiple names, separaed with slashes.
109     */
110     static int find_device_handle(struct of_data *ofd, char *name)
111     {
112     int handle = 1, cur_parent = 1;
113    
114     if (name[0] == 0)
115     return 0;
116    
117     for (;;) {
118     struct of_device *od = ofd->of_devices;
119     char tmp[200];
120     int i;
121    
122     while (name[0] == '/')
123     name++;
124     if (name[0] == '\0')
125     break;
126     snprintf(tmp, sizeof(tmp), "%s", name);
127     i = 0;
128     while (tmp[i] != '\0' && tmp[i] != '/')
129     i++;
130     tmp[i] = '\0';
131    
132     OF_FIND(od, strcmp(od->name, tmp) == 0 &&
133     od->parent == cur_parent);
134     if (od == NULL)
135     return -1;
136    
137     handle = cur_parent = od->handle;
138     name += strlen(tmp);
139     }
140    
141     return handle;
142     }
143    
144    
145     /*****************************************************************************/
146    
147    
148     OF_SERVICE(call_method_2_2)
149     {
150     fatal("[ of: call_method_2_2('%s'): TODO ]\n", arg[0]);
151     return -1;
152     }
153    
154    
155     OF_SERVICE(call_method_3_4)
156     {
157     fatal("[ of: call_method_3_4('%s'): TODO ]\n", arg[0]);
158     return -1;
159     }
160    
161    
162     OF_SERVICE(call_method_5_2)
163     {
164     if (strcmp(arg[0], "set-colors") == 0) {
165     /* Used by OpenBSD/macppc: */
166     struct vfb_data *v = cpu->machine->of_data->vfb_data;
167     int color = OF_GET_ARG(3);
168     uint64_t ptr = OF_GET_ARG(4);
169     unsigned char rgb[3];
170     cpu->memory_rw(cpu, cpu->mem, ptr, rgb, 3, MEM_READ,
171     CACHE_DATA | NO_EXCEPTIONS);
172     if (v != NULL) {
173     memcpy(v->rgb_palette + 3 * color, rgb, 3);
174     v->update_x1 = v->update_y1 = 0;
175     v->update_x2 = v->xsize - 1;
176     v->update_y2 = v->ysize - 1;
177     }
178     } else {
179     fatal("[ of: call_method_5_2('%s'): TODO ]\n", arg[0]);
180     return -1;
181     }
182     return 0;
183     }
184    
185    
186     OF_SERVICE(call_method_6_1)
187     {
188     fatal("[ of: call_method_6_1('%s'): TODO ]\n", arg[0]);
189     return -1;
190     }
191    
192    
193     OF_SERVICE(call_method_6_2)
194     {
195     fatal("[ of: call_method_6_2('%s'): TODO ]\n", arg[0]);
196     return -1;
197     }
198    
199    
200     OF_SERVICE(child)
201     {
202     struct of_device *od = cpu->machine->of_data->of_devices;
203     int handle = OF_GET_ARG(0);
204     OF_FIND(od, od->parent == handle);
205     store_32bit_word(cpu, base + retofs, od == NULL? 0 : od->handle);
206     return 0;
207     }
208    
209    
210     OF_SERVICE(exit)
211     {
212     cpu->running = 0;
213     return 0;
214     }
215    
216    
217     OF_SERVICE(finddevice)
218     {
219     int h = find_device_handle(cpu->machine->of_data, arg[0]);
220     store_32bit_word(cpu, base + retofs, h);
221     return h>0? 0 : -1;
222     }
223    
224    
225     OF_SERVICE(getprop)
226     {
227     struct of_device *od = cpu->machine->of_data->of_devices;
228     struct of_device_property *pr;
229     int handle = OF_GET_ARG(0), i, len_returned = 0;
230     uint64_t buf = OF_GET_ARG(2);
231     uint64_t max = OF_GET_ARG(3);
232    
233     OF_FIND(od, od->handle == handle);
234     if (od == NULL) {
235     fatal("[ of: WARNING: getprop handle=%i; no such handle ]\n",
236     handle);
237     return -1;
238     }
239    
240     pr = od->properties;
241     OF_FIND(pr, strcmp(pr->name, arg[1]) == 0);
242     if (pr == NULL) {
243     fatal("[ of: WARNING: getprop: no property '%s' at handle"
244     " %i (device '%s') ]\n", arg[1], handle, od->name);
245     /* exit(1); */
246     return -1;
247     }
248    
249     if (pr->data == NULL) {
250     fatal("[ of: WARNING: property '%s' of '%s' has no data! ]\n",
251     arg[1], od->name);
252     goto ret;
253     }
254    
255     /* Return the property into emulated RAM: */
256     len_returned = pr->len <= max? pr->len : max;
257    
258     for (i=0; i<len_returned; i++) {
259     if (!cpu->memory_rw(cpu, cpu->mem, buf + i, pr->data + i,
260     1, MEM_WRITE, CACHE_DATA | NO_EXCEPTIONS)) {
261     fatal("[ of: getprop memory_rw() error ]\n");
262     exit(1);
263     }
264     }
265    
266     ret:
267     store_32bit_word(cpu, base + retofs, len_returned);
268     return 0;
269     }
270    
271    
272     OF_SERVICE(getproplen)
273     {
274     struct of_device *od = cpu->machine->of_data->of_devices;
275     struct of_device_property *pr;
276     int handle = OF_GET_ARG(0);
277    
278     OF_FIND(od, od->handle == handle);
279     if (od == NULL) {
280     fatal("[ of: WARNING: getproplen handle=%i; no such handle ]\n",
281     handle);
282     exit(1);
283     /* return -1; */
284     }
285    
286     pr = od->properties;
287     OF_FIND(pr, strcmp(pr->name, arg[1]) == 0);
288     if (pr == NULL) {
289     fatal("[ of: WARNING: getproplen: no property '%s' at handle"
290     " %i (device '%s') ]\n", arg[1], handle, od->name);
291     exit(1);
292     }
293    
294     store_32bit_word(cpu, base + retofs, pr->len);
295     return 0;
296     }
297    
298    
299     OF_SERVICE(instance_to_package)
300     {
301     int handle = OF_GET_ARG(0);
302     /* TODO: actually do something here? :-) */
303     store_32bit_word(cpu, base + retofs, handle);
304     return 0;
305     }
306    
307    
308     OF_SERVICE(interpret_1)
309     {
310     if (strcmp(arg[0], "#lines 2 - to line#") == 0) {
311     } else {
312     fatal("[ of: interpret_1('%s'): TODO ]\n", arg[0]);
313     return -1;
314     }
315     return 0;
316     }
317    
318    
319     OF_SERVICE(interpret_2)
320     {
321     store_32bit_word(cpu, base + retofs, 0); /* ? TODO */
322     if (strcmp(arg[0], "#columns") == 0) {
323     store_32bit_word(cpu, base + retofs + 4, 80);
324     } else if (strcmp(arg[0], "#lines") == 0) {
325     store_32bit_word(cpu, base + retofs + 4, 40);
326     } else if (strcmp(arg[0], "char-height") == 0) {
327     store_32bit_word(cpu, base + retofs + 4, 15);
328     } else if (strcmp(arg[0], "char-width") == 0) {
329     store_32bit_word(cpu, base + retofs + 4, 10);
330     } else if (strcmp(arg[0], "line#") == 0) {
331     store_32bit_word(cpu, base + retofs + 4, 0);
332     } else if (strcmp(arg[0], "font-adr") == 0) {
333     store_32bit_word(cpu, base + retofs + 4, 0);
334     } else {
335     fatal("[ of: interpret_2('%s'): TODO ]\n", arg[0]);
336     return -1;
337     }
338     return 0;
339     }
340    
341    
342     OF_SERVICE(package_to_path)
343     {
344     fatal("[ of: package-to-path: TODO ]\n");
345     return -1;
346     }
347    
348    
349     OF_SERVICE(parent)
350     {
351     struct of_device *od = cpu->machine->of_data->of_devices;
352     int handle = OF_GET_ARG(0);
353     OF_FIND(od, od->handle == handle);
354     store_32bit_word(cpu, base + retofs, od == NULL? 0 : od->parent);
355     return 0;
356     }
357    
358    
359     OF_SERVICE(peer)
360     {
361     struct of_device *od = cpu->machine->of_data->of_devices;
362     int handle = OF_GET_ARG(0), parent = 0, peer = 0, seen_self = 1;
363    
364     if (handle == 0) {
365     /* Return the handle of the root node (1): */
366     store_32bit_word(cpu, base + retofs, 1);
367     return 0;
368     }
369    
370     OF_FIND(od, od->handle == handle);
371     if (od == NULL) {
372     fatal("[ of: peer(): can't find handle %i ]\n", handle);
373     exit(1);
374     }
375     parent = od->parent;
376     seen_self = 0;
377    
378     od = cpu->machine->of_data->of_devices;
379    
380     while (od != NULL) {
381     if (od->parent == parent) {
382     if (seen_self) {
383     peer = od->handle;
384     break;
385     }
386     if (od->handle == handle)
387     seen_self = 1;
388     }
389     od = od->next;
390     }
391     store_32bit_word(cpu, base + retofs, peer);
392     return 0;
393     }
394    
395    
396     OF_SERVICE(read)
397     {
398     /* int handle = OF_GET_ARG(0); */
399     uint64_t ptr = OF_GET_ARG(1);
400     /* int len = OF_GET_ARG(2); */
401     int c;
402     unsigned char ch;
403    
404     /* TODO: check handle! This just reads chars from the console! */
405     /* TODO: This is blocking! */
406    
407     c = console_readchar(cpu->machine->main_console_handle);
408     ch = c;
409     if (!cpu->memory_rw(cpu, cpu->mem, ptr, &ch, 1, MEM_WRITE,
410     CACHE_DATA | NO_EXCEPTIONS)) {
411     fatal("[ of: read: memory_rw() error ]\n");
412     exit(1);
413     }
414    
415     store_32bit_word(cpu, base + retofs, c == -1? 0 : 1);
416     return c == -1? -1 : 0;
417     }
418    
419    
420     OF_SERVICE(write)
421     {
422     /* int handle = OF_GET_ARG(0); */
423     uint64_t ptr = OF_GET_ARG(1);
424     int n_written = 0, i, len = OF_GET_ARG(2);
425    
426     /* TODO: check handle! This just dumps the data to the console! */
427    
428     for (i=0; i<len; i++) {
429     unsigned char ch;
430     if (!cpu->memory_rw(cpu, cpu->mem, ptr + i, &ch,
431     1, MEM_READ, CACHE_DATA | NO_EXCEPTIONS)) {
432     fatal("[ of: write: memory_rw() error ]\n");
433     exit(1);
434     }
435     if (ch != 7)
436     console_putchar(cpu->machine->main_console_handle, ch);
437     n_written ++;
438     }
439    
440     store_32bit_word(cpu, base + retofs, n_written);
441     return 0;
442     }
443    
444    
445     /*****************************************************************************/
446    
447    
448     /*
449     * of_get_unused_device_handle():
450     *
451     * Returns an unused device handle number (1 or higher).
452     */
453     static int of_get_unused_device_handle(struct of_data *of_data)
454     {
455     int max_handle = 0;
456     struct of_device *od = of_data->of_devices;
457    
458     while (od != NULL) {
459     if (od->handle > max_handle)
460     max_handle = od->handle;
461     od = od->next;
462     }
463    
464     return max_handle + 1;
465     }
466    
467    
468     /*
469     * of_add_device():
470     *
471     * Adds a device.
472     */
473     static struct of_device *of_add_device(struct of_data *of_data, char *name,
474     char *parentname)
475     {
476     struct of_device *od = malloc(sizeof(struct of_device));
477     if (od == NULL)
478     goto bad;
479     memset(od, 0, sizeof(struct of_device));
480    
481     od->name = strdup(name);
482     if (od->name == NULL)
483     goto bad;
484    
485     od->handle = of_get_unused_device_handle(of_data);
486     od->parent = find_device_handle(of_data, parentname);
487     if (od->parent < 0) {
488     fatal("of_add_device(): adding '%s' to parent '%s' failed: "
489     "parent not found!\n", name, parentname);
490     exit(1);
491     }
492    
493     od->next = of_data->of_devices;
494     of_data->of_devices = od;
495     return od;
496    
497     bad:
498     fatal("of_add_device(): out of memory\n");
499     exit(1);
500     }
501    
502    
503     /*
504     * of_add_prop():
505     *
506     * Adds a property to a device.
507     */
508     static void of_add_prop(struct of_data *of_data, char *devname,
509     char *propname, unsigned char *data, uint32_t len, int flags)
510     {
511     struct of_device_property *pr =
512     malloc(sizeof(struct of_device_property));
513     struct of_device *od = of_data->of_devices;
514     int h = find_device_handle(of_data, devname);
515    
516     OF_FIND(od, od->handle == h);
517     if (od == NULL) {
518     fatal("of_add_prop(): device '%s' not registered\n", devname);
519     exit(1);
520     }
521    
522     if (pr == NULL)
523     goto bad;
524     memset(pr, 0, sizeof(struct of_device_property));
525    
526     pr->name = strdup(propname);
527     if (pr->name == NULL)
528     goto bad;
529     pr->data = data;
530     pr->len = len;
531     pr->flags = flags;
532    
533     pr->next = od->properties;
534     od->properties = pr;
535     return;
536    
537     bad:
538     fatal("of_add_device(): out of memory\n");
539     exit(1);
540     }
541    
542    
543     /*
544     * of_add_service():
545     *
546     * Adds a service.
547     */
548     static void of_add_service(struct of_data *of_data, char *name,
549     int (*f)(OF_SERVICE_ARGS), int n_args, int n_ret_args)
550     {
551     struct of_service *os = malloc(sizeof(struct of_service));
552     if (os == NULL)
553     goto bad;
554     memset(os, 0, sizeof(struct of_service));
555    
556     os->name = strdup(name);
557     if (os->name == NULL)
558     goto bad;
559    
560     os->f = f;
561     os->n_args = n_args;
562     os->n_ret_args = n_ret_args;
563    
564     os->next = of_data->of_services;
565     of_data->of_services = os;
566     return;
567    
568     bad:
569     fatal("of_add_service(): out of memory\n");
570     exit(1);
571     }
572    
573    
574     /*
575     * of_dump_devices():
576     *
577     * Debug dump helper.
578     */
579     static void of_dump_devices(struct of_data *ofd, int parent)
580     {
581     int iadd = DEBUG_INDENTATION;
582     struct of_device *od = ofd->of_devices;
583    
584     while (od != NULL) {
585     struct of_device_property *pr = od->properties;
586     if (od->parent != parent) {
587     od = od->next;
588     continue;
589     }
590     debug("\"%s\"\n", od->name, od->handle);
591     debug_indentation(iadd);
592     while (pr != NULL) {
593     debug("(%s: ", pr->name);
594     if (pr->flags == OF_PROP_STRING)
595     debug("\"%s\"", pr->data);
596     else
597     debug("%i bytes", pr->len);
598     debug(")\n");
599     pr = pr->next;
600     }
601     of_dump_devices(ofd, od->handle);
602     debug_indentation(-iadd);
603     od = od->next;
604     }
605     }
606    
607    
608     /*
609     * of_dump_all():
610     *
611     * Debug dump.
612     */
613     static void of_dump_all(struct of_data *ofd)
614     {
615     int iadd = DEBUG_INDENTATION;
616     struct of_service *os;
617    
618     debug("openfirmware debug dump:\n");
619     debug_indentation(iadd);
620    
621     /* Devices: */
622     of_dump_devices(ofd, 0);
623    
624     /* Services: */
625     os = ofd->of_services;
626     while (os != NULL) {
627     debug("service '%s'", os->name);
628     if (os->n_ret_args > 0 || os->n_args > 0) {
629     debug(" (");
630     if (os->n_args > 0) {
631     debug("%i arg%s", os->n_args,
632     os->n_args > 1? "s" : "");
633     if (os->n_ret_args > 0)
634     debug(", ");
635     }
636     if (os->n_ret_args > 0)
637     debug("%i return value%s", os->n_ret_args,
638     os->n_ret_args > 1? "s" : "");
639     debug(")");
640     }
641     debug("\n");
642     os = os->next;
643     }
644    
645     debug_indentation(-iadd);
646     }
647    
648    
649     /*
650     * of_add_prop_int32():
651     *
652     * Helper function.
653     */
654     static void of_add_prop_int32(struct of_data *ofd,
655     char *devname, char *propname, uint32_t x)
656     {
657     unsigned char *p = malloc(sizeof(int32_t));
658     if (p == NULL) {
659     fatal("of_add_prop_int32(): out of memory\n");
660     exit(1);
661     }
662     of_store_32bit_in_host(p, x);
663     of_add_prop(ofd, devname, propname, p, sizeof(int32_t),
664     OF_PROP_INT);
665     }
666    
667    
668     /*
669     * of_add_prop_str():
670     *
671     * Helper function.
672     */
673     static void of_add_prop_str(struct machine *machine, struct of_data *ofd,
674     char *devname, char *propname, char *data)
675     {
676     char *p = strdup(data);
677     if (p == NULL) {
678     fatal("of_add_prop_str(): out of memory\n");
679     exit(1);
680     }
681    
682     of_add_prop(ofd, devname, propname, (unsigned char *)p, strlen(p) + 1,
683     OF_PROP_STRING);
684     }
685    
686    
687     /*
688     * of_emul_init_isa():
689     */
690     void of_emul_init_isa(struct machine *machine)
691     {
692     struct of_data *ofd = machine->of_data;
693     unsigned char *isa_ranges;
694    
695     of_add_device(ofd, "isa", "/");
696     isa_ranges = malloc(32);
697     if (isa_ranges == NULL)
698     goto bad;
699     memset(isa_ranges, 0, 32);
700     /* 2 *: isa_phys_hi, isa_phys_lo, parent_phys_start, size */
701     /* MEM space: */
702     of_store_32bit_in_host(isa_ranges + 0, 0);
703     of_store_32bit_in_host(isa_ranges + 4, 0xc0000000);
704     /* I/O space: low bit if isa_phys_hi set */
705     of_store_32bit_in_host(isa_ranges + 16, 1);
706     of_store_32bit_in_host(isa_ranges + 20, 0xd0000000);
707    
708     of_add_prop(ofd, "/isa", "ranges", isa_ranges, 32, 0);
709    
710     return;
711    
712     bad:
713     fatal("of_emul_init_isa(): out of memory\n");
714     exit(1);
715     }
716    
717    
718     /*
719     * of_emul_init_adb():
720     */
721     void of_emul_init_adb(struct machine *machine)
722     {
723     struct of_data *ofd = machine->of_data;
724     unsigned char *adb_interrupts, *adb_reg;
725    
726     adb_interrupts = malloc(4 * sizeof(uint32_t));
727     adb_reg = malloc(8 * sizeof(uint32_t));
728     if (adb_interrupts == NULL || adb_reg == NULL)
729     goto bad;
730    
731     of_add_device(ofd, "adb", "/bandit/gc");
732     of_add_prop_str(machine, ofd, "/bandit/gc/adb", "name", "via-cuda");
733     of_store_32bit_in_host(adb_interrupts + 0, 25);
734     of_store_32bit_in_host(adb_interrupts + 4, 0);
735     of_store_32bit_in_host(adb_interrupts + 8, 0);
736     of_store_32bit_in_host(adb_interrupts + 12, 0);
737     of_add_prop(ofd, "/bandit/gc/adb", "interrupts", adb_interrupts,
738     4*sizeof(uint32_t), 0);
739     of_store_32bit_in_host(adb_reg + 0, 0x16000);
740     of_store_32bit_in_host(adb_reg + 4, 0x2000);
741     of_store_32bit_in_host(adb_reg + 8, 0);
742     of_store_32bit_in_host(adb_reg + 12, 0);
743     of_store_32bit_in_host(adb_reg + 16, 0);
744     of_store_32bit_in_host(adb_reg + 20, 0);
745     of_store_32bit_in_host(adb_reg + 24, 0);
746     of_store_32bit_in_host(adb_reg + 28, 0);
747     of_add_prop(ofd, "/bandit/gc/adb", "reg", adb_reg,
748     8*sizeof(uint32_t), 0);
749    
750     return;
751    
752     bad:
753     fatal("of_emul_init_adb(): out of memory\n");
754     exit(1);
755     }
756    
757    
758     /*
759     * of_emul_init_zs():
760     */
761     void of_emul_init_zs(struct machine *machine)
762     {
763     struct of_data *ofd = machine->of_data;
764     unsigned char *zs_interrupts, *zs_reg;
765    
766     zs_reg = malloc(6 * sizeof(uint32_t));
767     if (zs_reg == NULL)
768     goto bad;
769    
770     /* The controller: */
771     of_add_device(ofd, "zs", "/bandit/gc");
772     of_add_prop_str(machine, ofd, "/bandit/gc/zs", "device_type", "serial");
773     of_add_prop_str(machine, ofd, "/bandit/gc/zs", "name", "escc");
774     of_store_32bit_in_host(zs_reg + 0, 0x13000);
775     of_store_32bit_in_host(zs_reg + 4, 0x40);
776     of_store_32bit_in_host(zs_reg + 8, 0x100);
777     of_store_32bit_in_host(zs_reg + 12, 0x100);
778     of_store_32bit_in_host(zs_reg + 16, 0x200);
779     of_store_32bit_in_host(zs_reg + 20, 0x100);
780     of_add_prop(ofd, "/bandit/gc/zs", "reg", zs_reg, 6*sizeof(uint32_t), 0);
781    
782     /* Port 1: */
783     zs_interrupts = malloc(3 * sizeof(uint32_t));
784     zs_reg = malloc(6 * sizeof(uint32_t));
785     if (zs_interrupts == NULL || zs_reg == NULL)
786     goto bad;
787    
788     of_add_device(ofd, "zstty1", "/bandit/gc/zs");
789     of_add_prop_str(machine, ofd, "/bandit/gc/zs/zstty1", "name", "ch-a");
790     of_store_32bit_in_host(zs_interrupts + 0, 16);
791     of_store_32bit_in_host(zs_interrupts + 4, 0);
792     of_store_32bit_in_host(zs_interrupts + 8, 0);
793     of_add_prop(ofd, "/bandit/gc/zs/zstty1", "interrupts", zs_interrupts,
794     3*sizeof(uint32_t), 0);
795     of_store_32bit_in_host(zs_reg + 0, 0x13800);
796     of_store_32bit_in_host(zs_reg + 4, 0x100);
797     of_store_32bit_in_host(zs_reg + 8, 0x100);
798     of_store_32bit_in_host(zs_reg + 12, 0x100);
799     of_store_32bit_in_host(zs_reg + 16, 0x200);
800     of_store_32bit_in_host(zs_reg + 20, 0x100);
801     of_add_prop(ofd, "/bandit/gc/zs/zstty1",
802     "reg", zs_reg, 6*sizeof(uint32_t), 0);
803    
804     /* Port 0: */
805     zs_interrupts = malloc(3 * sizeof(uint32_t));
806     zs_reg = malloc(6 * sizeof(uint32_t));
807     if (zs_interrupts == NULL || zs_reg == NULL)
808     goto bad;
809    
810     of_add_device(ofd, "zstty0", "/bandit/gc/zs");
811     of_add_prop_str(machine, ofd, "/bandit/gc/zs/zstty0", "name", "ch-b");
812     of_store_32bit_in_host(zs_interrupts + 0, 15);
813     of_store_32bit_in_host(zs_interrupts + 4, 0);
814     of_store_32bit_in_host(zs_interrupts + 8, 0);
815     of_add_prop(ofd, "/bandit/gc/zs/zstty0", "interrupts", zs_interrupts,
816     3*sizeof(uint32_t), 0);
817     of_store_32bit_in_host(zs_reg + 0, 0x13400);
818     of_store_32bit_in_host(zs_reg + 4, 0x100);
819     of_store_32bit_in_host(zs_reg + 8, 0x100);
820     of_store_32bit_in_host(zs_reg + 12, 0x100);
821     of_store_32bit_in_host(zs_reg + 16, 0x200);
822     of_store_32bit_in_host(zs_reg + 20, 0x100);
823     of_add_prop(ofd, "/bandit/gc/zs/zstty0",
824     "reg", zs_reg, 6*sizeof(uint32_t), 0);
825    
826     return;
827    
828     bad:
829     fatal("of_emul_init_zs(): out of memory\n");
830     exit(1);
831     }
832    
833    
834     /*
835     * of_emul_init_uninorth():
836     */
837     void of_emul_init_uninorth(struct machine *machine)
838     {
839     struct of_data *ofd = machine->of_data;
840     unsigned char *uninorth_reg, *uninorth_bus_range, *uninorth_ranges;
841     unsigned char *macio_aa, *ata_interrupts, *ata_reg;
842     struct of_device *ic;
843     char *n = "pci@e2000000";
844     char *macio = "mac-io";
845    
846     of_add_device(ofd, n, "/");
847     of_add_prop_str(machine, ofd, n, "name", "pci");
848     of_add_prop_str(machine, ofd, n, "device_type", "pci");
849     of_add_prop_str(machine, ofd, n, "compatible", "uni-north");
850    
851     uninorth_reg = malloc(2 * sizeof(uint32_t));
852     uninorth_bus_range = malloc(2 * sizeof(uint32_t));
853     uninorth_ranges = malloc(12 * sizeof(uint32_t));
854     macio_aa = malloc(5 * sizeof(uint32_t));
855     ata_interrupts = malloc(6 * sizeof(uint32_t));
856     ata_reg = malloc(8 * sizeof(uint32_t));
857     if (uninorth_ranges == NULL || uninorth_bus_range == NULL ||
858     uninorth_reg == NULL || macio_aa == NULL ||
859     ata_interrupts == NULL || ata_reg == NULL)
860     goto bad;
861    
862     of_store_32bit_in_host(uninorth_reg + 0, 0xe2000000);
863     of_store_32bit_in_host(uninorth_reg + 4, 0); /* not used? */
864     of_add_prop(ofd, n, "reg", uninorth_reg, 2*sizeof(uint32_t), 0);
865    
866     of_store_32bit_in_host(uninorth_bus_range + 0, 0);
867     of_store_32bit_in_host(uninorth_bus_range + 4, 0);
868     of_add_prop(ofd, n, "bus-range", uninorth_bus_range,
869     2*sizeof(uint32_t), 0);
870    
871     /* MEM: */
872     of_store_32bit_in_host(uninorth_ranges + 0, 0x02000000);
873     of_store_32bit_in_host(uninorth_ranges + 4, 0);
874     of_store_32bit_in_host(uninorth_ranges + 8, 0);
875     of_store_32bit_in_host(uninorth_ranges + 12, 0xd0000000);
876     of_store_32bit_in_host(uninorth_ranges + 16, 0);
877     of_store_32bit_in_host(uninorth_ranges + 20, 0x04000000);
878     /* IO: */
879     of_store_32bit_in_host(uninorth_ranges + 24, 0x01000000);
880     of_store_32bit_in_host(uninorth_ranges + 28, 0);
881     of_store_32bit_in_host(uninorth_ranges + 32, 0);
882     of_store_32bit_in_host(uninorth_ranges + 36, 0xe2000000);
883     of_store_32bit_in_host(uninorth_ranges + 40, 0);
884     of_store_32bit_in_host(uninorth_ranges + 44, 0x01000000);
885     of_add_prop(ofd, n, "ranges", uninorth_ranges,
886     12*sizeof(uint32_t), 0);
887    
888     ic = of_add_device(ofd, macio, "/");
889     memset(macio_aa, 0, 20);
890     of_store_32bit_in_host(macio_aa + 0, 15 << 11); /* pci tag */
891     of_store_32bit_in_host(macio_aa + 8, 0xf3000000);
892     of_add_prop(ofd, macio, "assigned-addresses", macio_aa,
893     5*sizeof(uint32_t), 0);
894     /* of_add_prop(ofd, n, "assigned-addresses", macio_aa,
895     5*sizeof(uint32_t), 0); */
896     of_add_prop_int32(ofd, "/chosen", "interrupt-controller", ic->handle);
897    
898     of_add_device(ofd, "bandit", "/");
899     of_add_device(ofd, "gc", "/bandit");
900     of_add_prop(ofd, "/bandit/gc", "assigned-addresses", macio_aa,
901     5*sizeof(uint32_t), 0);
902    
903     if (diskimage_exist(machine, 0, DISKIMAGE_IDE) ||
904     diskimage_exist(machine, 1, DISKIMAGE_IDE)) {
905     of_add_device(ofd, "ata", "/bandit/gc");
906     of_add_prop_str(machine, ofd, "/bandit/gc/ata", "name", "ata");
907     of_add_prop_str(machine, ofd, "/bandit/gc/ata", "compatible",
908     "heathrow-ata");
909     of_store_32bit_in_host(ata_interrupts + 0, 13);
910     of_store_32bit_in_host(ata_interrupts + 4, 0);
911     of_store_32bit_in_host(ata_interrupts + 8, 0);
912     of_store_32bit_in_host(ata_interrupts + 12, 0);
913     of_store_32bit_in_host(ata_interrupts + 16, 0);
914     of_store_32bit_in_host(ata_interrupts + 20, 0);
915     of_add_prop(ofd, "/bandit/gc/ata", "interrupts", ata_interrupts,
916     6*sizeof(uint32_t), 0);
917     of_store_32bit_in_host(ata_reg + 0, 0x20000);
918     of_store_32bit_in_host(ata_reg + 4, 0);
919     of_store_32bit_in_host(ata_reg + 8, 0x21000);
920     of_store_32bit_in_host(ata_reg + 12, 0x22000);
921     of_store_32bit_in_host(ata_reg + 16, 0);
922     of_store_32bit_in_host(ata_reg + 20, 0);
923     of_store_32bit_in_host(ata_reg + 24, 0);
924     of_store_32bit_in_host(ata_reg + 28, 0);
925     of_add_prop(ofd, "/bandit/gc/ata", "reg", ata_reg,
926     8*sizeof(uint32_t), 0);
927     device_add(machine, "wdc addr=0xf3020000 irq=21 "
928     "addr_mult=0x10");
929     }
930    
931     return;
932    
933     bad:
934     fatal("of_emul_init_uninorth(): out of memory\n");
935     exit(1);
936     }
937    
938    
939     /*
940     * of_emul_init():
941     *
942     * This function creates an OpenFirmware emulation instance.
943     */
944     struct of_data *of_emul_init(struct machine *machine, struct vfb_data *vfb_data,
945     uint64_t fb_addr, int fb_xsize, int fb_ysize)
946     {
947     unsigned char *memory_reg, *memory_av;
948     unsigned char *zs_assigned_addresses;
949     struct of_device *mmu, *devstdout, *devstdin;
950     struct of_data *ofd = malloc(sizeof(struct of_data));
951     int i;
952    
953     if (ofd == NULL)
954     goto bad;
955     memset(ofd, 0, sizeof(struct of_data));
956    
957     ofd->vfb_data = vfb_data;
958    
959     /* Devices: */
960    
961     /* Root = device 1 */
962     of_add_device(ofd, "", "");
963    
964     of_add_device(ofd, "io", "/");
965     devstdin = of_add_device(ofd, "stdin", "/io");
966     devstdout = of_add_device(ofd, "stdout", "/io");
967    
968     if (machine->use_x11) {
969     fatal("!\n! TODO: keyboard + framebuffer for MacPPC\n!\n");
970    
971     of_add_prop_str(machine, ofd, "/io/stdin", "name",
972     "keyboard");
973     of_add_prop_str(machine, ofd, "/io", "name", "adb");
974    
975     of_add_prop_str(machine, ofd, "/io/stdout", "device_type",
976     "display");
977     of_add_prop_int32(ofd, "/io/stdout", "width", fb_xsize);
978     of_add_prop_int32(ofd, "/io/stdout", "height", fb_ysize);
979     of_add_prop_int32(ofd, "/io/stdout", "linebytes", fb_xsize * 1);
980     of_add_prop_int32(ofd, "/io/stdout", "depth", 8);
981     of_add_prop_int32(ofd, "/io/stdout", "address", fb_addr);
982     } else {
983     zs_assigned_addresses = malloc(12);
984     if (zs_assigned_addresses == NULL)
985     goto bad;
986     memset(zs_assigned_addresses, 0, 12);
987     of_add_prop_str(machine, ofd, "/io/stdin", "name", "ch-b");
988     of_add_prop_str(machine, ofd, "/io/stdin", "device_type",
989     "serial");
990     of_add_prop_int32(ofd, "/io/stdin", "reg", 0xf3013000);
991     of_add_prop(ofd, "/io/stdin", "assigned-addresses",
992     zs_assigned_addresses, 12, 0);
993    
994     of_add_prop_str(machine, ofd, "/io/stdout", "device_type",
995     "serial");
996     }
997    
998     of_add_device(ofd, "cpus", "/");
999     for (i=0; i<machine->ncpus; i++) {
1000     char tmp[50];
1001     snprintf(tmp, sizeof(tmp), "@%x", i);
1002     of_add_device(ofd, tmp, "/cpus");
1003     snprintf(tmp, sizeof(tmp), "/cpus/@%x", i);
1004     of_add_prop_str(machine, ofd, tmp, "device_type", "cpu");
1005     of_add_prop_int32(ofd, tmp, "timebase-frequency",
1006     machine->emulated_hz / 4);
1007     of_add_prop_int32(ofd, tmp, "clock-frequency",
1008     machine->emulated_hz);
1009     of_add_prop_int32(ofd, tmp, "reg", i);
1010     }
1011    
1012     mmu = of_add_device(ofd, "mmu", "/");
1013    
1014     /* TODO: */
1015     of_add_prop(ofd, "/mmu", "translations", NULL, 0, 0);
1016    
1017     of_add_device(ofd, "chosen", "/");
1018     of_add_prop_int32(ofd, "/chosen", "mmu", mmu->handle);
1019     of_add_prop_int32(ofd, "/chosen", "stdin", devstdin->handle);
1020     of_add_prop_int32(ofd, "/chosen", "stdout", devstdout->handle);
1021    
1022     of_add_device(ofd, "memory", "/");
1023     memory_reg = malloc(2 * sizeof(uint32_t));
1024     memory_av = malloc(2 * sizeof(uint32_t));
1025     if (memory_reg == NULL || memory_av == NULL)
1026     goto bad;
1027     of_store_32bit_in_host(memory_reg + 0, 0);
1028     of_store_32bit_in_host(memory_reg + 4, machine->physical_ram_in_mb<<20);
1029     of_store_32bit_in_host(memory_av + 0, 10 << 20);
1030     of_store_32bit_in_host(memory_av + 4,
1031     (machine->physical_ram_in_mb - 10) << 20);
1032     of_add_prop(ofd, "/memory", "reg", memory_reg, 2 * sizeof(uint32_t), 0);
1033     of_add_prop(ofd, "/memory", "available",memory_av,2*sizeof(uint32_t),0);
1034     of_add_prop_str(machine, ofd, "/memory","device_type","memory"/*?*/);
1035    
1036     /* Services: */
1037     of_add_service(ofd, "call-method", of__call_method_2_2, 2, 2);
1038     of_add_service(ofd, "call-method", of__call_method_3_4, 3, 4);
1039     of_add_service(ofd, "call-method", of__call_method_5_2, 5, 2);
1040     of_add_service(ofd, "call-method", of__call_method_6_1, 6, 1);
1041     of_add_service(ofd, "call-method", of__call_method_6_2, 6, 2);
1042     of_add_service(ofd, "child", of__child, 1, 1);
1043     of_add_service(ofd, "exit", of__exit, 0, 0);
1044     of_add_service(ofd, "finddevice", of__finddevice, 1, 1);
1045     of_add_service(ofd, "getprop", of__getprop, 4, 1);
1046     of_add_service(ofd, "getproplen", of__getproplen, 2, 1);
1047     of_add_service(ofd, "instance-to-package",
1048     of__instance_to_package, 1, 1);
1049     of_add_service(ofd, "interpret", of__interpret_1, 1, 1);
1050     of_add_service(ofd, "interpret", of__interpret_2, 1, 2);
1051     of_add_service(ofd, "package-to-path", of__package_to_path, 3, 1);
1052     of_add_service(ofd, "parent", of__parent, 1, 1);
1053     of_add_service(ofd, "peer", of__peer, 1, 1);
1054     of_add_service(ofd, "read", of__read, 3, 1);
1055     of_add_service(ofd, "write", of__write, 3, 1);
1056    
1057     if (verbose >= 2)
1058     of_dump_all(ofd);
1059    
1060     machine->of_data = ofd;
1061     return ofd;
1062    
1063     bad:
1064     fatal("of_emul_init(): out of memory\n");
1065     exit(1);
1066     }
1067    
1068    
1069     /*
1070 dpavlin 14 * of_emul():
1071     *
1072     * OpenFirmware call emulation.
1073     */
1074     int of_emul(struct cpu *cpu)
1075     {
1076 dpavlin 22 int i, nargs, nret, ofs, retval = 0;
1077 dpavlin 14 char service[50];
1078 dpavlin 22 char *arg[OF_N_MAX_ARGS];
1079 dpavlin 14 uint64_t base, ptr;
1080 dpavlin 22 struct of_service *os;
1081     struct of_data *of_data = cpu->machine->of_data;
1082 dpavlin 14
1083 dpavlin 22 if (of_data == NULL) {
1084     fatal("of_emul(): no of_data struct?\n");
1085     exit(1);
1086     }
1087    
1088 dpavlin 14 /*
1089     * The first argument register points to "prom_args":
1090     *
1091     * char *service; (probably 32 bit)
1092     * int nargs;
1093     * int nret;
1094     * char *args[10];
1095     */
1096    
1097     switch (cpu->machine->arch) {
1098     case ARCH_ARM:
1099     base = cpu->cd.arm.r[0];
1100     break;
1101     case ARCH_PPC:
1102     base = cpu->cd.ppc.gpr[3];
1103     break;
1104 dpavlin 22 default:fatal("of_emul(): unimplemented arch (TODO)\n");
1105 dpavlin 14 exit(1);
1106     }
1107    
1108     /* TODO: how about 64-bit OpenFirmware? */
1109     ptr = load_32bit_word(cpu, base);
1110     nargs = load_32bit_word(cpu, base + 4);
1111     nret = load_32bit_word(cpu, base + 8);
1112    
1113     readstr(cpu, ptr, service, sizeof(service));
1114    
1115     debug("[ of: %s(", service);
1116     ofs = 12;
1117     for (i=0; i<nargs; i++) {
1118 dpavlin 22 int x;
1119 dpavlin 14 if (i > 0)
1120     debug(", ");
1121 dpavlin 22 if (i >= OF_N_MAX_ARGS) {
1122 dpavlin 14 fatal("TOO MANY ARGS!");
1123     continue;
1124     }
1125     ptr = load_32bit_word(cpu, base + ofs);
1126 dpavlin 22 arg[i] = malloc(OF_ARG_MAX_LEN + 1);
1127     if (arg[i] == NULL) {
1128     fatal("out of memory\n");
1129     exit(1);
1130     }
1131     memset(arg[i], 0, OF_ARG_MAX_LEN + 1);
1132     x = ptr;
1133     if (x > -256 && x < 256) {
1134     debug("%i", x);
1135     } else {
1136     readstr(cpu, ptr, arg[i], OF_ARG_MAX_LEN);
1137     if (arg[i][0])
1138     debug("\"%s\"", arg[i]);
1139 dpavlin 14 else
1140     debug("0x%x", x);
1141     }
1142     ofs += sizeof(uint32_t);
1143     }
1144     debug(") ]\n");
1145    
1146     /* Note: base + ofs points to the first return slot. */
1147    
1148 dpavlin 22 os = of_data->of_services;
1149     while (os != NULL) {
1150     if (strcmp(service, os->name) == 0 &&
1151     nargs == os->n_args && nret == os->n_ret_args) {
1152     retval = os->f(cpu, arg, base, ofs);
1153     break;
1154 dpavlin 14 }
1155 dpavlin 22 os = os->next;
1156     }
1157 dpavlin 14
1158 dpavlin 22 if (os == NULL) {
1159 dpavlin 14 quiet_mode = 0;
1160     cpu_register_dump(cpu->machine, cpu, 1, 0);
1161     printf("\n");
1162 dpavlin 22 fatal("[ of: unimplemented service \"%s\" with %i input "
1163     "args and %i output values ]\n", service, nargs, nret);
1164 dpavlin 14 cpu->running = 0;
1165     cpu->dead = 1;
1166     }
1167    
1168 dpavlin 22 for (i=0; i<nargs; i++)
1169     free(arg[i]);
1170    
1171     /* Return: */
1172 dpavlin 14 switch (cpu->machine->arch) {
1173     case ARCH_ARM:
1174     cpu->cd.arm.r[0] = retval;
1175     break;
1176     case ARCH_PPC:
1177     cpu->cd.ppc.gpr[3] = retval;
1178     break;
1179 dpavlin 22 default:fatal("of_emul(): TODO: unimplemented arch (Retval)\n");
1180 dpavlin 14 exit(1);
1181     }
1182    
1183     return 1;
1184     }
1185    

  ViewVC Help
Powered by ViewVC 1.1.26