/[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 30 - (show annotations)
Mon Oct 8 16:20:40 2007 UTC (16 years, 6 months ago) by dpavlin
File MIME type: text/plain
File size: 30609 byte(s)
++ trunk/HISTORY	(local)
$Id: HISTORY,v 1.1325 2006/08/15 15:38:37 debug Exp $
20060723	More Transputer instructions (pfix, nfix, opr, mint, ldl, ldlp,
		eqc, rev, ajw, stl, stlf, sthf, sub, ldnl, ldnlp, ldpi, move,
		wcnt, add, bcnt).
		Adding more SPARC instructions (andcc, addcc, bl, rdpr).
		Progress on the igsfb framebuffer used by NetBSD/netwinder.
		Enabling 8-bit fills in dev_fb.
		NetBSD/netwinder 3.0.1 can now run from a disk image :-)
20060724	Cleanup/performance fix for 64-bit virtual translation table
		updates (by removing the "timestamp" stuff). A full NetBSD/pmax
		3.0.1 install for R4400 has dropped from 667 seconds to 584 :)
		Fixing the igsfb "almost vga" color (it is 24-bit, not 18-bit).
		Adding some MIPS instruction combinations (3*lw, and 3*addu).
		The 8048 keyboard now turns off interrupt enable between the
		KBR_ACK and the KBR_RSTDONE, to work better with Linux 2.6.
		Not causing PPC DEC interrupts if PPC_NO_DEC is set for a
		specific CPU; NetBSD/bebox gets slightly further than before.
		Adding some more SPARC instructions: branches, udiv.
20060725	Refreshing dev_pckbc.c a little.
		Cleanups for the SH emulation mode, and adding the first
		"compact" (16-bit) instructions: various simple movs, nop,
		shll, stc, or, ldc.
20060726	Adding dummy "pcn" (AMD PCnet NIC) PCI glue.
20060727	Various cleanups; removing stuff from cpu.h, such as
		running_translated (not really meaningful anymore), and
		page flags (breaking into the debugger clears all translations
		anyway).
		Minor MIPS instruction combination updates.
20060807	Expanding the 3*sw and 3*lw MIPS instruction combinations to
		work with 2* and 4* too, resulting in a minor performance gain.
		Implementing a usleep hack for the RM52xx/MIPS32/MIPS64 "wait"
		instruction (when emulating 1 cpu).
20060808	Experimenting with some more MIPS instruction combinations.
		Implementing support for showing a (hardcoded 12x22) text
		cursor in igsfb.
20060809	Simplifying the NetBSD/evbmips (Malta) install instructions
		somewhat (by using a NetBSD/pmax ramdisk install kernel).
20060812	Experimenting more with the MIPS 'wait' instruction.
		PCI configuration register writes can now be handled, which
		allow PCI IDE controllers to work with NetBSD/Malta 3.0.1 and
		NetBSD/cobalt 3.0.1. (Previously only NetBSD 2.1 worked.)
20060813	Updating dev_gt.c based on numbers from Alec Voropay, to enable
		Linux 2.6 to use PCI on Malta.
		Continuing on Algor interrupt stuff.
20060814	Adding support for routing ISA interrupts to two different
		interrupts, making it possible to run NetBSD/algor :-)
20060814-15	Testing for the release.

==============  RELEASE 0.4.2  ==============


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