/[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 24 - (hide annotations)
Mon Oct 8 16:19:56 2007 UTC (16 years, 6 months ago) by dpavlin
File MIME type: text/plain
File size: 94274 byte(s)
++ trunk/HISTORY	(local)
$Id: HISTORY,v 1.1256 2006/06/23 20:43:44 debug Exp $
20060219	Various minor updates. Removing the old MIPS16 skeleton code,
		because it will need to be rewritten for dyntrans anyway.
20060220-22	Removing the non-working dyntrans backend support.
		Continuing on the 64-bit dyntrans virtual memory generalization.
20060223	More work on the 64-bit vm generalization.
20060225	Beginning on MIPS dyntrans load/store instructions.
		Minor PPC updates (64-bit load/store, etc).
		Fixes for the variable-instruction-length framework, some
		minor AVR updates (a simple Hello World program works!).
		Beginning on a skeleton for automatically generating documen-
		tation (for devices etc.).
20060226	PPC updates (adding some more 64-bit instructions, etc).
		AVR updates (more instructions).
		FINALLY found and fixed the zs bug, making NetBSD/macppc
		accept the serial console.
20060301	Adding more AVR instructions.
20060304	Continuing on AVR-related stuff. Beginning on a framework for
		cycle-accurate device emulation. Adding an experimental "PAL
		TV" device (just a dummy so far).
20060305	Adding more AVR instructions.
		Adding a dummy epcom serial controller (for TS7200 emulation).
20060310	Removing the emul() command from configuration files, so only
		net() and machine() are supported.
		Minor progress on the MIPS dyntrans rewrite.
20060311	Continuing on the MIPS dyntrans rewrite (adding more
		instructions, etc).
20060315	Adding more instructions (sllv, srav, srlv, bgtz[l], blez[l],
		beql, bnel, slti[u], various loads and stores).
20060316	Removing the ALWAYS_SIGNEXTEND_32 option, since it was rarely
		used.
		Adding more MIPS dyntrans instructions, and fixing bugs.
20060318	Implementing fast loads/stores for MIPS dyntrans (big/little
		endian, 32-bit and 64-bit modes).
20060320	Making MIPS dyntrans the default configure option; use
		"--enable-oldmips" to use the old bintrans system.
		Adding MIPS dyntrans dmult[u]; minor updates.
20060322	Continuing... adding some more instructions.
		Adding a simple skeleton for demangling C++ "_ZN" symbols.
20060323	Moving src/debugger.c into a new directory (src/debugger/).
20060324	Fixing the hack used to load PPC ELFs (useful for relocated
		Linux/ppc kernels), and adding a dummy G3 machine mode.
20060325-26	Beginning to experiment with GDB remote serial protocol
		connections; adding a -G command line option for selecting
		which TCP port to listen to.
20060330	Beginning a major cleanup to replace things like "0x%016llx"
		with more correct "0x%016"PRIx64, etc.
		Continuing on the GDB remote serial protocol support.
20060331	More cleanup, and some minor GDB remote progress.
20060402	Adding a hack to the configure script, to allow compilation
		on systems that lack PRIx64 etc.
20060406	Removing the temporary FreeBSD/arm hack in dev_ns16550.c and
		replacing it with a better fix from Olivier Houchard.
20060407	A remote debugger (gdb or ddd) can now start and stop the
		emulator using the GDB remote serial protocol, and registers
		and memory can be read. MIPS only for now.
20060408	More GDB progress: single-stepping also works, and also adding
		support for ARM, PowerPC, and Alpha targets.
		Continuing on the delay-slot-across-page-boundary issue.
20060412	Minor update: beginning to add support for the SPARC target
		to the remote GDB functionality.
20060414	Various MIPS updates: adding more instructions for dyntrans
		(eret, add), and making some exceptions work. Fixing a bug
		in dmult[u].
		Implementing the first SPARC instructions (sethi, or).
20060415	Adding "magic trap" instructions so that PROM calls can be
		software emulated in MIPS dyntrans.
		Adding more MIPS dyntrans instructions (ddiv, dadd) and
		fixing another bug in dmult.
20060416	More MIPS dyntrans progress: adding [d]addi, movn, movz, dsllv,
		rfi, an ugly hack for supporting R2000/R3000 style faked caches,
		preliminary interrupt support, and various other updates and
		bugfixes.
20060417	Adding more SPARC instructions (add, sub, sll[x], sra[x],
		srl[x]), and useful SPARC header definitions.
		Adding the first (trivial) x86/AMD64 dyntrans instructions (nop,
		cli/sti, stc/clc, std/cld, simple mov, inc ax). Various other
		x86 updates related to variable instruction length stuff.
		Adding unaligned loads/stores to the MIPS dyntrans mode (but
		still using the pre-dyntrans (slow) imlementation).
20060419	Fixing a MIPS dyntrans exception-in-delay-slot bug.
		Removing the old "show opcode statistics" functionality, since
		it wasn't really useful and isn't implemented for dyntrans.
		Single-stepping (or running with instruction trace) now looks
		ok with dyntrans with delay-slot architectures.
20060420	Minor hacks (removing the -B command line option when compiled
		for non-bintrans, and some other very minor updates).
		Adding (slow) MIPS dyntrans load-linked/store-conditional.
20060422	Applying fixes for bugs discovered by Nils Weller's nwcc
		(static DEC memmap => now per machine, and adding an extern
		keyword in cpu_arm_instr.c).
		Finally found one of the MIPS dyntrans bugs that I've been
		looking for (copy/paste spelling error BIG vs LITTLE endian in
		cpu_mips_instr_loadstore.c for 16-bit fast stores).
		FINALLY found the major MIPS dyntrans bug: slti vs sltiu
		signed/unsigned code in cpu_mips_instr.c. :-)
		Adding more MIPS dyntrans instructions (lwc1, swc1, bgezal[l],
		ctc1, tlt[u], tge[u], tne, beginning on rdhwr).
		NetBSD/hpcmips can now reach userland when using dyntrans :-)
		Adding some more x86 dyntrans instructions.
		Finally removed the old Alpha-specific virtual memory code,
		and replaced it with the generic 64-bit version.
		Beginning to add disassembly support for SPECIAL3 MIPS opcodes.
20060423	Continuing on the delay-slot-across-page-boundary issue;
		adding an end_of_page2 ic slot (like I had planned before, but
		had removed for some reason).
		Adding a quick-and-dirty fallback to legacy coprocessor 1
		code (i.e. skipping dyntrans implementation for now).
		NetBSD/hpcmips and NetBSD/pmax (when running on an emulated
		R4400) can now be installed and run. :-)  (Many bugs left
		to fix, though.)
		Adding more MIPS dyntrans instructions: madd[u], msub[u].
		Cleaning up the SPECIAL2 vs R5900/TX79/C790 "MMI" opcode
		maps somewhat (disassembly and dyntrans instruction decoding).
20060424	Adding an isa_revision field to mips_cpu_types.h, and making
		sure that SPECIAL3 opcodes cause Reserved Instruction
		exceptions on MIPS32/64 revisions lower than 2.
		Adding the SPARC 'ba', 'call', 'jmpl/retl', 'and', and 'xor'
		instructions.
20060425	Removing the -m command line option ("run at most x 
		instructions") and -T ("single_step_on_bad_addr"), because
		they never worked correctly with dyntrans anyway.
		Freshening up the man page.
20060428	Adding more MIPS dyntrans instructions: bltzal[l], idle.
		Enabling MIPS dyntrans compare interrupts.
20060429	FINALLY found the weird dyntrans bug, causing NetBSD etc. to
		behave strangely: some floating point code (conditional
		coprocessor branches) could not be reused from the old
		non-dyntrans code. The "quick-and-dirty fallback" only appeared
		to work. Fixing by implementing bc1* for MIPS dyntrans.
		More MIPS instructions: [d]sub, sdc1, ldc1, dmtc1, dmfc1, cfc0.
		Freshening up MIPS floating point disassembly appearance.
20060430	Continuing on C790/R5900/TX79 disassembly; implementing 128-bit
		"por" and "pextlw".
20060504	Disabling -u (userland emulation) unless compiled as unstable
		development version.
		Beginning on freshening up the testmachine include files,
		to make it easier to reuse those files (placing them in
		src/include/testmachine/), and beginning on a set of "demos"
		or "tutorials" for the testmachine functionality.
		Minor updates to the MIPS GDB remote protocol stub.
		Refreshing doc/experiments.html and gdb_remote.html.
		Enabling Alpha emulation in the stable release configuration,
		even though no guest OSes for Alpha can run yet.
20060505	Adding a generic 'settings' object, which will contain
		references to settable variables (which will later be possible
		to access using the debugger).
20060506	Updating dev_disk and corresponding demo/documentation (and
		switching from SCSI to IDE disk types, so it actually works
		with current test machines :-).
20060510	Adding a -D_LARGEFILE_SOURCE hack for 64-bit Linux hosts,
		so that fseeko() doesn't give a warning.
		Updating the section about how dyntrans works (the "runnable
		IR") in doc/intro.html.
		Instruction updates (some x64=1 checks, some more R5900
		dyntrans stuff: better mul/mult separation from MIPS32/64,
		adding ei and di).
		Updating MIPS cpuregs.h to a newer one (from NetBSD).
		Adding more MIPS dyntrans instructions: deret, ehb.
20060514	Adding disassembly and beginning implementation of SPARC wr
		and wrpr instructions.
20060515	Adding a SUN SPARC machine mode, with dummy SS20 and Ultra1
		machines. Adding the 32-bit "rd psr" instruction.
20060517	Disassembly support for the general SPARC rd instruction.
		Partial implementation of the cmp (subcc) instruction.
		Some other minor updates (making sure that R5900 processors
		start up with the EIE bit enabled, otherwise Linux/playstation2
		receives no interrupts).
20060519	Minor MIPS updates/cleanups.
20060521	Moving the MeshCube machine into evbmips; this seems to work
		reasonably well with a snapshot of a NetBSD MeshCube kernel.
		Cleanup/fix of MIPS config0 register initialization.
20060529	Minor MIPS fixes, including a sign-extension fix to the
		unaligned load/store code, which makes NetBSD/pmax on R3000
		work better with dyntrans. (Ultrix and Linux/DECstation still
		don't work, though.)
20060530	Minor updates to the Alpha machine mode: adding an AlphaBook
		mode, an LCA bus (forwarding accesses to an ISA bus), etc.
20060531	Applying a bugfix for the MIPS dyntrans sc[d] instruction from
		Ondrej Palkovsky. (Many thanks.)
20060601	Minifix to allow ARM immediate msr instruction to not give
		an error for some valid values.
		More Alpha updates.
20060602	Some minor Alpha updates.
20060603	Adding the Alpha cmpbge instruction. NetBSD/alpha prints its
		first boot messages :-) on an emulated Alphabook 1.
20060612	Minor updates; adding a dev_ether.h include file for the
		testmachine ether device. Continuing the hunt for the dyntrans
		bug which makes Linux and Ultrix on DECstation behave
		strangely... FINALLY found it! It seems to be related to
		invalidation of the translation cache, on tlbw{r,i}. There
		also seems to be some remaining interrupt-related problems.
20060614	Correcting the implementation of ldc1/sdc1 for MIPS dyntrans
		(so that it uses 16 32-bit registers if the FR bit in the
		status register is not set).
20060616	REMOVING BINTRANS COMPLETELY!
		Removing the old MIPS interpretation mode.
		Removing the MFHILO_DELAY and instruction delay stuff, because
		they wouldn't work with dyntrans anyway.
20060617	Some documentation updates (adding "NetBSD-archive" to some
		URLs, and new Debian/DECstation installation screenshots).
		Removing the "tracenull" and "enable-caches" configure options.
		Improving MIPS dyntrans performance somewhat (only invalidate
		translations if necessary, on writes to the entryhi register,
		instead of doing it for all cop0 writes).
20060618	More cleanup after the removal of the old MIPS emulation.
		Trying to fix the MIPS dyntrans performance bugs/bottlenecks;
		only semi-successful so far (for R3000).
20060620	Minor update to allow clean compilation again on Tru64/Alpha.
20060622	MIPS cleanup and fixes (removing the pc_last stuff, which
		doesn't make sense with dyntrans anyway, and fixing a cross-
		page-delay-slot-with-exception case in end_of_page).
		Removing the old max_random_cycles_per_chunk stuff, and the
		concept of cycles vs instructions for MIPS emulation.
		FINALLY found and fixed the bug which caused NetBSD/pmax
		clocks to behave strangely (it was a load to the zero register,
		which was treated as a NOP; now it is treated as a load to a
		dummy scratch register).
20060623	Increasing the dyntrans chunk size back to
		N_SAFE_DYNTRANS_LIMIT, instead of N_SAFE_DYNTRANS_LIMIT/2.
		Preparing for a quick release, even though there are known
		bugs, and performance for non-R3000 MIPS emulation is very
		poor. :-/
		Reverting to half the dyntrans chunk size again, because
		NetBSD/cats seemed less stable with full size chunks. :(
		NetBSD/sgimips 3.0 can now run :-)  (With release 0.3.8, only
		NetBSD/sgimips 2.1 worked, not 3.0.)

==============  RELEASE 0.4.0  ==============


1 dpavlin 14 /*
2 dpavlin 22 * Copyright (C) 2003-2006 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 24 * $Id: arcbios.c,v 1.8 2006/04/15 08:21:07 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     cpu->dead = 1;
1127     }
1128     }
1129    
1130    
1131     /*
1132     * arcbios_emul(): ARCBIOS emulation
1133     *
1134     * 0x0c Halt()
1135     * 0x10 PowerDown()
1136     * 0x14 Restart()
1137     * 0x18 Reboot()
1138     * 0x1c EnterInteractiveMode()
1139     * 0x20 ReturnFromMain()
1140     * 0x24 GetPeer(node)
1141     * 0x28 GetChild(node)
1142     * 0x2c GetParent(node)
1143     * 0x30 GetConfigurationData(config_data, node)
1144     * 0x3c GetComponent(name)
1145     * 0x44 GetSystemId()
1146     * 0x48 GetMemoryDescriptor(void *)
1147     * 0x50 GetTime()
1148     * 0x54 GetRelativeTime()
1149     * 0x5c Open(path, mode, &fileid)
1150     * 0x60 Close(handle)
1151     * 0x64 Read(handle, &buf, len, &actuallen)
1152     * 0x6c Write(handle, buf, len, &returnlen)
1153     * 0x70 Seek(handle, &offset, len)
1154     * 0x78 GetEnvironmentVariable(char *)
1155     * 0x7c SetEnvironmentVariable(char *, char *)
1156     * 0x80 GetFileInformation(handle, buf)
1157     * 0x88 FlushAllCaches()
1158     * 0x90 GetDisplayStatus(uint32_t handle)
1159     * 0x100 undocumented IRIX (?)
1160     */
1161     int arcbios_emul(struct cpu *cpu)
1162     {
1163     struct machine *machine = cpu->machine;
1164     int vector = cpu->pc & 0xfff;
1165     int i, j, handle;
1166     unsigned char ch2;
1167     unsigned char buf[40];
1168    
1169     if (cpu->pc >= ARC_PRIVATE_ENTRIES &&
1170     cpu->pc < ARC_PRIVATE_ENTRIES + 100*sizeof(uint32_t)) {
1171     arcbios_private_emul(cpu);
1172     return 1;
1173     }
1174    
1175     if (machine->md.arc.arc_64bit)
1176     vector /= 2;
1177    
1178     /* Special case for reboot by jumping to 0xbfc00000: */
1179     if (vector == 0 && (cpu->pc & 0xffffffffULL) == 0xbfc00000ULL)
1180     vector = 0x18;
1181    
1182     switch (vector) {
1183     case 0x0c: /* Halt() */
1184     case 0x10: /* PowerDown() */
1185     case 0x14: /* Restart() */
1186     case 0x18: /* Reboot() */
1187     case 0x1c: /* EnterInteractiveMode() */
1188     case 0x20: /* ReturnFromMain() */
1189     debug("[ ARCBIOS Halt() or similar ]\n");
1190     /* Halt all CPUs. */
1191     for (i=0; i<machine->ncpus; i++) {
1192     machine->cpus[i]->running = 0;
1193     machine->cpus[i]->dead = 1;
1194     }
1195     machine->exit_without_entering_debugger = 1;
1196     break;
1197     case 0x24: /* GetPeer(node) */
1198     if (cpu->cd.mips.gpr[MIPS_GPR_A0] == 0) {
1199     /* NULL ptr argument: return NULL. */
1200     cpu->cd.mips.gpr[MIPS_GPR_V0] = 0;
1201     } else {
1202     uint64_t peer;
1203     cpu->memory_rw(cpu, cpu->mem,
1204     cpu->cd.mips.gpr[MIPS_GPR_A0] - 3 *
1205     machine->md.arc.wordlen, &buf[0],
1206     machine->md.arc.wordlen, MEM_READ, CACHE_NONE);
1207     if (machine->md.arc.arc_64bit) {
1208     if (cpu->byte_order == EMUL_BIG_ENDIAN) {
1209     unsigned char tmp; tmp = buf[0];
1210     buf[0] = buf[7]; buf[7] = tmp;
1211     tmp = buf[1]; buf[1] = buf[6];
1212     buf[6] = tmp;
1213     tmp = buf[2]; buf[2] = buf[5];
1214     buf[5] = tmp;
1215     tmp = buf[3]; buf[3] = buf[4];
1216     buf[4] = tmp;
1217     }
1218     peer = (uint64_t)buf[0] + ((uint64_t)buf[1]<<8)
1219     + ((uint64_t)buf[2]<<16)
1220     + ((uint64_t)buf[3]<<24)
1221     + ((uint64_t)buf[4]<<32)
1222     + ((uint64_t)buf[5]<<40)
1223     + ((uint64_t)buf[6]<<48)
1224     + ((uint64_t)buf[7]<<56);
1225     } else {
1226     if (cpu->byte_order == EMUL_BIG_ENDIAN) {
1227     unsigned char tmp; tmp = buf[0];
1228     buf[0] = buf[3]; buf[3] = tmp;
1229     tmp = buf[1]; buf[1] = buf[2];
1230     buf[2] = tmp;
1231     }
1232     peer = buf[0] + (buf[1]<<8) + (buf[2]<<16)
1233     + (buf[3]<<24);
1234     }
1235    
1236     cpu->cd.mips.gpr[MIPS_GPR_V0] = peer?
1237     (peer + 3 * machine->md.arc.wordlen) : 0;
1238     if (!machine->md.arc.arc_64bit)
1239     cpu->cd.mips.gpr[MIPS_GPR_V0] = (int64_t)
1240     (int32_t) cpu->cd.mips.gpr[MIPS_GPR_V0];
1241     }
1242 dpavlin 24 debug("[ ARCBIOS GetPeer(node 0x%016"PRIx64"): 0x%016"PRIx64
1243     " ]\n", (uint64_t) cpu->cd.mips.gpr[MIPS_GPR_A0],
1244     (uint64_t) cpu->cd.mips.gpr[MIPS_GPR_V0]);
1245 dpavlin 14 break;
1246     case 0x28: /* GetChild(node) */
1247     /* 0 for the root, non-0 for children: */
1248     if (cpu->cd.mips.gpr[MIPS_GPR_A0] == 0)
1249     cpu->cd.mips.gpr[MIPS_GPR_V0] = FIRST_ARC_COMPONENT
1250     + machine->md.arc.wordlen * 3;
1251     else {
1252     uint64_t child = 0;
1253     cpu->memory_rw(cpu, cpu->mem,
1254     cpu->cd.mips.gpr[MIPS_GPR_A0] - 2 *
1255     machine->md.arc.wordlen, &buf[0], machine->
1256     md.arc.wordlen, MEM_READ, CACHE_NONE);
1257     if (machine->md.arc.arc_64bit) {
1258     if (cpu->byte_order == EMUL_BIG_ENDIAN) {
1259     unsigned char tmp; tmp = buf[0];
1260     buf[0] = buf[7]; buf[7] = tmp;
1261     tmp = buf[1]; buf[1] = buf[6];
1262     buf[6] = tmp;
1263     tmp = buf[2]; buf[2] = buf[5];
1264     buf[5] = tmp;
1265     tmp = buf[3]; buf[3] = buf[4];
1266     buf[4] = tmp;
1267     }
1268     child = (uint64_t)buf[0] +
1269     ((uint64_t)buf[1]<<8) +
1270     ((uint64_t)buf[2]<<16) +
1271     ((uint64_t)buf[3]<<24) +
1272     ((uint64_t)buf[4]<<32) +
1273     ((uint64_t)buf[5]<<40) +
1274     ((uint64_t)buf[6]<<48) +
1275     ((uint64_t)buf[7]<<56);
1276     } else {
1277     if (cpu->byte_order == EMUL_BIG_ENDIAN) {
1278     unsigned char tmp; tmp = buf[0];
1279     buf[0] = buf[3]; buf[3] = tmp;
1280     tmp = buf[1]; buf[1] = buf[2];
1281     buf[2] = tmp;
1282     }
1283     child = buf[0] + (buf[1]<<8) + (buf[2]<<16) +
1284     (buf[3]<<24);
1285     }
1286    
1287     cpu->cd.mips.gpr[MIPS_GPR_V0] = child?
1288     (child + 3 * machine->md.arc.wordlen) : 0;
1289     if (!machine->md.arc.arc_64bit)
1290     cpu->cd.mips.gpr[MIPS_GPR_V0] = (int64_t)
1291     (int32_t)cpu->cd.mips.gpr[MIPS_GPR_V0];
1292     }
1293 dpavlin 24 debug("[ ARCBIOS GetChild(node 0x%016"PRIx64"): 0x%016"
1294     PRIx64" ]\n", (uint64_t) cpu->cd.mips.gpr[MIPS_GPR_A0],
1295     (uint64_t) cpu->cd.mips.gpr[MIPS_GPR_V0]);
1296 dpavlin 14 break;
1297     case 0x2c: /* GetParent(node) */
1298     {
1299     uint64_t parent;
1300    
1301     cpu->memory_rw(cpu, cpu->mem,
1302     cpu->cd.mips.gpr[MIPS_GPR_A0] - 1 * machine->
1303     md.arc.wordlen, &buf[0], machine->md.arc.wordlen,
1304     MEM_READ, CACHE_NONE);
1305    
1306     if (machine->md.arc.arc_64bit) {
1307     if (cpu->byte_order == EMUL_BIG_ENDIAN) {
1308     unsigned char tmp; tmp = buf[0];
1309     buf[0] = buf[7]; buf[7] = tmp;
1310     tmp = buf[1]; buf[1] = buf[6];
1311     buf[6] = tmp;
1312     tmp = buf[2]; buf[2] = buf[5];
1313     buf[5] = tmp;
1314     tmp = buf[3]; buf[3] = buf[4];
1315     buf[4] = tmp;
1316     }
1317     parent = (uint64_t)buf[0] +
1318     ((uint64_t)buf[1]<<8) +
1319     ((uint64_t)buf[2]<<16) +
1320     ((uint64_t)buf[3]<<24) +
1321     ((uint64_t)buf[4]<<32) +
1322     ((uint64_t)buf[5]<<40) +
1323     ((uint64_t)buf[6]<<48) +
1324     ((uint64_t)buf[7]<<56);
1325     } else {
1326     if (cpu->byte_order == EMUL_BIG_ENDIAN) {
1327     unsigned char tmp; tmp = buf[0];
1328     buf[0] = buf[3]; buf[3] = tmp;
1329     tmp = buf[1]; buf[1] = buf[2];
1330     buf[2] = tmp;
1331     }
1332     parent = buf[0] + (buf[1]<<8) +
1333     (buf[2]<<16) + (buf[3]<<24);
1334     }
1335    
1336     cpu->cd.mips.gpr[MIPS_GPR_V0] = parent?
1337     (parent + 3 * machine->md.arc.wordlen) : 0;
1338     if (!machine->md.arc.arc_64bit)
1339     cpu->cd.mips.gpr[MIPS_GPR_V0] = (int64_t)
1340     (int32_t) cpu->cd.mips.gpr[MIPS_GPR_V0];
1341     }
1342 dpavlin 24 debug("[ ARCBIOS GetParent(node 0x%016"PRIx64"): 0x%016"
1343     PRIx64" ]\n", (uint64_t) cpu->cd.mips.gpr[MIPS_GPR_A0],
1344     (uint64_t) cpu->cd.mips.gpr[MIPS_GPR_V0]);
1345 dpavlin 14 break;
1346     case 0x30: /* GetConfigurationData(void *configdata, void *node) */
1347 dpavlin 24 /* fatal("[ ARCBIOS GetConfigurationData(0x%016"PRIx64","
1348     "0x%016"PRIx64") ]\n",
1349     (uint64_t) cpu->cd.mips.gpr[MIPS_GPR_A0],
1350     (uint64_t) cpu->cd.mips.gpr[MIPS_GPR_A1]); */
1351 dpavlin 14 cpu->cd.mips.gpr[MIPS_GPR_V0] = ARCBIOS_EINVAL;
1352     for (i=0; i<machine->md.arc.n_configuration_data; i++) {
1353     /* fatal("configuration_data_component[%i] = "
1354 dpavlin 24 "0x%016"PRIx64"\n", i, (uint64_t) machine->
1355 dpavlin 14 md.arc.configuration_data_component[i]); */
1356     if (cpu->cd.mips.gpr[MIPS_GPR_A1] ==
1357     machine->md.arc.configuration_data_component[i]) {
1358     cpu->cd.mips.gpr[MIPS_GPR_V0] = 0;
1359     for (j=0; j<machine->
1360     md.arc.configuration_data_len[i]; j++) {
1361     unsigned char ch;
1362     cpu->memory_rw(cpu, cpu->mem,
1363     machine->md.arc.
1364     configuration_data_configdata[i] +
1365     j, &ch, 1, MEM_READ, CACHE_NONE);
1366     cpu->memory_rw(cpu, cpu->mem,
1367     cpu->cd.mips.gpr[MIPS_GPR_A0] + j,
1368     &ch, 1, MEM_WRITE, CACHE_NONE);
1369     }
1370     break;
1371     }
1372     }
1373     break;
1374     case 0x3c: /* GetComponent(char *name) */
1375     debug("[ ARCBIOS GetComponent(\"");
1376     dump_mem_string(cpu, cpu->cd.mips.gpr[MIPS_GPR_A0]);
1377     debug("\") ]\n");
1378    
1379     if (cpu->cd.mips.gpr[MIPS_GPR_A0] == 0) {
1380     fatal("[ ARCBIOS GetComponent: NULL ptr ]\n");
1381     } else {
1382     unsigned char buf[500];
1383     int match_index = -1;
1384     int match_len = 0;
1385    
1386     memset(buf, 0, sizeof(buf));
1387 dpavlin 22 for (i=0; i<(ssize_t)sizeof(buf); i++) {
1388 dpavlin 14 cpu->memory_rw(cpu, cpu->mem,
1389     cpu->cd.mips.gpr[MIPS_GPR_A0] + i,
1390     &buf[i], 1, MEM_READ, CACHE_NONE);
1391     if (buf[i] == '\0')
1392     i = sizeof(buf);
1393     }
1394     buf[sizeof(buf) - 1] = '\0';
1395    
1396     /* "scsi(0)disk(0)rdisk(0)partition(0)" and such. */
1397     /* printf("GetComponent(\"%s\")\n", buf); */
1398    
1399     /* Default to NULL return value. */
1400     cpu->cd.mips.gpr[MIPS_GPR_V0] = 0;
1401    
1402     /* Scan the string to component table: */
1403     for (i=0; i<machine->md.arc.n_string_to_components;
1404     i++) {
1405     int m = 0;
1406     while (buf[m] && machine->md.arc.
1407     string_to_component[i][m] &&
1408     machine->md.arc.string_to_component[i][m]
1409     == buf[m])
1410     m++;
1411     if (m > match_len) {
1412     match_len = m;
1413     match_index = i;
1414     }
1415     }
1416    
1417     if (match_index >= 0) {
1418     /* printf("Longest match: '%s'\n",
1419     machine->md.arc.string_to_component[
1420     match_index]); */
1421     cpu->cd.mips.gpr[MIPS_GPR_V0] =
1422     machine->md.arc.string_to_component_value[
1423     match_index];
1424     }
1425     }
1426     break;
1427     case 0x44: /* GetSystemId() */
1428     debug("[ ARCBIOS GetSystemId() ]\n");
1429     cpu->cd.mips.gpr[MIPS_GPR_V0] = SGI_SYSID_ADDR;
1430     break;
1431     case 0x48: /* void *GetMemoryDescriptor(void *ptr) */
1432     debug("[ ARCBIOS GetMemoryDescriptor(0x%08x) ]\n",
1433     (int)cpu->cd.mips.gpr[MIPS_GPR_A0]);
1434    
1435     /* If a0=NULL, then return the first descriptor: */
1436     if ((uint32_t)cpu->cd.mips.gpr[MIPS_GPR_A0] == 0)
1437     cpu->cd.mips.gpr[MIPS_GPR_V0] =
1438     machine->md.arc.memdescriptor_base;
1439     else {
1440     int s = machine->md.arc.arc_64bit?
1441     sizeof(struct arcbios_mem64)
1442     : sizeof(struct arcbios_mem);
1443     int nr = cpu->cd.mips.gpr[MIPS_GPR_A0] -
1444     machine->md.arc.memdescriptor_base;
1445     nr /= s;
1446     nr ++;
1447     cpu->cd.mips.gpr[MIPS_GPR_V0] =
1448     machine->md.arc.memdescriptor_base + s * nr;
1449     if (nr >= machine->md.arc.n_memdescriptors)
1450     cpu->cd.mips.gpr[MIPS_GPR_V0] = 0;
1451     }
1452     break;
1453     case 0x50: /* GetTime() */
1454     debug("[ ARCBIOS GetTime() ]\n");
1455     cpu->cd.mips.gpr[MIPS_GPR_V0] = 0xffffffff80001000ULL;
1456     /* TODO! */
1457     break;
1458     case 0x54: /* GetRelativeTime() */
1459     debug("[ ARCBIOS GetRelativeTime() ]\n");
1460     cpu->cd.mips.gpr[MIPS_GPR_V0] = (int64_t)(int32_t)time(NULL);
1461     break;
1462     case 0x5c: /* Open(char *path, uint32_t mode, uint32_t *fileID) */
1463     debug("[ ARCBIOS Open(\"");
1464     dump_mem_string(cpu, cpu->cd.mips.gpr[MIPS_GPR_A0]);
1465     debug("\",0x%x,0x%x)", (int)cpu->cd.mips.gpr[MIPS_GPR_A0],
1466     (int)cpu->cd.mips.gpr[MIPS_GPR_A1],
1467     (int)cpu->cd.mips.gpr[MIPS_GPR_A2]);
1468    
1469     cpu->cd.mips.gpr[MIPS_GPR_V0] = ARCBIOS_ENOENT;
1470    
1471     handle = 3;
1472     /* TODO: Starting at 0 would require some updates... */
1473     while (machine->md.arc.file_handle_in_use[handle]) {
1474     handle ++;
1475     if (handle >= ARC_MAX_HANDLES) {
1476     cpu->cd.mips.gpr[MIPS_GPR_V0] = ARCBIOS_EMFILE;
1477     break;
1478     }
1479     }
1480    
1481     if (handle >= ARC_MAX_HANDLES) {
1482     fatal("[ ARCBIOS Open: out of file handles ]\n");
1483     } else if (cpu->cd.mips.gpr[MIPS_GPR_A0] == 0) {
1484     fatal("[ ARCBIOS Open: NULL ptr ]\n");
1485     } else {
1486     /*
1487     * TODO: This is hardcoded to successfully open
1488     * anything. It is used by the Windows NT SETUPLDR
1489     * program to load stuff from the boot partition.
1490     */
1491     unsigned char *buf = malloc(MAX_OPEN_STRINGLEN);
1492     if (buf == NULL) {
1493     fprintf(stderr, "out of memory\n");
1494     exit(1);
1495     }
1496     memset(buf, 0, MAX_OPEN_STRINGLEN);
1497     for (i=0; i<MAX_OPEN_STRINGLEN; i++) {
1498     cpu->memory_rw(cpu, cpu->mem,
1499     cpu->cd.mips.gpr[MIPS_GPR_A0] + i,
1500     &buf[i], 1, MEM_READ, CACHE_NONE);
1501     if (buf[i] == '\0')
1502     i = MAX_OPEN_STRINGLEN;
1503     }
1504     buf[MAX_OPEN_STRINGLEN - 1] = '\0';
1505     machine->md.arc.file_handle_string[handle] =
1506     (char *)buf;
1507     machine->md.arc.current_seek_offset[handle] = 0;
1508     cpu->cd.mips.gpr[MIPS_GPR_V0] = ARCBIOS_ESUCCESS;
1509     }
1510    
1511     if (cpu->cd.mips.gpr[MIPS_GPR_V0] == ARCBIOS_ESUCCESS) {
1512     debug(" = handle %i ]\n", (int)handle);
1513     store_32bit_word(cpu, cpu->cd.mips.gpr[MIPS_GPR_A2],
1514     handle);
1515     machine->md.arc.file_handle_in_use[handle] = 1;
1516     } else
1517     debug(" = ERROR %i ]\n",
1518     (int)cpu->cd.mips.gpr[MIPS_GPR_V0]);
1519     break;
1520     case 0x60: /* Close(uint32_t handle) */
1521     debug("[ ARCBIOS Close(%i) ]\n",
1522     (int)cpu->cd.mips.gpr[MIPS_GPR_A0]);
1523     if (!machine->md.arc.file_handle_in_use[cpu->cd.mips.gpr[
1524     MIPS_GPR_A0]]) {
1525     fatal("ARCBIOS Close(%i): bad handle\n",
1526     (int)cpu->cd.mips.gpr[MIPS_GPR_A0]);
1527     cpu->cd.mips.gpr[MIPS_GPR_V0] = ARCBIOS_EBADF;
1528     } else {
1529     machine->md.arc.file_handle_in_use[
1530     cpu->cd.mips.gpr[MIPS_GPR_A0]] = 0;
1531     if (machine->md.arc.file_handle_string[
1532     cpu->cd.mips.gpr[MIPS_GPR_A0]] != NULL)
1533     free(machine->md.arc.file_handle_string[
1534     cpu->cd.mips.gpr[MIPS_GPR_A0]]);
1535     machine->md.arc.file_handle_string[cpu->cd.mips.
1536     gpr[MIPS_GPR_A0]] = NULL;
1537     cpu->cd.mips.gpr[MIPS_GPR_V0] = ARCBIOS_ESUCCESS;
1538     }
1539     break;
1540     case 0x64: /* Read(handle, void *buf, length, uint32_t *count) */
1541     if (cpu->cd.mips.gpr[MIPS_GPR_A0] == ARCBIOS_STDIN) {
1542     int i, nread = 0;
1543     /*
1544     * Before going into the loop, make sure stdout
1545     * is flushed. If we're using an X11 VGA console,
1546     * then it needs to be flushed as well.
1547     */
1548     fflush(stdin);
1549     fflush(stdout);
1550     /* NOTE/TODO: This gives a tick to _everything_ */
1551     for (i=0; i<machine->n_tick_entries; i++)
1552     machine->tick_func[i](cpu,
1553     machine->tick_extra[i]);
1554    
1555 dpavlin 22 for (i=0; i<(int32_t)cpu->cd.mips.gpr[MIPS_GPR_A2];
1556     i++) {
1557 dpavlin 14 int x;
1558     unsigned char ch;
1559    
1560     /* Read from STDIN is blocking (at least
1561     that seems to be how NetBSD's arcdiag
1562     wants it) */
1563     x = console_readchar(
1564     machine->main_console_handle);
1565     if (x < 0)
1566     return 0;
1567    
1568     /*
1569     * ESC + '[' should be transformed into 0x9b:
1570     *
1571     * NOTE/TODO: This makes the behaviour of just
1572     * pressing ESC a bit harder to define.
1573     */
1574     if (x == 27) {
1575     x = console_readchar(cpu->
1576     machine->main_console_handle);
1577     if (x == '[' || x == 'O')
1578     x = 0x9b;
1579     }
1580    
1581     ch = x;
1582     nread ++;
1583     cpu->memory_rw(cpu, cpu->mem,
1584     cpu->cd.mips.gpr[MIPS_GPR_A1] + i,
1585     &ch, 1, MEM_WRITE, CACHE_NONE);
1586    
1587     /* NOTE: Only one char, from STDIN: */
1588     i = cpu->cd.mips.gpr[MIPS_GPR_A2]; /* :-) */
1589     }
1590     store_32bit_word(cpu, cpu->cd.mips.gpr[MIPS_GPR_A3],
1591     nread);
1592     /* TODO: not EAGAIN? */
1593     cpu->cd.mips.gpr[MIPS_GPR_V0] =
1594     nread? ARCBIOS_ESUCCESS: ARCBIOS_EAGAIN;
1595     } else {
1596     int handle = cpu->cd.mips.gpr[MIPS_GPR_A0];
1597 dpavlin 20 int disk_type = 0;
1598 dpavlin 14 int disk_id = arcbios_handle_to_disk_id_and_type(
1599     machine, handle, &disk_type);
1600     uint64_t partition_offset = 0;
1601     int res;
1602     uint64_t size; /* dummy */
1603     unsigned char *tmp_buf;
1604    
1605     arcbios_handle_to_start_and_size(machine, handle,
1606     &partition_offset, &size);
1607    
1608     debug("[ ARCBIOS Read(%i,0x%08x,0x%08x,0x%08x) ]\n",
1609     (int)cpu->cd.mips.gpr[MIPS_GPR_A0],
1610     (int)cpu->cd.mips.gpr[MIPS_GPR_A1],
1611     (int)cpu->cd.mips.gpr[MIPS_GPR_A2],
1612     (int)cpu->cd.mips.gpr[MIPS_GPR_A3]);
1613    
1614     tmp_buf = malloc(cpu->cd.mips.gpr[MIPS_GPR_A2]);
1615     if (tmp_buf == NULL) {
1616     fprintf(stderr, "[ *** Out of memory in "
1617     "arcbios.c, allocating %i bytes ]\n",
1618     (int)cpu->cd.mips.gpr[MIPS_GPR_A2]);
1619     break;
1620     }
1621    
1622     res = diskimage_access(machine, disk_id, disk_type,
1623     0, partition_offset + machine->md.arc.
1624     current_seek_offset[handle], tmp_buf,
1625     cpu->cd.mips.gpr[MIPS_GPR_A2]);
1626    
1627     /* If the transfer was successful, transfer the
1628     data to emulated memory: */
1629     if (res) {
1630     uint64_t dst = cpu->cd.mips.gpr[MIPS_GPR_A1];
1631     store_buf(cpu, dst, (char *)tmp_buf,
1632     cpu->cd.mips.gpr[MIPS_GPR_A2]);
1633     store_32bit_word(cpu,
1634     cpu->cd.mips.gpr[MIPS_GPR_A3],
1635     cpu->cd.mips.gpr[MIPS_GPR_A2]);
1636     machine->md.arc.current_seek_offset[handle] +=
1637     cpu->cd.mips.gpr[MIPS_GPR_A2];
1638     cpu->cd.mips.gpr[MIPS_GPR_V0] = 0;
1639     } else
1640     cpu->cd.mips.gpr[MIPS_GPR_V0] = ARCBIOS_EIO;
1641     free(tmp_buf);
1642     }
1643     break;
1644     case 0x68: /* GetReadStatus(handle) */
1645     /*
1646     * According to arcbios_tty_getchar() in NetBSD's
1647     * dev/arcbios/arcbios_tty.c, GetReadStatus should
1648     * return 0 if there is something available.
1649     *
1650     * TODO: Error codes are things like ARCBIOS_EAGAIN.
1651     */
1652     if (cpu->cd.mips.gpr[MIPS_GPR_A0] == ARCBIOS_STDIN) {
1653     cpu->cd.mips.gpr[MIPS_GPR_V0] = console_charavail(
1654     machine->main_console_handle)? 0 : 1;
1655     } else {
1656     fatal("[ ARCBIOS GetReadStatus(%i) from "
1657     "something other than STDIN: TODO ]\n",
1658     (int)cpu->cd.mips.gpr[MIPS_GPR_A0]);
1659     /* TODO */
1660     cpu->cd.mips.gpr[MIPS_GPR_V0] = 1;
1661     }
1662     break;
1663     case 0x6c: /* Write(handle, buf, len, &returnlen) */
1664     if (cpu->cd.mips.gpr[MIPS_GPR_A0] != ARCBIOS_STDOUT) {
1665     /*
1666     * TODO: this is just a test
1667     */
1668     int handle = cpu->cd.mips.gpr[MIPS_GPR_A0];
1669 dpavlin 20 int disk_type = 0;
1670 dpavlin 14 int disk_id = arcbios_handle_to_disk_id_and_type(
1671     machine, handle, &disk_type);
1672     uint64_t partition_offset = 0;
1673     int res, i;
1674     uint64_t size; /* dummy */
1675     unsigned char *tmp_buf;
1676    
1677     arcbios_handle_to_start_and_size(machine,
1678     handle, &partition_offset, &size);
1679    
1680 dpavlin 24 debug("[ ARCBIOS Write(%i,0x%08"PRIx64",%i,0x%08"
1681     PRIx64") ]\n", (int) cpu->cd.mips.gpr[MIPS_GPR_A0],
1682     (uint64_t) cpu->cd.mips.gpr[MIPS_GPR_A1],
1683     (int) cpu->cd.mips.gpr[MIPS_GPR_A2],
1684     (uint64_t) cpu->cd.mips.gpr[MIPS_GPR_A3]);
1685 dpavlin 14
1686     tmp_buf = malloc(cpu->cd.mips.gpr[MIPS_GPR_A2]);
1687     if (tmp_buf == NULL) {
1688     fprintf(stderr, "[ *** Out of memory in"
1689     " arcbios.c, allocating %i bytes ]\n",
1690     (int)cpu->cd.mips.gpr[MIPS_GPR_A2]);
1691     break;
1692     }
1693    
1694 dpavlin 22 for (i=0; i<(int32_t)cpu->cd.mips.gpr[MIPS_GPR_A2]; i++)
1695 dpavlin 14 cpu->memory_rw(cpu, cpu->mem,
1696     cpu->cd.mips.gpr[MIPS_GPR_A1] + i,
1697     &tmp_buf[i], sizeof(char), MEM_READ,
1698     CACHE_NONE);
1699    
1700     res = diskimage_access(machine, disk_id, disk_type,
1701     1, partition_offset + machine->md.arc.
1702     current_seek_offset[handle], tmp_buf,
1703     cpu->cd.mips.gpr[MIPS_GPR_A2]);
1704    
1705     if (res) {
1706     store_32bit_word(cpu,
1707     cpu->cd.mips.gpr[MIPS_GPR_A3],
1708     cpu->cd.mips.gpr[MIPS_GPR_A2]);
1709     machine->md.arc.current_seek_offset[handle] +=
1710     cpu->cd.mips.gpr[MIPS_GPR_A2];
1711     cpu->cd.mips.gpr[MIPS_GPR_V0] = 0;
1712     } else
1713     cpu->cd.mips.gpr[MIPS_GPR_V0] = ARCBIOS_EIO;
1714     free(tmp_buf);
1715     } else {
1716 dpavlin 22 for (i=0; i<(int32_t)cpu->cd.mips.gpr[MIPS_GPR_A2];
1717     i++) {
1718 dpavlin 14 unsigned char ch = '\0';
1719     cpu->memory_rw(cpu, cpu->mem,
1720     cpu->cd.mips.gpr[MIPS_GPR_A1] + i,
1721     &ch, sizeof(ch), MEM_READ, CACHE_NONE);
1722    
1723     arcbios_putchar(cpu, ch);
1724     }
1725     }
1726     store_32bit_word(cpu, cpu->cd.mips.gpr[MIPS_GPR_A3],
1727     cpu->cd.mips.gpr[MIPS_GPR_A2]);
1728     cpu->cd.mips.gpr[MIPS_GPR_V0] = 0; /* Success. */
1729     break;
1730     case 0x70: /* Seek(uint32_t handle, int64_t *ofs,
1731     uint32_t whence): uint32_t */
1732 dpavlin 24 debug("[ ARCBIOS Seek(%i,0x%08"PRIx64",%i): ",
1733     (int) cpu->cd.mips.gpr[MIPS_GPR_A0],
1734     (uint64_t)cpu->cd.mips.gpr[MIPS_GPR_A1],
1735     (int) cpu->cd.mips.gpr[MIPS_GPR_A2]);
1736 dpavlin 14
1737     if (cpu->cd.mips.gpr[MIPS_GPR_A2] != 0) {
1738 dpavlin 24 fatal("[ ARCBIOS Seek(%i,0x%08"PRIx64",%i): "
1739 dpavlin 14 "UNIMPLEMENTED whence=%i ]\n",
1740 dpavlin 24 (int) cpu->cd.mips.gpr[MIPS_GPR_A0],
1741     (uint64_t) cpu->cd.mips.gpr[MIPS_GPR_A1],
1742     (int) cpu->cd.mips.gpr[MIPS_GPR_A2],
1743     (int) cpu->cd.mips.gpr[MIPS_GPR_A2]);
1744 dpavlin 14 }
1745    
1746     {
1747     unsigned char buf[8];
1748     uint64_t ofs;
1749     cpu->memory_rw(cpu, cpu->mem,
1750     cpu->cd.mips.gpr[MIPS_GPR_A1], &buf[0],
1751     sizeof(buf), MEM_READ, CACHE_NONE);
1752     if (cpu->byte_order == EMUL_BIG_ENDIAN) {
1753     unsigned char tmp;
1754     tmp = buf[0]; buf[0] = buf[7]; buf[7] = tmp;
1755     tmp = buf[1]; buf[1] = buf[6]; buf[6] = tmp;
1756     tmp = buf[2]; buf[2] = buf[5]; buf[5] = tmp;
1757     tmp = buf[3]; buf[3] = buf[4]; buf[4] = tmp;
1758     }
1759     ofs = buf[0] + (buf[1] << 8) + (buf[2] << 16) +
1760     (buf[3] << 24) + ((uint64_t)buf[4] << 32) +
1761     ((uint64_t)buf[5] << 40) + ((uint64_t)buf[6] << 48)
1762     + ((uint64_t)buf[7] << 56);
1763     machine->md.arc.current_seek_offset[
1764     cpu->cd.mips.gpr[MIPS_GPR_A0]] = ofs;
1765 dpavlin 24 debug("%016"PRIx64" ]\n", (uint64_t) ofs);
1766 dpavlin 14 }
1767    
1768     cpu->cd.mips.gpr[MIPS_GPR_V0] = 0; /* Success. */
1769    
1770     break;
1771     case 0x78: /* GetEnvironmentVariable(char *) */
1772     /* Find the environment variable given by a0: */
1773 dpavlin 22 for (i=0; i<(ssize_t)sizeof(buf); i++)
1774 dpavlin 14 cpu->memory_rw(cpu, cpu->mem,
1775     cpu->cd.mips.gpr[MIPS_GPR_A0] + i,
1776     &buf[i], sizeof(char), MEM_READ, CACHE_NONE);
1777     buf[sizeof(buf)-1] = '\0';
1778     debug("[ ARCBIOS GetEnvironmentVariable(\"%s\") ]\n", buf);
1779     for (i=0; i<0x1000; i++) {
1780     /* Matching string at offset i? */
1781     int nmatches = 0;
1782 dpavlin 22 for (j=0; j<(ssize_t)strlen((char *)buf); j++) {
1783 dpavlin 14 cpu->memory_rw(cpu, cpu->mem,
1784     (uint64_t)(ARC_ENV_STRINGS + i + j),
1785     &ch2, sizeof(char), MEM_READ, CACHE_NONE);
1786     if (ch2 == buf[j])
1787     nmatches++;
1788     }
1789     cpu->memory_rw(cpu, cpu->mem,
1790     (uint64_t)(ARC_ENV_STRINGS + i +
1791     strlen((char *)buf)), &ch2, sizeof(char),
1792     MEM_READ, CACHE_NONE);
1793 dpavlin 22 if (nmatches == (int)strlen((char *)buf) && ch2=='=') {
1794 dpavlin 14 cpu->cd.mips.gpr[MIPS_GPR_V0] =
1795     ARC_ENV_STRINGS + i +
1796     strlen((char *)buf) + 1;
1797     return 1;
1798     }
1799     }
1800     /* Return NULL if string wasn't found. */
1801     cpu->cd.mips.gpr[MIPS_GPR_V0] = 0;
1802     break;
1803     case 0x7c: /* SetEnvironmentVariable(char *, char *) */
1804     debug("[ ARCBIOS SetEnvironmentVariable(\"");
1805     dump_mem_string(cpu, cpu->cd.mips.gpr[MIPS_GPR_A0]);
1806     debug("\",\"");
1807     dump_mem_string(cpu, cpu->cd.mips.gpr[MIPS_GPR_A1]);
1808     debug("\") ]\n");
1809     /* TODO: This is a dummy. */
1810     cpu->cd.mips.gpr[MIPS_GPR_V0] = ARCBIOS_ESUCCESS;
1811     break;
1812     case 0x80: /* GetFileInformation() */
1813     debug("[ ARCBIOS GetFileInformation(%i,0x%x): ",
1814     (int)cpu->cd.mips.gpr[MIPS_GPR_A0],
1815     (int)cpu->cd.mips.gpr[MIPS_GPR_A1]);
1816    
1817     if (cpu->cd.mips.gpr[MIPS_GPR_A0] >= ARC_MAX_HANDLES) {
1818     debug("invalid file handle ]\n");
1819     cpu->cd.mips.gpr[MIPS_GPR_V0] = ARCBIOS_EINVAL;
1820     } else if (!machine->md.arc.file_handle_in_use[cpu->cd.
1821     mips.gpr[MIPS_GPR_A0]]) {
1822     debug("file handle not in use! ]\n");
1823     cpu->cd.mips.gpr[MIPS_GPR_V0] = ARCBIOS_EBADF;
1824     } else {
1825     debug("'%s' ]\n", machine->md.arc.file_handle_string[
1826     cpu->cd.mips.gpr[MIPS_GPR_A0]]);
1827     cpu->cd.mips.gpr[MIPS_GPR_V0] =
1828     arcbios_getfileinformation(cpu);
1829     }
1830     break;
1831     case 0x88: /* FlushAllCaches() */
1832     debug("[ ARCBIOS FlushAllCaches(): TODO ]\n");
1833     cpu->cd.mips.gpr[MIPS_GPR_V0] = 0;
1834     break;
1835     case 0x90: /* void *GetDisplayStatus(handle) */
1836     debug("[ ARCBIOS GetDisplayStatus(%i) ]\n",
1837     (int)cpu->cd.mips.gpr[MIPS_GPR_A0]);
1838     /* TODO: handle different values of 'handle'? */
1839     cpu->cd.mips.gpr[MIPS_GPR_V0] = ARC_DSPSTAT_ADDR;
1840     break;
1841     case 0x100:
1842     /*
1843     * Undocumented, used by IRIX.
1844     */
1845     debug("[ ARCBIOS: IRIX 0x100 (?) ]\n");
1846     /* TODO */
1847     cpu->cd.mips.gpr[MIPS_GPR_V0] = 0;
1848     break;
1849     case 0x888:
1850     /*
1851     * Magical crash if there is no exception handling code.
1852     */
1853     fatal("EXCEPTION, but no exception handler installed yet.\n");
1854     quiet_mode = 0;
1855     cpu_register_dump(machine, cpu, 1, 0x1);
1856     cpu->running = 0;
1857     cpu->dead = 1;
1858     break;
1859     default:
1860     quiet_mode = 0;
1861     cpu_register_dump(machine, cpu, 1, 0x1);
1862     debug("a0 points to: ");
1863     dump_mem_string(cpu, cpu->cd.mips.gpr[MIPS_GPR_A0]);
1864     debug("\n");
1865     fatal("ARCBIOS: unimplemented vector 0x%x\n", vector);
1866     cpu->running = 0;
1867     cpu->dead = 1;
1868     }
1869    
1870     return 1;
1871     }
1872    
1873    
1874     /*
1875     * arcbios_set_default_exception_handler():
1876     */
1877     void arcbios_set_default_exception_handler(struct cpu *cpu)
1878     {
1879     /*
1880     * The default exception handlers simply jump to 0xbfc88888,
1881     * which is then taken care of in arcbios_emul() above.
1882     *
1883     * 3c1abfc8 lui k0,0xbfc8
1884     * 375a8888 ori k0,k0,0x8888
1885     * 03400008 jr k0
1886     * 00000000 nop
1887     */
1888     store_32bit_word(cpu, 0xffffffff80000000ULL, 0x3c1abfc8);
1889     store_32bit_word(cpu, 0xffffffff80000004ULL, 0x375a8888);
1890     store_32bit_word(cpu, 0xffffffff80000008ULL, 0x03400008);
1891     store_32bit_word(cpu, 0xffffffff8000000cULL, 0x00000000);
1892    
1893     store_32bit_word(cpu, 0xffffffff80000080ULL, 0x3c1abfc8);
1894     store_32bit_word(cpu, 0xffffffff80000084ULL, 0x375a8888);
1895     store_32bit_word(cpu, 0xffffffff80000088ULL, 0x03400008);
1896     store_32bit_word(cpu, 0xffffffff8000008cULL, 0x00000000);
1897    
1898     store_32bit_word(cpu, 0xffffffff80000180ULL, 0x3c1abfc8);
1899     store_32bit_word(cpu, 0xffffffff80000184ULL, 0x375a8888);
1900     store_32bit_word(cpu, 0xffffffff80000188ULL, 0x03400008);
1901     store_32bit_word(cpu, 0xffffffff8000018cULL, 0x00000000);
1902     }
1903    
1904    
1905     /*
1906     * arcbios_add_other_components():
1907     *
1908     * TODO: How should this be synched with the hardware devices
1909     * added in machine.c?
1910     */
1911     static void arcbios_add_other_components(struct machine *machine,
1912     uint64_t system)
1913     {
1914     struct cpu *cpu = machine->cpus[0];
1915    
1916     if (machine->machine_type == MACHINE_ARC &&
1917     ( machine->machine_subtype == MACHINE_ARC_NEC_RD94 ||
1918     machine->machine_subtype == MACHINE_ARC_NEC_R94 ||
1919     machine->machine_subtype == MACHINE_ARC_NEC_R96 )) {
1920     uint64_t jazzbus, eisa, other;
1921    
1922     jazzbus = arcbios_addchild_manual(cpu,
1923     COMPONENT_CLASS_AdapterClass,
1924     COMPONENT_TYPE_MultiFunctionAdapter,
1925     0, 1, 2, 0, 0xffffffff, "Jazz-Internal Bus",
1926     system, NULL, 0);
1927    
1928     switch (machine->machine_subtype) {
1929     case MACHINE_ARC_NEC_RD94:
1930     case MACHINE_ARC_NEC_R94:
1931     if (machine->use_x11)
1932     arcbios_addchild_manual(cpu,
1933     COMPONENT_CLASS_ControllerClass,
1934     COMPONENT_TYPE_DisplayController,
1935     0, 1, 2, 0, 0x0, "10110004",
1936     system, NULL, 0);
1937     break;
1938     case MACHINE_ARC_NEC_R96:
1939     if (machine->use_x11) {
1940     uint64_t x;
1941     x = arcbios_addchild_manual(cpu,
1942     COMPONENT_CLASS_ControllerClass,
1943     COMPONENT_TYPE_DisplayController,
1944     COMPONENT_FLAG_ConsoleOut |
1945     COMPONENT_FLAG_Output,
1946     1, 2, 0, 0x0, "necvdfrb",
1947     jazzbus, NULL, 0);
1948     arcbios_addchild_manual(cpu,
1949     COMPONENT_CLASS_PeripheralClass,
1950     COMPONENT_TYPE_MonitorPeripheral,
1951     COMPONENT_FLAG_ConsoleOut |
1952     COMPONENT_FLAG_Output,
1953     1, 2, 0, 0xffffffff, "640x480",
1954     x, NULL, 0);
1955     }
1956    
1957     /* TODO: R[D]94 too? */
1958     eisa = arcbios_addchild_manual(cpu,
1959     COMPONENT_CLASS_AdapterClass,
1960     COMPONENT_TYPE_EISAAdapter,
1961     0, 1, 2, 0, 0xffffffff, "EISA",
1962     system, NULL, 0);
1963    
1964     other = arcbios_addchild_manual(cpu,
1965     COMPONENT_CLASS_ControllerClass,
1966     COMPONENT_TYPE_OtherController,
1967     0, 1, 2, 0, 0xffffffff, "NEC1C01",
1968     eisa, NULL, 0);
1969     break;
1970     }
1971     }
1972    
1973     if (machine->machine_type == MACHINE_ARC &&
1974     (machine->machine_subtype == MACHINE_ARC_JAZZ_PICA
1975     || machine->machine_subtype == MACHINE_ARC_JAZZ_MAGNUM)) {
1976     uint64_t jazzbus, ali_s3, vxl;
1977     uint64_t diskcontroller, floppy, kbdctl, kbd;
1978     uint64_t ptrctl, ptr, paral, audio;
1979     uint64_t eisa, scsi;
1980     /* uint64_t serial1, serial2; */
1981    
1982     jazzbus = arcbios_addchild_manual(cpu,
1983     COMPONENT_CLASS_AdapterClass,
1984     COMPONENT_TYPE_MultiFunctionAdapter,
1985     0, 1, 2, 0, 0xffffffff, "Jazz-Internal Bus",
1986     system, NULL, 0);
1987    
1988     /*
1989     * DisplayController, needed by NetBSD:
1990     * TODO: NetBSD still doesn't use it :(
1991     */
1992     switch (machine->machine_subtype) {
1993     case MACHINE_ARC_JAZZ_PICA:
1994     /* Default TLB entries on PICA-61: */
1995    
1996     /* 7: 256K, asid: 0x0, v: 0xe1000000,
1997     p0: 0xfff00000(2.VG), p1: 0x0(0..G) */
1998     mips_coproc_tlb_set_entry(cpu, 7, 262144,
1999     0xffffffffe1000000ULL,
2000     0x0fff00000ULL, 0, 1, 0, 0, 0, 1, 0, 2, 0);
2001    
2002     /* 8: 64K, asid: 0x0, v: 0xe0000000,
2003     p0: 0x80000000(2DVG), p1: 0x0(0..G) */
2004     mips_coproc_tlb_set_entry(cpu, 8, 65536,
2005     0xffffffffe0000000ULL,
2006     0x080000000ULL, 0, 1, 0, 1, 0, 1, 0, 2, 0);
2007    
2008     /* 9: 64K, asid: 0x0, v: 0xe00e0000,
2009     p0: 0x800e0000(2DVG), p1: 0x800f0000(2DVG) */
2010     mips_coproc_tlb_set_entry(cpu, 9, 65536,
2011     (uint64_t)0xffffffffe00e0000ULL,
2012     (uint64_t)0x0800e0000ULL,
2013     (uint64_t)0x0800f0000ULL, 1, 1, 1, 1, 1, 0, 2, 2);
2014    
2015     /* 10: 4K, asid: 0x0, v: 0xe0100000,
2016     p0: 0xf0000000(2DVG), p1: 0x0(0..G) */
2017     mips_coproc_tlb_set_entry(cpu, 10, 4096,
2018     (uint64_t)0xffffffffe0100000ULL,
2019     (uint64_t)0x0f0000000ULL, 0,1, 0, 1, 0, 1, 0, 2, 0);
2020    
2021     /* 11: 1M, asid: 0x0, v: 0xe0200000,
2022     p0: 0x60000000(2DVG), p1: 0x60100000(2DVG) */
2023     mips_coproc_tlb_set_entry(cpu, 11, 1048576,
2024     0xffffffffe0200000ULL,
2025     0x060000000ULL, 0x060100000ULL,1,1,1,1,1, 0, 2, 2);
2026    
2027     /* 12: 1M, asid: 0x0, v: 0xe0400000,
2028     p0: 0x60200000(2DVG), p1: 0x60300000(2DVG) */
2029     mips_coproc_tlb_set_entry(cpu, 12, 1048576,
2030     0xffffffffe0400000ULL, 0x060200000ULL,
2031     0x060300000ULL, 1, 1, 1, 1, 1, 0, 2, 2);
2032    
2033     /* 13: 4M, asid: 0x0, v: 0xe0800000,
2034     p0: 0x40000000(2DVG), p1: 0x40400000(2DVG) */
2035     mips_coproc_tlb_set_entry(cpu, 13, 1048576*4,
2036     0xffffffffe0800000ULL, 0x040000000ULL,
2037     0x040400000ULL, 1, 1, 1, 1, 1, 0, 2, 2);
2038    
2039     /* 14: 16M, asid: 0x0, v: 0xe2000000,
2040     p0: 0x90000000(2DVG), p1: 0x91000000(2DVG) */
2041     mips_coproc_tlb_set_entry(cpu, 14, 1048576*16,
2042     0xffffffffe2000000ULL, 0x090000000ULL,
2043     0x091000000ULL, 1, 1, 1, 1, 1, 0, 2, 2);
2044    
2045     if (machine->use_x11) {
2046     ali_s3 = arcbios_addchild_manual(cpu,
2047     COMPONENT_CLASS_ControllerClass,
2048     COMPONENT_TYPE_DisplayController,
2049     COMPONENT_FLAG_ConsoleOut |
2050     COMPONENT_FLAG_Output,
2051     1, 2, 0, 0xffffffff, "ALI_S3",
2052     jazzbus, NULL, 0);
2053    
2054     arcbios_addchild_manual(cpu,
2055     COMPONENT_CLASS_PeripheralClass,
2056     COMPONENT_TYPE_MonitorPeripheral,
2057     COMPONENT_FLAG_ConsoleOut |
2058     COMPONENT_FLAG_Output,
2059     1, 2, 0, 0xffffffff, "1024x768",
2060     ali_s3, NULL, 0);
2061     }
2062     break;
2063     case MACHINE_ARC_JAZZ_MAGNUM:
2064     if (machine->use_x11) {
2065     vxl = arcbios_addchild_manual(cpu,
2066     COMPONENT_CLASS_ControllerClass,
2067     COMPONENT_TYPE_DisplayController,
2068     COMPONENT_FLAG_ConsoleOut |
2069     COMPONENT_FLAG_Output,
2070     1, 2, 0, 0xffffffff, "VXL",
2071     jazzbus, NULL, 0);
2072    
2073     arcbios_addchild_manual(cpu,
2074     COMPONENT_CLASS_PeripheralClass,
2075     COMPONENT_TYPE_MonitorPeripheral,
2076     COMPONENT_FLAG_ConsoleOut |
2077     COMPONENT_FLAG_Output,
2078     1, 2, 0, 0xffffffff, "1024x768",
2079     vxl, NULL, 0);
2080     }
2081     break;
2082     }
2083    
2084     diskcontroller = arcbios_addchild_manual(cpu,
2085     COMPONENT_CLASS_ControllerClass,
2086     COMPONENT_TYPE_DiskController,
2087     COMPONENT_FLAG_Input | COMPONENT_FLAG_Output,
2088     1, 2, 0, 0xffffffff, "I82077", jazzbus, NULL, 0);
2089    
2090     floppy = arcbios_addchild_manual(cpu,
2091     COMPONENT_CLASS_PeripheralClass,
2092     COMPONENT_TYPE_FloppyDiskPeripheral,
2093     COMPONENT_FLAG_Removable |
2094     COMPONENT_FLAG_Input | COMPONENT_FLAG_Output,
2095     1, 2, 0, 0xffffffff, NULL, diskcontroller, NULL, 0);
2096    
2097     kbdctl = arcbios_addchild_manual(cpu,
2098     COMPONENT_CLASS_ControllerClass,
2099     COMPONENT_TYPE_KeyboardController,
2100     COMPONENT_FLAG_ConsoleIn | COMPONENT_FLAG_Input,
2101     1, 2, 0, 0xffffffff, "I8742", jazzbus, NULL, 0);
2102    
2103     kbd = arcbios_addchild_manual(cpu,
2104     COMPONENT_CLASS_PeripheralClass,
2105     COMPONENT_TYPE_KeyboardPeripheral,
2106     COMPONENT_FLAG_ConsoleIn | COMPONENT_FLAG_Input,
2107     1, 2, 0, 0xffffffff, "PCAT_ENHANCED", kbdctl, NULL, 0);
2108    
2109     ptrctl = arcbios_addchild_manual(cpu,
2110     COMPONENT_CLASS_ControllerClass,
2111     COMPONENT_TYPE_PointerController, COMPONENT_FLAG_Input,
2112     1, 2, 0, 0xffffffff, "I8742", jazzbus, NULL, 0);
2113    
2114     ptr = arcbios_addchild_manual(cpu,
2115     COMPONENT_CLASS_PeripheralClass,
2116     COMPONENT_TYPE_PointerPeripheral, COMPONENT_FLAG_Input,
2117     1, 2, 0, 0xffffffff, "PS2 MOUSE", ptrctl, NULL, 0);
2118    
2119     /* These cause Windows NT to bug out. */
2120     #if 0
2121     serial1 = arcbios_addchild_manual(cpu,
2122     COMPONENT_CLASS_ControllerClass,
2123     COMPONENT_TYPE_SerialController,
2124     COMPONENT_FLAG_Input | COMPONENT_FLAG_Output,
2125     1, 2, 0, 0xffffffff, "COM1", jazzbus, NULL, 0);
2126    
2127     serial2 = arcbios_addchild_manual(cpu,
2128     COMPONENT_CLASS_ControllerClass,
2129     COMPONENT_TYPE_SerialController,
2130     COMPONENT_FLAG_Input | COMPONENT_FLAG_Output,
2131     1, 2, 0, 0xffffffff, "COM1", jazzbus, NULL, 0);
2132     #endif
2133    
2134     paral = arcbios_addchild_manual(cpu,
2135     COMPONENT_CLASS_ControllerClass,
2136     COMPONENT_TYPE_ParallelController,
2137     COMPONENT_FLAG_Input | COMPONENT_FLAG_Output,
2138     1, 2, 0, 0xffffffff, "LPT1", jazzbus, NULL, 0);
2139    
2140     audio = arcbios_addchild_manual(cpu,
2141     COMPONENT_CLASS_ControllerClass,
2142     COMPONENT_TYPE_AudioController,
2143     COMPONENT_FLAG_Input | COMPONENT_FLAG_Output,
2144     1, 2, 0, 0xffffffff, "MAGNUM", jazzbus, NULL, 0);
2145    
2146     eisa = arcbios_addchild_manual(cpu,
2147     COMPONENT_CLASS_AdapterClass, COMPONENT_TYPE_EISAAdapter,
2148     0, 1, 2, 0, 0xffffffff, "EISA", system, NULL, 0);
2149    
2150     {
2151     unsigned char config[78];
2152     memset(config, 0, sizeof(config));
2153    
2154     /* config data version: 1, revision: 2, count: 4 */
2155     config[0] = 0x01; config[1] = 0x00;
2156     config[2] = 0x02; config[3] = 0x00;
2157     config[4] = 0x04; config[5] = 0x00; config[6] = 0x00; config[7] = 0x00;
2158    
2159     /*
2160     type: Interrupt
2161     share_disposition: DeviceExclusive, flags: LevelSensitive
2162     level: 4, vector: 22, reserved1: 0
2163     */
2164     config[8] = arc_CmResourceTypeInterrupt;
2165     config[9] = arc_CmResourceShareDeviceExclusive;
2166     config[10] = arc_CmResourceInterruptLevelSensitive;
2167     config[12] = 4;
2168     config[16] = 22;
2169     config[20] = 0;
2170    
2171     /*
2172     type: Memory
2173     share_disposition: DeviceExclusive, flags: ReadWrite
2174     start: 0x 0 80002000, length: 0x1000
2175     */
2176     config[24] = arc_CmResourceTypeMemory;
2177     config[25] = arc_CmResourceShareDeviceExclusive;
2178     config[26] = arc_CmResourceMemoryReadWrite;
2179     config[28] = 0x00; config[29] = 0x20; config[30] = 0x00; config[31] = 0x80;
2180     config[32] = 0x00; config[33] = 0x00; config[34] = 0x00; config[35] = 0x00;
2181     config[36] = 0x00; config[37] = 0x10; config[38] = 0x00; config[39] = 0x00;
2182    
2183     /*
2184     type: DMA
2185     share_disposition: DeviceExclusive, flags: 0x0
2186     channel: 0, port: 0, reserved1: 0
2187     */
2188     config[40] = arc_CmResourceTypeDMA;
2189     config[41] = arc_CmResourceShareDeviceExclusive;
2190     /* 42..43 = flags, 44,45,46,47 = channel, 48,49,50,51 = port, 52,53,54,55
2191     = reserved */
2192    
2193     /* type: DeviceSpecific
2194     share_disposition: DeviceExclusive, flags: 0x0
2195     datasize: 6, reserved1: 0, reserved2: 0
2196     data: [0x1:0x0:0x2:0x0:0x7:0x30]
2197     */
2198     config[56] = arc_CmResourceTypeDeviceSpecific;
2199     config[57] = arc_CmResourceShareDeviceExclusive;
2200     /* 58,59 = flags 60,61,62,63 = data size, 64..71 = reserved */
2201     config[60] = 6;
2202     /* 72..77 = the data */
2203     config[72] = 0x01; config[73] = 0x00; config[74] = 0x02;
2204     config[75] = 0x00; config[76] = 0x07; config[77] = 0x30;
2205     scsi = arcbios_addchild_manual(cpu,
2206     COMPONENT_CLASS_AdapterClass,
2207     COMPONENT_TYPE_SCSIAdapter,
2208     0, 1, 2, 0, 0xffffffff, "ESP216",
2209     system, config, sizeof(config));
2210    
2211     arcbios_register_scsicontroller(machine, scsi);
2212     }
2213     }
2214     }
2215    
2216    
2217     /*
2218     * arcbios_console_init():
2219     *
2220     * Called from machine.c whenever an ARC-based machine is running with
2221     * a graphical VGA-style framebuffer, which can be used as console.
2222     */
2223     void arcbios_console_init(struct machine *machine,
2224     uint64_t vram, uint64_t ctrlregs)
2225     {
2226     machine->md.arc.vgaconsole = 1;
2227    
2228     machine->md.arc.console_vram = vram;
2229     machine->md.arc.console_ctrlregs = ctrlregs;
2230     machine->md.arc.console_maxx = ARC_CONSOLE_MAX_X;
2231     machine->md.arc.console_maxy = ARC_CONSOLE_MAX_Y;
2232     machine->md.arc.in_escape_sequence = 0;
2233     machine->md.arc.escape_sequence[0] = '\0';
2234     }
2235    
2236    
2237     /*
2238 dpavlin 22 * arc_environment_setup():
2239     *
2240     * Initialize the emulated environment variables.
2241     */
2242     static void arc_environment_setup(struct machine *machine, int is64bit,
2243     char *primary_ether_addr)
2244     {
2245     size_t bootpath_len = 500;
2246     char *init_bootpath;
2247     uint64_t addr, addr2;
2248     struct cpu *cpu = machine->cpus[0];
2249    
2250     /*
2251     * Boot string in ARC format:
2252     *
2253     * TODO: How about floppies? multi()disk()fdisk()
2254     * Is tftp() good for netbooting?
2255     */
2256     init_bootpath = malloc(bootpath_len);
2257     if (init_bootpath == NULL) {
2258     fprintf(stderr, "out of mem, bootpath\n");
2259     exit(1);
2260     }
2261     init_bootpath[0] = '\0';
2262    
2263     if (machine->bootdev_id < 0 || machine->force_netboot) {
2264     snprintf(init_bootpath, bootpath_len, "tftp()");
2265     } else {
2266     /* TODO: Make this nicer. */
2267     if (machine->machine_type == MACHINE_SGI) {
2268     if (machine->machine_subtype == 30)
2269     strlcat(init_bootpath, "xio(0)pci(15)",
2270     MACHINE_NAME_MAXBUF);
2271     if (machine->machine_subtype == 32)
2272     strlcat(init_bootpath, "pci(0)",
2273     MACHINE_NAME_MAXBUF);
2274     }
2275    
2276     if (diskimage_is_a_cdrom(machine, machine->bootdev_id,
2277     machine->bootdev_type))
2278     snprintf(init_bootpath + strlen(init_bootpath),
2279     bootpath_len - strlen(init_bootpath),
2280     "scsi(0)cdrom(%i)fdisk(0)", machine->bootdev_id);
2281     else
2282     snprintf(init_bootpath + strlen(init_bootpath),
2283     bootpath_len - strlen(init_bootpath),
2284     "scsi(0)disk(%i)rdisk(0)partition(1)",
2285     machine->bootdev_id);
2286     }
2287    
2288     if (machine->machine_type == MACHINE_ARC)
2289     strlcat(init_bootpath, "\\", MACHINE_NAME_MAXBUF);
2290    
2291     machine->bootstr = malloc(ARC_BOOTSTR_BUFLEN);
2292     if (machine->bootstr == NULL) {
2293     fprintf(stderr, "out of memory\n");
2294     exit(1);
2295     }
2296    
2297     strlcpy(machine->bootstr, init_bootpath, ARC_BOOTSTR_BUFLEN);
2298     if (strlcat(machine->bootstr, machine->boot_kernel_filename,
2299     ARC_BOOTSTR_BUFLEN) >= ARC_BOOTSTR_BUFLEN) {
2300     fprintf(stderr, "boot string too long?\n");
2301     exit(1);
2302     }
2303    
2304     /* Boot args., eg "-a" */
2305     machine->bootarg = machine->boot_string_argument;
2306    
2307     /* argc, argv, envp in a0, a1, a2: */
2308     cpu->cd.mips.gpr[MIPS_GPR_A0] = 0; /* note: argc is increased later */
2309    
2310     /* TODO: not needed? */
2311     cpu->cd.mips.gpr[MIPS_GPR_SP] = (int64_t)(int32_t)
2312     (machine->physical_ram_in_mb * 1048576 + 0x80000000 - 0x2080);
2313    
2314     /* Set up argc/argv: */
2315     addr = ARC_ENV_STRINGS;
2316     addr2 = ARC_ARGV_START;
2317     cpu->cd.mips.gpr[MIPS_GPR_A1] = addr2;
2318    
2319     /* bootstr: */
2320     store_pointer_and_advance(cpu, &addr2, addr, is64bit);
2321     add_environment_string(cpu, machine->bootstr, &addr);
2322     cpu->cd.mips.gpr[MIPS_GPR_A0] ++;
2323    
2324     /* bootarg: */
2325     if (machine->bootarg[0] != '\0') {
2326     store_pointer_and_advance(cpu, &addr2, addr, is64bit);
2327     add_environment_string(cpu, machine->bootarg, &addr);
2328     cpu->cd.mips.gpr[MIPS_GPR_A0] ++;
2329     }
2330    
2331     cpu->cd.mips.gpr[MIPS_GPR_A2] = addr2;
2332    
2333     /*
2334     * Add environment variables. For each variable, add it
2335     * as a string using add_environment_string(), and add a
2336     * pointer to it to the ARC_ENV_POINTERS array.
2337     */
2338     if (machine->use_x11) {
2339     if (machine->machine_type == MACHINE_ARC) {
2340     store_pointer_and_advance(cpu, &addr2, addr, is64bit);
2341     add_environment_string(cpu,
2342     "CONSOLEIN=multi()key()keyboard()console()", &addr);
2343     store_pointer_and_advance(cpu, &addr2, addr, is64bit);
2344     add_environment_string(cpu,
2345     "CONSOLEOUT=multi()video()monitor()console()",
2346     &addr);
2347     } else {
2348     store_pointer_and_advance(cpu, &addr2, addr, is64bit);
2349     add_environment_string(cpu, "ConsoleIn=keyboard()",
2350     &addr);
2351     store_pointer_and_advance(cpu, &addr2, addr, is64bit);
2352     add_environment_string(cpu, "ConsoleOut=video()",
2353     &addr);
2354    
2355     /* g for graphical mode. G for graphical mode
2356     with SGI logo visible on Irix? */
2357     store_pointer_and_advance(cpu, &addr2, addr, is64bit);
2358     add_environment_string(cpu, "console=g", &addr);
2359     }
2360     } else {
2361     if (machine->machine_type == MACHINE_ARC) {
2362     /* TODO: serial console for ARC? */
2363     store_pointer_and_advance(cpu, &addr2, addr, is64bit);
2364     add_environment_string(cpu,
2365     "CONSOLEIN=multi()serial(0)", &addr);
2366     store_pointer_and_advance(cpu, &addr2, addr, is64bit);
2367     add_environment_string(cpu,
2368     "CONSOLEOUT=multi()serial(0)", &addr);
2369     } else {
2370     store_pointer_and_advance(cpu, &addr2, addr, is64bit);
2371     add_environment_string(cpu, "ConsoleIn=serial(0)",
2372     &addr);
2373     store_pointer_and_advance(cpu, &addr2, addr, is64bit);
2374     add_environment_string(cpu, "ConsoleOut=serial(0)",
2375     &addr);
2376    
2377     /* 'd' or 'd2' in Irix, 'ttyS0' in Linux? */
2378     store_pointer_and_advance(cpu, &addr2, addr, is64bit);
2379     add_environment_string(cpu, "console=d", &addr);
2380     }
2381     }
2382    
2383     if (machine->machine_type == MACHINE_SGI) {
2384     store_pointer_and_advance(cpu, &addr2, addr, is64bit);
2385     add_environment_string(cpu, "AutoLoad=No", &addr);
2386     store_pointer_and_advance(cpu, &addr2, addr, is64bit);
2387     add_environment_string(cpu, "diskless=0", &addr);
2388     store_pointer_and_advance(cpu, &addr2, addr, is64bit);
2389     add_environment_string(cpu, "volume=80", &addr);
2390     store_pointer_and_advance(cpu, &addr2, addr, is64bit);
2391     add_environment_string(cpu, "sgilogo=y", &addr);
2392    
2393     store_pointer_and_advance(cpu, &addr2, addr, is64bit);
2394     add_environment_string(cpu, "monitor=h", &addr);
2395     store_pointer_and_advance(cpu, &addr2, addr, is64bit);
2396     add_environment_string(cpu, "TimeZone=GMT", &addr);
2397     store_pointer_and_advance(cpu, &addr2, addr, is64bit);
2398     add_environment_string(cpu, "nogfxkbd=1", &addr);
2399    
2400     /* TODO: 'xio(0)pci(15)scsi(0)disk(1)rdisk(0)partition(0)'
2401     on IP30 at least */
2402    
2403     store_pointer_and_advance(cpu, &addr2, addr, is64bit);
2404     add_environment_string(cpu,
2405     "SystemPartition=pci(0)scsi(0)disk(2)rdisk(0)partition(8)",
2406     &addr);
2407     store_pointer_and_advance(cpu, &addr2, addr, is64bit);
2408     add_environment_string(cpu,
2409     "OSLoadPartition=pci(0)scsi(0)disk(2)rdisk(0)partition(0)",
2410     &addr);
2411     store_pointer_and_advance(cpu, &addr2, addr, is64bit);
2412     add_environment_string(cpu, "OSLoadFilename=/unix", &addr);
2413     store_pointer_and_advance(cpu, &addr2, addr, is64bit);
2414     add_environment_string(cpu, "OSLoader=sash", &addr);
2415    
2416     store_pointer_and_advance(cpu, &addr2, addr, is64bit);
2417     add_environment_string(cpu, "rbaud=9600", &addr);
2418     store_pointer_and_advance(cpu, &addr2, addr, is64bit);
2419     add_environment_string(cpu, "rebound=y", &addr);
2420     store_pointer_and_advance(cpu, &addr2, addr, is64bit);
2421     add_environment_string(cpu, "crt_option=1", &addr);
2422     store_pointer_and_advance(cpu, &addr2, addr, is64bit);
2423     add_environment_string(cpu, "netaddr=10.0.0.1", &addr);
2424    
2425     store_pointer_and_advance(cpu, &addr2, addr, is64bit);
2426     add_environment_string(cpu, "keybd=US", &addr);
2427    
2428     store_pointer_and_advance(cpu, &addr2, addr, is64bit);
2429     add_environment_string(cpu, "cpufreq=3", &addr);
2430     store_pointer_and_advance(cpu, &addr2, addr, is64bit);
2431     add_environment_string(cpu, "dbaud=9600", &addr);
2432     store_pointer_and_advance(cpu, &addr2, addr, is64bit);
2433     add_environment_string(cpu, primary_ether_addr, &addr);
2434     store_pointer_and_advance(cpu, &addr2, addr, is64bit);
2435     add_environment_string(cpu, "verbose=istrue", &addr);
2436     store_pointer_and_advance(cpu, &addr2, addr, is64bit);
2437     add_environment_string(cpu, "showconfig=istrue", &addr);
2438     store_pointer_and_advance(cpu, &addr2, addr, is64bit);
2439     add_environment_string(cpu, "diagmode=v", &addr);
2440     store_pointer_and_advance(cpu, &addr2, addr, is64bit);
2441     add_environment_string(cpu, "kernname=unix", &addr);
2442     } else {
2443     char *tmp;
2444     size_t mlen = strlen(machine->bootarg) +
2445     strlen("OSLOADOPTIONS=") + 2;
2446     tmp = malloc(mlen);
2447     snprintf(tmp, mlen, "OSLOADOPTIONS=%s", machine->bootarg);
2448     store_pointer_and_advance(cpu, &addr2, addr, is64bit);
2449     add_environment_string(cpu, tmp, &addr);
2450    
2451     store_pointer_and_advance(cpu, &addr2, addr, is64bit);
2452     add_environment_string(cpu, "OSLOADPARTITION=scsi(0)cdrom(6)"
2453     "fdisk(0);scsi(0)disk(0)rdisk(0)partition(1)", &addr);
2454    
2455     store_pointer_and_advance(cpu, &addr2, addr, is64bit);
2456     add_environment_string(cpu, "SYSTEMPARTITION=scsi(0)cdrom(6)"
2457     "fdisk(0);scsi(0)disk(0)rdisk(0)partition(1)", &addr);
2458     }
2459    
2460     /* End the environment strings with an empty zero-terminated
2461     string, and the envp array with a NULL pointer. */
2462     add_environment_string(cpu, "", &addr); /* the end */
2463     store_pointer_and_advance(cpu, &addr2, 0, is64bit);
2464    
2465     /* Return address: (0x20 = ReturnFromMain()) */
2466     cpu->cd.mips.gpr[MIPS_GPR_RA] = ARC_FIRMWARE_ENTRIES + 0x20;
2467     }
2468    
2469    
2470     /*
2471 dpavlin 14 * arcbios_init():
2472     *
2473     * Should be called before any other arcbios function is used. An exception
2474     * is arcbios_console_init(), which may be called before this function.
2475 dpavlin 22 *
2476     * TODO: Refactor; this is too long.
2477 dpavlin 14 */
2478 dpavlin 22 void arcbios_init(struct machine *machine, int is64bit, uint64_t sgi_ram_offset,
2479     char *primary_ether_addr, uint8_t *primary_ether_macaddr)
2480 dpavlin 14 {
2481     int i, alloclen = 20;
2482     char *name;
2483     uint64_t arc_reserved, mem_base, mem_count;
2484     struct cpu *cpu = machine->cpus[0];
2485     struct arcbios_sysid arcbios_sysid;
2486     struct arcbios_dsp_stat arcbios_dsp_stat;
2487     uint64_t system = 0;
2488     struct arcbios_spb arcbios_spb;
2489     struct arcbios_spb_64 arcbios_spb_64;
2490    
2491     machine->md.arc.arc_64bit = is64bit;
2492     machine->md.arc.wordlen = is64bit? sizeof(uint64_t) : sizeof(uint32_t);
2493    
2494     machine->md.arc.next_component_address = FIRST_ARC_COMPONENT;
2495     machine->md.arc.configuration_data_next_addr = ARC_CONFIG_DATA_ADDR;
2496    
2497     if (machine->physical_ram_in_mb < 16)
2498     fprintf(stderr, "WARNING! The ARC platform specification "
2499     "doesn't allow less than 16 MB of RAM. Continuing "
2500     "anyway.\n");
2501    
2502     /* File handles 0, 1, and 2 are stdin, stdout, and stderr. */
2503     for (i=0; i<ARC_MAX_HANDLES; i++) {
2504     machine->md.arc.file_handle_in_use[i] = i<3? 1 : 0;
2505     machine->md.arc.file_handle_string[i] = i>=3? NULL :
2506     (i==0? "(stdin)" : (i==1? "(stdout)" : "(stderr)"));
2507     machine->md.arc.current_seek_offset[i] = 0;
2508     }
2509    
2510     if (!machine->use_x11)
2511     machine->md.arc.vgaconsole = 0;
2512    
2513     if (machine->md.arc.vgaconsole) {
2514     char tmpstr[100];
2515     int x, y;
2516    
2517     machine->md.arc.console_curcolor = 0x1f;
2518     for (y=0; y<machine->md.arc.console_maxy; y++)
2519     for (x=0; x<machine->md.arc.console_maxx; x++)
2520     arcbios_putcell(cpu, ' ', x, y);
2521    
2522     machine->md.arc.console_curx = 0;
2523     machine->md.arc.console_cury = 0;
2524    
2525     arcbios_putstring(cpu, "GXemul");
2526     #ifdef VERSION
2527     arcbios_putstring(cpu, " "VERSION);
2528     #endif
2529     arcbios_putstring(cpu, " ARCBIOS emulation\n");
2530    
2531     snprintf(tmpstr, sizeof(tmpstr), "%i cpu%s (%s), %i MB "
2532     "memory\n\n", machine->ncpus, machine->ncpus > 1? "s" : "",
2533     cpu->cd.mips.cpu_type.name,
2534     machine->physical_ram_in_mb);
2535     arcbios_putstring(cpu, tmpstr);
2536     }
2537    
2538     arcbios_set_default_exception_handler(cpu);
2539    
2540     memset(&arcbios_sysid, 0, sizeof(arcbios_sysid));
2541     if (machine->machine_type == MACHINE_SGI) {
2542     /* Vendor ID, max 8 chars: */
2543     strncpy(arcbios_sysid.VendorId, "SGI", 3);
2544     switch (machine->machine_subtype) {
2545     case 22:
2546     strncpy(arcbios_sysid.ProductId,
2547     "87654321", 8); /* some kind of ID? */
2548     break;
2549     case 32:
2550     strncpy(arcbios_sysid.ProductId, "8", 1);
2551     /* 6 or 8 (?) */
2552     break;
2553     default:
2554     snprintf(arcbios_sysid.ProductId, 8, "IP%i",
2555     machine->machine_subtype);
2556     }
2557     } else {
2558     switch (machine->machine_subtype) {
2559     case MACHINE_ARC_NEC_RD94:
2560     strncpy(arcbios_sysid.VendorId, "NEC W&S", 8);
2561     strncpy(arcbios_sysid.ProductId, "RD94", 4);
2562     break;
2563     case MACHINE_ARC_NEC_R94:
2564     strncpy(arcbios_sysid.VendorId, "NEC W&S", 8);
2565     strncpy(arcbios_sysid.ProductId, "ijkl", 4);
2566     break;
2567     case MACHINE_ARC_NEC_R96:
2568     strncpy(arcbios_sysid.VendorId, "MIPS DUO", 8);
2569     strncpy(arcbios_sysid.ProductId, "blahblah", 8);
2570     break;
2571     case MACHINE_ARC_NEC_R98:
2572     strncpy(arcbios_sysid.VendorId, "NEC W&S", 8);
2573     strncpy(arcbios_sysid.ProductId, "R98", 4);
2574     break;
2575     case MACHINE_ARC_JAZZ_PICA:
2576     strncpy(arcbios_sysid.VendorId, "MIPS MAG", 8);
2577     strncpy(arcbios_sysid.ProductId, "ijkl", 4);
2578     break;
2579     case MACHINE_ARC_JAZZ_MAGNUM:
2580     strncpy(arcbios_sysid.VendorId, "MIPS MAG", 8);
2581     strncpy(arcbios_sysid.ProductId, "ijkl", 4);
2582     break;
2583     case MACHINE_ARC_JAZZ_M700:
2584     strncpy(arcbios_sysid.VendorId, "OLI00000", 8);
2585     strncpy(arcbios_sysid.ProductId, "ijkl", 4);
2586     break;
2587     case MACHINE_ARC_DESKTECH_TYNE:
2588     strncpy(arcbios_sysid.VendorId, "DESKTECH", 8);
2589     strncpy(arcbios_sysid.ProductId, "ijkl", 4);
2590     break;
2591     default:
2592     fatal("error in machine.c sysid\n");
2593     exit(1);
2594     }
2595     }
2596    
2597     store_buf(cpu, SGI_SYSID_ADDR, (char *)&arcbios_sysid,
2598     sizeof(arcbios_sysid));
2599    
2600     arcbios_get_dsp_stat(cpu, &arcbios_dsp_stat);
2601     store_buf(cpu, ARC_DSPSTAT_ADDR, (char *)&arcbios_dsp_stat,
2602     sizeof(arcbios_dsp_stat));
2603    
2604     /*
2605     * The first 12 MBs of RAM are simply reserved... this simplifies
2606     * things a lot. If there's more than 512MB of RAM, it has to be
2607     * split in two, according to the ARC spec. This code creates a
2608     * number of chunks of at most 512MB each.
2609     *
2610     * NOTE: The region of physical address space between 0x10000000 and
2611     * 0x1fffffff (256 - 512 MB) is usually occupied by memory mapped
2612     * devices, so that portion is "lost".
2613     */
2614     machine->md.arc.memdescriptor_base = ARC_MEMDESC_ADDR;
2615    
2616     arc_reserved = 0x2000;
2617     if (machine->machine_type == MACHINE_SGI)
2618     arc_reserved = 0x4000;
2619    
2620     arcbios_add_memory_descriptor(cpu, 0, arc_reserved,
2621     ARCBIOS_MEM_FirmwarePermanent);
2622     arcbios_add_memory_descriptor(cpu, sgi_ram_offset + arc_reserved,
2623     0x60000-arc_reserved, ARCBIOS_MEM_FirmwareTemporary);
2624    
2625     mem_base = 12;
2626     mem_base += sgi_ram_offset / 1048576;
2627    
2628     while (mem_base < machine->physical_ram_in_mb+sgi_ram_offset/1048576) {
2629     mem_count = machine->physical_ram_in_mb+sgi_ram_offset/1048576
2630     - mem_base;
2631    
2632     /* Skip the 256-512MB region (for devices) */
2633     if (mem_base < 256 && mem_base + mem_count > 256) {
2634     mem_count = 256-mem_base;
2635     }
2636    
2637     /* At most 512MB per descriptor (at least the first 512MB
2638     must be separated this way, according to the ARC spec) */
2639     if (mem_count > 512)
2640     mem_count = 512;
2641    
2642     arcbios_add_memory_descriptor(cpu, mem_base * 1048576,
2643     mem_count * 1048576, ARCBIOS_MEM_FreeMemory);
2644    
2645     mem_base += mem_count;
2646    
2647     /* Skip the devices: */
2648     if (mem_base == 256)
2649     mem_base = 512;
2650     }
2651    
2652     /*
2653     * Components: (this is an example of what a system could look like)
2654     *
2655     * [System]
2656     * [CPU] (one for each cpu)
2657     * [FPU] (one for each cpu)
2658     * [CPU Caches]
2659     * [Memory]
2660     * [Ethernet]
2661     * [Serial]
2662     * [SCSI]
2663     * [Disk]
2664     *
2665     * Here's a good list of what hardware is in different IP-models:
2666     * http://www.linux-mips.org/archives/linux-mips/2001-03/msg00101.html
2667     */
2668    
2669     if (machine->machine_name == NULL)
2670     fatal("ERROR: machine_name == NULL\n");
2671    
2672     /* Add the root node: */
2673     switch (machine->machine_type) {
2674     case MACHINE_SGI:
2675     name = malloc(alloclen);
2676     if (name == NULL) {
2677     fprintf(stderr, "out of memory\n");
2678     exit(1);
2679     }
2680     snprintf(name, alloclen, "SGI-IP%i",
2681     machine->machine_subtype);
2682    
2683     /* A very special case for IP24 (which identifies itself
2684     as an IP22): */
2685     if (machine->machine_subtype == 24)
2686     snprintf(name, alloclen, "SGI-IP22");
2687     break;
2688     case MACHINE_ARC:
2689     /* ARC: */
2690     switch (machine->machine_subtype) {
2691     case MACHINE_ARC_NEC_RD94:
2692     name = "NEC-RD94";
2693     break;
2694     case MACHINE_ARC_NEC_R94:
2695     name = "NEC-R94";
2696     break;
2697     case MACHINE_ARC_NEC_R96:
2698     name = "NEC-R96";
2699     break;
2700     case MACHINE_ARC_NEC_R98:
2701     name = "NEC-R98";
2702     break;
2703     case MACHINE_ARC_JAZZ_PICA:
2704     name = "PICA-61";
2705     break;
2706     case MACHINE_ARC_JAZZ_MAGNUM:
2707     case MACHINE_ARC_JAZZ_M700:
2708     name = "Microsoft-Jazz";
2709     break;
2710     case MACHINE_ARC_DESKTECH_TYNE:
2711     name = "DESKTECH-TYNE";
2712     break;
2713     default:
2714     fatal("Unimplemented ARC machine type %i\n",
2715     machine->machine_subtype);
2716     exit(1);
2717     }
2718     break;
2719     default:
2720     fatal("ERROR: non-SGI and non-ARC?\n");
2721     exit(1);
2722     }
2723    
2724     system = arcbios_addchild_manual(cpu, COMPONENT_CLASS_SystemClass,
2725     COMPONENT_TYPE_ARC, 0,1,2,0, 0xffffffff, name, 0/*ROOT*/, NULL, 0);
2726 dpavlin 24 debug("ARC system @ 0x%"PRIx64" (\"%s\")\n", (uint64_t) system, name);
2727 dpavlin 14
2728    
2729     /*
2730     * Add tree nodes for CPUs and their caches:
2731     */
2732    
2733     for (i=0; i<machine->ncpus; i++) {
2734     uint64_t cpuaddr, fpu=0, picache, pdcache, sdcache=0;
2735     int cache_size, cache_line_size;
2736     unsigned int jj;
2737     char arc_cpu_name[100];
2738     char arc_fpc_name[105];
2739    
2740     snprintf(arc_cpu_name, sizeof(arc_cpu_name),
2741     "MIPS-%s", machine->cpu_name);
2742    
2743     if (machine->machine_type == MACHINE_ARC &&
2744     machine->machine_subtype == MACHINE_ARC_NEC_R96)
2745     snprintf(arc_cpu_name, sizeof(arc_cpu_name),
2746     "MIPS-%s - Pr 4/5.0, Fp 5/0", machine->cpu_name);
2747    
2748     arc_cpu_name[sizeof(arc_cpu_name)-1] = 0;
2749     for (jj=0; jj<strlen(arc_cpu_name); jj++)
2750     if (arc_cpu_name[jj] >= 'a' && arc_cpu_name[jj] <= 'z')
2751     arc_cpu_name[jj] += ('A' - 'a');
2752    
2753     strlcpy(arc_fpc_name, arc_cpu_name, sizeof(arc_fpc_name));
2754     strlcat(arc_fpc_name, "FPC", sizeof(arc_fpc_name));
2755    
2756     cpuaddr = arcbios_addchild_manual(cpu,
2757     COMPONENT_CLASS_ProcessorClass, COMPONENT_TYPE_CPU,
2758     0, 1, 2, i, 0xffffffff, arc_cpu_name, system, NULL, 0);
2759    
2760     /*
2761     * TODO: This was in the ARC specs, but it isn't really used
2762     * by ARC implementations? At least SGI-IP32 uses it.
2763     */
2764     if (machine->machine_type == MACHINE_SGI)
2765     fpu = arcbios_addchild_manual(cpu,
2766     COMPONENT_CLASS_ProcessorClass, COMPONENT_TYPE_FPU,
2767     0, 1, 2, 0, 0xffffffff, arc_fpc_name, cpuaddr,
2768     NULL, 0);
2769    
2770     cache_size = DEFAULT_PCACHE_SIZE - 12;
2771     if (machine->cache_picache)
2772     cache_size = machine->cache_picache - 12;
2773     if (cache_size < 0)
2774     cache_size = 0;
2775    
2776     cache_line_size = DEFAULT_PCACHE_LINESIZE;
2777     if (machine->cache_picache_linesize)
2778     cache_line_size = machine->cache_picache_linesize;
2779     if (cache_line_size < 0)
2780     cache_line_size = 0;
2781    
2782     picache = arcbios_addchild_manual(cpu,
2783     COMPONENT_CLASS_CacheClass, COMPONENT_TYPE_PrimaryICache,
2784     0, 1, 2,
2785     /*
2786     * Key bits: 0xXXYYZZZZ
2787     * XX is refill-size.
2788     * Cache line size is 1 << YY,
2789     * Cache size is 4KB << ZZZZ.
2790     */
2791     0x01000000 + (cache_line_size << 16) + cache_size,
2792     /* 32 bytes per line, default = 32 KB total */
2793     0xffffffff, NULL, cpuaddr, NULL, 0);
2794    
2795     cache_size = DEFAULT_PCACHE_SIZE - 12;
2796     if (machine->cache_pdcache)
2797     cache_size = machine->cache_pdcache - 12;
2798     if (cache_size < 0)
2799     cache_size = 0;
2800    
2801     cache_line_size = DEFAULT_PCACHE_LINESIZE;
2802     if (machine->cache_pdcache_linesize)
2803     cache_line_size = machine->cache_pdcache_linesize;
2804     if (cache_line_size < 0)
2805     cache_line_size = 0;
2806    
2807     pdcache = arcbios_addchild_manual(cpu,
2808     COMPONENT_CLASS_CacheClass,
2809     COMPONENT_TYPE_PrimaryDCache, 0, 1, 2,
2810     /*
2811     * Key bits: 0xYYZZZZ
2812     * Cache line size is 1 << YY,
2813     * Cache size is 4KB << ZZZZ.
2814     */
2815     0x01000000 + (cache_line_size << 16) + cache_size,
2816     /* 32 bytes per line, default = 32 KB total */
2817     0xffffffff, NULL, cpuaddr, NULL, 0);
2818    
2819     if (machine->cache_secondary >= 12) {
2820     cache_size = machine->cache_secondary - 12;
2821    
2822     cache_line_size = 6; /* 64 bytes default */
2823     if (machine->cache_secondary_linesize)
2824     cache_line_size = machine->
2825     cache_secondary_linesize;
2826     if (cache_line_size < 0)
2827     cache_line_size = 0;
2828    
2829     sdcache = arcbios_addchild_manual(cpu,
2830     COMPONENT_CLASS_CacheClass,
2831     COMPONENT_TYPE_SecondaryDCache, 0, 1, 2,
2832     /*
2833     * Key bits: 0xYYZZZZ
2834     * Cache line size is 1 << YY,
2835     * Cache size is 4KB << ZZZZ.
2836     */
2837     0x01000000 + (cache_line_size << 16) + cache_size,
2838     /* 64 bytes per line, default = 1 MB total */
2839     0xffffffff, NULL, cpuaddr, NULL, 0);
2840     }
2841    
2842 dpavlin 24 debug("ARC cpu%i @ 0x%"PRIx64, i, (uint64_t) cpuaddr);
2843 dpavlin 14
2844     if (fpu != 0)
2845 dpavlin 24 debug(" (fpu @ 0x%"PRIx64")\n", (uint64_t) fpu);
2846 dpavlin 14 else
2847     debug("\n");
2848    
2849 dpavlin 24 debug(" picache @ 0x%"PRIx64", pdcache @ 0x%"PRIx64"\n",
2850     (uint64_t) picache, (uint64_t) pdcache);
2851 dpavlin 14
2852     if (machine->cache_secondary >= 12)
2853 dpavlin 24 debug(" sdcache @ 0x%"PRIx64"\n",
2854     (uint64_t) sdcache);
2855 dpavlin 14
2856     if (machine->machine_type == MACHINE_SGI) {
2857     /* TODO: Memory amount (and base address?)! */
2858     uint64_t memory = arcbios_addchild_manual(cpu,
2859     COMPONENT_CLASS_MemoryClass,
2860     COMPONENT_TYPE_MemoryUnit, 0, 1, 2, 0,
2861     0xffffffff, "memory", cpuaddr, NULL, 0);
2862 dpavlin 24 debug("ARC memory @ 0x%"PRIx64"\n", (uint64_t) memory);
2863 dpavlin 14 }
2864     }
2865    
2866    
2867     /*
2868     * Add other components:
2869     *
2870     * TODO: How should this be synched with the hardware devices
2871     * added in machine.c?
2872     */
2873    
2874     arcbios_add_other_components(machine, system);
2875    
2876    
2877     /*
2878     * Defalt TLB entry for 64-bit SGI machines:
2879     */
2880     if (machine->machine_type == MACHINE_SGI &&
2881     machine->machine_subtype != 12 /* TODO: ugly */ ) {
2882     /* TODO: On which models is this required? */
2883     mips_coproc_tlb_set_entry(cpu, 0, 1048576*16,
2884     0xc000000000000000ULL, 0, 1048576*16, 1,1,1,1,1, 0, 2, 2);
2885     }
2886    
2887    
2888     /*
2889     * Set up Firmware Vectors:
2890     */
2891     add_symbol_name(&machine->symbol_context,
2892     ARC_FIRMWARE_ENTRIES, 0x10000, "[ARCBIOS entry]", 0, 1);
2893    
2894     for (i=0; i<100; i++) {
2895     if (is64bit) {
2896     store_64bit_word(cpu, ARC_FIRMWARE_VECTORS + i*8,
2897     ARC_FIRMWARE_ENTRIES + i*8);
2898     store_64bit_word(cpu, ARC_PRIVATE_VECTORS + i*8,
2899     ARC_PRIVATE_ENTRIES + i*8);
2900 dpavlin 24
2901     /* "Magic trap" instruction: */
2902     store_32bit_word(cpu, ARC_FIRMWARE_ENTRIES + i*8,
2903     0x00c0de0c);
2904     store_32bit_word(cpu, ARC_PRIVATE_ENTRIES + i*8,
2905     0x00c0de0c);
2906 dpavlin 14 } else {
2907     store_32bit_word(cpu, ARC_FIRMWARE_VECTORS + i*4,
2908     ARC_FIRMWARE_ENTRIES + i*4);
2909     store_32bit_word(cpu, ARC_PRIVATE_VECTORS + i*4,
2910     ARC_PRIVATE_ENTRIES + i*4);
2911 dpavlin 24
2912     /* "Magic trap" instruction: */
2913     store_32bit_word(cpu, ARC_FIRMWARE_ENTRIES + i*4,
2914     0x00c0de0c);
2915     store_32bit_word(cpu, ARC_PRIVATE_ENTRIES + i*4,
2916     0x00c0de0c);
2917 dpavlin 14 }
2918     }
2919    
2920    
2921     /*
2922     * Set up the ARC SPD:
2923     */
2924     if (is64bit) {
2925     /* ARCS64 SPD (TODO: This is just a guess) */
2926     memset(&arcbios_spb_64, 0, sizeof(arcbios_spb_64));
2927     store_64bit_word_in_host(cpu, (unsigned char *)
2928     &arcbios_spb_64.SPBSignature, ARCBIOS_SPB_SIGNATURE);
2929     store_16bit_word_in_host(cpu, (unsigned char *)
2930     &arcbios_spb_64.Version, 64);
2931     store_16bit_word_in_host(cpu, (unsigned char *)
2932     &arcbios_spb_64.Revision, 0);
2933     store_64bit_word_in_host(cpu, (unsigned char *)
2934     &arcbios_spb_64.FirmwareVector, ARC_FIRMWARE_VECTORS);
2935     store_buf(cpu, SGI_SPB_ADDR, (char *)&arcbios_spb_64,
2936     sizeof(arcbios_spb_64));
2937     } else {
2938     /* ARCBIOS SPB: (For ARC and 32-bit SGI modes) */
2939     memset(&arcbios_spb, 0, sizeof(arcbios_spb));
2940     store_32bit_word_in_host(cpu, (unsigned char *)
2941     &arcbios_spb.SPBSignature, ARCBIOS_SPB_SIGNATURE);
2942     store_32bit_word_in_host(cpu, (unsigned char *)
2943     &arcbios_spb.SPBLength, sizeof(arcbios_spb));
2944     store_16bit_word_in_host(cpu, (unsigned char *)
2945     &arcbios_spb.Version, 1);
2946     store_16bit_word_in_host(cpu, (unsigned char *)
2947     &arcbios_spb.Revision, machine->machine_type ==
2948     MACHINE_SGI? 10 : 2);
2949     store_32bit_word_in_host(cpu, (unsigned char *)
2950     &arcbios_spb.FirmwareVector, ARC_FIRMWARE_VECTORS);
2951     store_32bit_word_in_host(cpu, (unsigned char *)
2952     &arcbios_spb.FirmwareVectorLength, 100 * 4); /* ? */
2953     store_32bit_word_in_host(cpu, (unsigned char *)
2954     &arcbios_spb.PrivateVector, ARC_PRIVATE_VECTORS);
2955     store_32bit_word_in_host(cpu, (unsigned char *)
2956     &arcbios_spb.PrivateVectorLength, 100 * 4); /* ? */
2957     store_buf(cpu, SGI_SPB_ADDR, (char *)&arcbios_spb,
2958     sizeof(arcbios_spb));
2959     }
2960 dpavlin 22
2961    
2962     /*
2963     * TODO: How to build the component tree intermixed with
2964     * the rest of device initialization?
2965     */
2966    
2967     arc_environment_setup(machine, is64bit, primary_ether_addr);
2968 dpavlin 14 }
2969    

  ViewVC Help
Powered by ViewVC 1.1.26