/[gxemul]/trunk/src/promemul/arcbios.c
This is repository of my old source code which isn't updated any more. Go to git.rot13.org for current projects!
ViewVC logotype

Annotation of /trunk/src/promemul/arcbios.c

Parent Directory Parent Directory | Revision Log Revision Log


Revision 34 - (hide annotations)
Mon Oct 8 16:21:17 2007 UTC (16 years, 6 months ago) by dpavlin
File MIME type: text/plain
File size: 94172 byte(s)
++ trunk/HISTORY	(local)
$Id: HISTORY,v 1.1480 2007/02/19 01:34:42 debug Exp $
20061029	Changing usleep(1) calls in the debugger to usleep(10000)
20061107	Adding a new disk image option (-d o...) which sets the ISO9660
		filesystem base offset; also making some other hacks to allow
		NetBSD/dreamcast and homebrew demos/games to boot directly
		from a filesystem image.
		Moving Dreamcast-specific stuff in the documentation to its
		own page (dreamcast.html).
		Adding a border to the Dreamcast PVR framebuffer.
20061108	Adding a -T command line option (again?), for halting the
		emulator on unimplemented memory accesses.
20061109	Continuing on various SH4 and Dreamcast related things.
		The emulator should now halt on more unimplemented device
		accesses, instead of just printing a warning, forcing me to
		actually implement missing stuff :)
20061111	Continuing on SH4 and Dreamcast stuff.
		Adding a bogus Landisk (SH4) machine mode.
20061112	Implementing some parts of the Dreamcast GDROM device. With
		some ugly hacks, NetBSD can (barely) mount an ISO image.
20061113	NetBSD/dreamcast now starts booting from the Live CD image,
		but crashes randomly quite early on in the boot process.
20061122	Beginning on a skeleton interrupt.h and interrupt.c for the
		new interrupt subsystem.
20061124	Continuing on the new interrupt system; taking the first steps
		to attempt to connect CPUs (SuperH and MIPS) and devices
		(dev_cons and SH4 timer interrupts) to it. Many things will
		probably break from now on.
20061125	Converting dev_ns16550, dev_8253 to the new interrupt system.
		Attempting to begin to convert the ISA bus.
20061130	Incorporating a patch from Brian Foley for the configure
		script, which checks for X11 libs in /usr/X11R6/lib64 (which
		is used on some Linux systems).
20061227	Adding a note in the man page about booting from Dreamcast
		CDROM images (i.e. that no external kernel is needed).
20061229	Continuing on the interrupt system rewrite: beginning to
		convert more devices, adding abort() calls for legacy interrupt
		system calls so that everything now _has_ to be rewritten!
		Almost all machine modes are now completely broken.
20061230	More progress on removing old interrupt code, mostly related
		to the ISA bus + devices, the LCA bus (on AlphaBook1), and
		the Footbridge bus (for CATS). And some minor PCI stuff.
		Connecting the ARM cpu to the new interrupt system.
		The CATS, NetWinder, and QEMU_MIPS machine modes now work with
		the new interrupt system :)
20061231	Connecting PowerPC CPUs to the new interrupt system.
		Making PReP machines (IBM 6050) work again.
		Beginning to convert the GT PCI controller (for e.g. Malta
		and Cobalt emulation). Some things work, but not everything.
		Updating Copyright notices for 2007.
20070101	Converting dev_kn02 from legacy style to devinit; the 3max
		machine mode now works with the new interrupt system :-]
20070105	Beginning to convert the SGI O2 machine to the new interrupt
		system; finally converting O2 (IP32) devices to devinit, etc.
20070106	Continuing on the interrupt system redesign/rewrite; KN01
		(PMAX), KN230, and Dreamcast ASIC interrupts should work again,
		moving out stuff from machine.h and devices.h into the
		corresponding devices, beginning the rewrite of i80321
		interrupts, etc.
20070107	Beginning on the rewrite of Eagle interrupt stuff (PReP, etc).
20070117	Beginning the rewrite of Algor (V3) interrupts (finally
		changing dev_v3 into devinit style).
20070118	Removing the "bus" registry concept from machine.h, because
		it was practically meaningless.
		Continuing on the rewrite of Algor V3 ISA interrupts.
20070121	More work on Algor interrupts; they are now working again,
		well enough to run NetBSD/algor. :-)
20070122	Converting VR41xx (HPCmips) interrupts. NetBSD/hpcmips
		can be installed using the new interrupt system :-)
20070123	Making the testmips mode work with the new interrupt system.
20070127	Beginning to convert DEC5800 devices to devinit, and to the
		new interrupt system.
		Converting Playstation 2 devices to devinit, and converting
		the interrupt system. Also fixing a severe bug: the interrupt
		mask register on Playstation 2 is bitwise _toggled_ on writes.
20070128	Removing the dummy NetGear machine mode and the 8250 device
		(which was only used by the NetGear machine).
		Beginning to convert the MacPPC GC (Grand Central) interrupt
		controller to the new interrupt system.
		Converting Jazz interrupts (PICA61 etc.) to the new interrupt
		system. NetBSD/arc can be installed again :-)
		Fixing the JAZZ timer (hardcoding it at 100 Hz, works with
		NetBSD and it is better than a completely dummy timer as it
		was before).
		Converting dev_mp to the new interrupt system, although I
		haven't had time to actually test it yet.
		Completely removing src/machines/interrupts.c, cpu_interrupt
		and cpu_interrupt_ack in src/cpu.c, and
		src/include/machine_interrupts.h! Adding fatal error messages
		+ abort() in the few places that are left to fix.
		Converting dev_z8530 to the new interrupt system.
		FINALLY removing the md_int struct completely from the
		machine struct.
		SH4 fixes (adding a PADDR invalidation in the ITLB replacement
		code in memory_sh.c); the NetBSD/dreamcast LiveCD now runs
		all the way to the login prompt, and can be interacted with :-)
		Converting the CPC700 controller (PCI and interrupt controller
		for PM/PPC) to the new interrupt system.
20070129	Fixing MACE ISA interrupts (SGI IP32 emulation). Both NetBSD/
		sgimips' and OpenBSD/sgi's ramdisk kernels can now be
		interacted with again.
20070130	Moving out the MIPS multi_lw and _sw instruction combinations
		so that they are auto-generated at compile time instead.
20070131	Adding detection of amd64/x86_64 hosts in the configure script,
		for doing initial experiments (again :-) with native code
		generation.
		Adding a -k command line option to set the size of the dyntrans
		cache, and a -B command line option to disable native code
		generation, even if GXemul was compiled with support for
		native code generation for the specific host CPU architecture.
20070201	Experimenting with a skeleton for native code generation.
		Changing the default behaviour, so that native code generation
		is now disabled by default, and has to be enabled by using
		-b on the command line.
20070202	Continuing the native code generation experiments.
		Making PCI interrupts work for Footbridge again.
20070203	More native code generation experiments.
		Removing most of the native code generation experimental code,
		it does not make sense to include any quick hacks like this.
		Minor cleanup/removal of some more legacy MIPS interrupt code.
20070204	Making i80321 interrupts work again (for NetBSD/evbarm etc.),
		and fixing the timer at 100 Hz.
20070206	Experimenting with removing the wdc interrupt slowness hack.
20070207	Lowering the number of dyntrans TLB entries for MIPS from
		192 to 128, resulting in a minor speed improvement.
		Minor optimization to the code invalidation routine in
		cpu_dyntrans.c.
20070208	Increasing (experimentally) the nr of dyntrans instructions per
		loop from 60 to 120.
20070210	Commenting out (experimentally) the dyntrans_device_danger
		detection in memory_rw.c.
		Changing the testmips and baremips machines to use a revision 2
		MIPS64 CPU by default, instead of revision 1.
		Removing the dummy i960, IA64, x86, AVR32, and HP PA-RISC
		files, the PC bios emulation, and the Olivetti M700 (ARC) and
		db64360 emulation modes.
20070211	Adding an "mp" demo to the demos directory, which tests the
		SMP functionality of the testmips machine.
		Fixing PReP interrupts some more. NetBSD/prep now boots again.
20070216	Adding a "nop workaround" for booting Mach/PMAX to the
		documentation; thanks to Artur Bujdoso for the values.
		Converting more of the MacPPC interrupt stuff to the new
		system.
		Beginning to convert BeBox interrupts to the new system.
		PPC603e should NOT have the PPC_NO_DEC flag! Removing it.
		Correcting BeBox clock speed (it was set to 100 in the NetBSD
		bootinfo block, but should be 33000000/4), allowing NetBSD
		to start without using the (incorrect) PPC_NO_DEC hack.
20070217	Implementing (slow) AltiVec vector loads and stores, allowing
		NetBSD/macppc to finally boot using the GENERIC kernel :-)
		Updating the documentation with install instructions for
		NetBSD/macppc.
20070218-19	Regression testing for the release.

==============  RELEASE 0.4.4  ==============


1 dpavlin 14 /*
2 dpavlin 34 * Copyright (C) 2003-2007 Anders Gavare. All rights reserved.
3 dpavlin 14 *
4     * Redistribution and use in source and binary forms, with or without
5     * modification, are permitted provided that the following conditions are met:
6     *
7     * 1. Redistributions of source code must retain the above copyright
8     * notice, this list of conditions and the following disclaimer.
9     * 2. Redistributions in binary form must reproduce the above copyright
10     * notice, this list of conditions and the following disclaimer in the
11     * documentation and/or other materials provided with the distribution.
12     * 3. The name of the author may not be used to endorse or promote products
13     * derived from this software without specific prior written permission.
14     *
15     * THIS SOFTWARE IS PROVIDED BY THE AUTHOR AND CONTRIBUTORS ``AS IS'' AND
16     * ANY EXPRESS OR IMPLIED WARRANTIES, INCLUDING, BUT NOT LIMITED TO, THE
17     * IMPLIED WARRANTIES OF MERCHANTABILITY AND FITNESS FOR A PARTICULAR PURPOSE
18     * ARE DISCLAIMED. IN NO EVENT SHALL THE AUTHOR OR CONTRIBUTORS BE LIABLE
19     * FOR ANY DIRECT, INDIRECT, INCIDENTAL, SPECIAL, EXEMPLARY, OR CONSEQUENTIAL
20     * DAMAGES (INCLUDING, BUT NOT LIMITED TO, PROCUREMENT OF SUBSTITUTE GOODS
21     * OR SERVICES; LOSS OF USE, DATA, OR PROFITS; OR BUSINESS INTERRUPTION)
22     * HOWEVER CAUSED AND ON ANY THEORY OF LIABILITY, WHETHER IN CONTRACT, STRICT
23     * LIABILITY, OR TORT (INCLUDING NEGLIGENCE OR OTHERWISE) ARISING IN ANY WAY
24     * OUT OF THE USE OF THIS SOFTWARE, EVEN IF ADVISED OF THE POSSIBILITY OF
25     * SUCH DAMAGE.
26     *
27     *
28 dpavlin 34 * $Id: arcbios.c,v 1.11 2006/12/30 13:31:02 debug Exp $
29 dpavlin 14 *
30     * ARCBIOS emulation.
31     */
32    
33     #include <stdio.h>
34     #include <stdlib.h>
35     #include <string.h>
36     #include <time.h>
37     #include <unistd.h>
38     #include <sys/time.h>
39     #include <sys/types.h>
40     #include <sys/resource.h>
41    
42     #include "arcbios.h"
43     #include "arcbios_other.h"
44     #include "console.h"
45     #include "cpu.h"
46     #include "cpu_mips.h"
47     #include "diskimage.h"
48     #include "machine.h"
49     #include "memory.h"
50     #include "misc.h"
51    
52    
53     extern int quiet_mode;
54    
55    
56     /*
57     * arcbios_add_string_to_component():
58     */
59     void arcbios_add_string_to_component(struct machine *machine,
60     char *string, uint64_t component)
61     {
62     if (machine->md.arc.n_string_to_components >= MAX_STRING_TO_COMPONENT) {
63     printf("Too many string-to-component mappings.\n");
64     exit(1);
65     }
66    
67     machine->md.arc.string_to_component[machine->
68     md.arc.n_string_to_components] = strdup(string);
69     if (machine->md.arc.string_to_component[machine->
70     md.arc.n_string_to_components] == NULL) {
71     fprintf(stderr, "out of memory in "
72     "arcbios_add_string_to_component()\n");
73     exit(1);
74     }
75     debug("adding ARC component mapping: 0x%08x = %s\n",
76     (int)component, string);
77    
78     machine->md.arc.string_to_component_value[
79     machine->md.arc.n_string_to_components] = component;
80    
81     machine->md.arc.n_string_to_components ++;
82     }
83    
84    
85     /*
86     * arcbios_get_dsp_stat():
87     *
88     * Fills in an arcbios_dsp_stat struct with valid data.
89     */
90     static void arcbios_get_dsp_stat(struct cpu *cpu,
91     struct arcbios_dsp_stat *dspstat)
92     {
93     memset(dspstat, 0, sizeof(struct arcbios_dsp_stat));
94    
95     store_16bit_word_in_host(cpu, (unsigned char *)&dspstat->
96     CursorXPosition, cpu->machine->md.arc.console_curx + 1);
97     store_16bit_word_in_host(cpu, (unsigned char *)&dspstat->
98     CursorYPosition, cpu->machine->md.arc.console_cury + 1);
99     store_16bit_word_in_host(cpu, (unsigned char *)&dspstat->
100     CursorMaxXPosition, ARC_CONSOLE_MAX_X);
101     store_16bit_word_in_host(cpu, (unsigned char *)&dspstat->
102     CursorMaxYPosition, ARC_CONSOLE_MAX_Y);
103     dspstat->ForegroundColor = cpu->machine->md.arc.console_curcolor;
104     dspstat->HighIntensity = cpu->machine->md.arc.console_curcolor ^ 0x08;
105     }
106    
107    
108     /*
109     * arcbios_putcell():
110     */
111     static void arcbios_putcell(struct cpu *cpu, int ch, int x, int y)
112     {
113     unsigned char buf[2];
114     buf[0] = ch;
115     buf[1] = cpu->machine->md.arc.console_curcolor;
116     if (cpu->machine->md.arc.console_reverse)
117     buf[1] = ((buf[1] & 0x70) >> 4) | ((buf[1] & 7) << 4)
118     | (buf[1] & 0x88);
119     cpu->memory_rw(cpu, cpu->mem, cpu->machine->md.arc.console_vram +
120     2*(x + cpu->machine->md.arc.console_maxx * y),
121     &buf[0], sizeof(buf), MEM_WRITE,
122     CACHE_NONE | PHYSICAL);
123     }
124    
125    
126     /*
127     * handle_esc_seq():
128     *
129     * Used by arcbios_putchar().
130     */
131     static void handle_esc_seq(struct cpu *cpu)
132     {
133     int i, len = strlen(cpu->machine->md.arc.escape_sequence);
134     int row, col, color, code, start, stop;
135     char *p;
136    
137     if (cpu->machine->md.arc.escape_sequence[0] != '[')
138     return;
139    
140     code = cpu->machine->md.arc.escape_sequence[len-1];
141     cpu->machine->md.arc.escape_sequence[len-1] = '\0';
142    
143     switch (code) {
144     case 'm':
145     color = atoi(cpu->machine->md.arc.escape_sequence + 1);
146     switch (color) {
147     case 0: /* Default. */
148     cpu->machine->md.arc.console_curcolor = 0x1f;
149     cpu->machine->md.arc.console_reverse = 0; break;
150     case 1: /* "Bold". */
151     cpu->machine->md.arc.console_curcolor |= 0x08; break;
152     case 7: /* "Reverse". */
153     cpu->machine->md.arc.console_reverse = 1; break;
154     case 30: /* Black foreground. */
155     cpu->machine->md.arc.console_curcolor &= 0xf0;
156     cpu->machine->md.arc.console_curcolor |= 0x00; break;
157     case 31: /* Red foreground. */
158     cpu->machine->md.arc.console_curcolor &= 0xf0;
159     cpu->machine->md.arc.console_curcolor |= 0x04; break;
160     case 32: /* Green foreground. */
161     cpu->machine->md.arc.console_curcolor &= 0xf0;
162     cpu->machine->md.arc.console_curcolor |= 0x02; break;
163     case 33: /* Yellow foreground. */
164     cpu->machine->md.arc.console_curcolor &= 0xf0;
165     cpu->machine->md.arc.console_curcolor |= 0x06; break;
166     case 34: /* Blue foreground. */
167     cpu->machine->md.arc.console_curcolor &= 0xf0;
168     cpu->machine->md.arc.console_curcolor |= 0x01; break;
169     case 35: /* Red-blue foreground. */
170     cpu->machine->md.arc.console_curcolor &= 0xf0;
171     cpu->machine->md.arc.console_curcolor |= 0x05; break;
172     case 36: /* Green-blue foreground. */
173     cpu->machine->md.arc.console_curcolor &= 0xf0;
174     cpu->machine->md.arc.console_curcolor |= 0x03; break;
175     case 37: /* White foreground. */
176     cpu->machine->md.arc.console_curcolor &= 0xf0;
177     cpu->machine->md.arc.console_curcolor |= 0x07; break;
178     case 40: /* Black background. */
179     cpu->machine->md.arc.console_curcolor &= 0x0f;
180     cpu->machine->md.arc.console_curcolor |= 0x00; break;
181     case 41: /* Red background. */
182     cpu->machine->md.arc.console_curcolor &= 0x0f;
183     cpu->machine->md.arc.console_curcolor |= 0x40; break;
184     case 42: /* Green background. */
185     cpu->machine->md.arc.console_curcolor &= 0x0f;
186     cpu->machine->md.arc.console_curcolor |= 0x20; break;
187     case 43: /* Yellow background. */
188     cpu->machine->md.arc.console_curcolor &= 0x0f;
189     cpu->machine->md.arc.console_curcolor |= 0x60; break;
190     case 44: /* Blue background. */
191     cpu->machine->md.arc.console_curcolor &= 0x0f;
192     cpu->machine->md.arc.console_curcolor |= 0x10; break;
193     case 45: /* Red-blue background. */
194     cpu->machine->md.arc.console_curcolor &= 0x0f;
195     cpu->machine->md.arc.console_curcolor |= 0x50; break;
196     case 46: /* Green-blue background. */
197     cpu->machine->md.arc.console_curcolor &= 0x0f;
198     cpu->machine->md.arc.console_curcolor |= 0x30; break;
199     case 47: /* White background. */
200     cpu->machine->md.arc.console_curcolor &= 0x0f;
201     cpu->machine->md.arc.console_curcolor |= 0x70; break;
202     default:fatal("{ handle_esc_seq: color %i }\n", color);
203     }
204     return;
205     case 'H':
206     p = strchr(cpu->machine->md.arc.escape_sequence, ';');
207     if (p == NULL)
208     return; /* TODO */
209     row = atoi(cpu->machine->md.arc.escape_sequence + 1);
210     col = atoi(p + 1);
211     if (col < 1)
212     col = 1;
213     if (row < 1)
214     row = 1;
215     cpu->machine->md.arc.console_curx = col - 1;
216     cpu->machine->md.arc.console_cury = row - 1;
217     return;
218     case 'J':
219     /*
220     * J = clear screen below cursor, and the rest of the
221     * current line,
222     * 2J = clear whole screen.
223     */
224     i = atoi(cpu->machine->md.arc.escape_sequence + 1);
225     if (i != 0 && i != 2)
226     fatal("{ handle_esc_seq(): %iJ }\n", i);
227     if (i == 0)
228     for (col = cpu->machine->md.arc.console_curx;
229     col < cpu->machine->md.arc.console_maxx; col++)
230     arcbios_putcell(cpu, ' ', col,
231     cpu->machine->md.arc.console_cury);
232     for (col = 0; col < cpu->machine->md.arc.console_maxx; col++)
233     for (row = i? 0 : cpu->machine->md.arc.console_cury+1;
234     row < cpu->machine->md.arc.console_maxy; row++)
235     arcbios_putcell(cpu, ' ', col, row);
236     return;
237     case 'K':
238     col = atoi(cpu->machine->md.arc.escape_sequence + 1);
239     /* 2 = clear line to the right. 1 = to the left (?) */
240     start = 0; stop = cpu->machine->md.arc.console_curx;
241     if (col == 2) {
242     start = cpu->machine->md.arc.console_curx;
243     stop = cpu->machine->md.arc.console_maxx - 1;
244     }
245     for (i=start; i<=stop; i++)
246     arcbios_putcell(cpu, ' ', i,
247     cpu->machine->md.arc.console_cury);
248    
249     return;
250     }
251    
252     fatal("{ handle_esc_seq(): unimplemented escape sequence: ");
253     for (i=0; i<len; i++) {
254     int x = cpu->machine->md.arc.escape_sequence[i];
255     if (i == len-1)
256     x = code;
257    
258     if (x >= ' ' && x < 127)
259     fatal("%c", x);
260     else
261     fatal("[0x%02x]", x);
262     }
263     fatal(" }\n");
264     }
265    
266    
267     /*
268     * scroll_if_necessary():
269     */
270     static void scroll_if_necessary(struct cpu *cpu)
271     {
272     /* Scroll? */
273     if (cpu->machine->md.arc.console_cury >=
274     cpu->machine->md.arc.console_maxy) {
275     unsigned char buf[2];
276     int x, y;
277     for (y=0; y<cpu->machine->md.arc.console_maxy-1; y++)
278     for (x=0; x<cpu->machine->md.arc.console_maxx;
279     x++) {
280     cpu->memory_rw(cpu, cpu->mem,
281     cpu->machine->md.arc.console_vram +
282     2*(x + cpu->machine->md.arc.
283     console_maxx * (y+1)),
284     &buf[0], sizeof(buf), MEM_READ,
285     CACHE_NONE | PHYSICAL);
286     cpu->memory_rw(cpu, cpu->mem,
287     cpu->machine->md.arc.console_vram +
288     2*(x + cpu->machine->md.arc.
289     console_maxx * y),
290     &buf[0], sizeof(buf), MEM_WRITE,
291     CACHE_NONE | PHYSICAL);
292     }
293    
294     cpu->machine->md.arc.console_cury =
295     cpu->machine->md.arc.console_maxy - 1;
296    
297     for (x=0; x<cpu->machine->md.arc.console_maxx; x++)
298     arcbios_putcell(cpu, ' ', x,
299     cpu->machine->md.arc.console_cury);
300     }
301     }
302    
303    
304     /*
305     * arcbios_putchar():
306     *
307     * If we're using X11 with VGA-style console, then output to that console.
308     * Otherwise, use console_putchar().
309     */
310     static void arcbios_putchar(struct cpu *cpu, int ch)
311     {
312     int addr;
313     unsigned char byte;
314    
315     if (!cpu->machine->md.arc.vgaconsole) {
316     /* Text console output: */
317    
318     /* Hack for Windows NT, which uses 0x9b instead of ESC + [ */
319     if (ch == 0x9b) {
320     console_putchar(cpu->machine->main_console_handle, 27);
321     ch = '[';
322     }
323     console_putchar(cpu->machine->main_console_handle, ch);
324     return;
325     }
326    
327     if (cpu->machine->md.arc.in_escape_sequence) {
328     int len = strlen(cpu->machine->md.arc.escape_sequence);
329     cpu->machine->md.arc.escape_sequence[len] = ch;
330     len++;
331     if (len >= ARC_MAX_ESC)
332     len = ARC_MAX_ESC;
333     cpu->machine->md.arc.escape_sequence[len] = '\0';
334     if ((ch >= 'a' && ch <= 'z') ||
335     (ch >= 'A' && ch <= 'Z') || len >= ARC_MAX_ESC) {
336     handle_esc_seq(cpu);
337     cpu->machine->md.arc.in_escape_sequence = 0;
338     }
339     } else {
340     if (ch == 27) {
341     cpu->machine->md.arc.in_escape_sequence = 1;
342     cpu->machine->md.arc.escape_sequence[0] = '\0';
343     } else if (ch == 0x9b) {
344     cpu->machine->md.arc.in_escape_sequence = 1;
345     cpu->machine->md.arc.escape_sequence[0] = '[';
346     cpu->machine->md.arc.escape_sequence[1] = '\0';
347     } else if (ch == '\b') {
348     if (cpu->machine->md.arc.console_curx > 0)
349     cpu->machine->md.arc.console_curx --;
350     } else if (ch == '\r') {
351     cpu->machine->md.arc.console_curx = 0;
352     } else if (ch == '\n') {
353     cpu->machine->md.arc.console_cury ++;
354     } else if (ch == '\t') {
355     cpu->machine->md.arc.console_curx =
356     ((cpu->machine->md.arc.console_curx - 1)
357     | 7) + 1;
358     /* TODO: Print spaces? */
359     } else {
360     /* Put char: */
361     if (cpu->machine->md.arc.console_curx >=
362     cpu->machine->md.arc.console_maxx) {
363     cpu->machine->md.arc.console_curx = 0;
364     cpu->machine->md.arc.console_cury ++;
365     scroll_if_necessary(cpu);
366     }
367     arcbios_putcell(cpu, ch,
368     cpu->machine->md.arc.console_curx,
369     cpu->machine->md.arc.console_cury);
370     cpu->machine->md.arc.console_curx ++;
371     }
372     }
373    
374     scroll_if_necessary(cpu);
375    
376     /* Update cursor position: */
377     addr = (cpu->machine->md.arc.console_curx >=
378     cpu->machine->md.arc.console_maxx?
379     cpu->machine->md.arc.console_maxx - 1 :
380     cpu->machine->md.arc.console_curx) +
381     cpu->machine->md.arc.console_cury *
382     cpu->machine->md.arc.console_maxx;
383     byte = 0x0e;
384     cpu->memory_rw(cpu, cpu->mem, cpu->machine->md.arc.
385     console_ctrlregs + 0x14,
386     &byte, sizeof(byte), MEM_WRITE, CACHE_NONE | PHYSICAL);
387     byte = (addr >> 8) & 255;
388     cpu->memory_rw(cpu, cpu->mem, cpu->machine->md.arc.
389     console_ctrlregs + 0x15,
390     &byte, sizeof(byte), MEM_WRITE, CACHE_NONE | PHYSICAL);
391     byte = 0x0f;
392     cpu->memory_rw(cpu, cpu->mem, cpu->machine->md.arc.
393     console_ctrlregs + 0x14,
394     &byte, sizeof(byte), MEM_WRITE, CACHE_NONE | PHYSICAL);
395     byte = addr & 255;
396     cpu->memory_rw(cpu, cpu->mem, cpu->machine->md.arc.
397     console_ctrlregs + 0x15,
398     &byte, sizeof(byte), MEM_WRITE, CACHE_NONE | PHYSICAL);
399     }
400    
401    
402     /*
403     * arcbios_putstring():
404     */
405     static void arcbios_putstring(struct cpu *cpu, char *s)
406     {
407     while (*s) {
408     if (*s == '\n')
409     arcbios_putchar(cpu, '\r');
410     arcbios_putchar(cpu, *s++);
411     }
412     }
413    
414    
415     /*
416     * arcbios_register_scsicontroller():
417     */
418     void arcbios_register_scsicontroller(struct machine *machine,
419     uint64_t scsicontroller_component)
420     {
421     machine->md.arc.scsicontroller = scsicontroller_component;
422     }
423    
424    
425     /*
426     * arcbios_get_scsicontroller():
427     */
428     uint64_t arcbios_get_scsicontroller(struct machine *machine)
429     {
430     return machine->md.arc.scsicontroller;
431     }
432    
433    
434     /*
435     * arcbios_add_memory_descriptor():
436     *
437     * NOTE: arctype is the ARC type, not the SGI type. This function takes
438     * care of converting, when necessary.
439     */
440     void arcbios_add_memory_descriptor(struct cpu *cpu,
441     uint64_t base, uint64_t len, int arctype)
442     {
443     uint64_t memdesc_addr;
444     int s;
445     struct arcbios_mem arcbios_mem;
446     struct arcbios_mem64 arcbios_mem64;
447    
448     base /= 4096;
449     len /= 4096;
450    
451     /*
452     * TODO: Huh? Why isn't it necessary to convert from arc to sgi types?
453     *
454 dpavlin 22 * TODO 2: It seems that it _is_ necessary, but NetBSD's arcdiag
455 dpavlin 14 * doesn't handle the sgi case separately.
456     */
457     #if 1
458     if (cpu->machine->machine_type == MACHINE_SGI) {
459     /* arctype is SGI style */
460     /* printf("%i => ", arctype); */
461     switch (arctype) {
462     case 0: arctype = 0; break;
463     case 1: arctype = 1; break;
464     case 2: arctype = 3; break;
465     case 3: arctype = 4; break;
466     case 4: arctype = 5; break;
467     case 5: arctype = 6; break;
468     case 6: arctype = 7; break;
469     case 7: arctype = 2; break;
470     }
471     /* printf("%i\n", arctype); */
472     }
473     #endif
474     if (cpu->machine->md.arc.arc_64bit)
475     s = sizeof(arcbios_mem64);
476     else
477     s = sizeof(arcbios_mem);
478    
479     memdesc_addr = cpu->machine->md.arc.memdescriptor_base +
480     cpu->machine->md.arc.n_memdescriptors * s;
481    
482     if (cpu->machine->md.arc.arc_64bit) {
483     memset(&arcbios_mem64, 0, s);
484     store_32bit_word_in_host(cpu,
485     (unsigned char *)&arcbios_mem64.Type, arctype);
486     store_64bit_word_in_host(cpu,
487     (unsigned char *)&arcbios_mem64.BasePage, base);
488     store_64bit_word_in_host(cpu,
489     (unsigned char *)&arcbios_mem64.PageCount, len);
490     store_buf(cpu, memdesc_addr, (char *)&arcbios_mem64, s);
491     } else {
492     memset(&arcbios_mem, 0, s);
493     store_32bit_word_in_host(cpu,
494     (unsigned char *)&arcbios_mem.Type, arctype);
495     store_32bit_word_in_host(cpu,
496     (unsigned char *)&arcbios_mem.BasePage, base);
497     store_32bit_word_in_host(cpu,
498     (unsigned char *)&arcbios_mem.PageCount, len);
499     store_buf(cpu, memdesc_addr, (char *)&arcbios_mem, s);
500     }
501    
502     cpu->machine->md.arc.n_memdescriptors ++;
503     }
504    
505    
506     /*
507     * arcbios_addchild():
508     *
509     * host_tmp_component is a temporary component, with data formated for
510     * the host system. It needs to be translated/copied into emulated RAM.
511     *
512     * Return value is the virtual (emulated) address of the added component.
513     *
514     * TODO: This function doesn't care about memory management, but simply
515     * stores the new child after the last stored child.
516     * TODO: This stuff is really ugly.
517     */
518     static uint64_t arcbios_addchild(struct cpu *cpu,
519     struct arcbios_component *host_tmp_component,
520     char *identifier, uint32_t parent)
521     {
522     struct machine *machine = cpu->machine;
523     uint64_t a = machine->md.arc.next_component_address;
524     uint32_t peer=0;
525     uint32_t child=0;
526     int n_left;
527     uint64_t peeraddr = FIRST_ARC_COMPONENT;
528    
529     /*
530     * This component has no children yet, but it may have peers (that is,
531     * other components that share this component's parent) so we have to
532     * set the peer value correctly.
533     *
534     * Also, if this is the first child of some parent, the parent's child
535     * pointer should be set to point to this component. (But only if it
536     * is the first.)
537     *
538     * This is really ugly: scan through all components, starting from
539     * FIRST_ARC_COMPONENT, to find a component with the same parent as
540     * this component will have. If such a component is found, and its
541     * 'peer' value is NULL, then set it to this component's address (a).
542     *
543     * TODO: make this nicer
544     */
545    
546     n_left = machine->md.arc.n_components;
547     while (n_left > 0) {
548     /* Load parent, child, and peer values: */
549     uint32_t eparent, echild, epeer, tmp;
550     unsigned char buf[4];
551    
552     /* debug("[ addchild: peeraddr = 0x%08x ]\n",
553     (int)peeraddr); */
554    
555     cpu->memory_rw(cpu, cpu->mem,
556     peeraddr + 0 * machine->md.arc.wordlen, &buf[0],
557     sizeof(eparent), MEM_READ, CACHE_NONE);
558     if (cpu->byte_order == EMUL_BIG_ENDIAN) {
559     unsigned char tmp;
560     tmp = buf[0]; buf[0] = buf[3]; buf[3] = tmp;
561     tmp = buf[1]; buf[1] = buf[2]; buf[2] = tmp;
562     }
563     epeer = buf[0] + (buf[1]<<8) + (buf[2]<<16) + (buf[3]<<24);
564    
565     cpu->memory_rw(cpu, cpu->mem, peeraddr + 1 *
566     machine->md.arc.wordlen,
567     &buf[0], sizeof(eparent), MEM_READ, CACHE_NONE);
568     if (cpu->byte_order == EMUL_BIG_ENDIAN) {
569     unsigned char tmp; tmp = buf[0];
570     buf[0] = buf[3]; buf[3] = tmp;
571     tmp = buf[1]; buf[1] = buf[2]; buf[2] = tmp;
572     }
573     echild = buf[0] + (buf[1]<<8) + (buf[2]<<16) + (buf[3]<<24);
574    
575     cpu->memory_rw(cpu, cpu->mem, peeraddr + 2 *
576     machine->md.arc.wordlen,
577     &buf[0], sizeof(eparent), MEM_READ, CACHE_NONE);
578     if (cpu->byte_order == EMUL_BIG_ENDIAN) {
579     unsigned char tmp; tmp = buf[0];
580     buf[0] = buf[3]; buf[3] = tmp;
581     tmp = buf[1]; buf[1] = buf[2]; buf[2] = tmp;
582     }
583     eparent = buf[0] + (buf[1]<<8) + (buf[2]<<16) + (buf[3]<<24);
584    
585     /* debug(" epeer=%x echild=%x eparent=%x\n",
586     (int)epeer,(int)echild,(int)eparent); */
587    
588     if ((uint32_t)eparent == (uint32_t)parent &&
589     (uint32_t)epeer == 0) {
590     epeer = a;
591     store_32bit_word(cpu, peeraddr + 0x00, epeer);
592     /* debug("[ addchild: adding 0x%08x as peer "
593     "to 0x%08x ]\n", (int)a, (int)peeraddr); */
594     }
595     if ((uint32_t)peeraddr == (uint32_t)parent &&
596     (uint32_t)echild == 0) {
597     echild = a;
598     store_32bit_word(cpu, peeraddr + 0x04, echild);
599     /* debug("[ addchild: adding 0x%08x as "
600     "child to 0x%08x ]\n", (int)a, (int)peeraddr); */
601     }
602    
603     /* Go to the next component: */
604     cpu->memory_rw(cpu, cpu->mem, peeraddr + 0x28, &buf[0],
605     sizeof(eparent), MEM_READ, CACHE_NONE);
606     if (cpu->byte_order == EMUL_BIG_ENDIAN) {
607     unsigned char tmp; tmp = buf[0];
608     buf[0] = buf[3]; buf[3] = tmp;
609     tmp = buf[1]; buf[1] = buf[2]; buf[2] = tmp;
610     }
611     tmp = buf[0] + (buf[1]<<8) + (buf[2]<<16) + (buf[3]<<24);
612     peeraddr += 0x30;
613     peeraddr += tmp + 1;
614     peeraddr = ((peeraddr - 1) | 3) + 1;
615    
616     n_left --;
617     }
618    
619     store_32bit_word(cpu, a + 0x00, peer);
620     store_32bit_word(cpu, a + 0x04, child);
621     store_32bit_word(cpu, a + 0x08, parent);
622     store_32bit_word(cpu, a+ 0x0c, host_tmp_component->Class);
623     store_32bit_word(cpu, a+ 0x10, host_tmp_component->Type);
624     store_32bit_word(cpu, a+ 0x14, host_tmp_component->Flags +
625     65536 * host_tmp_component->Version);
626     store_32bit_word(cpu, a+ 0x18, host_tmp_component->Revision);
627     store_32bit_word(cpu, a+ 0x1c, host_tmp_component->Key);
628     store_32bit_word(cpu, a+ 0x20, host_tmp_component->AffinityMask);
629     store_32bit_word(cpu, a+ 0x24, host_tmp_component->
630     ConfigurationDataSize);
631     store_32bit_word(cpu, a+ 0x28, host_tmp_component->IdentifierLength);
632     store_32bit_word(cpu, a+ 0x2c, host_tmp_component->Identifier);
633    
634     machine->md.arc.next_component_address += 0x30;
635    
636     if (host_tmp_component->IdentifierLength != 0) {
637     store_32bit_word(cpu, a + 0x2c, a + 0x30);
638     store_string(cpu, a + 0x30, identifier);
639     if (identifier != NULL)
640     machine->md.arc.next_component_address +=
641     strlen(identifier) + 1;
642     }
643    
644     machine->md.arc.next_component_address ++;
645    
646     /* Round up to next 0x4 bytes: */
647     machine->md.arc.next_component_address =
648     ((machine->md.arc.next_component_address - 1) | 3) + 1;
649    
650     machine->md.arc.n_components ++;
651    
652     return a;
653     }
654    
655    
656     /*
657     * arcbios_addchild64():
658     *
659     * host_tmp_component is a temporary component, with data formated for
660     * the host system. It needs to be translated/copied into emulated RAM.
661     *
662     * Return value is the virtual (emulated) address of the added component.
663     *
664     * TODO: This function doesn't care about memory management, but simply
665     * stores the new child after the last stored child.
666     * TODO: This stuff is really ugly.
667     */
668     static uint64_t arcbios_addchild64(struct cpu *cpu,
669     struct arcbios_component64 *host_tmp_component,
670     char *identifier, uint64_t parent)
671     {
672     struct machine *machine = cpu->machine;
673     uint64_t a = machine->md.arc.next_component_address;
674     uint64_t peer=0;
675     uint64_t child=0;
676     int n_left;
677     uint64_t peeraddr = FIRST_ARC_COMPONENT;
678    
679     /*
680     * This component has no children yet, but it may have peers (that is,
681     * other components that share this component's parent) so we have to
682     * set the peer value correctly.
683     *
684     * Also, if this is the first child of some parent, the parent's child
685     * pointer should be set to point to this component. (But only if it
686     * is the first.)
687     *
688     * This is really ugly: scan through all components, starting from
689     * FIRST_ARC_COMPONENT, to find a component with the same parent as
690     * this component will have. If such a component is found, and its
691     * 'peer' value is NULL, then set it to this component's address (a).
692     *
693     * TODO: make this nicer
694     */
695    
696     n_left = machine->md.arc.n_components;
697     while (n_left > 0) {
698     /* Load parent, child, and peer values: */
699     uint64_t eparent, echild, epeer, tmp;
700     unsigned char buf[8];
701    
702 dpavlin 24 /* debug("[ addchild: peeraddr = 0x%016"PRIx64" ]\n",
703     (uint64_t) peeraddr); */
704 dpavlin 14
705     cpu->memory_rw(cpu, cpu->mem,
706     peeraddr + 0 * machine->md.arc.wordlen, &buf[0],
707     sizeof(eparent), MEM_READ, CACHE_NONE);
708     if (cpu->byte_order == EMUL_BIG_ENDIAN) {
709     unsigned char tmp;
710     tmp = buf[0]; buf[0] = buf[7]; buf[7] = tmp;
711     tmp = buf[1]; buf[1] = buf[6]; buf[6] = tmp;
712     tmp = buf[2]; buf[2] = buf[5]; buf[5] = tmp;
713     tmp = buf[3]; buf[3] = buf[4]; buf[4] = tmp;
714     }
715     epeer = buf[0] + (buf[1]<<8) + (buf[2]<<16) + (buf[3]<<24)
716     + ((uint64_t)buf[4] << 32) + ((uint64_t)buf[5] << 40)
717     + ((uint64_t)buf[6] << 48) + ((uint64_t)buf[7] << 56);
718    
719     cpu->memory_rw(cpu, cpu->mem, peeraddr + 1 *
720     machine->md.arc.wordlen,
721     &buf[0], sizeof(eparent), MEM_READ, CACHE_NONE);
722     if (cpu->byte_order == EMUL_BIG_ENDIAN) {
723     unsigned char tmp;
724     tmp = buf[0]; buf[0] = buf[7]; buf[7] = tmp;
725     tmp = buf[1]; buf[1] = buf[6]; buf[6] = tmp;
726     tmp = buf[2]; buf[2] = buf[5]; buf[5] = tmp;
727     tmp = buf[3]; buf[3] = buf[4]; buf[4] = tmp;
728     }
729     echild = buf[0] + (buf[1]<<8) + (buf[2]<<16) + (buf[3]<<24)
730     + ((uint64_t)buf[4] << 32) + ((uint64_t)buf[5] << 40)
731     + ((uint64_t)buf[6] << 48) + ((uint64_t)buf[7] << 56);
732    
733     cpu->memory_rw(cpu, cpu->mem, peeraddr + 2 *
734     machine->md.arc.wordlen,
735     &buf[0], sizeof(eparent), MEM_READ, CACHE_NONE);
736     if (cpu->byte_order == EMUL_BIG_ENDIAN) {
737     unsigned char tmp;
738     tmp = buf[0]; buf[0] = buf[7]; buf[7] = tmp;
739     tmp = buf[1]; buf[1] = buf[6]; buf[6] = tmp;
740     tmp = buf[2]; buf[2] = buf[5]; buf[5] = tmp;
741     tmp = buf[3]; buf[3] = buf[4]; buf[4] = tmp;
742     }
743     eparent = buf[0] + (buf[1]<<8) + (buf[2]<<16) + (buf[3]<<24)
744     + ((uint64_t)buf[4] << 32) + ((uint64_t)buf[5] << 40)
745     + ((uint64_t)buf[6] << 48) + ((uint64_t)buf[7] << 56);
746    
747 dpavlin 24 /* debug(" epeer=%"PRIx64" echild=%"PRIx64" eparent=%"PRIx64
748     "\n", (uint64_t) epeer, (uint64_t) echild,
749     (uint64_t) eparent); */
750 dpavlin 14
751     if (eparent == parent && epeer == 0) {
752     epeer = a;
753     store_64bit_word(cpu, peeraddr + 0 *
754     machine->md.arc.wordlen, epeer);
755 dpavlin 24 /* debug("[ addchild: adding 0x%016"PRIx64" as peer "
756     "to 0x%016"PRIx64" ]\n", (uint64_t) a,
757     (uint64_t) peeraddr); */
758 dpavlin 14 }
759     if (peeraddr == parent && echild == 0) {
760     echild = a;
761     store_64bit_word(cpu, peeraddr + 1 *
762     machine->md.arc.wordlen, echild);
763 dpavlin 24 /* debug("[ addchild: adding 0x%016"PRIx64" as child "
764     "to 0x%016"PRIx64" ]\n", (uint64_t) a,
765     (uint64_t) peeraddr); */
766 dpavlin 14 }
767    
768     /* Go to the next component: */
769     cpu->memory_rw(cpu, cpu->mem, peeraddr + 0x34,
770     &buf[0], sizeof(uint32_t), MEM_READ, CACHE_NONE);
771     if (cpu->byte_order == EMUL_BIG_ENDIAN) {
772     unsigned char tmp;
773     tmp = buf[0]; buf[0] = buf[3]; buf[3] = tmp;
774     tmp = buf[1]; buf[1] = buf[2]; buf[2] = tmp;
775     }
776     tmp = buf[0] + (buf[1]<<8) + (buf[2]<<16) + (buf[3]<<24);
777    
778     tmp &= 0xfffff;
779    
780     peeraddr += 0x50;
781     peeraddr += tmp + 1;
782     peeraddr = ((peeraddr - 1) | 3) + 1;
783    
784     n_left --;
785     }
786    
787     store_64bit_word(cpu, a + 0x00, peer);
788     store_64bit_word(cpu, a + 0x08, child);
789     store_64bit_word(cpu, a + 0x10, parent);
790     store_32bit_word(cpu, a+ 0x18, host_tmp_component->Class);
791     store_32bit_word(cpu, a+ 0x1c, host_tmp_component->Type);
792     store_32bit_word(cpu, a+ 0x20, host_tmp_component->Flags);
793     store_32bit_word(cpu, a+ 0x24, host_tmp_component->Version +
794     ((uint64_t)host_tmp_component->Revision << 16));
795     store_32bit_word(cpu, a+ 0x28, host_tmp_component->Key);
796     store_64bit_word(cpu, a+ 0x30, host_tmp_component->AffinityMask);
797     store_64bit_word(cpu, a+ 0x38, host_tmp_component->
798     ConfigurationDataSize);
799     store_64bit_word(cpu, a+ 0x40, host_tmp_component->IdentifierLength);
800     store_64bit_word(cpu, a+ 0x48, host_tmp_component->Identifier);
801    
802     /* TODO: Find out how a REAL ARCS64 implementation does it. */
803    
804     machine->md.arc.next_component_address += 0x50;
805    
806     if (host_tmp_component->IdentifierLength != 0) {
807     store_64bit_word(cpu, a + 0x48, a + 0x50);
808     store_string(cpu, a + 0x50, identifier);
809     if (identifier != NULL)
810     machine->md.arc.next_component_address +=
811     strlen(identifier) + 1;
812     }
813    
814     machine->md.arc.next_component_address ++;
815    
816     /* Round up to next 0x8 bytes: */
817     machine->md.arc.next_component_address =
818     ((machine->md.arc.next_component_address - 1) | 7) + 1;
819    
820     machine->md.arc.n_components ++;
821     return a;
822     }
823    
824    
825     /*
826     * arcbios_addchild_manual():
827     *
828     * Used internally to set up component structures.
829     * Parent may only be NULL for the first (system) component.
830     *
831     * Return value is the virtual (emulated) address of the added component.
832     */
833     uint64_t arcbios_addchild_manual(struct cpu *cpu,
834     uint64_t class, uint64_t type, uint64_t flags,
835     uint64_t version, uint64_t revision, uint64_t key,
836     uint64_t affinitymask, char *identifier, uint64_t parent,
837     void *config_data, size_t config_len)
838     {
839     struct machine *machine = cpu->machine;
840     /* This component is only for temporary use: */
841     struct arcbios_component component;
842     struct arcbios_component64 component64;
843    
844     if (config_data != NULL) {
845     unsigned char *p = config_data;
846 dpavlin 22 size_t i;
847 dpavlin 14
848     if (machine->md.arc.n_configuration_data >= MAX_CONFIG_DATA) {
849     printf("fatal error: you need to increase "
850     "MAX_CONFIG_DATA\n");
851     exit(1);
852     }
853    
854     for (i=0; i<config_len; i++) {
855     unsigned char ch = p[i];
856     cpu->memory_rw(cpu, cpu->mem,
857     machine->md.arc.configuration_data_next_addr + i,
858     &ch, 1, MEM_WRITE, CACHE_NONE);
859     }
860    
861     machine->md.arc.configuration_data_len[
862     machine->md.arc.n_configuration_data] = config_len;
863     machine->md.arc.configuration_data_configdata[
864     machine->md.arc.n_configuration_data] =
865     machine->md.arc.configuration_data_next_addr;
866     machine->md.arc.configuration_data_next_addr += config_len;
867     machine->md.arc.configuration_data_component[
868     machine->md.arc.n_configuration_data] =
869     machine->md.arc.next_component_address +
870     (cpu->machine->md.arc.arc_64bit? 0x18 : 0x0c);
871    
872 dpavlin 24 /* printf("& ADDING %i: configdata=0x%016"PRIx64" "
873     "component=0x%016"PRIx64"\n",
874 dpavlin 14 machine->md.arc.n_configuration_data,
875 dpavlin 24 (uint64_t) machine->md.arc.configuration_data_configdata[
876 dpavlin 14 machine->md.arc.n_configuration_data],
877 dpavlin 24 (uint64_t) machine->md.arc.configuration_data_component[
878 dpavlin 14 machine->md.arc.n_configuration_data]); */
879    
880     machine->md.arc.n_configuration_data ++;
881     }
882    
883     if (!cpu->machine->md.arc.arc_64bit) {
884     component.Class = class;
885     component.Type = type;
886     component.Flags = flags;
887     component.Version = version;
888     component.Revision = revision;
889     component.Key = key;
890     component.AffinityMask = affinitymask;
891     component.ConfigurationDataSize = config_len;
892     component.IdentifierLength = 0;
893     component.Identifier = 0;
894     if (identifier != NULL) {
895     component.IdentifierLength = strlen(identifier) + 1;
896     }
897     return arcbios_addchild(cpu, &component, identifier, parent);
898     } else {
899     component64.Class = class;
900     component64.Type = type;
901     component64.Flags = flags;
902     component64.Version = version;
903     component64.Revision = revision;
904     component64.Key = key;
905     component64.AffinityMask = affinitymask;
906     component64.ConfigurationDataSize = config_len;
907     component64.IdentifierLength = 0;
908     component64.Identifier = 0;
909     if (identifier != NULL) {
910     component64.IdentifierLength = strlen(identifier) + 1;
911     }
912     return arcbios_addchild64(cpu, &component64, identifier,
913     parent);
914     }
915     }
916    
917    
918     /*
919     * arcbios_get_msdos_partition_size():
920     *
921     * This function tries to parse MSDOS-style partition tables on a disk
922     * image, and return the starting offset (counted in bytes), and the
923     * size, of a specific partition.
924     *
925     * NOTE: partition_nr is 1-based!
926     *
927     * TODO: This is buggy, it doesn't really handle extended partitions.
928     *
929     * See http://www.nondot.org/sabre/os/files/Partitions/Partitions.html
930     * for more info.
931     */
932     static void arcbios_get_msdos_partition_size(struct machine *machine,
933     int disk_id, int disk_type, int partition_nr, uint64_t *start,
934     uint64_t *size)
935     {
936     int res, i, partition_type, cur_partition = 0;
937     unsigned char sector[512];
938     unsigned char buf[16];
939     uint64_t offset = 0, st;
940    
941     /* Partition 0 is the entire disk image: */
942     *start = 0;
943     *size = diskimage_getsize(machine, disk_id, disk_type);
944     if (partition_nr == 0)
945     return;
946    
947     ugly_goto:
948     *start = 0; *size = 0;
949    
950 dpavlin 24 /* printf("reading MSDOS partition from offset 0x%"PRIx64"\n",
951     (uint64_t) offset); */
952 dpavlin 14
953     res = diskimage_access(machine, disk_id, disk_type, 0, offset,
954     sector, sizeof(sector));
955     if (!res) {
956     fatal("[ arcbios_get_msdos_partition_size(): couldn't "
957 dpavlin 24 "read the disk image, id %i, offset 0x%"PRIx64" ]\n",
958     disk_id, (uint64_t) offset);
959 dpavlin 14 return;
960     }
961    
962     if (sector[510] != 0x55 || sector[511] != 0xaa) {
963     fatal("[ arcbios_get_msdos_partition_size(): not an "
964     "MSDOS partition table ]\n");
965     }
966    
967     #if 0
968     /* Debug dump: */
969     for (i=0; i<4; i++) {
970     int j;
971     printf(" partition %i: ", i+1);
972     for (j=0; j<16; j++)
973     printf(" %02x", sector[446 + i*16 + j]);
974     printf("\n");
975     }
976     #endif
977    
978     for (i=0; i<4; i++) {
979     memmove(buf, sector + 446 + 16*i, 16);
980    
981     partition_type = buf[4];
982    
983     if (partition_type == 0)
984     continue;
985    
986     st = (buf[8] + (buf[9] << 8) + (buf[10] << 16) +
987     (buf[11] << 24)) * 512;
988    
989     if (start != NULL)
990     *start = st;
991     if (size != NULL)
992     *size = (buf[12] + (buf[13] << 8) + (buf[14] << 16) +
993     (buf[15] << 24)) * 512;
994    
995     /* Extended DOS partition: */
996     if (partition_type == 5) {
997     offset += st;
998     goto ugly_goto;
999     }
1000    
1001     /* Found the right partition? Then return. */
1002     cur_partition ++;
1003     if (cur_partition == partition_nr)
1004     return;
1005     }
1006    
1007     fatal("[ partition(%i) NOT found ]\n", partition_nr);
1008     }
1009    
1010    
1011     /*
1012     * arcbios_handle_to_disk_id_and_type():
1013     */
1014     static int arcbios_handle_to_disk_id_and_type(struct machine *machine,
1015     int handle, int *typep)
1016     {
1017     int id, cdrom;
1018     char *s;
1019    
1020     if (handle < 0 || handle >= ARC_MAX_HANDLES)
1021     return -1;
1022    
1023     s = machine->md.arc.file_handle_string[handle];
1024     if (s == NULL)
1025     return -1;
1026    
1027     /*
1028     * s is something like "scsi(0)disk(0)rdisk(0)partition(0)".
1029     * TODO: This is really ugly and hardcoded.
1030     */
1031    
1032     if (strncmp(s, "scsi(", 5) != 0 || strlen(s) < 13)
1033     return -1;
1034    
1035     *typep = DISKIMAGE_SCSI;
1036    
1037     cdrom = (s[7] == 'c');
1038     id = cdrom? atoi(s + 13) : atoi(s + 12);
1039    
1040     return id;
1041     }
1042    
1043    
1044     /*
1045     * arcbios_handle_to_start_and_size():
1046     */
1047     static void arcbios_handle_to_start_and_size(struct machine *machine,
1048     int handle, uint64_t *start, uint64_t *size)
1049     {
1050     char *s = machine->md.arc.file_handle_string[handle];
1051     char *s2;
1052     int disk_id, disk_type;
1053    
1054     disk_id = arcbios_handle_to_disk_id_and_type(machine,
1055     handle, &disk_type);
1056    
1057     if (disk_id < 0)
1058     return;
1059    
1060     /* This works for "partition(0)": */
1061     *start = 0;
1062     *size = diskimage_getsize(machine, disk_id, disk_type);
1063    
1064     s2 = strstr(s, "partition(");
1065     if (s2 != NULL) {
1066     int partition_nr = atoi(s2 + 10);
1067     /* printf("partition_nr = %i\n", partition_nr); */
1068     if (partition_nr != 0)
1069     arcbios_get_msdos_partition_size(machine,
1070     disk_id, disk_type, partition_nr, start, size);
1071     }
1072     }
1073    
1074    
1075     /*
1076     * arcbios_getfileinformation():
1077     *
1078     * Fill in a GetFileInformation struct in emulated memory,
1079     * for a specific file handle. (This is used to get the size
1080     * and offsets of partitions on disk images.)
1081     */
1082     static int arcbios_getfileinformation(struct cpu *cpu)
1083     {
1084     int handle = cpu->cd.mips.gpr[MIPS_GPR_A0];
1085     uint64_t addr = cpu->cd.mips.gpr[MIPS_GPR_A1];
1086     uint64_t start, size;
1087    
1088     arcbios_handle_to_start_and_size(cpu->machine, handle, &start, &size);
1089    
1090     store_64bit_word(cpu, addr + 0, 0);
1091     store_64bit_word(cpu, addr + 8, size);
1092     store_64bit_word(cpu, addr + 16, 0);
1093     store_32bit_word(cpu, addr + 24, 1);
1094     store_32bit_word(cpu, addr + 28, 0);
1095     store_32bit_word(cpu, addr + 32, 0);
1096    
1097     /* printf("\n!!! size=0x%x start=0x%x\n", (int)size, (int)start); */
1098    
1099     return ARCBIOS_ESUCCESS;
1100     }
1101    
1102    
1103     /*
1104     * arcbios_private_emul():
1105     *
1106     * TODO: This is probably SGI specific. (?)
1107     *
1108     * 0x04 get nvram table
1109     */
1110     void arcbios_private_emul(struct cpu *cpu)
1111     {
1112     int vector = cpu->pc & 0xfff;
1113    
1114     switch (vector) {
1115     case 0x04:
1116     debug("[ ARCBIOS PRIVATE get nvram table(): TODO ]\n");
1117     cpu->cd.mips.gpr[MIPS_GPR_V0] = 0;
1118     break;
1119     default:
1120     cpu_register_dump(cpu->machine, cpu, 1, 0x1);
1121     debug("a0 points to: ");
1122     dump_mem_string(cpu, cpu->cd.mips.gpr[MIPS_GPR_A0]);
1123     debug("\n");
1124     fatal("ARCBIOS: unimplemented PRIVATE vector 0x%x\n", vector);
1125     cpu->running = 0;
1126     }
1127     }
1128    
1129    
1130     /*
1131     * arcbios_emul(): ARCBIOS emulation
1132     *
1133     * 0x0c Halt()
1134     * 0x10 PowerDown()
1135     * 0x14 Restart()
1136     * 0x18 Reboot()
1137     * 0x1c EnterInteractiveMode()
1138     * 0x20 ReturnFromMain()
1139     * 0x24 GetPeer(node)
1140     * 0x28 GetChild(node)
1141     * 0x2c GetParent(node)
1142     * 0x30 GetConfigurationData(config_data, node)
1143     * 0x3c GetComponent(name)
1144     * 0x44 GetSystemId()
1145     * 0x48 GetMemoryDescriptor(void *)
1146     * 0x50 GetTime()
1147     * 0x54 GetRelativeTime()
1148     * 0x5c Open(path, mode, &fileid)
1149     * 0x60 Close(handle)
1150     * 0x64 Read(handle, &buf, len, &actuallen)
1151     * 0x6c Write(handle, buf, len, &returnlen)
1152     * 0x70 Seek(handle, &offset, len)
1153     * 0x78 GetEnvironmentVariable(char *)
1154     * 0x7c SetEnvironmentVariable(char *, char *)
1155     * 0x80 GetFileInformation(handle, buf)
1156     * 0x88 FlushAllCaches()
1157     * 0x90 GetDisplayStatus(uint32_t handle)
1158     * 0x100 undocumented IRIX (?)
1159     */
1160     int arcbios_emul(struct cpu *cpu)
1161     {
1162     struct machine *machine = cpu->machine;
1163     int vector = cpu->pc & 0xfff;
1164     int i, j, handle;
1165     unsigned char ch2;
1166     unsigned char buf[40];
1167    
1168     if (cpu->pc >= ARC_PRIVATE_ENTRIES &&
1169     cpu->pc < ARC_PRIVATE_ENTRIES + 100*sizeof(uint32_t)) {
1170     arcbios_private_emul(cpu);
1171     return 1;
1172     }
1173    
1174     if (machine->md.arc.arc_64bit)
1175     vector /= 2;
1176    
1177     /* Special case for reboot by jumping to 0xbfc00000: */
1178     if (vector == 0 && (cpu->pc & 0xffffffffULL) == 0xbfc00000ULL)
1179     vector = 0x18;
1180    
1181     switch (vector) {
1182     case 0x0c: /* Halt() */
1183     case 0x10: /* PowerDown() */
1184     case 0x14: /* Restart() */
1185     case 0x18: /* Reboot() */
1186     case 0x1c: /* EnterInteractiveMode() */
1187     case 0x20: /* ReturnFromMain() */
1188     debug("[ ARCBIOS Halt() or similar ]\n");
1189     /* Halt all CPUs. */
1190     for (i=0; i<machine->ncpus; i++) {
1191     machine->cpus[i]->running = 0;
1192     }
1193     machine->exit_without_entering_debugger = 1;
1194     break;
1195     case 0x24: /* GetPeer(node) */
1196     if (cpu->cd.mips.gpr[MIPS_GPR_A0] == 0) {
1197     /* NULL ptr argument: return NULL. */
1198     cpu->cd.mips.gpr[MIPS_GPR_V0] = 0;
1199     } else {
1200     uint64_t peer;
1201     cpu->memory_rw(cpu, cpu->mem,
1202     cpu->cd.mips.gpr[MIPS_GPR_A0] - 3 *
1203     machine->md.arc.wordlen, &buf[0],
1204     machine->md.arc.wordlen, MEM_READ, CACHE_NONE);
1205     if (machine->md.arc.arc_64bit) {
1206     if (cpu->byte_order == EMUL_BIG_ENDIAN) {
1207     unsigned char tmp; tmp = buf[0];
1208     buf[0] = buf[7]; buf[7] = tmp;
1209     tmp = buf[1]; buf[1] = buf[6];
1210     buf[6] = tmp;
1211     tmp = buf[2]; buf[2] = buf[5];
1212     buf[5] = tmp;
1213     tmp = buf[3]; buf[3] = buf[4];
1214     buf[4] = tmp;
1215     }
1216     peer = (uint64_t)buf[0] + ((uint64_t)buf[1]<<8)
1217     + ((uint64_t)buf[2]<<16)
1218     + ((uint64_t)buf[3]<<24)
1219     + ((uint64_t)buf[4]<<32)
1220     + ((uint64_t)buf[5]<<40)
1221     + ((uint64_t)buf[6]<<48)
1222     + ((uint64_t)buf[7]<<56);
1223     } else {
1224     if (cpu->byte_order == EMUL_BIG_ENDIAN) {
1225     unsigned char tmp; tmp = buf[0];
1226     buf[0] = buf[3]; buf[3] = tmp;
1227     tmp = buf[1]; buf[1] = buf[2];
1228     buf[2] = tmp;
1229     }
1230     peer = buf[0] + (buf[1]<<8) + (buf[2]<<16)
1231     + (buf[3]<<24);
1232     }
1233    
1234     cpu->cd.mips.gpr[MIPS_GPR_V0] = peer?
1235     (peer + 3 * machine->md.arc.wordlen) : 0;
1236     if (!machine->md.arc.arc_64bit)
1237     cpu->cd.mips.gpr[MIPS_GPR_V0] = (int64_t)
1238     (int32_t) cpu->cd.mips.gpr[MIPS_GPR_V0];
1239     }
1240 dpavlin 24 debug("[ ARCBIOS GetPeer(node 0x%016"PRIx64"): 0x%016"PRIx64
1241     " ]\n", (uint64_t) cpu->cd.mips.gpr[MIPS_GPR_A0],
1242     (uint64_t) cpu->cd.mips.gpr[MIPS_GPR_V0]);
1243 dpavlin 14 break;
1244     case 0x28: /* GetChild(node) */
1245     /* 0 for the root, non-0 for children: */
1246     if (cpu->cd.mips.gpr[MIPS_GPR_A0] == 0)
1247     cpu->cd.mips.gpr[MIPS_GPR_V0] = FIRST_ARC_COMPONENT
1248     + machine->md.arc.wordlen * 3;
1249     else {
1250     uint64_t child = 0;
1251     cpu->memory_rw(cpu, cpu->mem,
1252     cpu->cd.mips.gpr[MIPS_GPR_A0] - 2 *
1253     machine->md.arc.wordlen, &buf[0], machine->
1254     md.arc.wordlen, MEM_READ, CACHE_NONE);
1255     if (machine->md.arc.arc_64bit) {
1256     if (cpu->byte_order == EMUL_BIG_ENDIAN) {
1257     unsigned char tmp; tmp = buf[0];
1258     buf[0] = buf[7]; buf[7] = tmp;
1259     tmp = buf[1]; buf[1] = buf[6];
1260     buf[6] = tmp;
1261     tmp = buf[2]; buf[2] = buf[5];
1262     buf[5] = tmp;
1263     tmp = buf[3]; buf[3] = buf[4];
1264     buf[4] = tmp;
1265     }
1266     child = (uint64_t)buf[0] +
1267     ((uint64_t)buf[1]<<8) +
1268     ((uint64_t)buf[2]<<16) +
1269     ((uint64_t)buf[3]<<24) +
1270     ((uint64_t)buf[4]<<32) +
1271     ((uint64_t)buf[5]<<40) +
1272     ((uint64_t)buf[6]<<48) +
1273     ((uint64_t)buf[7]<<56);
1274     } else {
1275     if (cpu->byte_order == EMUL_BIG_ENDIAN) {
1276     unsigned char tmp; tmp = buf[0];
1277     buf[0] = buf[3]; buf[3] = tmp;
1278     tmp = buf[1]; buf[1] = buf[2];
1279     buf[2] = tmp;
1280     }
1281     child = buf[0] + (buf[1]<<8) + (buf[2]<<16) +
1282     (buf[3]<<24);
1283     }
1284    
1285     cpu->cd.mips.gpr[MIPS_GPR_V0] = child?
1286     (child + 3 * machine->md.arc.wordlen) : 0;
1287     if (!machine->md.arc.arc_64bit)
1288     cpu->cd.mips.gpr[MIPS_GPR_V0] = (int64_t)
1289     (int32_t)cpu->cd.mips.gpr[MIPS_GPR_V0];
1290     }
1291 dpavlin 24 debug("[ ARCBIOS GetChild(node 0x%016"PRIx64"): 0x%016"
1292     PRIx64" ]\n", (uint64_t) cpu->cd.mips.gpr[MIPS_GPR_A0],
1293     (uint64_t) cpu->cd.mips.gpr[MIPS_GPR_V0]);
1294 dpavlin 14 break;
1295     case 0x2c: /* GetParent(node) */
1296     {
1297     uint64_t parent;
1298    
1299     cpu->memory_rw(cpu, cpu->mem,
1300     cpu->cd.mips.gpr[MIPS_GPR_A0] - 1 * machine->
1301     md.arc.wordlen, &buf[0], machine->md.arc.wordlen,
1302     MEM_READ, CACHE_NONE);
1303    
1304     if (machine->md.arc.arc_64bit) {
1305     if (cpu->byte_order == EMUL_BIG_ENDIAN) {
1306     unsigned char tmp; tmp = buf[0];
1307     buf[0] = buf[7]; buf[7] = tmp;
1308     tmp = buf[1]; buf[1] = buf[6];
1309     buf[6] = tmp;
1310     tmp = buf[2]; buf[2] = buf[5];
1311     buf[5] = tmp;
1312     tmp = buf[3]; buf[3] = buf[4];
1313     buf[4] = tmp;
1314     }
1315     parent = (uint64_t)buf[0] +
1316     ((uint64_t)buf[1]<<8) +
1317     ((uint64_t)buf[2]<<16) +
1318     ((uint64_t)buf[3]<<24) +
1319     ((uint64_t)buf[4]<<32) +
1320     ((uint64_t)buf[5]<<40) +
1321     ((uint64_t)buf[6]<<48) +
1322     ((uint64_t)buf[7]<<56);
1323     } else {
1324     if (cpu->byte_order == EMUL_BIG_ENDIAN) {
1325     unsigned char tmp; tmp = buf[0];
1326     buf[0] = buf[3]; buf[3] = tmp;
1327     tmp = buf[1]; buf[1] = buf[2];
1328     buf[2] = tmp;
1329     }
1330     parent = buf[0] + (buf[1]<<8) +
1331     (buf[2]<<16) + (buf[3]<<24);
1332     }
1333    
1334     cpu->cd.mips.gpr[MIPS_GPR_V0] = parent?
1335     (parent + 3 * machine->md.arc.wordlen) : 0;
1336     if (!machine->md.arc.arc_64bit)
1337     cpu->cd.mips.gpr[MIPS_GPR_V0] = (int64_t)
1338     (int32_t) cpu->cd.mips.gpr[MIPS_GPR_V0];
1339     }
1340 dpavlin 24 debug("[ ARCBIOS GetParent(node 0x%016"PRIx64"): 0x%016"
1341     PRIx64" ]\n", (uint64_t) cpu->cd.mips.gpr[MIPS_GPR_A0],
1342     (uint64_t) cpu->cd.mips.gpr[MIPS_GPR_V0]);
1343 dpavlin 14 break;
1344     case 0x30: /* GetConfigurationData(void *configdata, void *node) */
1345 dpavlin 24 /* fatal("[ ARCBIOS GetConfigurationData(0x%016"PRIx64","
1346     "0x%016"PRIx64") ]\n",
1347     (uint64_t) cpu->cd.mips.gpr[MIPS_GPR_A0],
1348     (uint64_t) cpu->cd.mips.gpr[MIPS_GPR_A1]); */
1349 dpavlin 14 cpu->cd.mips.gpr[MIPS_GPR_V0] = ARCBIOS_EINVAL;
1350     for (i=0; i<machine->md.arc.n_configuration_data; i++) {
1351     /* fatal("configuration_data_component[%i] = "
1352 dpavlin 24 "0x%016"PRIx64"\n", i, (uint64_t) machine->
1353 dpavlin 14 md.arc.configuration_data_component[i]); */
1354     if (cpu->cd.mips.gpr[MIPS_GPR_A1] ==
1355     machine->md.arc.configuration_data_component[i]) {
1356     cpu->cd.mips.gpr[MIPS_GPR_V0] = 0;
1357     for (j=0; j<machine->
1358     md.arc.configuration_data_len[i]; j++) {
1359     unsigned char ch;
1360     cpu->memory_rw(cpu, cpu->mem,
1361     machine->md.arc.
1362     configuration_data_configdata[i] +
1363     j, &ch, 1, MEM_READ, CACHE_NONE);
1364     cpu->memory_rw(cpu, cpu->mem,
1365     cpu->cd.mips.gpr[MIPS_GPR_A0] + j,
1366     &ch, 1, MEM_WRITE, CACHE_NONE);
1367     }
1368     break;
1369     }
1370     }
1371     break;
1372     case 0x3c: /* GetComponent(char *name) */
1373     debug("[ ARCBIOS GetComponent(\"");
1374     dump_mem_string(cpu, cpu->cd.mips.gpr[MIPS_GPR_A0]);
1375     debug("\") ]\n");
1376    
1377     if (cpu->cd.mips.gpr[MIPS_GPR_A0] == 0) {
1378     fatal("[ ARCBIOS GetComponent: NULL ptr ]\n");
1379     } else {
1380     unsigned char buf[500];
1381     int match_index = -1;
1382     int match_len = 0;
1383    
1384     memset(buf, 0, sizeof(buf));
1385 dpavlin 22 for (i=0; i<(ssize_t)sizeof(buf); i++) {
1386 dpavlin 14 cpu->memory_rw(cpu, cpu->mem,
1387     cpu->cd.mips.gpr[MIPS_GPR_A0] + i,
1388     &buf[i], 1, MEM_READ, CACHE_NONE);
1389     if (buf[i] == '\0')
1390     i = sizeof(buf);
1391     }
1392     buf[sizeof(buf) - 1] = '\0';
1393    
1394     /* "scsi(0)disk(0)rdisk(0)partition(0)" and such. */
1395     /* printf("GetComponent(\"%s\")\n", buf); */
1396    
1397     /* Default to NULL return value. */
1398     cpu->cd.mips.gpr[MIPS_GPR_V0] = 0;
1399    
1400     /* Scan the string to component table: */
1401     for (i=0; i<machine->md.arc.n_string_to_components;
1402     i++) {
1403     int m = 0;
1404     while (buf[m] && machine->md.arc.
1405     string_to_component[i][m] &&
1406     machine->md.arc.string_to_component[i][m]
1407     == buf[m])
1408     m++;
1409     if (m > match_len) {
1410     match_len = m;
1411     match_index = i;
1412     }
1413     }
1414    
1415     if (match_index >= 0) {
1416     /* printf("Longest match: '%s'\n",
1417     machine->md.arc.string_to_component[
1418     match_index]); */
1419     cpu->cd.mips.gpr[MIPS_GPR_V0] =
1420     machine->md.arc.string_to_component_value[
1421     match_index];
1422     }
1423     }
1424     break;
1425     case 0x44: /* GetSystemId() */
1426     debug("[ ARCBIOS GetSystemId() ]\n");
1427     cpu->cd.mips.gpr[MIPS_GPR_V0] = SGI_SYSID_ADDR;
1428     break;
1429     case 0x48: /* void *GetMemoryDescriptor(void *ptr) */
1430     debug("[ ARCBIOS GetMemoryDescriptor(0x%08x) ]\n",
1431     (int)cpu->cd.mips.gpr[MIPS_GPR_A0]);
1432    
1433     /* If a0=NULL, then return the first descriptor: */
1434     if ((uint32_t)cpu->cd.mips.gpr[MIPS_GPR_A0] == 0)
1435     cpu->cd.mips.gpr[MIPS_GPR_V0] =
1436     machine->md.arc.memdescriptor_base;
1437     else {
1438     int s = machine->md.arc.arc_64bit?
1439     sizeof(struct arcbios_mem64)
1440     : sizeof(struct arcbios_mem);
1441     int nr = cpu->cd.mips.gpr[MIPS_GPR_A0] -
1442     machine->md.arc.memdescriptor_base;
1443     nr /= s;
1444     nr ++;
1445     cpu->cd.mips.gpr[MIPS_GPR_V0] =
1446     machine->md.arc.memdescriptor_base + s * nr;
1447     if (nr >= machine->md.arc.n_memdescriptors)
1448     cpu->cd.mips.gpr[MIPS_GPR_V0] = 0;
1449     }
1450     break;
1451     case 0x50: /* GetTime() */
1452     debug("[ ARCBIOS GetTime() ]\n");
1453     cpu->cd.mips.gpr[MIPS_GPR_V0] = 0xffffffff80001000ULL;
1454     /* TODO! */
1455     break;
1456     case 0x54: /* GetRelativeTime() */
1457     debug("[ ARCBIOS GetRelativeTime() ]\n");
1458     cpu->cd.mips.gpr[MIPS_GPR_V0] = (int64_t)(int32_t)time(NULL);
1459     break;
1460     case 0x5c: /* Open(char *path, uint32_t mode, uint32_t *fileID) */
1461     debug("[ ARCBIOS Open(\"");
1462     dump_mem_string(cpu, cpu->cd.mips.gpr[MIPS_GPR_A0]);
1463     debug("\",0x%x,0x%x)", (int)cpu->cd.mips.gpr[MIPS_GPR_A0],
1464     (int)cpu->cd.mips.gpr[MIPS_GPR_A1],
1465     (int)cpu->cd.mips.gpr[MIPS_GPR_A2]);
1466    
1467     cpu->cd.mips.gpr[MIPS_GPR_V0] = ARCBIOS_ENOENT;
1468    
1469     handle = 3;
1470     /* TODO: Starting at 0 would require some updates... */
1471     while (machine->md.arc.file_handle_in_use[handle]) {
1472     handle ++;
1473     if (handle >= ARC_MAX_HANDLES) {
1474     cpu->cd.mips.gpr[MIPS_GPR_V0] = ARCBIOS_EMFILE;
1475     break;
1476     }
1477     }
1478    
1479     if (handle >= ARC_MAX_HANDLES) {
1480     fatal("[ ARCBIOS Open: out of file handles ]\n");
1481     } else if (cpu->cd.mips.gpr[MIPS_GPR_A0] == 0) {
1482     fatal("[ ARCBIOS Open: NULL ptr ]\n");
1483     } else {
1484     /*
1485     * TODO: This is hardcoded to successfully open
1486     * anything. It is used by the Windows NT SETUPLDR
1487     * program to load stuff from the boot partition.
1488     */
1489     unsigned char *buf = malloc(MAX_OPEN_STRINGLEN);
1490     if (buf == NULL) {
1491     fprintf(stderr, "out of memory\n");
1492     exit(1);
1493     }
1494     memset(buf, 0, MAX_OPEN_STRINGLEN);
1495     for (i=0; i<MAX_OPEN_STRINGLEN; i++) {
1496     cpu->memory_rw(cpu, cpu->mem,
1497     cpu->cd.mips.gpr[MIPS_GPR_A0] + i,
1498     &buf[i], 1, MEM_READ, CACHE_NONE);
1499     if (buf[i] == '\0')
1500     i = MAX_OPEN_STRINGLEN;
1501     }
1502     buf[MAX_OPEN_STRINGLEN - 1] = '\0';
1503     machine->md.arc.file_handle_string[handle] =
1504     (char *)buf;
1505     machine->md.arc.current_seek_offset[handle] = 0;
1506     cpu->cd.mips.gpr[MIPS_GPR_V0] = ARCBIOS_ESUCCESS;
1507     }
1508    
1509     if (cpu->cd.mips.gpr[MIPS_GPR_V0] == ARCBIOS_ESUCCESS) {
1510     debug(" = handle %i ]\n", (int)handle);
1511     store_32bit_word(cpu, cpu->cd.mips.gpr[MIPS_GPR_A2],
1512     handle);
1513     machine->md.arc.file_handle_in_use[handle] = 1;
1514     } else
1515     debug(" = ERROR %i ]\n",
1516     (int)cpu->cd.mips.gpr[MIPS_GPR_V0]);
1517     break;
1518     case 0x60: /* Close(uint32_t handle) */
1519     debug("[ ARCBIOS Close(%i) ]\n",
1520     (int)cpu->cd.mips.gpr[MIPS_GPR_A0]);
1521     if (!machine->md.arc.file_handle_in_use[cpu->cd.mips.gpr[
1522     MIPS_GPR_A0]]) {
1523     fatal("ARCBIOS Close(%i): bad handle\n",
1524     (int)cpu->cd.mips.gpr[MIPS_GPR_A0]);
1525     cpu->cd.mips.gpr[MIPS_GPR_V0] = ARCBIOS_EBADF;
1526     } else {
1527     machine->md.arc.file_handle_in_use[
1528     cpu->cd.mips.gpr[MIPS_GPR_A0]] = 0;
1529     if (machine->md.arc.file_handle_string[
1530     cpu->cd.mips.gpr[MIPS_GPR_A0]] != NULL)
1531     free(machine->md.arc.file_handle_string[
1532     cpu->cd.mips.gpr[MIPS_GPR_A0]]);
1533     machine->md.arc.file_handle_string[cpu->cd.mips.
1534     gpr[MIPS_GPR_A0]] = NULL;
1535     cpu->cd.mips.gpr[MIPS_GPR_V0] = ARCBIOS_ESUCCESS;
1536     }
1537     break;
1538     case 0x64: /* Read(handle, void *buf, length, uint32_t *count) */
1539     if (cpu->cd.mips.gpr[MIPS_GPR_A0] == ARCBIOS_STDIN) {
1540     int i, nread = 0;
1541     /*
1542     * Before going into the loop, make sure stdout
1543     * is flushed. If we're using an X11 VGA console,
1544     * then it needs to be flushed as well.
1545     */
1546     fflush(stdin);
1547     fflush(stdout);
1548     /* NOTE/TODO: This gives a tick to _everything_ */
1549     for (i=0; i<machine->n_tick_entries; i++)
1550     machine->tick_func[i](cpu,
1551     machine->tick_extra[i]);
1552    
1553 dpavlin 22 for (i=0; i<(int32_t)cpu->cd.mips.gpr[MIPS_GPR_A2];
1554     i++) {
1555 dpavlin 14 int x;
1556     unsigned char ch;
1557    
1558     /* Read from STDIN is blocking (at least
1559     that seems to be how NetBSD's arcdiag
1560     wants it) */
1561     x = console_readchar(
1562     machine->main_console_handle);
1563     if (x < 0)
1564     return 0;
1565    
1566     /*
1567     * ESC + '[' should be transformed into 0x9b:
1568     *
1569     * NOTE/TODO: This makes the behaviour of just
1570     * pressing ESC a bit harder to define.
1571     */
1572     if (x == 27) {
1573     x = console_readchar(cpu->
1574     machine->main_console_handle);
1575     if (x == '[' || x == 'O')
1576     x = 0x9b;
1577     }
1578    
1579     ch = x;
1580     nread ++;
1581     cpu->memory_rw(cpu, cpu->mem,
1582     cpu->cd.mips.gpr[MIPS_GPR_A1] + i,
1583     &ch, 1, MEM_WRITE, CACHE_NONE);
1584    
1585     /* NOTE: Only one char, from STDIN: */
1586     i = cpu->cd.mips.gpr[MIPS_GPR_A2]; /* :-) */
1587     }
1588     store_32bit_word(cpu, cpu->cd.mips.gpr[MIPS_GPR_A3],
1589     nread);
1590     /* TODO: not EAGAIN? */
1591     cpu->cd.mips.gpr[MIPS_GPR_V0] =
1592     nread? ARCBIOS_ESUCCESS: ARCBIOS_EAGAIN;
1593     } else {
1594     int handle = cpu->cd.mips.gpr[MIPS_GPR_A0];
1595 dpavlin 20 int disk_type = 0;
1596 dpavlin 14 int disk_id = arcbios_handle_to_disk_id_and_type(
1597     machine, handle, &disk_type);
1598     uint64_t partition_offset = 0;
1599     int res;
1600     uint64_t size; /* dummy */
1601     unsigned char *tmp_buf;
1602    
1603     arcbios_handle_to_start_and_size(machine, handle,
1604     &partition_offset, &size);
1605    
1606     debug("[ ARCBIOS Read(%i,0x%08x,0x%08x,0x%08x) ]\n",
1607     (int)cpu->cd.mips.gpr[MIPS_GPR_A0],
1608     (int)cpu->cd.mips.gpr[MIPS_GPR_A1],
1609     (int)cpu->cd.mips.gpr[MIPS_GPR_A2],
1610     (int)cpu->cd.mips.gpr[MIPS_GPR_A3]);
1611    
1612     tmp_buf = malloc(cpu->cd.mips.gpr[MIPS_GPR_A2]);
1613     if (tmp_buf == NULL) {
1614     fprintf(stderr, "[ *** Out of memory in "
1615     "arcbios.c, allocating %i bytes ]\n",
1616     (int)cpu->cd.mips.gpr[MIPS_GPR_A2]);
1617     break;
1618     }
1619    
1620     res = diskimage_access(machine, disk_id, disk_type,
1621     0, partition_offset + machine->md.arc.
1622     current_seek_offset[handle], tmp_buf,
1623     cpu->cd.mips.gpr[MIPS_GPR_A2]);
1624    
1625     /* If the transfer was successful, transfer the
1626     data to emulated memory: */
1627     if (res) {
1628     uint64_t dst = cpu->cd.mips.gpr[MIPS_GPR_A1];
1629     store_buf(cpu, dst, (char *)tmp_buf,
1630     cpu->cd.mips.gpr[MIPS_GPR_A2]);
1631     store_32bit_word(cpu,
1632     cpu->cd.mips.gpr[MIPS_GPR_A3],
1633     cpu->cd.mips.gpr[MIPS_GPR_A2]);
1634     machine->md.arc.current_seek_offset[handle] +=
1635     cpu->cd.mips.gpr[MIPS_GPR_A2];
1636     cpu->cd.mips.gpr[MIPS_GPR_V0] = 0;
1637     } else
1638     cpu->cd.mips.gpr[MIPS_GPR_V0] = ARCBIOS_EIO;
1639     free(tmp_buf);
1640     }
1641     break;
1642     case 0x68: /* GetReadStatus(handle) */
1643     /*
1644     * According to arcbios_tty_getchar() in NetBSD's
1645     * dev/arcbios/arcbios_tty.c, GetReadStatus should
1646     * return 0 if there is something available.
1647     *
1648     * TODO: Error codes are things like ARCBIOS_EAGAIN.
1649     */
1650     if (cpu->cd.mips.gpr[MIPS_GPR_A0] == ARCBIOS_STDIN) {
1651     cpu->cd.mips.gpr[MIPS_GPR_V0] = console_charavail(
1652     machine->main_console_handle)? 0 : 1;
1653     } else {
1654     fatal("[ ARCBIOS GetReadStatus(%i) from "
1655     "something other than STDIN: TODO ]\n",
1656     (int)cpu->cd.mips.gpr[MIPS_GPR_A0]);
1657     /* TODO */
1658     cpu->cd.mips.gpr[MIPS_GPR_V0] = 1;
1659     }
1660     break;
1661     case 0x6c: /* Write(handle, buf, len, &returnlen) */
1662     if (cpu->cd.mips.gpr[MIPS_GPR_A0] != ARCBIOS_STDOUT) {
1663     /*
1664     * TODO: this is just a test
1665     */
1666     int handle = cpu->cd.mips.gpr[MIPS_GPR_A0];
1667 dpavlin 20 int disk_type = 0;
1668 dpavlin 14 int disk_id = arcbios_handle_to_disk_id_and_type(
1669     machine, handle, &disk_type);
1670     uint64_t partition_offset = 0;
1671     int res, i;
1672     uint64_t size; /* dummy */
1673     unsigned char *tmp_buf;
1674    
1675     arcbios_handle_to_start_and_size(machine,
1676     handle, &partition_offset, &size);
1677    
1678 dpavlin 24 debug("[ ARCBIOS Write(%i,0x%08"PRIx64",%i,0x%08"
1679     PRIx64") ]\n", (int) cpu->cd.mips.gpr[MIPS_GPR_A0],
1680     (uint64_t) cpu->cd.mips.gpr[MIPS_GPR_A1],
1681     (int) cpu->cd.mips.gpr[MIPS_GPR_A2],
1682     (uint64_t) cpu->cd.mips.gpr[MIPS_GPR_A3]);
1683 dpavlin 14
1684     tmp_buf = malloc(cpu->cd.mips.gpr[MIPS_GPR_A2]);
1685     if (tmp_buf == NULL) {
1686     fprintf(stderr, "[ *** Out of memory in"
1687     " arcbios.c, allocating %i bytes ]\n",
1688     (int)cpu->cd.mips.gpr[MIPS_GPR_A2]);
1689     break;
1690     }
1691    
1692 dpavlin 22 for (i=0; i<(int32_t)cpu->cd.mips.gpr[MIPS_GPR_A2]; i++)
1693 dpavlin 14 cpu->memory_rw(cpu, cpu->mem,
1694     cpu->cd.mips.gpr[MIPS_GPR_A1] + i,
1695     &tmp_buf[i], sizeof(char), MEM_READ,
1696     CACHE_NONE);
1697    
1698     res = diskimage_access(machine, disk_id, disk_type,
1699     1, partition_offset + machine->md.arc.
1700     current_seek_offset[handle], tmp_buf,
1701     cpu->cd.mips.gpr[MIPS_GPR_A2]);
1702    
1703     if (res) {
1704     store_32bit_word(cpu,
1705     cpu->cd.mips.gpr[MIPS_GPR_A3],
1706     cpu->cd.mips.gpr[MIPS_GPR_A2]);
1707     machine->md.arc.current_seek_offset[handle] +=
1708     cpu->cd.mips.gpr[MIPS_GPR_A2];
1709     cpu->cd.mips.gpr[MIPS_GPR_V0] = 0;
1710     } else
1711     cpu->cd.mips.gpr[MIPS_GPR_V0] = ARCBIOS_EIO;
1712     free(tmp_buf);
1713     } else {
1714 dpavlin 22 for (i=0; i<(int32_t)cpu->cd.mips.gpr[MIPS_GPR_A2];
1715     i++) {
1716 dpavlin 14 unsigned char ch = '\0';
1717     cpu->memory_rw(cpu, cpu->mem,
1718     cpu->cd.mips.gpr[MIPS_GPR_A1] + i,
1719     &ch, sizeof(ch), MEM_READ, CACHE_NONE);
1720    
1721     arcbios_putchar(cpu, ch);
1722     }
1723     }
1724     store_32bit_word(cpu, cpu->cd.mips.gpr[MIPS_GPR_A3],
1725     cpu->cd.mips.gpr[MIPS_GPR_A2]);
1726     cpu->cd.mips.gpr[MIPS_GPR_V0] = 0; /* Success. */
1727     break;
1728     case 0x70: /* Seek(uint32_t handle, int64_t *ofs,
1729     uint32_t whence): uint32_t */
1730 dpavlin 24 debug("[ ARCBIOS Seek(%i,0x%08"PRIx64",%i): ",
1731     (int) cpu->cd.mips.gpr[MIPS_GPR_A0],
1732     (uint64_t)cpu->cd.mips.gpr[MIPS_GPR_A1],
1733     (int) cpu->cd.mips.gpr[MIPS_GPR_A2]);
1734 dpavlin 14
1735     if (cpu->cd.mips.gpr[MIPS_GPR_A2] != 0) {
1736 dpavlin 24 fatal("[ ARCBIOS Seek(%i,0x%08"PRIx64",%i): "
1737 dpavlin 14 "UNIMPLEMENTED whence=%i ]\n",
1738 dpavlin 24 (int) cpu->cd.mips.gpr[MIPS_GPR_A0],
1739     (uint64_t) cpu->cd.mips.gpr[MIPS_GPR_A1],
1740     (int) cpu->cd.mips.gpr[MIPS_GPR_A2],
1741     (int) cpu->cd.mips.gpr[MIPS_GPR_A2]);
1742 dpavlin 14 }
1743    
1744     {
1745     unsigned char buf[8];
1746     uint64_t ofs;
1747     cpu->memory_rw(cpu, cpu->mem,
1748     cpu->cd.mips.gpr[MIPS_GPR_A1], &buf[0],
1749     sizeof(buf), MEM_READ, CACHE_NONE);
1750     if (cpu->byte_order == EMUL_BIG_ENDIAN) {
1751     unsigned char tmp;
1752     tmp = buf[0]; buf[0] = buf[7]; buf[7] = tmp;
1753     tmp = buf[1]; buf[1] = buf[6]; buf[6] = tmp;
1754     tmp = buf[2]; buf[2] = buf[5]; buf[5] = tmp;
1755     tmp = buf[3]; buf[3] = buf[4]; buf[4] = tmp;
1756     }
1757     ofs = buf[0] + (buf[1] << 8) + (buf[2] << 16) +
1758     (buf[3] << 24) + ((uint64_t)buf[4] << 32) +
1759     ((uint64_t)buf[5] << 40) + ((uint64_t)buf[6] << 48)
1760     + ((uint64_t)buf[7] << 56);
1761     machine->md.arc.current_seek_offset[
1762     cpu->cd.mips.gpr[MIPS_GPR_A0]] = ofs;
1763 dpavlin 24 debug("%016"PRIx64" ]\n", (uint64_t) ofs);
1764 dpavlin 14 }
1765    
1766     cpu->cd.mips.gpr[MIPS_GPR_V0] = 0; /* Success. */
1767    
1768     break;
1769     case 0x78: /* GetEnvironmentVariable(char *) */
1770     /* Find the environment variable given by a0: */
1771 dpavlin 22 for (i=0; i<(ssize_t)sizeof(buf); i++)
1772 dpavlin 14 cpu->memory_rw(cpu, cpu->mem,
1773     cpu->cd.mips.gpr[MIPS_GPR_A0] + i,
1774     &buf[i], sizeof(char), MEM_READ, CACHE_NONE);
1775     buf[sizeof(buf)-1] = '\0';
1776     debug("[ ARCBIOS GetEnvironmentVariable(\"%s\") ]\n", buf);
1777     for (i=0; i<0x1000; i++) {
1778     /* Matching string at offset i? */
1779     int nmatches = 0;
1780 dpavlin 22 for (j=0; j<(ssize_t)strlen((char *)buf); j++) {
1781 dpavlin 14 cpu->memory_rw(cpu, cpu->mem,
1782     (uint64_t)(ARC_ENV_STRINGS + i + j),
1783     &ch2, sizeof(char), MEM_READ, CACHE_NONE);
1784     if (ch2 == buf[j])
1785     nmatches++;
1786     }
1787     cpu->memory_rw(cpu, cpu->mem,
1788     (uint64_t)(ARC_ENV_STRINGS + i +
1789     strlen((char *)buf)), &ch2, sizeof(char),
1790     MEM_READ, CACHE_NONE);
1791 dpavlin 22 if (nmatches == (int)strlen((char *)buf) && ch2=='=') {
1792 dpavlin 14 cpu->cd.mips.gpr[MIPS_GPR_V0] =
1793     ARC_ENV_STRINGS + i +
1794     strlen((char *)buf) + 1;
1795     return 1;
1796     }
1797     }
1798     /* Return NULL if string wasn't found. */
1799     cpu->cd.mips.gpr[MIPS_GPR_V0] = 0;
1800     break;
1801     case 0x7c: /* SetEnvironmentVariable(char *, char *) */
1802     debug("[ ARCBIOS SetEnvironmentVariable(\"");
1803     dump_mem_string(cpu, cpu->cd.mips.gpr[MIPS_GPR_A0]);
1804     debug("\",\"");
1805     dump_mem_string(cpu, cpu->cd.mips.gpr[MIPS_GPR_A1]);
1806     debug("\") ]\n");
1807     /* TODO: This is a dummy. */
1808     cpu->cd.mips.gpr[MIPS_GPR_V0] = ARCBIOS_ESUCCESS;
1809     break;
1810     case 0x80: /* GetFileInformation() */
1811     debug("[ ARCBIOS GetFileInformation(%i,0x%x): ",
1812     (int)cpu->cd.mips.gpr[MIPS_GPR_A0],
1813     (int)cpu->cd.mips.gpr[MIPS_GPR_A1]);
1814    
1815     if (cpu->cd.mips.gpr[MIPS_GPR_A0] >= ARC_MAX_HANDLES) {
1816     debug("invalid file handle ]\n");
1817     cpu->cd.mips.gpr[MIPS_GPR_V0] = ARCBIOS_EINVAL;
1818     } else if (!machine->md.arc.file_handle_in_use[cpu->cd.
1819     mips.gpr[MIPS_GPR_A0]]) {
1820     debug("file handle not in use! ]\n");
1821     cpu->cd.mips.gpr[MIPS_GPR_V0] = ARCBIOS_EBADF;
1822     } else {
1823     debug("'%s' ]\n", machine->md.arc.file_handle_string[
1824     cpu->cd.mips.gpr[MIPS_GPR_A0]]);
1825     cpu->cd.mips.gpr[MIPS_GPR_V0] =
1826     arcbios_getfileinformation(cpu);
1827     }
1828     break;
1829     case 0x88: /* FlushAllCaches() */
1830     debug("[ ARCBIOS FlushAllCaches(): TODO ]\n");
1831     cpu->cd.mips.gpr[MIPS_GPR_V0] = 0;
1832     break;
1833     case 0x90: /* void *GetDisplayStatus(handle) */
1834     debug("[ ARCBIOS GetDisplayStatus(%i) ]\n",
1835     (int)cpu->cd.mips.gpr[MIPS_GPR_A0]);
1836     /* TODO: handle different values of 'handle'? */
1837     cpu->cd.mips.gpr[MIPS_GPR_V0] = ARC_DSPSTAT_ADDR;
1838     break;
1839     case 0x100:
1840     /*
1841     * Undocumented, used by IRIX.
1842     */
1843     debug("[ ARCBIOS: IRIX 0x100 (?) ]\n");
1844     /* TODO */
1845     cpu->cd.mips.gpr[MIPS_GPR_V0] = 0;
1846     break;
1847     case 0x888:
1848     /*
1849     * Magical crash if there is no exception handling code.
1850     */
1851     fatal("EXCEPTION, but no exception handler installed yet.\n");
1852     quiet_mode = 0;
1853     cpu_register_dump(machine, cpu, 1, 0x1);
1854     cpu->running = 0;
1855     break;
1856     default:
1857     quiet_mode = 0;
1858     cpu_register_dump(machine, cpu, 1, 0x1);
1859     debug("a0 points to: ");
1860     dump_mem_string(cpu, cpu->cd.mips.gpr[MIPS_GPR_A0]);
1861     debug("\n");
1862     fatal("ARCBIOS: unimplemented vector 0x%x\n", vector);
1863     cpu->running = 0;
1864     }
1865    
1866     return 1;
1867     }
1868    
1869    
1870     /*
1871     * arcbios_set_default_exception_handler():
1872     */
1873     void arcbios_set_default_exception_handler(struct cpu *cpu)
1874     {
1875     /*
1876     * The default exception handlers simply jump to 0xbfc88888,
1877     * which is then taken care of in arcbios_emul() above.
1878     *
1879     * 3c1abfc8 lui k0,0xbfc8
1880     * 375a8888 ori k0,k0,0x8888
1881     * 03400008 jr k0
1882     * 00000000 nop
1883     */
1884     store_32bit_word(cpu, 0xffffffff80000000ULL, 0x3c1abfc8);
1885     store_32bit_word(cpu, 0xffffffff80000004ULL, 0x375a8888);
1886     store_32bit_word(cpu, 0xffffffff80000008ULL, 0x03400008);
1887     store_32bit_word(cpu, 0xffffffff8000000cULL, 0x00000000);
1888    
1889     store_32bit_word(cpu, 0xffffffff80000080ULL, 0x3c1abfc8);
1890     store_32bit_word(cpu, 0xffffffff80000084ULL, 0x375a8888);
1891     store_32bit_word(cpu, 0xffffffff80000088ULL, 0x03400008);
1892     store_32bit_word(cpu, 0xffffffff8000008cULL, 0x00000000);
1893    
1894     store_32bit_word(cpu, 0xffffffff80000180ULL, 0x3c1abfc8);
1895     store_32bit_word(cpu, 0xffffffff80000184ULL, 0x375a8888);
1896     store_32bit_word(cpu, 0xffffffff80000188ULL, 0x03400008);
1897     store_32bit_word(cpu, 0xffffffff8000018cULL, 0x00000000);
1898     }
1899    
1900    
1901     /*
1902     * arcbios_add_other_components():
1903     *
1904     * TODO: How should this be synched with the hardware devices
1905     * added in machine.c?
1906     */
1907     static void arcbios_add_other_components(struct machine *machine,
1908     uint64_t system)
1909     {
1910     struct cpu *cpu = machine->cpus[0];
1911    
1912     if (machine->machine_type == MACHINE_ARC &&
1913     ( machine->machine_subtype == MACHINE_ARC_NEC_RD94 ||
1914     machine->machine_subtype == MACHINE_ARC_NEC_R94 ||
1915     machine->machine_subtype == MACHINE_ARC_NEC_R96 )) {
1916     uint64_t jazzbus, eisa, other;
1917    
1918     jazzbus = arcbios_addchild_manual(cpu,
1919     COMPONENT_CLASS_AdapterClass,
1920     COMPONENT_TYPE_MultiFunctionAdapter,
1921     0, 1, 2, 0, 0xffffffff, "Jazz-Internal Bus",
1922     system, NULL, 0);
1923    
1924     switch (machine->machine_subtype) {
1925     case MACHINE_ARC_NEC_RD94:
1926     case MACHINE_ARC_NEC_R94:
1927     if (machine->use_x11)
1928     arcbios_addchild_manual(cpu,
1929     COMPONENT_CLASS_ControllerClass,
1930     COMPONENT_TYPE_DisplayController,
1931     0, 1, 2, 0, 0x0, "10110004",
1932     system, NULL, 0);
1933     break;
1934     case MACHINE_ARC_NEC_R96:
1935     if (machine->use_x11) {
1936     uint64_t x;
1937     x = arcbios_addchild_manual(cpu,
1938     COMPONENT_CLASS_ControllerClass,
1939     COMPONENT_TYPE_DisplayController,
1940     COMPONENT_FLAG_ConsoleOut |
1941     COMPONENT_FLAG_Output,
1942     1, 2, 0, 0x0, "necvdfrb",
1943     jazzbus, NULL, 0);
1944     arcbios_addchild_manual(cpu,
1945     COMPONENT_CLASS_PeripheralClass,
1946     COMPONENT_TYPE_MonitorPeripheral,
1947     COMPONENT_FLAG_ConsoleOut |
1948     COMPONENT_FLAG_Output,
1949     1, 2, 0, 0xffffffff, "640x480",
1950     x, NULL, 0);
1951     }
1952    
1953     /* TODO: R[D]94 too? */
1954     eisa = arcbios_addchild_manual(cpu,
1955     COMPONENT_CLASS_AdapterClass,
1956     COMPONENT_TYPE_EISAAdapter,
1957     0, 1, 2, 0, 0xffffffff, "EISA",
1958     system, NULL, 0);
1959    
1960     other = arcbios_addchild_manual(cpu,
1961     COMPONENT_CLASS_ControllerClass,
1962     COMPONENT_TYPE_OtherController,
1963     0, 1, 2, 0, 0xffffffff, "NEC1C01",
1964     eisa, NULL, 0);
1965     break;
1966     }
1967     }
1968    
1969     if (machine->machine_type == MACHINE_ARC &&
1970     (machine->machine_subtype == MACHINE_ARC_JAZZ_PICA
1971     || machine->machine_subtype == MACHINE_ARC_JAZZ_MAGNUM)) {
1972     uint64_t jazzbus, ali_s3, vxl;
1973     uint64_t diskcontroller, floppy, kbdctl, kbd;
1974     uint64_t ptrctl, ptr, paral, audio;
1975     uint64_t eisa, scsi;
1976     /* uint64_t serial1, serial2; */
1977    
1978     jazzbus = arcbios_addchild_manual(cpu,
1979     COMPONENT_CLASS_AdapterClass,
1980     COMPONENT_TYPE_MultiFunctionAdapter,
1981     0, 1, 2, 0, 0xffffffff, "Jazz-Internal Bus",
1982     system, NULL, 0);
1983    
1984     /*
1985     * DisplayController, needed by NetBSD:
1986     * TODO: NetBSD still doesn't use it :(
1987     */
1988     switch (machine->machine_subtype) {
1989     case MACHINE_ARC_JAZZ_PICA:
1990     /* Default TLB entries on PICA-61: */
1991    
1992     /* 7: 256K, asid: 0x0, v: 0xe1000000,
1993     p0: 0xfff00000(2.VG), p1: 0x0(0..G) */
1994     mips_coproc_tlb_set_entry(cpu, 7, 262144,
1995     0xffffffffe1000000ULL,
1996     0x0fff00000ULL, 0, 1, 0, 0, 0, 1, 0, 2, 0);
1997    
1998     /* 8: 64K, asid: 0x0, v: 0xe0000000,
1999     p0: 0x80000000(2DVG), p1: 0x0(0..G) */
2000     mips_coproc_tlb_set_entry(cpu, 8, 65536,
2001     0xffffffffe0000000ULL,
2002     0x080000000ULL, 0, 1, 0, 1, 0, 1, 0, 2, 0);
2003    
2004     /* 9: 64K, asid: 0x0, v: 0xe00e0000,
2005     p0: 0x800e0000(2DVG), p1: 0x800f0000(2DVG) */
2006     mips_coproc_tlb_set_entry(cpu, 9, 65536,
2007     (uint64_t)0xffffffffe00e0000ULL,
2008     (uint64_t)0x0800e0000ULL,
2009     (uint64_t)0x0800f0000ULL, 1, 1, 1, 1, 1, 0, 2, 2);
2010    
2011     /* 10: 4K, asid: 0x0, v: 0xe0100000,
2012     p0: 0xf0000000(2DVG), p1: 0x0(0..G) */
2013     mips_coproc_tlb_set_entry(cpu, 10, 4096,
2014     (uint64_t)0xffffffffe0100000ULL,
2015     (uint64_t)0x0f0000000ULL, 0,1, 0, 1, 0, 1, 0, 2, 0);
2016    
2017     /* 11: 1M, asid: 0x0, v: 0xe0200000,
2018     p0: 0x60000000(2DVG), p1: 0x60100000(2DVG) */
2019     mips_coproc_tlb_set_entry(cpu, 11, 1048576,
2020     0xffffffffe0200000ULL,
2021     0x060000000ULL, 0x060100000ULL,1,1,1,1,1, 0, 2, 2);
2022    
2023     /* 12: 1M, asid: 0x0, v: 0xe0400000,
2024     p0: 0x60200000(2DVG), p1: 0x60300000(2DVG) */
2025     mips_coproc_tlb_set_entry(cpu, 12, 1048576,
2026     0xffffffffe0400000ULL, 0x060200000ULL,
2027     0x060300000ULL, 1, 1, 1, 1, 1, 0, 2, 2);
2028    
2029     /* 13: 4M, asid: 0x0, v: 0xe0800000,
2030     p0: 0x40000000(2DVG), p1: 0x40400000(2DVG) */
2031     mips_coproc_tlb_set_entry(cpu, 13, 1048576*4,
2032     0xffffffffe0800000ULL, 0x040000000ULL,
2033     0x040400000ULL, 1, 1, 1, 1, 1, 0, 2, 2);
2034    
2035     /* 14: 16M, asid: 0x0, v: 0xe2000000,
2036     p0: 0x90000000(2DVG), p1: 0x91000000(2DVG) */
2037     mips_coproc_tlb_set_entry(cpu, 14, 1048576*16,
2038     0xffffffffe2000000ULL, 0x090000000ULL,
2039     0x091000000ULL, 1, 1, 1, 1, 1, 0, 2, 2);
2040    
2041     if (machine->use_x11) {
2042     ali_s3 = arcbios_addchild_manual(cpu,
2043     COMPONENT_CLASS_ControllerClass,
2044     COMPONENT_TYPE_DisplayController,
2045     COMPONENT_FLAG_ConsoleOut |
2046     COMPONENT_FLAG_Output,
2047     1, 2, 0, 0xffffffff, "ALI_S3",
2048     jazzbus, NULL, 0);
2049    
2050     arcbios_addchild_manual(cpu,
2051     COMPONENT_CLASS_PeripheralClass,
2052     COMPONENT_TYPE_MonitorPeripheral,
2053     COMPONENT_FLAG_ConsoleOut |
2054     COMPONENT_FLAG_Output,
2055     1, 2, 0, 0xffffffff, "1024x768",
2056     ali_s3, NULL, 0);
2057     }
2058     break;
2059     case MACHINE_ARC_JAZZ_MAGNUM:
2060     if (machine->use_x11) {
2061     vxl = arcbios_addchild_manual(cpu,
2062     COMPONENT_CLASS_ControllerClass,
2063     COMPONENT_TYPE_DisplayController,
2064     COMPONENT_FLAG_ConsoleOut |
2065     COMPONENT_FLAG_Output,
2066     1, 2, 0, 0xffffffff, "VXL",
2067     jazzbus, NULL, 0);
2068    
2069     arcbios_addchild_manual(cpu,
2070     COMPONENT_CLASS_PeripheralClass,
2071     COMPONENT_TYPE_MonitorPeripheral,
2072     COMPONENT_FLAG_ConsoleOut |
2073     COMPONENT_FLAG_Output,
2074     1, 2, 0, 0xffffffff, "1024x768",
2075     vxl, NULL, 0);
2076     }
2077     break;
2078     }
2079    
2080     diskcontroller = arcbios_addchild_manual(cpu,
2081     COMPONENT_CLASS_ControllerClass,
2082     COMPONENT_TYPE_DiskController,
2083     COMPONENT_FLAG_Input | COMPONENT_FLAG_Output,
2084     1, 2, 0, 0xffffffff, "I82077", jazzbus, NULL, 0);
2085    
2086     floppy = arcbios_addchild_manual(cpu,
2087     COMPONENT_CLASS_PeripheralClass,
2088     COMPONENT_TYPE_FloppyDiskPeripheral,
2089     COMPONENT_FLAG_Removable |
2090     COMPONENT_FLAG_Input | COMPONENT_FLAG_Output,
2091     1, 2, 0, 0xffffffff, NULL, diskcontroller, NULL, 0);
2092    
2093     kbdctl = arcbios_addchild_manual(cpu,
2094     COMPONENT_CLASS_ControllerClass,
2095     COMPONENT_TYPE_KeyboardController,
2096     COMPONENT_FLAG_ConsoleIn | COMPONENT_FLAG_Input,
2097     1, 2, 0, 0xffffffff, "I8742", jazzbus, NULL, 0);
2098    
2099     kbd = arcbios_addchild_manual(cpu,
2100     COMPONENT_CLASS_PeripheralClass,
2101     COMPONENT_TYPE_KeyboardPeripheral,
2102     COMPONENT_FLAG_ConsoleIn | COMPONENT_FLAG_Input,
2103     1, 2, 0, 0xffffffff, "PCAT_ENHANCED", kbdctl, NULL, 0);
2104    
2105     ptrctl = arcbios_addchild_manual(cpu,
2106     COMPONENT_CLASS_ControllerClass,
2107     COMPONENT_TYPE_PointerController, COMPONENT_FLAG_Input,
2108     1, 2, 0, 0xffffffff, "I8742", jazzbus, NULL, 0);
2109    
2110     ptr = arcbios_addchild_manual(cpu,
2111     COMPONENT_CLASS_PeripheralClass,
2112     COMPONENT_TYPE_PointerPeripheral, COMPONENT_FLAG_Input,
2113     1, 2, 0, 0xffffffff, "PS2 MOUSE", ptrctl, NULL, 0);
2114    
2115     /* These cause Windows NT to bug out. */
2116     #if 0
2117     serial1 = arcbios_addchild_manual(cpu,
2118     COMPONENT_CLASS_ControllerClass,
2119     COMPONENT_TYPE_SerialController,
2120     COMPONENT_FLAG_Input | COMPONENT_FLAG_Output,
2121     1, 2, 0, 0xffffffff, "COM1", jazzbus, NULL, 0);
2122    
2123     serial2 = arcbios_addchild_manual(cpu,
2124     COMPONENT_CLASS_ControllerClass,
2125     COMPONENT_TYPE_SerialController,
2126     COMPONENT_FLAG_Input | COMPONENT_FLAG_Output,
2127     1, 2, 0, 0xffffffff, "COM1", jazzbus, NULL, 0);
2128     #endif
2129    
2130     paral = arcbios_addchild_manual(cpu,
2131     COMPONENT_CLASS_ControllerClass,
2132     COMPONENT_TYPE_ParallelController,
2133     COMPONENT_FLAG_Input | COMPONENT_FLAG_Output,
2134     1, 2, 0, 0xffffffff, "LPT1", jazzbus, NULL, 0);
2135    
2136     audio = arcbios_addchild_manual(cpu,
2137     COMPONENT_CLASS_ControllerClass,
2138     COMPONENT_TYPE_AudioController,
2139     COMPONENT_FLAG_Input | COMPONENT_FLAG_Output,
2140     1, 2, 0, 0xffffffff, "MAGNUM", jazzbus, NULL, 0);
2141    
2142     eisa = arcbios_addchild_manual(cpu,
2143     COMPONENT_CLASS_AdapterClass, COMPONENT_TYPE_EISAAdapter,
2144     0, 1, 2, 0, 0xffffffff, "EISA", system, NULL, 0);
2145    
2146     {
2147     unsigned char config[78];
2148     memset(config, 0, sizeof(config));
2149    
2150     /* config data version: 1, revision: 2, count: 4 */
2151     config[0] = 0x01; config[1] = 0x00;
2152     config[2] = 0x02; config[3] = 0x00;
2153     config[4] = 0x04; config[5] = 0x00; config[6] = 0x00; config[7] = 0x00;
2154    
2155     /*
2156     type: Interrupt
2157     share_disposition: DeviceExclusive, flags: LevelSensitive
2158     level: 4, vector: 22, reserved1: 0
2159     */
2160     config[8] = arc_CmResourceTypeInterrupt;
2161     config[9] = arc_CmResourceShareDeviceExclusive;
2162     config[10] = arc_CmResourceInterruptLevelSensitive;
2163     config[12] = 4;
2164     config[16] = 22;
2165     config[20] = 0;
2166    
2167     /*
2168     type: Memory
2169     share_disposition: DeviceExclusive, flags: ReadWrite
2170     start: 0x 0 80002000, length: 0x1000
2171     */
2172     config[24] = arc_CmResourceTypeMemory;
2173     config[25] = arc_CmResourceShareDeviceExclusive;
2174     config[26] = arc_CmResourceMemoryReadWrite;
2175     config[28] = 0x00; config[29] = 0x20; config[30] = 0x00; config[31] = 0x80;
2176     config[32] = 0x00; config[33] = 0x00; config[34] = 0x00; config[35] = 0x00;
2177     config[36] = 0x00; config[37] = 0x10; config[38] = 0x00; config[39] = 0x00;
2178    
2179     /*
2180     type: DMA
2181     share_disposition: DeviceExclusive, flags: 0x0
2182     channel: 0, port: 0, reserved1: 0
2183     */
2184     config[40] = arc_CmResourceTypeDMA;
2185     config[41] = arc_CmResourceShareDeviceExclusive;
2186     /* 42..43 = flags, 44,45,46,47 = channel, 48,49,50,51 = port, 52,53,54,55
2187     = reserved */
2188    
2189     /* type: DeviceSpecific
2190     share_disposition: DeviceExclusive, flags: 0x0
2191     datasize: 6, reserved1: 0, reserved2: 0
2192     data: [0x1:0x0:0x2:0x0:0x7:0x30]
2193     */
2194     config[56] = arc_CmResourceTypeDeviceSpecific;
2195     config[57] = arc_CmResourceShareDeviceExclusive;
2196     /* 58,59 = flags 60,61,62,63 = data size, 64..71 = reserved */
2197     config[60] = 6;
2198     /* 72..77 = the data */
2199     config[72] = 0x01; config[73] = 0x00; config[74] = 0x02;
2200     config[75] = 0x00; config[76] = 0x07; config[77] = 0x30;
2201     scsi = arcbios_addchild_manual(cpu,
2202     COMPONENT_CLASS_AdapterClass,
2203     COMPONENT_TYPE_SCSIAdapter,
2204     0, 1, 2, 0, 0xffffffff, "ESP216",
2205     system, config, sizeof(config));
2206    
2207     arcbios_register_scsicontroller(machine, scsi);
2208     }
2209     }
2210     }
2211    
2212    
2213     /*
2214     * arcbios_console_init():
2215     *
2216     * Called from machine.c whenever an ARC-based machine is running with
2217     * a graphical VGA-style framebuffer, which can be used as console.
2218     */
2219     void arcbios_console_init(struct machine *machine,
2220     uint64_t vram, uint64_t ctrlregs)
2221     {
2222     machine->md.arc.vgaconsole = 1;
2223    
2224     machine->md.arc.console_vram = vram;
2225     machine->md.arc.console_ctrlregs = ctrlregs;
2226     machine->md.arc.console_maxx = ARC_CONSOLE_MAX_X;
2227     machine->md.arc.console_maxy = ARC_CONSOLE_MAX_Y;
2228     machine->md.arc.in_escape_sequence = 0;
2229     machine->md.arc.escape_sequence[0] = '\0';
2230     }
2231    
2232    
2233     /*
2234 dpavlin 22 * arc_environment_setup():
2235     *
2236     * Initialize the emulated environment variables.
2237     */
2238     static void arc_environment_setup(struct machine *machine, int is64bit,
2239     char *primary_ether_addr)
2240     {
2241     size_t bootpath_len = 500;
2242     char *init_bootpath;
2243     uint64_t addr, addr2;
2244     struct cpu *cpu = machine->cpus[0];
2245    
2246     /*
2247     * Boot string in ARC format:
2248     *
2249     * TODO: How about floppies? multi()disk()fdisk()
2250     * Is tftp() good for netbooting?
2251     */
2252     init_bootpath = malloc(bootpath_len);
2253     if (init_bootpath == NULL) {
2254     fprintf(stderr, "out of mem, bootpath\n");
2255     exit(1);
2256     }
2257     init_bootpath[0] = '\0';
2258    
2259     if (machine->bootdev_id < 0 || machine->force_netboot) {
2260     snprintf(init_bootpath, bootpath_len, "tftp()");
2261     } else {
2262     /* TODO: Make this nicer. */
2263     if (machine->machine_type == MACHINE_SGI) {
2264     if (machine->machine_subtype == 30)
2265     strlcat(init_bootpath, "xio(0)pci(15)",
2266 dpavlin 28 bootpath_len);
2267 dpavlin 22 if (machine->machine_subtype == 32)
2268     strlcat(init_bootpath, "pci(0)",
2269 dpavlin 28 bootpath_len);
2270 dpavlin 22 }
2271    
2272     if (diskimage_is_a_cdrom(machine, machine->bootdev_id,
2273     machine->bootdev_type))
2274     snprintf(init_bootpath + strlen(init_bootpath),
2275     bootpath_len - strlen(init_bootpath),
2276     "scsi(0)cdrom(%i)fdisk(0)", machine->bootdev_id);
2277     else
2278     snprintf(init_bootpath + strlen(init_bootpath),
2279     bootpath_len - strlen(init_bootpath),
2280     "scsi(0)disk(%i)rdisk(0)partition(1)",
2281     machine->bootdev_id);
2282     }
2283    
2284     if (machine->machine_type == MACHINE_ARC)
2285 dpavlin 28 strlcat(init_bootpath, "\\", bootpath_len);
2286 dpavlin 22
2287     machine->bootstr = malloc(ARC_BOOTSTR_BUFLEN);
2288     if (machine->bootstr == NULL) {
2289     fprintf(stderr, "out of memory\n");
2290     exit(1);
2291     }
2292    
2293     strlcpy(machine->bootstr, init_bootpath, ARC_BOOTSTR_BUFLEN);
2294     if (strlcat(machine->bootstr, machine->boot_kernel_filename,
2295     ARC_BOOTSTR_BUFLEN) >= ARC_BOOTSTR_BUFLEN) {
2296     fprintf(stderr, "boot string too long?\n");
2297     exit(1);
2298     }
2299    
2300     /* Boot args., eg "-a" */
2301     machine->bootarg = machine->boot_string_argument;
2302    
2303     /* argc, argv, envp in a0, a1, a2: */
2304     cpu->cd.mips.gpr[MIPS_GPR_A0] = 0; /* note: argc is increased later */
2305    
2306     /* TODO: not needed? */
2307     cpu->cd.mips.gpr[MIPS_GPR_SP] = (int64_t)(int32_t)
2308     (machine->physical_ram_in_mb * 1048576 + 0x80000000 - 0x2080);
2309    
2310     /* Set up argc/argv: */
2311     addr = ARC_ENV_STRINGS;
2312     addr2 = ARC_ARGV_START;
2313     cpu->cd.mips.gpr[MIPS_GPR_A1] = addr2;
2314    
2315     /* bootstr: */
2316     store_pointer_and_advance(cpu, &addr2, addr, is64bit);
2317     add_environment_string(cpu, machine->bootstr, &addr);
2318     cpu->cd.mips.gpr[MIPS_GPR_A0] ++;
2319    
2320     /* bootarg: */
2321     if (machine->bootarg[0] != '\0') {
2322     store_pointer_and_advance(cpu, &addr2, addr, is64bit);
2323     add_environment_string(cpu, machine->bootarg, &addr);
2324     cpu->cd.mips.gpr[MIPS_GPR_A0] ++;
2325     }
2326    
2327     cpu->cd.mips.gpr[MIPS_GPR_A2] = addr2;
2328    
2329     /*
2330     * Add environment variables. For each variable, add it
2331     * as a string using add_environment_string(), and add a
2332     * pointer to it to the ARC_ENV_POINTERS array.
2333     */
2334     if (machine->use_x11) {
2335     if (machine->machine_type == MACHINE_ARC) {
2336     store_pointer_and_advance(cpu, &addr2, addr, is64bit);
2337     add_environment_string(cpu,
2338     "CONSOLEIN=multi()key()keyboard()console()", &addr);
2339     store_pointer_and_advance(cpu, &addr2, addr, is64bit);
2340     add_environment_string(cpu,
2341     "CONSOLEOUT=multi()video()monitor()console()",
2342     &addr);
2343     } else {
2344     store_pointer_and_advance(cpu, &addr2, addr, is64bit);
2345     add_environment_string(cpu, "ConsoleIn=keyboard()",
2346     &addr);
2347     store_pointer_and_advance(cpu, &addr2, addr, is64bit);
2348     add_environment_string(cpu, "ConsoleOut=video()",
2349     &addr);
2350    
2351     /* g for graphical mode. G for graphical mode
2352     with SGI logo visible on Irix? */
2353     store_pointer_and_advance(cpu, &addr2, addr, is64bit);
2354     add_environment_string(cpu, "console=g", &addr);
2355     }
2356     } else {
2357     if (machine->machine_type == MACHINE_ARC) {
2358     /* TODO: serial console for ARC? */
2359     store_pointer_and_advance(cpu, &addr2, addr, is64bit);
2360     add_environment_string(cpu,
2361     "CONSOLEIN=multi()serial(0)", &addr);
2362     store_pointer_and_advance(cpu, &addr2, addr, is64bit);
2363     add_environment_string(cpu,
2364     "CONSOLEOUT=multi()serial(0)", &addr);
2365     } else {
2366     store_pointer_and_advance(cpu, &addr2, addr, is64bit);
2367     add_environment_string(cpu, "ConsoleIn=serial(0)",
2368     &addr);
2369     store_pointer_and_advance(cpu, &addr2, addr, is64bit);
2370     add_environment_string(cpu, "ConsoleOut=serial(0)",
2371     &addr);
2372    
2373     /* 'd' or 'd2' in Irix, 'ttyS0' in Linux? */
2374     store_pointer_and_advance(cpu, &addr2, addr, is64bit);
2375     add_environment_string(cpu, "console=d", &addr);
2376     }
2377     }
2378    
2379     if (machine->machine_type == MACHINE_SGI) {
2380     store_pointer_and_advance(cpu, &addr2, addr, is64bit);
2381     add_environment_string(cpu, "AutoLoad=No", &addr);
2382     store_pointer_and_advance(cpu, &addr2, addr, is64bit);
2383     add_environment_string(cpu, "diskless=0", &addr);
2384     store_pointer_and_advance(cpu, &addr2, addr, is64bit);
2385     add_environment_string(cpu, "volume=80", &addr);
2386     store_pointer_and_advance(cpu, &addr2, addr, is64bit);
2387     add_environment_string(cpu, "sgilogo=y", &addr);
2388    
2389     store_pointer_and_advance(cpu, &addr2, addr, is64bit);
2390     add_environment_string(cpu, "monitor=h", &addr);
2391     store_pointer_and_advance(cpu, &addr2, addr, is64bit);
2392     add_environment_string(cpu, "TimeZone=GMT", &addr);
2393     store_pointer_and_advance(cpu, &addr2, addr, is64bit);
2394     add_environment_string(cpu, "nogfxkbd=1", &addr);
2395    
2396     /* TODO: 'xio(0)pci(15)scsi(0)disk(1)rdisk(0)partition(0)'
2397     on IP30 at least */
2398    
2399     store_pointer_and_advance(cpu, &addr2, addr, is64bit);
2400     add_environment_string(cpu,
2401     "SystemPartition=pci(0)scsi(0)disk(2)rdisk(0)partition(8)",
2402     &addr);
2403     store_pointer_and_advance(cpu, &addr2, addr, is64bit);
2404     add_environment_string(cpu,
2405     "OSLoadPartition=pci(0)scsi(0)disk(2)rdisk(0)partition(0)",
2406     &addr);
2407     store_pointer_and_advance(cpu, &addr2, addr, is64bit);
2408     add_environment_string(cpu, "OSLoadFilename=/unix", &addr);
2409     store_pointer_and_advance(cpu, &addr2, addr, is64bit);
2410     add_environment_string(cpu, "OSLoader=sash", &addr);
2411    
2412     store_pointer_and_advance(cpu, &addr2, addr, is64bit);
2413     add_environment_string(cpu, "rbaud=9600", &addr);
2414     store_pointer_and_advance(cpu, &addr2, addr, is64bit);
2415     add_environment_string(cpu, "rebound=y", &addr);
2416     store_pointer_and_advance(cpu, &addr2, addr, is64bit);
2417     add_environment_string(cpu, "crt_option=1", &addr);
2418     store_pointer_and_advance(cpu, &addr2, addr, is64bit);
2419     add_environment_string(cpu, "netaddr=10.0.0.1", &addr);
2420    
2421     store_pointer_and_advance(cpu, &addr2, addr, is64bit);
2422     add_environment_string(cpu, "keybd=US", &addr);
2423    
2424     store_pointer_and_advance(cpu, &addr2, addr, is64bit);
2425     add_environment_string(cpu, "cpufreq=3", &addr);
2426     store_pointer_and_advance(cpu, &addr2, addr, is64bit);
2427     add_environment_string(cpu, "dbaud=9600", &addr);
2428     store_pointer_and_advance(cpu, &addr2, addr, is64bit);
2429     add_environment_string(cpu, primary_ether_addr, &addr);
2430     store_pointer_and_advance(cpu, &addr2, addr, is64bit);
2431     add_environment_string(cpu, "verbose=istrue", &addr);
2432     store_pointer_and_advance(cpu, &addr2, addr, is64bit);
2433     add_environment_string(cpu, "showconfig=istrue", &addr);
2434     store_pointer_and_advance(cpu, &addr2, addr, is64bit);
2435     add_environment_string(cpu, "diagmode=v", &addr);
2436     store_pointer_and_advance(cpu, &addr2, addr, is64bit);
2437     add_environment_string(cpu, "kernname=unix", &addr);
2438     } else {
2439     char *tmp;
2440     size_t mlen = strlen(machine->bootarg) +
2441     strlen("OSLOADOPTIONS=") + 2;
2442     tmp = malloc(mlen);
2443     snprintf(tmp, mlen, "OSLOADOPTIONS=%s", machine->bootarg);
2444     store_pointer_and_advance(cpu, &addr2, addr, is64bit);
2445     add_environment_string(cpu, tmp, &addr);
2446    
2447     store_pointer_and_advance(cpu, &addr2, addr, is64bit);
2448     add_environment_string(cpu, "OSLOADPARTITION=scsi(0)cdrom(6)"
2449     "fdisk(0);scsi(0)disk(0)rdisk(0)partition(1)", &addr);
2450    
2451     store_pointer_and_advance(cpu, &addr2, addr, is64bit);
2452     add_environment_string(cpu, "SYSTEMPARTITION=scsi(0)cdrom(6)"
2453     "fdisk(0);scsi(0)disk(0)rdisk(0)partition(1)", &addr);
2454     }
2455    
2456     /* End the environment strings with an empty zero-terminated
2457     string, and the envp array with a NULL pointer. */
2458     add_environment_string(cpu, "", &addr); /* the end */
2459     store_pointer_and_advance(cpu, &addr2, 0, is64bit);
2460    
2461     /* Return address: (0x20 = ReturnFromMain()) */
2462     cpu->cd.mips.gpr[MIPS_GPR_RA] = ARC_FIRMWARE_ENTRIES + 0x20;
2463     }
2464    
2465    
2466     /*
2467 dpavlin 14 * arcbios_init():
2468     *
2469     * Should be called before any other arcbios function is used. An exception
2470     * is arcbios_console_init(), which may be called before this function.
2471 dpavlin 22 *
2472     * TODO: Refactor; this is too long.
2473 dpavlin 14 */
2474 dpavlin 22 void arcbios_init(struct machine *machine, int is64bit, uint64_t sgi_ram_offset,
2475     char *primary_ether_addr, uint8_t *primary_ether_macaddr)
2476 dpavlin 14 {
2477     int i, alloclen = 20;
2478     char *name;
2479     uint64_t arc_reserved, mem_base, mem_count;
2480     struct cpu *cpu = machine->cpus[0];
2481     struct arcbios_sysid arcbios_sysid;
2482     struct arcbios_dsp_stat arcbios_dsp_stat;
2483     uint64_t system = 0;
2484     struct arcbios_spb arcbios_spb;
2485     struct arcbios_spb_64 arcbios_spb_64;
2486    
2487     machine->md.arc.arc_64bit = is64bit;
2488     machine->md.arc.wordlen = is64bit? sizeof(uint64_t) : sizeof(uint32_t);
2489    
2490     machine->md.arc.next_component_address = FIRST_ARC_COMPONENT;
2491     machine->md.arc.configuration_data_next_addr = ARC_CONFIG_DATA_ADDR;
2492    
2493     if (machine->physical_ram_in_mb < 16)
2494     fprintf(stderr, "WARNING! The ARC platform specification "
2495     "doesn't allow less than 16 MB of RAM. Continuing "
2496     "anyway.\n");
2497    
2498     /* File handles 0, 1, and 2 are stdin, stdout, and stderr. */
2499     for (i=0; i<ARC_MAX_HANDLES; i++) {
2500     machine->md.arc.file_handle_in_use[i] = i<3? 1 : 0;
2501     machine->md.arc.file_handle_string[i] = i>=3? NULL :
2502     (i==0? "(stdin)" : (i==1? "(stdout)" : "(stderr)"));
2503     machine->md.arc.current_seek_offset[i] = 0;
2504     }
2505    
2506     if (!machine->use_x11)
2507     machine->md.arc.vgaconsole = 0;
2508    
2509     if (machine->md.arc.vgaconsole) {
2510     char tmpstr[100];
2511     int x, y;
2512    
2513     machine->md.arc.console_curcolor = 0x1f;
2514     for (y=0; y<machine->md.arc.console_maxy; y++)
2515     for (x=0; x<machine->md.arc.console_maxx; x++)
2516     arcbios_putcell(cpu, ' ', x, y);
2517    
2518     machine->md.arc.console_curx = 0;
2519     machine->md.arc.console_cury = 0;
2520    
2521     arcbios_putstring(cpu, "GXemul");
2522     #ifdef VERSION
2523     arcbios_putstring(cpu, " "VERSION);
2524     #endif
2525     arcbios_putstring(cpu, " ARCBIOS emulation\n");
2526    
2527     snprintf(tmpstr, sizeof(tmpstr), "%i cpu%s (%s), %i MB "
2528     "memory\n\n", machine->ncpus, machine->ncpus > 1? "s" : "",
2529     cpu->cd.mips.cpu_type.name,
2530     machine->physical_ram_in_mb);
2531     arcbios_putstring(cpu, tmpstr);
2532     }
2533    
2534     arcbios_set_default_exception_handler(cpu);
2535    
2536     memset(&arcbios_sysid, 0, sizeof(arcbios_sysid));
2537     if (machine->machine_type == MACHINE_SGI) {
2538     /* Vendor ID, max 8 chars: */
2539     strncpy(arcbios_sysid.VendorId, "SGI", 3);
2540     switch (machine->machine_subtype) {
2541     case 22:
2542     strncpy(arcbios_sysid.ProductId,
2543     "87654321", 8); /* some kind of ID? */
2544     break;
2545     case 32:
2546     strncpy(arcbios_sysid.ProductId, "8", 1);
2547     /* 6 or 8 (?) */
2548     break;
2549     default:
2550     snprintf(arcbios_sysid.ProductId, 8, "IP%i",
2551     machine->machine_subtype);
2552     }
2553     } else {
2554     switch (machine->machine_subtype) {
2555     case MACHINE_ARC_NEC_RD94:
2556     strncpy(arcbios_sysid.VendorId, "NEC W&S", 8);
2557     strncpy(arcbios_sysid.ProductId, "RD94", 4);
2558     break;
2559     case MACHINE_ARC_NEC_R94:
2560     strncpy(arcbios_sysid.VendorId, "NEC W&S", 8);
2561     strncpy(arcbios_sysid.ProductId, "ijkl", 4);
2562     break;
2563     case MACHINE_ARC_NEC_R96:
2564     strncpy(arcbios_sysid.VendorId, "MIPS DUO", 8);
2565     strncpy(arcbios_sysid.ProductId, "blahblah", 8);
2566     break;
2567     case MACHINE_ARC_NEC_R98:
2568     strncpy(arcbios_sysid.VendorId, "NEC W&S", 8);
2569     strncpy(arcbios_sysid.ProductId, "R98", 4);
2570     break;
2571     case MACHINE_ARC_JAZZ_PICA:
2572     strncpy(arcbios_sysid.VendorId, "MIPS MAG", 8);
2573     strncpy(arcbios_sysid.ProductId, "ijkl", 4);
2574     break;
2575     case MACHINE_ARC_JAZZ_MAGNUM:
2576     strncpy(arcbios_sysid.VendorId, "MIPS MAG", 8);
2577     strncpy(arcbios_sysid.ProductId, "ijkl", 4);
2578     break;
2579     case MACHINE_ARC_JAZZ_M700:
2580     strncpy(arcbios_sysid.VendorId, "OLI00000", 8);
2581     strncpy(arcbios_sysid.ProductId, "ijkl", 4);
2582     break;
2583     case MACHINE_ARC_DESKTECH_TYNE:
2584     strncpy(arcbios_sysid.VendorId, "DESKTECH", 8);
2585     strncpy(arcbios_sysid.ProductId, "ijkl", 4);
2586     break;
2587     default:
2588     fatal("error in machine.c sysid\n");
2589     exit(1);
2590     }
2591     }
2592    
2593     store_buf(cpu, SGI_SYSID_ADDR, (char *)&arcbios_sysid,
2594     sizeof(arcbios_sysid));
2595    
2596     arcbios_get_dsp_stat(cpu, &arcbios_dsp_stat);
2597     store_buf(cpu, ARC_DSPSTAT_ADDR, (char *)&arcbios_dsp_stat,
2598     sizeof(arcbios_dsp_stat));
2599    
2600     /*
2601     * The first 12 MBs of RAM are simply reserved... this simplifies
2602     * things a lot. If there's more than 512MB of RAM, it has to be
2603     * split in two, according to the ARC spec. This code creates a
2604     * number of chunks of at most 512MB each.
2605     *
2606     * NOTE: The region of physical address space between 0x10000000 and
2607     * 0x1fffffff (256 - 512 MB) is usually occupied by memory mapped
2608     * devices, so that portion is "lost".
2609     */
2610     machine->md.arc.memdescriptor_base = ARC_MEMDESC_ADDR;
2611    
2612     arc_reserved = 0x2000;
2613     if (machine->machine_type == MACHINE_SGI)
2614     arc_reserved = 0x4000;
2615    
2616     arcbios_add_memory_descriptor(cpu, 0, arc_reserved,
2617     ARCBIOS_MEM_FirmwarePermanent);
2618     arcbios_add_memory_descriptor(cpu, sgi_ram_offset + arc_reserved,
2619     0x60000-arc_reserved, ARCBIOS_MEM_FirmwareTemporary);
2620    
2621     mem_base = 12;
2622     mem_base += sgi_ram_offset / 1048576;
2623    
2624     while (mem_base < machine->physical_ram_in_mb+sgi_ram_offset/1048576) {
2625     mem_count = machine->physical_ram_in_mb+sgi_ram_offset/1048576
2626     - mem_base;
2627    
2628     /* Skip the 256-512MB region (for devices) */
2629     if (mem_base < 256 && mem_base + mem_count > 256) {
2630     mem_count = 256-mem_base;
2631     }
2632    
2633     /* At most 512MB per descriptor (at least the first 512MB
2634     must be separated this way, according to the ARC spec) */
2635     if (mem_count > 512)
2636     mem_count = 512;
2637    
2638     arcbios_add_memory_descriptor(cpu, mem_base * 1048576,
2639     mem_count * 1048576, ARCBIOS_MEM_FreeMemory);
2640    
2641     mem_base += mem_count;
2642    
2643     /* Skip the devices: */
2644     if (mem_base == 256)
2645     mem_base = 512;
2646     }
2647    
2648     /*
2649     * Components: (this is an example of what a system could look like)
2650     *
2651     * [System]
2652     * [CPU] (one for each cpu)
2653     * [FPU] (one for each cpu)
2654     * [CPU Caches]
2655     * [Memory]
2656     * [Ethernet]
2657     * [Serial]
2658     * [SCSI]
2659     * [Disk]
2660     *
2661     * Here's a good list of what hardware is in different IP-models:
2662     * http://www.linux-mips.org/archives/linux-mips/2001-03/msg00101.html
2663     */
2664    
2665     if (machine->machine_name == NULL)
2666     fatal("ERROR: machine_name == NULL\n");
2667    
2668     /* Add the root node: */
2669     switch (machine->machine_type) {
2670     case MACHINE_SGI:
2671     name = malloc(alloclen);
2672     if (name == NULL) {
2673     fprintf(stderr, "out of memory\n");
2674     exit(1);
2675     }
2676     snprintf(name, alloclen, "SGI-IP%i",
2677     machine->machine_subtype);
2678    
2679     /* A very special case for IP24 (which identifies itself
2680     as an IP22): */
2681     if (machine->machine_subtype == 24)
2682     snprintf(name, alloclen, "SGI-IP22");
2683     break;
2684     case MACHINE_ARC:
2685     /* ARC: */
2686     switch (machine->machine_subtype) {
2687     case MACHINE_ARC_NEC_RD94:
2688     name = "NEC-RD94";
2689     break;
2690     case MACHINE_ARC_NEC_R94:
2691     name = "NEC-R94";
2692     break;
2693     case MACHINE_ARC_NEC_R96:
2694     name = "NEC-R96";
2695     break;
2696     case MACHINE_ARC_NEC_R98:
2697     name = "NEC-R98";
2698     break;
2699     case MACHINE_ARC_JAZZ_PICA:
2700     name = "PICA-61";
2701     break;
2702     case MACHINE_ARC_JAZZ_MAGNUM:
2703     case MACHINE_ARC_JAZZ_M700:
2704     name = "Microsoft-Jazz";
2705     break;
2706     case MACHINE_ARC_DESKTECH_TYNE:
2707     name = "DESKTECH-TYNE";
2708     break;
2709     default:
2710     fatal("Unimplemented ARC machine type %i\n",
2711     machine->machine_subtype);
2712     exit(1);
2713     }
2714     break;
2715     default:
2716     fatal("ERROR: non-SGI and non-ARC?\n");
2717     exit(1);
2718     }
2719    
2720     system = arcbios_addchild_manual(cpu, COMPONENT_CLASS_SystemClass,
2721     COMPONENT_TYPE_ARC, 0,1,2,0, 0xffffffff, name, 0/*ROOT*/, NULL, 0);
2722 dpavlin 24 debug("ARC system @ 0x%"PRIx64" (\"%s\")\n", (uint64_t) system, name);
2723 dpavlin 14
2724    
2725     /*
2726     * Add tree nodes for CPUs and their caches:
2727     */
2728    
2729     for (i=0; i<machine->ncpus; i++) {
2730     uint64_t cpuaddr, fpu=0, picache, pdcache, sdcache=0;
2731     int cache_size, cache_line_size;
2732     unsigned int jj;
2733     char arc_cpu_name[100];
2734     char arc_fpc_name[105];
2735    
2736     snprintf(arc_cpu_name, sizeof(arc_cpu_name),
2737     "MIPS-%s", machine->cpu_name);
2738    
2739     if (machine->machine_type == MACHINE_ARC &&
2740     machine->machine_subtype == MACHINE_ARC_NEC_R96)
2741     snprintf(arc_cpu_name, sizeof(arc_cpu_name),
2742     "MIPS-%s - Pr 4/5.0, Fp 5/0", machine->cpu_name);
2743    
2744     arc_cpu_name[sizeof(arc_cpu_name)-1] = 0;
2745     for (jj=0; jj<strlen(arc_cpu_name); jj++)
2746     if (arc_cpu_name[jj] >= 'a' && arc_cpu_name[jj] <= 'z')
2747     arc_cpu_name[jj] += ('A' - 'a');
2748    
2749     strlcpy(arc_fpc_name, arc_cpu_name, sizeof(arc_fpc_name));
2750     strlcat(arc_fpc_name, "FPC", sizeof(arc_fpc_name));
2751    
2752     cpuaddr = arcbios_addchild_manual(cpu,
2753     COMPONENT_CLASS_ProcessorClass, COMPONENT_TYPE_CPU,
2754     0, 1, 2, i, 0xffffffff, arc_cpu_name, system, NULL, 0);
2755    
2756     /*
2757     * TODO: This was in the ARC specs, but it isn't really used
2758     * by ARC implementations? At least SGI-IP32 uses it.
2759     */
2760     if (machine->machine_type == MACHINE_SGI)
2761     fpu = arcbios_addchild_manual(cpu,
2762     COMPONENT_CLASS_ProcessorClass, COMPONENT_TYPE_FPU,
2763     0, 1, 2, 0, 0xffffffff, arc_fpc_name, cpuaddr,
2764     NULL, 0);
2765    
2766     cache_size = DEFAULT_PCACHE_SIZE - 12;
2767     if (machine->cache_picache)
2768     cache_size = machine->cache_picache - 12;
2769     if (cache_size < 0)
2770     cache_size = 0;
2771    
2772     cache_line_size = DEFAULT_PCACHE_LINESIZE;
2773     if (machine->cache_picache_linesize)
2774     cache_line_size = machine->cache_picache_linesize;
2775     if (cache_line_size < 0)
2776     cache_line_size = 0;
2777    
2778     picache = arcbios_addchild_manual(cpu,
2779     COMPONENT_CLASS_CacheClass, COMPONENT_TYPE_PrimaryICache,
2780     0, 1, 2,
2781     /*
2782     * Key bits: 0xXXYYZZZZ
2783     * XX is refill-size.
2784     * Cache line size is 1 << YY,
2785     * Cache size is 4KB << ZZZZ.
2786     */
2787     0x01000000 + (cache_line_size << 16) + cache_size,
2788     /* 32 bytes per line, default = 32 KB total */
2789     0xffffffff, NULL, cpuaddr, NULL, 0);
2790    
2791     cache_size = DEFAULT_PCACHE_SIZE - 12;
2792     if (machine->cache_pdcache)
2793     cache_size = machine->cache_pdcache - 12;
2794     if (cache_size < 0)
2795     cache_size = 0;
2796    
2797     cache_line_size = DEFAULT_PCACHE_LINESIZE;
2798     if (machine->cache_pdcache_linesize)
2799     cache_line_size = machine->cache_pdcache_linesize;
2800     if (cache_line_size < 0)
2801     cache_line_size = 0;
2802    
2803     pdcache = arcbios_addchild_manual(cpu,
2804     COMPONENT_CLASS_CacheClass,
2805     COMPONENT_TYPE_PrimaryDCache, 0, 1, 2,
2806     /*
2807     * Key bits: 0xYYZZZZ
2808     * Cache line size is 1 << YY,
2809     * Cache size is 4KB << ZZZZ.
2810     */
2811     0x01000000 + (cache_line_size << 16) + cache_size,
2812     /* 32 bytes per line, default = 32 KB total */
2813     0xffffffff, NULL, cpuaddr, NULL, 0);
2814    
2815     if (machine->cache_secondary >= 12) {
2816     cache_size = machine->cache_secondary - 12;
2817    
2818     cache_line_size = 6; /* 64 bytes default */
2819     if (machine->cache_secondary_linesize)
2820     cache_line_size = machine->
2821     cache_secondary_linesize;
2822     if (cache_line_size < 0)
2823     cache_line_size = 0;
2824    
2825     sdcache = arcbios_addchild_manual(cpu,
2826     COMPONENT_CLASS_CacheClass,
2827     COMPONENT_TYPE_SecondaryDCache, 0, 1, 2,
2828     /*
2829     * Key bits: 0xYYZZZZ
2830     * Cache line size is 1 << YY,
2831     * Cache size is 4KB << ZZZZ.
2832     */
2833     0x01000000 + (cache_line_size << 16) + cache_size,
2834     /* 64 bytes per line, default = 1 MB total */
2835     0xffffffff, NULL, cpuaddr, NULL, 0);
2836     }
2837    
2838 dpavlin 24 debug("ARC cpu%i @ 0x%"PRIx64, i, (uint64_t) cpuaddr);
2839 dpavlin 14
2840     if (fpu != 0)
2841 dpavlin 24 debug(" (fpu @ 0x%"PRIx64")\n", (uint64_t) fpu);
2842 dpavlin 14 else
2843     debug("\n");
2844    
2845 dpavlin 24 debug(" picache @ 0x%"PRIx64", pdcache @ 0x%"PRIx64"\n",
2846     (uint64_t) picache, (uint64_t) pdcache);
2847 dpavlin 14
2848     if (machine->cache_secondary >= 12)
2849 dpavlin 24 debug(" sdcache @ 0x%"PRIx64"\n",
2850     (uint64_t) sdcache);
2851 dpavlin 14
2852     if (machine->machine_type == MACHINE_SGI) {
2853     /* TODO: Memory amount (and base address?)! */
2854     uint64_t memory = arcbios_addchild_manual(cpu,
2855     COMPONENT_CLASS_MemoryClass,
2856     COMPONENT_TYPE_MemoryUnit, 0, 1, 2, 0,
2857     0xffffffff, "memory", cpuaddr, NULL, 0);
2858 dpavlin 24 debug("ARC memory @ 0x%"PRIx64"\n", (uint64_t) memory);
2859 dpavlin 14 }
2860     }
2861    
2862    
2863     /*
2864     * Add other components:
2865     *
2866     * TODO: How should this be synched with the hardware devices
2867     * added in machine.c?
2868     */
2869    
2870     arcbios_add_other_components(machine, system);
2871    
2872    
2873     /*
2874     * Defalt TLB entry for 64-bit SGI machines:
2875     */
2876     if (machine->machine_type == MACHINE_SGI &&
2877     machine->machine_subtype != 12 /* TODO: ugly */ ) {
2878     /* TODO: On which models is this required? */
2879     mips_coproc_tlb_set_entry(cpu, 0, 1048576*16,
2880     0xc000000000000000ULL, 0, 1048576*16, 1,1,1,1,1, 0, 2, 2);
2881     }
2882    
2883    
2884     /*
2885     * Set up Firmware Vectors:
2886     */
2887     add_symbol_name(&machine->symbol_context,
2888     ARC_FIRMWARE_ENTRIES, 0x10000, "[ARCBIOS entry]", 0, 1);
2889    
2890     for (i=0; i<100; i++) {
2891     if (is64bit) {
2892     store_64bit_word(cpu, ARC_FIRMWARE_VECTORS + i*8,
2893     ARC_FIRMWARE_ENTRIES + i*8);
2894     store_64bit_word(cpu, ARC_PRIVATE_VECTORS + i*8,
2895     ARC_PRIVATE_ENTRIES + i*8);
2896 dpavlin 24
2897     /* "Magic trap" instruction: */
2898     store_32bit_word(cpu, ARC_FIRMWARE_ENTRIES + i*8,
2899     0x00c0de0c);
2900     store_32bit_word(cpu, ARC_PRIVATE_ENTRIES + i*8,
2901     0x00c0de0c);
2902 dpavlin 14 } else {
2903     store_32bit_word(cpu, ARC_FIRMWARE_VECTORS + i*4,
2904     ARC_FIRMWARE_ENTRIES + i*4);
2905     store_32bit_word(cpu, ARC_PRIVATE_VECTORS + i*4,
2906     ARC_PRIVATE_ENTRIES + i*4);
2907 dpavlin 24
2908     /* "Magic trap" instruction: */
2909     store_32bit_word(cpu, ARC_FIRMWARE_ENTRIES + i*4,
2910     0x00c0de0c);
2911     store_32bit_word(cpu, ARC_PRIVATE_ENTRIES + i*4,
2912     0x00c0de0c);
2913 dpavlin 14 }
2914     }
2915    
2916    
2917     /*
2918     * Set up the ARC SPD:
2919     */
2920     if (is64bit) {
2921     /* ARCS64 SPD (TODO: This is just a guess) */
2922     memset(&arcbios_spb_64, 0, sizeof(arcbios_spb_64));
2923     store_64bit_word_in_host(cpu, (unsigned char *)
2924     &arcbios_spb_64.SPBSignature, ARCBIOS_SPB_SIGNATURE);
2925     store_16bit_word_in_host(cpu, (unsigned char *)
2926     &arcbios_spb_64.Version, 64);
2927     store_16bit_word_in_host(cpu, (unsigned char *)
2928     &arcbios_spb_64.Revision, 0);
2929     store_64bit_word_in_host(cpu, (unsigned char *)
2930     &arcbios_spb_64.FirmwareVector, ARC_FIRMWARE_VECTORS);
2931     store_buf(cpu, SGI_SPB_ADDR, (char *)&arcbios_spb_64,
2932     sizeof(arcbios_spb_64));
2933     } else {
2934     /* ARCBIOS SPB: (For ARC and 32-bit SGI modes) */
2935     memset(&arcbios_spb, 0, sizeof(arcbios_spb));
2936     store_32bit_word_in_host(cpu, (unsigned char *)
2937     &arcbios_spb.SPBSignature, ARCBIOS_SPB_SIGNATURE);
2938     store_32bit_word_in_host(cpu, (unsigned char *)
2939     &arcbios_spb.SPBLength, sizeof(arcbios_spb));
2940     store_16bit_word_in_host(cpu, (unsigned char *)
2941     &arcbios_spb.Version, 1);
2942     store_16bit_word_in_host(cpu, (unsigned char *)
2943     &arcbios_spb.Revision, machine->machine_type ==
2944     MACHINE_SGI? 10 : 2);
2945     store_32bit_word_in_host(cpu, (unsigned char *)
2946     &arcbios_spb.FirmwareVector, ARC_FIRMWARE_VECTORS);
2947     store_32bit_word_in_host(cpu, (unsigned char *)
2948     &arcbios_spb.FirmwareVectorLength, 100 * 4); /* ? */
2949     store_32bit_word_in_host(cpu, (unsigned char *)
2950     &arcbios_spb.PrivateVector, ARC_PRIVATE_VECTORS);
2951     store_32bit_word_in_host(cpu, (unsigned char *)
2952     &arcbios_spb.PrivateVectorLength, 100 * 4); /* ? */
2953     store_buf(cpu, SGI_SPB_ADDR, (char *)&arcbios_spb,
2954     sizeof(arcbios_spb));
2955     }
2956 dpavlin 22
2957    
2958     /*
2959     * TODO: How to build the component tree intermixed with
2960     * the rest of device initialization?
2961     */
2962    
2963     arc_environment_setup(machine, is64bit, primary_ether_addr);
2964 dpavlin 14 }
2965    

  ViewVC Help
Powered by ViewVC 1.1.26