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

Contents of /trunk/src/promemul/of.c

Parent Directory Parent Directory | Revision Log Revision Log


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

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


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

  ViewVC Help
Powered by ViewVC 1.1.26