/[gxemul]/upstream/0.4.3/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 /upstream/0.4.3/src/promemul/of.c

Parent Directory Parent Directory | Revision Log Revision Log


Revision 33 - (hide annotations)
Mon Oct 8 16:21:06 2007 UTC (16 years, 7 months ago) by dpavlin
File MIME type: text/plain
File size: 30609 byte(s)
0.4.3
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 30 * $Id: of.c,v 1.19 2006/07/26 23:21:48 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     }
1166    
1167 dpavlin 22 for (i=0; i<nargs; i++)
1168     free(arg[i]);
1169    
1170     /* Return: */
1171 dpavlin 14 switch (cpu->machine->arch) {
1172     case ARCH_ARM:
1173     cpu->cd.arm.r[0] = retval;
1174     break;
1175     case ARCH_PPC:
1176     cpu->cd.ppc.gpr[3] = retval;
1177     break;
1178 dpavlin 22 default:fatal("of_emul(): TODO: unimplemented arch (Retval)\n");
1179 dpavlin 14 exit(1);
1180     }
1181    
1182     return 1;
1183     }
1184    

  ViewVC Help
Powered by ViewVC 1.1.26