/[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 38 - (hide annotations)
Mon Oct 8 16:21:53 2007 UTC (16 years, 7 months ago) by dpavlin
File MIME type: text/plain
File size: 30880 byte(s)
++ trunk/HISTORY	(local)
$Id: HISTORY,v 1.1515 2007/04/14 05:39:46 debug Exp $
20070324	Adding a "--debug" option to the configure script, to disable
		optimizations in unstable development builds.
		Moving out SCSI-specific stuff from diskimage.c into a new
		diskimage_scsicmd.c.
		Applying Hĺvard Eidnes' patch for SCSICDROM_READ_DISKINFO and
		SCSICDROM_READ_TRACKINFO. (Not really tested yet.)
		Implementing disk image "overlays" (to allow simple roll-back
		to previous disk state). Adding a 'V' disk flag for this, and
		updating the man page and misc.html.
20070325	Stability fix to cpu_dyntrans.c, when multiple physical pages
		share the same initial table entry. (The ppp == NULL check
		should be physpage_ofs == 0.) Bug found by analysing GXemul
		against a version patched for Godson.
		Fixing a second occurance of the same problem (also in
		cpu_dyntrans.c).
		Fixing a MAJOR physical page leak in cpu_dyntrans.c; pages
		weren't _added_ to the set of translated pages, they _replaced_
		all previous pages. It's amazing that this bug has been able
		to live for this long. (Triggered when emulating >128MB RAM.)
20070326	Removing the GDB debugging stub support; it was too hackish
		and ugly.
20070328	Moving around some native code generation skeleton code.
20070329	The -lm check in the configure script now also checks for sin()
		in addition to sqrt(). (Thanks to Nigel Horne for noticing that
		sqrt was not enough on Fedora Core 6.) (Not verified yet.)
20070330	Fixing an indexing bug in dev_sh4.c, found by using gcc version
		4.3.0 20070323.
20070331	Some more experimentation with native code generation.
20070404	Attempting to fix some more SH4 SCIF interrupt bugs; rewriting
		the SH interrupt assertion/deassertion code somewhat.
20070410	Splitting src/file.c into separate files in src/file/.
		Cleanup: Removing the dummy TS7200, Walnut, PB1000, and
		Meshcube emulation modes, and dev_epcom and dev_au1x00.
		Removing the experimental CHIP8/RCA180x code; it wasn't really
		working much lately, anyway. It was fun while it lasted.
		Also removing the experimental Transputer CPU support.
20070412	Moving the section about how the dynamic translation system
		works from intro.html to a separate translation.html file.
		Minor SH fixes; attempting to get OpenBSD/landisk to run
		without randomly bugging out, but no success yet.
20070413	SH SCI (serial bit interface) should now work together with a
		(new) RS5C313 clock device (for Landisk emulation).
20070414	Moving Redhat/MIPS down from supported to experimental, in
		guestoses.html.
		Preparing for a new release; doing some regression testing etc.

==============  RELEASE 0.4.5  ==============


1 dpavlin 14 /*
2 dpavlin 34 * Copyright (C) 2005-2007 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 38 * $Id: of.c,v 1.23 2007/03/24 06:40:16 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 dpavlin 34 struct vfb_data *v = cpu->machine->md.of_data->vfb_data;
167 dpavlin 22 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 dpavlin 34 struct of_device *od = cpu->machine->md.of_data->of_devices;
203 dpavlin 22 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 dpavlin 34 int h = find_device_handle(cpu->machine->md.of_data, arg[0]);
220 dpavlin 22 store_32bit_word(cpu, base + retofs, h);
221     return h>0? 0 : -1;
222     }
223    
224    
225     OF_SERVICE(getprop)
226     {
227 dpavlin 34 struct of_device *od = cpu->machine->md.of_data->of_devices;
228 dpavlin 22 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 dpavlin 34 struct of_device *od = cpu->machine->md.of_data->of_devices;
275 dpavlin 22 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 dpavlin 34 struct of_device *od = cpu->machine->md.of_data->of_devices;
352 dpavlin 22 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 dpavlin 34 struct of_device *od = cpu->machine->md.of_data->of_devices;
362 dpavlin 22 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 dpavlin 34 od = cpu->machine->md.of_data->of_devices;
379 dpavlin 22
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 dpavlin 38
501     return NULL; /* Silences a compiler warning */
502 dpavlin 22 }
503    
504    
505     /*
506     * of_add_prop():
507     *
508     * Adds a property to a device.
509     */
510     static void of_add_prop(struct of_data *of_data, char *devname,
511     char *propname, unsigned char *data, uint32_t len, int flags)
512     {
513     struct of_device_property *pr =
514     malloc(sizeof(struct of_device_property));
515     struct of_device *od = of_data->of_devices;
516     int h = find_device_handle(of_data, devname);
517    
518     OF_FIND(od, od->handle == h);
519     if (od == NULL) {
520     fatal("of_add_prop(): device '%s' not registered\n", devname);
521     exit(1);
522     }
523    
524     if (pr == NULL)
525     goto bad;
526     memset(pr, 0, sizeof(struct of_device_property));
527    
528     pr->name = strdup(propname);
529     if (pr->name == NULL)
530     goto bad;
531     pr->data = data;
532     pr->len = len;
533     pr->flags = flags;
534    
535     pr->next = od->properties;
536     od->properties = pr;
537     return;
538    
539     bad:
540     fatal("of_add_device(): out of memory\n");
541     exit(1);
542     }
543    
544    
545     /*
546     * of_add_service():
547     *
548     * Adds a service.
549     */
550     static void of_add_service(struct of_data *of_data, char *name,
551     int (*f)(OF_SERVICE_ARGS), int n_args, int n_ret_args)
552     {
553     struct of_service *os = malloc(sizeof(struct of_service));
554     if (os == NULL)
555     goto bad;
556     memset(os, 0, sizeof(struct of_service));
557    
558     os->name = strdup(name);
559     if (os->name == NULL)
560     goto bad;
561    
562     os->f = f;
563     os->n_args = n_args;
564     os->n_ret_args = n_ret_args;
565    
566     os->next = of_data->of_services;
567     of_data->of_services = os;
568     return;
569    
570     bad:
571     fatal("of_add_service(): out of memory\n");
572     exit(1);
573     }
574    
575    
576     /*
577     * of_dump_devices():
578     *
579     * Debug dump helper.
580     */
581     static void of_dump_devices(struct of_data *ofd, int parent)
582     {
583     int iadd = DEBUG_INDENTATION;
584     struct of_device *od = ofd->of_devices;
585    
586     while (od != NULL) {
587     struct of_device_property *pr = od->properties;
588     if (od->parent != parent) {
589     od = od->next;
590     continue;
591     }
592     debug("\"%s\"\n", od->name, od->handle);
593     debug_indentation(iadd);
594     while (pr != NULL) {
595     debug("(%s: ", pr->name);
596     if (pr->flags == OF_PROP_STRING)
597     debug("\"%s\"", pr->data);
598     else
599     debug("%i bytes", pr->len);
600     debug(")\n");
601     pr = pr->next;
602     }
603     of_dump_devices(ofd, od->handle);
604     debug_indentation(-iadd);
605     od = od->next;
606     }
607     }
608    
609    
610     /*
611     * of_dump_all():
612     *
613     * Debug dump.
614     */
615     static void of_dump_all(struct of_data *ofd)
616     {
617     int iadd = DEBUG_INDENTATION;
618     struct of_service *os;
619    
620     debug("openfirmware debug dump:\n");
621     debug_indentation(iadd);
622    
623     /* Devices: */
624     of_dump_devices(ofd, 0);
625    
626     /* Services: */
627     os = ofd->of_services;
628     while (os != NULL) {
629     debug("service '%s'", os->name);
630     if (os->n_ret_args > 0 || os->n_args > 0) {
631     debug(" (");
632     if (os->n_args > 0) {
633     debug("%i arg%s", os->n_args,
634     os->n_args > 1? "s" : "");
635     if (os->n_ret_args > 0)
636     debug(", ");
637     }
638     if (os->n_ret_args > 0)
639     debug("%i return value%s", os->n_ret_args,
640     os->n_ret_args > 1? "s" : "");
641     debug(")");
642     }
643     debug("\n");
644     os = os->next;
645     }
646    
647     debug_indentation(-iadd);
648     }
649    
650    
651     /*
652     * of_add_prop_int32():
653     *
654     * Helper function.
655     */
656     static void of_add_prop_int32(struct of_data *ofd,
657     char *devname, char *propname, uint32_t x)
658     {
659     unsigned char *p = malloc(sizeof(int32_t));
660     if (p == NULL) {
661     fatal("of_add_prop_int32(): out of memory\n");
662     exit(1);
663     }
664     of_store_32bit_in_host(p, x);
665     of_add_prop(ofd, devname, propname, p, sizeof(int32_t),
666     OF_PROP_INT);
667     }
668    
669    
670     /*
671     * of_add_prop_str():
672     *
673     * Helper function.
674     */
675     static void of_add_prop_str(struct machine *machine, struct of_data *ofd,
676     char *devname, char *propname, char *data)
677     {
678     char *p = strdup(data);
679     if (p == NULL) {
680     fatal("of_add_prop_str(): out of memory\n");
681     exit(1);
682     }
683    
684     of_add_prop(ofd, devname, propname, (unsigned char *)p, strlen(p) + 1,
685     OF_PROP_STRING);
686     }
687    
688    
689     /*
690     * of_emul_init_isa():
691     */
692     void of_emul_init_isa(struct machine *machine)
693     {
694 dpavlin 34 struct of_data *ofd = machine->md.of_data;
695 dpavlin 22 unsigned char *isa_ranges;
696    
697     of_add_device(ofd, "isa", "/");
698     isa_ranges = malloc(32);
699     if (isa_ranges == NULL)
700     goto bad;
701     memset(isa_ranges, 0, 32);
702     /* 2 *: isa_phys_hi, isa_phys_lo, parent_phys_start, size */
703     /* MEM space: */
704     of_store_32bit_in_host(isa_ranges + 0, 0);
705     of_store_32bit_in_host(isa_ranges + 4, 0xc0000000);
706     /* I/O space: low bit if isa_phys_hi set */
707     of_store_32bit_in_host(isa_ranges + 16, 1);
708     of_store_32bit_in_host(isa_ranges + 20, 0xd0000000);
709    
710     of_add_prop(ofd, "/isa", "ranges", isa_ranges, 32, 0);
711    
712     return;
713    
714     bad:
715     fatal("of_emul_init_isa(): out of memory\n");
716     exit(1);
717     }
718    
719    
720     /*
721     * of_emul_init_adb():
722     */
723     void of_emul_init_adb(struct machine *machine)
724     {
725 dpavlin 34 struct of_data *ofd = machine->md.of_data;
726 dpavlin 22 unsigned char *adb_interrupts, *adb_reg;
727    
728     adb_interrupts = malloc(4 * sizeof(uint32_t));
729     adb_reg = malloc(8 * sizeof(uint32_t));
730     if (adb_interrupts == NULL || adb_reg == NULL)
731     goto bad;
732    
733     of_add_device(ofd, "adb", "/bandit/gc");
734     of_add_prop_str(machine, ofd, "/bandit/gc/adb", "name", "via-cuda");
735     of_store_32bit_in_host(adb_interrupts + 0, 25);
736     of_store_32bit_in_host(adb_interrupts + 4, 0);
737     of_store_32bit_in_host(adb_interrupts + 8, 0);
738     of_store_32bit_in_host(adb_interrupts + 12, 0);
739     of_add_prop(ofd, "/bandit/gc/adb", "interrupts", adb_interrupts,
740     4*sizeof(uint32_t), 0);
741     of_store_32bit_in_host(adb_reg + 0, 0x16000);
742     of_store_32bit_in_host(adb_reg + 4, 0x2000);
743     of_store_32bit_in_host(adb_reg + 8, 0);
744     of_store_32bit_in_host(adb_reg + 12, 0);
745     of_store_32bit_in_host(adb_reg + 16, 0);
746     of_store_32bit_in_host(adb_reg + 20, 0);
747     of_store_32bit_in_host(adb_reg + 24, 0);
748     of_store_32bit_in_host(adb_reg + 28, 0);
749     of_add_prop(ofd, "/bandit/gc/adb", "reg", adb_reg,
750     8*sizeof(uint32_t), 0);
751    
752     return;
753    
754     bad:
755     fatal("of_emul_init_adb(): out of memory\n");
756     exit(1);
757     }
758    
759    
760     /*
761     * of_emul_init_zs():
762     */
763     void of_emul_init_zs(struct machine *machine)
764     {
765 dpavlin 34 struct of_data *ofd = machine->md.of_data;
766 dpavlin 22 unsigned char *zs_interrupts, *zs_reg;
767    
768     zs_reg = malloc(6 * sizeof(uint32_t));
769     if (zs_reg == NULL)
770     goto bad;
771    
772     /* The controller: */
773     of_add_device(ofd, "zs", "/bandit/gc");
774     of_add_prop_str(machine, ofd, "/bandit/gc/zs", "device_type", "serial");
775     of_add_prop_str(machine, ofd, "/bandit/gc/zs", "name", "escc");
776     of_store_32bit_in_host(zs_reg + 0, 0x13000);
777     of_store_32bit_in_host(zs_reg + 4, 0x40);
778     of_store_32bit_in_host(zs_reg + 8, 0x100);
779     of_store_32bit_in_host(zs_reg + 12, 0x100);
780     of_store_32bit_in_host(zs_reg + 16, 0x200);
781     of_store_32bit_in_host(zs_reg + 20, 0x100);
782     of_add_prop(ofd, "/bandit/gc/zs", "reg", zs_reg, 6*sizeof(uint32_t), 0);
783    
784     /* Port 1: */
785     zs_interrupts = malloc(3 * sizeof(uint32_t));
786     zs_reg = malloc(6 * sizeof(uint32_t));
787     if (zs_interrupts == NULL || zs_reg == NULL)
788     goto bad;
789    
790     of_add_device(ofd, "zstty1", "/bandit/gc/zs");
791     of_add_prop_str(machine, ofd, "/bandit/gc/zs/zstty1", "name", "ch-a");
792     of_store_32bit_in_host(zs_interrupts + 0, 16);
793     of_store_32bit_in_host(zs_interrupts + 4, 0);
794     of_store_32bit_in_host(zs_interrupts + 8, 0);
795     of_add_prop(ofd, "/bandit/gc/zs/zstty1", "interrupts", zs_interrupts,
796     3*sizeof(uint32_t), 0);
797     of_store_32bit_in_host(zs_reg + 0, 0x13800);
798     of_store_32bit_in_host(zs_reg + 4, 0x100);
799     of_store_32bit_in_host(zs_reg + 8, 0x100);
800     of_store_32bit_in_host(zs_reg + 12, 0x100);
801     of_store_32bit_in_host(zs_reg + 16, 0x200);
802     of_store_32bit_in_host(zs_reg + 20, 0x100);
803     of_add_prop(ofd, "/bandit/gc/zs/zstty1",
804     "reg", zs_reg, 6*sizeof(uint32_t), 0);
805    
806     /* Port 0: */
807     zs_interrupts = malloc(3 * sizeof(uint32_t));
808     zs_reg = malloc(6 * sizeof(uint32_t));
809     if (zs_interrupts == NULL || zs_reg == NULL)
810     goto bad;
811    
812     of_add_device(ofd, "zstty0", "/bandit/gc/zs");
813     of_add_prop_str(machine, ofd, "/bandit/gc/zs/zstty0", "name", "ch-b");
814     of_store_32bit_in_host(zs_interrupts + 0, 15);
815     of_store_32bit_in_host(zs_interrupts + 4, 0);
816     of_store_32bit_in_host(zs_interrupts + 8, 0);
817     of_add_prop(ofd, "/bandit/gc/zs/zstty0", "interrupts", zs_interrupts,
818     3*sizeof(uint32_t), 0);
819     of_store_32bit_in_host(zs_reg + 0, 0x13400);
820     of_store_32bit_in_host(zs_reg + 4, 0x100);
821     of_store_32bit_in_host(zs_reg + 8, 0x100);
822     of_store_32bit_in_host(zs_reg + 12, 0x100);
823     of_store_32bit_in_host(zs_reg + 16, 0x200);
824     of_store_32bit_in_host(zs_reg + 20, 0x100);
825     of_add_prop(ofd, "/bandit/gc/zs/zstty0",
826     "reg", zs_reg, 6*sizeof(uint32_t), 0);
827    
828     return;
829    
830     bad:
831     fatal("of_emul_init_zs(): out of memory\n");
832     exit(1);
833     }
834    
835    
836     /*
837     * of_emul_init_uninorth():
838     */
839     void of_emul_init_uninorth(struct machine *machine)
840     {
841 dpavlin 34 struct of_data *ofd = machine->md.of_data;
842 dpavlin 22 unsigned char *uninorth_reg, *uninorth_bus_range, *uninorth_ranges;
843     unsigned char *macio_aa, *ata_interrupts, *ata_reg;
844     struct of_device *ic;
845     char *n = "pci@e2000000";
846     char *macio = "mac-io";
847    
848     of_add_device(ofd, n, "/");
849     of_add_prop_str(machine, ofd, n, "name", "pci");
850     of_add_prop_str(machine, ofd, n, "device_type", "pci");
851     of_add_prop_str(machine, ofd, n, "compatible", "uni-north");
852    
853     uninorth_reg = malloc(2 * sizeof(uint32_t));
854     uninorth_bus_range = malloc(2 * sizeof(uint32_t));
855     uninorth_ranges = malloc(12 * sizeof(uint32_t));
856     macio_aa = malloc(5 * sizeof(uint32_t));
857     ata_interrupts = malloc(6 * sizeof(uint32_t));
858     ata_reg = malloc(8 * sizeof(uint32_t));
859     if (uninorth_ranges == NULL || uninorth_bus_range == NULL ||
860     uninorth_reg == NULL || macio_aa == NULL ||
861     ata_interrupts == NULL || ata_reg == NULL)
862     goto bad;
863    
864     of_store_32bit_in_host(uninorth_reg + 0, 0xe2000000);
865     of_store_32bit_in_host(uninorth_reg + 4, 0); /* not used? */
866     of_add_prop(ofd, n, "reg", uninorth_reg, 2*sizeof(uint32_t), 0);
867    
868     of_store_32bit_in_host(uninorth_bus_range + 0, 0);
869     of_store_32bit_in_host(uninorth_bus_range + 4, 0);
870     of_add_prop(ofd, n, "bus-range", uninorth_bus_range,
871     2*sizeof(uint32_t), 0);
872    
873     /* MEM: */
874     of_store_32bit_in_host(uninorth_ranges + 0, 0x02000000);
875     of_store_32bit_in_host(uninorth_ranges + 4, 0);
876     of_store_32bit_in_host(uninorth_ranges + 8, 0);
877     of_store_32bit_in_host(uninorth_ranges + 12, 0xd0000000);
878     of_store_32bit_in_host(uninorth_ranges + 16, 0);
879     of_store_32bit_in_host(uninorth_ranges + 20, 0x04000000);
880     /* IO: */
881     of_store_32bit_in_host(uninorth_ranges + 24, 0x01000000);
882     of_store_32bit_in_host(uninorth_ranges + 28, 0);
883     of_store_32bit_in_host(uninorth_ranges + 32, 0);
884     of_store_32bit_in_host(uninorth_ranges + 36, 0xe2000000);
885     of_store_32bit_in_host(uninorth_ranges + 40, 0);
886     of_store_32bit_in_host(uninorth_ranges + 44, 0x01000000);
887     of_add_prop(ofd, n, "ranges", uninorth_ranges,
888     12*sizeof(uint32_t), 0);
889    
890     ic = of_add_device(ofd, macio, "/");
891     memset(macio_aa, 0, 20);
892     of_store_32bit_in_host(macio_aa + 0, 15 << 11); /* pci tag */
893     of_store_32bit_in_host(macio_aa + 8, 0xf3000000);
894     of_add_prop(ofd, macio, "assigned-addresses", macio_aa,
895     5*sizeof(uint32_t), 0);
896     /* of_add_prop(ofd, n, "assigned-addresses", macio_aa,
897     5*sizeof(uint32_t), 0); */
898     of_add_prop_int32(ofd, "/chosen", "interrupt-controller", ic->handle);
899    
900     of_add_device(ofd, "bandit", "/");
901     of_add_device(ofd, "gc", "/bandit");
902     of_add_prop(ofd, "/bandit/gc", "assigned-addresses", macio_aa,
903     5*sizeof(uint32_t), 0);
904    
905     if (diskimage_exist(machine, 0, DISKIMAGE_IDE) ||
906     diskimage_exist(machine, 1, DISKIMAGE_IDE)) {
907 dpavlin 34 char tmpstr[400];
908 dpavlin 22 of_add_device(ofd, "ata", "/bandit/gc");
909     of_add_prop_str(machine, ofd, "/bandit/gc/ata", "name", "ata");
910     of_add_prop_str(machine, ofd, "/bandit/gc/ata", "compatible",
911     "heathrow-ata");
912     of_store_32bit_in_host(ata_interrupts + 0, 13);
913     of_store_32bit_in_host(ata_interrupts + 4, 0);
914     of_store_32bit_in_host(ata_interrupts + 8, 0);
915     of_store_32bit_in_host(ata_interrupts + 12, 0);
916     of_store_32bit_in_host(ata_interrupts + 16, 0);
917     of_store_32bit_in_host(ata_interrupts + 20, 0);
918     of_add_prop(ofd, "/bandit/gc/ata", "interrupts", ata_interrupts,
919     6*sizeof(uint32_t), 0);
920     of_store_32bit_in_host(ata_reg + 0, 0x20000);
921     of_store_32bit_in_host(ata_reg + 4, 0);
922     of_store_32bit_in_host(ata_reg + 8, 0x21000);
923     of_store_32bit_in_host(ata_reg + 12, 0x22000);
924     of_store_32bit_in_host(ata_reg + 16, 0);
925     of_store_32bit_in_host(ata_reg + 20, 0);
926     of_store_32bit_in_host(ata_reg + 24, 0);
927     of_store_32bit_in_host(ata_reg + 28, 0);
928     of_add_prop(ofd, "/bandit/gc/ata", "reg", ata_reg,
929     8*sizeof(uint32_t), 0);
930 dpavlin 34
931     snprintf(tmpstr, sizeof(tmpstr), "wdc addr=0xf3020000 "
932     "irq=%s.cpu[%i].gc.lo.21 addr_mult=0x10", machine->path,
933     machine->bootstrap_cpu);
934     device_add(machine, tmpstr);
935 dpavlin 22 }
936    
937     return;
938    
939     bad:
940     fatal("of_emul_init_uninorth(): out of memory\n");
941     exit(1);
942     }
943    
944    
945     /*
946     * of_emul_init():
947     *
948     * This function creates an OpenFirmware emulation instance.
949     */
950     struct of_data *of_emul_init(struct machine *machine, struct vfb_data *vfb_data,
951     uint64_t fb_addr, int fb_xsize, int fb_ysize)
952     {
953     unsigned char *memory_reg, *memory_av;
954     unsigned char *zs_assigned_addresses;
955     struct of_device *mmu, *devstdout, *devstdin;
956     struct of_data *ofd = malloc(sizeof(struct of_data));
957     int i;
958    
959     if (ofd == NULL)
960     goto bad;
961     memset(ofd, 0, sizeof(struct of_data));
962    
963     ofd->vfb_data = vfb_data;
964    
965     /* Devices: */
966    
967     /* Root = device 1 */
968     of_add_device(ofd, "", "");
969    
970     of_add_device(ofd, "io", "/");
971     devstdin = of_add_device(ofd, "stdin", "/io");
972     devstdout = of_add_device(ofd, "stdout", "/io");
973    
974     if (machine->use_x11) {
975     fatal("!\n! TODO: keyboard + framebuffer for MacPPC\n!\n");
976    
977     of_add_prop_str(machine, ofd, "/io/stdin", "name",
978     "keyboard");
979     of_add_prop_str(machine, ofd, "/io", "name", "adb");
980    
981     of_add_prop_str(machine, ofd, "/io/stdout", "device_type",
982     "display");
983     of_add_prop_int32(ofd, "/io/stdout", "width", fb_xsize);
984     of_add_prop_int32(ofd, "/io/stdout", "height", fb_ysize);
985     of_add_prop_int32(ofd, "/io/stdout", "linebytes", fb_xsize * 1);
986     of_add_prop_int32(ofd, "/io/stdout", "depth", 8);
987     of_add_prop_int32(ofd, "/io/stdout", "address", fb_addr);
988     } else {
989     zs_assigned_addresses = malloc(12);
990     if (zs_assigned_addresses == NULL)
991     goto bad;
992     memset(zs_assigned_addresses, 0, 12);
993     of_add_prop_str(machine, ofd, "/io/stdin", "name", "ch-b");
994     of_add_prop_str(machine, ofd, "/io/stdin", "device_type",
995     "serial");
996     of_add_prop_int32(ofd, "/io/stdin", "reg", 0xf3013000);
997     of_add_prop(ofd, "/io/stdin", "assigned-addresses",
998     zs_assigned_addresses, 12, 0);
999    
1000     of_add_prop_str(machine, ofd, "/io/stdout", "device_type",
1001     "serial");
1002     }
1003    
1004     of_add_device(ofd, "cpus", "/");
1005     for (i=0; i<machine->ncpus; i++) {
1006     char tmp[50];
1007     snprintf(tmp, sizeof(tmp), "@%x", i);
1008     of_add_device(ofd, tmp, "/cpus");
1009     snprintf(tmp, sizeof(tmp), "/cpus/@%x", i);
1010     of_add_prop_str(machine, ofd, tmp, "device_type", "cpu");
1011     of_add_prop_int32(ofd, tmp, "timebase-frequency",
1012     machine->emulated_hz / 4);
1013     of_add_prop_int32(ofd, tmp, "clock-frequency",
1014     machine->emulated_hz);
1015     of_add_prop_int32(ofd, tmp, "reg", i);
1016     }
1017    
1018     mmu = of_add_device(ofd, "mmu", "/");
1019    
1020     /* TODO: */
1021     of_add_prop(ofd, "/mmu", "translations", NULL, 0, 0);
1022    
1023     of_add_device(ofd, "chosen", "/");
1024     of_add_prop_int32(ofd, "/chosen", "mmu", mmu->handle);
1025     of_add_prop_int32(ofd, "/chosen", "stdin", devstdin->handle);
1026     of_add_prop_int32(ofd, "/chosen", "stdout", devstdout->handle);
1027    
1028     of_add_device(ofd, "memory", "/");
1029     memory_reg = malloc(2 * sizeof(uint32_t));
1030     memory_av = malloc(2 * sizeof(uint32_t));
1031     if (memory_reg == NULL || memory_av == NULL)
1032     goto bad;
1033     of_store_32bit_in_host(memory_reg + 0, 0);
1034     of_store_32bit_in_host(memory_reg + 4, machine->physical_ram_in_mb<<20);
1035     of_store_32bit_in_host(memory_av + 0, 10 << 20);
1036     of_store_32bit_in_host(memory_av + 4,
1037     (machine->physical_ram_in_mb - 10) << 20);
1038     of_add_prop(ofd, "/memory", "reg", memory_reg, 2 * sizeof(uint32_t), 0);
1039     of_add_prop(ofd, "/memory", "available",memory_av,2*sizeof(uint32_t),0);
1040     of_add_prop_str(machine, ofd, "/memory","device_type","memory"/*?*/);
1041    
1042     /* Services: */
1043     of_add_service(ofd, "call-method", of__call_method_2_2, 2, 2);
1044     of_add_service(ofd, "call-method", of__call_method_3_4, 3, 4);
1045     of_add_service(ofd, "call-method", of__call_method_5_2, 5, 2);
1046     of_add_service(ofd, "call-method", of__call_method_6_1, 6, 1);
1047     of_add_service(ofd, "call-method", of__call_method_6_2, 6, 2);
1048     of_add_service(ofd, "child", of__child, 1, 1);
1049     of_add_service(ofd, "exit", of__exit, 0, 0);
1050     of_add_service(ofd, "finddevice", of__finddevice, 1, 1);
1051     of_add_service(ofd, "getprop", of__getprop, 4, 1);
1052     of_add_service(ofd, "getproplen", of__getproplen, 2, 1);
1053     of_add_service(ofd, "instance-to-package",
1054     of__instance_to_package, 1, 1);
1055     of_add_service(ofd, "interpret", of__interpret_1, 1, 1);
1056     of_add_service(ofd, "interpret", of__interpret_2, 1, 2);
1057     of_add_service(ofd, "package-to-path", of__package_to_path, 3, 1);
1058     of_add_service(ofd, "parent", of__parent, 1, 1);
1059     of_add_service(ofd, "peer", of__peer, 1, 1);
1060     of_add_service(ofd, "read", of__read, 3, 1);
1061     of_add_service(ofd, "write", of__write, 3, 1);
1062    
1063     if (verbose >= 2)
1064     of_dump_all(ofd);
1065    
1066 dpavlin 34 machine->md.of_data = ofd;
1067 dpavlin 22 return ofd;
1068    
1069     bad:
1070     fatal("of_emul_init(): out of memory\n");
1071     exit(1);
1072 dpavlin 38
1073     return NULL; /* Silences a compiler warning */
1074 dpavlin 22 }
1075    
1076    
1077     /*
1078 dpavlin 14 * of_emul():
1079     *
1080     * OpenFirmware call emulation.
1081     */
1082     int of_emul(struct cpu *cpu)
1083     {
1084 dpavlin 22 int i, nargs, nret, ofs, retval = 0;
1085 dpavlin 14 char service[50];
1086 dpavlin 22 char *arg[OF_N_MAX_ARGS];
1087 dpavlin 14 uint64_t base, ptr;
1088 dpavlin 22 struct of_service *os;
1089 dpavlin 34 struct of_data *of_data = cpu->machine->md.of_data;
1090 dpavlin 14
1091 dpavlin 22 if (of_data == NULL) {
1092     fatal("of_emul(): no of_data struct?\n");
1093     exit(1);
1094     }
1095    
1096 dpavlin 14 /*
1097     * The first argument register points to "prom_args":
1098     *
1099     * char *service; (probably 32 bit)
1100     * int nargs;
1101     * int nret;
1102     * char *args[10];
1103     */
1104    
1105     switch (cpu->machine->arch) {
1106     case ARCH_ARM:
1107     base = cpu->cd.arm.r[0];
1108     break;
1109     case ARCH_PPC:
1110     base = cpu->cd.ppc.gpr[3];
1111     break;
1112 dpavlin 22 default:fatal("of_emul(): unimplemented arch (TODO)\n");
1113 dpavlin 14 exit(1);
1114     }
1115    
1116     /* TODO: how about 64-bit OpenFirmware? */
1117     ptr = load_32bit_word(cpu, base);
1118     nargs = load_32bit_word(cpu, base + 4);
1119     nret = load_32bit_word(cpu, base + 8);
1120    
1121     readstr(cpu, ptr, service, sizeof(service));
1122    
1123     debug("[ of: %s(", service);
1124     ofs = 12;
1125     for (i=0; i<nargs; i++) {
1126 dpavlin 22 int x;
1127 dpavlin 14 if (i > 0)
1128     debug(", ");
1129 dpavlin 22 if (i >= OF_N_MAX_ARGS) {
1130 dpavlin 14 fatal("TOO MANY ARGS!");
1131     continue;
1132     }
1133     ptr = load_32bit_word(cpu, base + ofs);
1134 dpavlin 22 arg[i] = malloc(OF_ARG_MAX_LEN + 1);
1135     if (arg[i] == NULL) {
1136     fatal("out of memory\n");
1137     exit(1);
1138     }
1139     memset(arg[i], 0, OF_ARG_MAX_LEN + 1);
1140     x = ptr;
1141     if (x > -256 && x < 256) {
1142     debug("%i", x);
1143     } else {
1144     readstr(cpu, ptr, arg[i], OF_ARG_MAX_LEN);
1145     if (arg[i][0])
1146     debug("\"%s\"", arg[i]);
1147 dpavlin 14 else
1148     debug("0x%x", x);
1149     }
1150     ofs += sizeof(uint32_t);
1151     }
1152     debug(") ]\n");
1153    
1154     /* Note: base + ofs points to the first return slot. */
1155    
1156 dpavlin 22 os = of_data->of_services;
1157     while (os != NULL) {
1158     if (strcmp(service, os->name) == 0 &&
1159     nargs == os->n_args && nret == os->n_ret_args) {
1160     retval = os->f(cpu, arg, base, ofs);
1161     break;
1162 dpavlin 14 }
1163 dpavlin 22 os = os->next;
1164     }
1165 dpavlin 14
1166 dpavlin 22 if (os == NULL) {
1167 dpavlin 14 quiet_mode = 0;
1168     cpu_register_dump(cpu->machine, cpu, 1, 0);
1169     printf("\n");
1170 dpavlin 22 fatal("[ of: unimplemented service \"%s\" with %i input "
1171     "args and %i output values ]\n", service, nargs, nret);
1172 dpavlin 14 cpu->running = 0;
1173     }
1174    
1175 dpavlin 22 for (i=0; i<nargs; i++)
1176     free(arg[i]);
1177    
1178     /* Return: */
1179 dpavlin 14 switch (cpu->machine->arch) {
1180     case ARCH_ARM:
1181     cpu->cd.arm.r[0] = retval;
1182     break;
1183     case ARCH_PPC:
1184     cpu->cd.ppc.gpr[3] = retval;
1185     break;
1186 dpavlin 22 default:fatal("of_emul(): TODO: unimplemented arch (Retval)\n");
1187 dpavlin 14 exit(1);
1188     }
1189    
1190     return 1;
1191     }
1192    

  ViewVC Help
Powered by ViewVC 1.1.26