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

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

  ViewVC Help
Powered by ViewVC 1.1.26