/[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 44 - (hide annotations)
Mon Oct 8 16:22:56 2007 UTC (16 years, 7 months ago) by dpavlin
File MIME type: text/plain
File size: 29786 byte(s)
++ trunk/HISTORY	(local)
$Id: HISTORY,v 1.1632 2007/09/11 21:46:35 debug Exp $
20070616	Implementing the MIPS32/64 revision 2 "ror" instruction.
20070617	Adding a struct for each physpage which keeps track of which
		ranges within that page (base offset, length) that are
		continuously translatable. When running with native code
		generation enabled (-b), a range is added after each read-
		ahead loop.
		Experimenting with using the physical program counter sample
		data (implemented 20070608) together with the "translatable
		range" information, to figure out which physical address ranges
		would be worth translating to native code (if the number of
		samples falling within a range is above a certain threshold).
20070618	Adding automagic building of .index comment files for
		src/file/, src/promemul/, src src/useremul/ as well.
		Adding a "has been translated" bit to the ranges, so that only
		not-yet-translated ranges will be sampled.
20070619	Moving src/cpu.c and src/memory_rw.c into src/cpus/,
		src/device.c into src/devices/, and src/machine.c into
		src/machines/.
		Creating a skeleton cc/ld native backend module; beginning on
		the function which will detect cc command line, etc.
20070620	Continuing on the native code generation infrastructure.
20070621	Moving src/x11.c and src/console.c into a new src/console/
		subdir (for everything that is console or framebuffer related).
		Moving src/symbol*.c into a new src/symbol/, which should
		contain anything that is symbol handling related.
20070624	Making the program counter sampling threshold a "settings
		variable" (sampling_threshold), i.e. it can now be changed
		during runtime.
		Switching the RELEASE notes format from plain text to HTML.
		If the TMPDIR environment variable is set, it is used instead
		of "/tmp" for temporary files.
		Continuing on the cc/ld backend: simple .c code is generated,
		the compiler and linker are called, etc.
		Adding detection of host architecture to the configure script
		(again), and adding icache invalidation support (only
		implemented for Alpha hosts so far).
20070625	Simplifying the program counter sampling mechanism.
20070626	Removing the cc/ld native code generation stuff, program
		counter sampling, etc; it would not have worked well in the
		general case.
20070627	Removing everything related to native code generation.
20070629	Removing the (practically unusable) support for multiple
		emulations. (The single emulation allowed now still supports
		multiple simultaneous machines, as before.)
		Beginning on PCCTWO and M88K interrupts.
20070723	Adding a dummy skeleton for emulation of M32R processors.
20070901	Fixing a warning found by "gcc version 4.3.0 20070817
		(experimental)" on amd64.
20070905	Removing some more traces of the old "multiple emulations"
		code.
		Also looking in /usr/local/include and /usr/local/lib for
		X11 libs, when running configure.
20070909	Minor updates to the guest OS install instructions, in
		preparation for the NetBSD 4.0 release.
20070918	More testing of NetBSD 4.0 RC1.

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

  ViewVC Help
Powered by ViewVC 1.1.26