/[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

Contents of /upstream/0.4.3/src/promemul/of.c

Parent Directory Parent Directory | Revision Log Revision Log


Revision 33 - (show 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 /*
2 * Copyright (C) 2005-2006 Anders Gavare. All rights reserved.
3 *
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 * $Id: of.c,v 1.19 2006/07/26 23:21:48 debug Exp $
29 *
30 * OpenFirmware emulation.
31 *
32 * 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 */
42
43 #include <stdio.h>
44 #include <stdlib.h>
45 #include <string.h>
46 #include <sys/types.h>
47
48 #define OF_C
49
50 #include "console.h"
51 #include "cpu.h"
52 #include "device.h"
53 #include "devices.h"
54 #include "diskimage.h"
55 #include "machine.h"
56 #include "memory.h"
57 #include "misc.h"
58 #include "of.h"
59
60
61 /* #define debug fatal */
62
63 extern int quiet_mode;
64 extern int verbose;
65
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 * 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 * of_emul():
1071 *
1072 * OpenFirmware call emulation.
1073 */
1074 int of_emul(struct cpu *cpu)
1075 {
1076 int i, nargs, nret, ofs, retval = 0;
1077 char service[50];
1078 char *arg[OF_N_MAX_ARGS];
1079 uint64_t base, ptr;
1080 struct of_service *os;
1081 struct of_data *of_data = cpu->machine->of_data;
1082
1083 if (of_data == NULL) {
1084 fatal("of_emul(): no of_data struct?\n");
1085 exit(1);
1086 }
1087
1088 /*
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 default:fatal("of_emul(): unimplemented arch (TODO)\n");
1105 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 int x;
1119 if (i > 0)
1120 debug(", ");
1121 if (i >= OF_N_MAX_ARGS) {
1122 fatal("TOO MANY ARGS!");
1123 continue;
1124 }
1125 ptr = load_32bit_word(cpu, base + ofs);
1126 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 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 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 }
1155 os = os->next;
1156 }
1157
1158 if (os == NULL) {
1159 quiet_mode = 0;
1160 cpu_register_dump(cpu->machine, cpu, 1, 0);
1161 printf("\n");
1162 fatal("[ of: unimplemented service \"%s\" with %i input "
1163 "args and %i output values ]\n", service, nargs, nret);
1164 cpu->running = 0;
1165 }
1166
1167 for (i=0; i<nargs; i++)
1168 free(arg[i]);
1169
1170 /* Return: */
1171 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 default:fatal("of_emul(): TODO: unimplemented arch (Retval)\n");
1179 exit(1);
1180 }
1181
1182 return 1;
1183 }
1184

  ViewVC Help
Powered by ViewVC 1.1.26