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

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

Parent Directory Parent Directory | Revision Log Revision Log


Revision 24 - (show 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 /*
2 * Copyright (C) 2003-2006 Anders Gavare. All rights reserved.
3 *
4 * Redistribution and use in source and binary forms, with or without
5 * modification, are permitted provided that the following conditions are met:
6 *
7 * 1. Redistributions of source code must retain the above copyright
8 * notice, this list of conditions and the following disclaimer.
9 * 2. Redistributions in binary form must reproduce the above copyright
10 * notice, this list of conditions and the following disclaimer in the
11 * documentation and/or other materials provided with the distribution.
12 * 3. The name of the author may not be used to endorse or promote products
13 * derived from this software without specific prior written permission.
14 *
15 * THIS SOFTWARE IS PROVIDED BY THE AUTHOR AND CONTRIBUTORS ``AS IS'' AND
16 * ANY EXPRESS OR IMPLIED WARRANTIES, INCLUDING, BUT NOT LIMITED TO, THE
17 * IMPLIED WARRANTIES OF MERCHANTABILITY AND FITNESS FOR A PARTICULAR PURPOSE
18 * ARE DISCLAIMED. IN NO EVENT SHALL THE AUTHOR OR CONTRIBUTORS BE LIABLE
19 * FOR ANY DIRECT, INDIRECT, INCIDENTAL, SPECIAL, EXEMPLARY, OR CONSEQUENTIAL
20 * DAMAGES (INCLUDING, BUT NOT LIMITED TO, PROCUREMENT OF SUBSTITUTE GOODS
21 * OR SERVICES; LOSS OF USE, DATA, OR PROFITS; OR BUSINESS INTERRUPTION)
22 * HOWEVER CAUSED AND ON ANY THEORY OF LIABILITY, WHETHER IN CONTRACT, STRICT
23 * LIABILITY, OR TORT (INCLUDING NEGLIGENCE OR OTHERWISE) ARISING IN ANY WAY
24 * OUT OF THE USE OF THIS SOFTWARE, EVEN IF ADVISED OF THE POSSIBILITY OF
25 * SUCH DAMAGE.
26 *
27 *
28 * $Id: arcbios.c,v 1.8 2006/04/15 08:21:07 debug Exp $
29 *
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 * TODO 2: It seems that it _is_ necessary, but NetBSD's arcdiag
455 * 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 /* debug("[ addchild: peeraddr = 0x%016"PRIx64" ]\n",
703 (uint64_t) peeraddr); */
704
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 /* debug(" epeer=%"PRIx64" echild=%"PRIx64" eparent=%"PRIx64
748 "\n", (uint64_t) epeer, (uint64_t) echild,
749 (uint64_t) eparent); */
750
751 if (eparent == parent && epeer == 0) {
752 epeer = a;
753 store_64bit_word(cpu, peeraddr + 0 *
754 machine->md.arc.wordlen, epeer);
755 /* debug("[ addchild: adding 0x%016"PRIx64" as peer "
756 "to 0x%016"PRIx64" ]\n", (uint64_t) a,
757 (uint64_t) peeraddr); */
758 }
759 if (peeraddr == parent && echild == 0) {
760 echild = a;
761 store_64bit_word(cpu, peeraddr + 1 *
762 machine->md.arc.wordlen, echild);
763 /* debug("[ addchild: adding 0x%016"PRIx64" as child "
764 "to 0x%016"PRIx64" ]\n", (uint64_t) a,
765 (uint64_t) peeraddr); */
766 }
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 size_t i;
847
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 /* printf("& ADDING %i: configdata=0x%016"PRIx64" "
873 "component=0x%016"PRIx64"\n",
874 machine->md.arc.n_configuration_data,
875 (uint64_t) machine->md.arc.configuration_data_configdata[
876 machine->md.arc.n_configuration_data],
877 (uint64_t) machine->md.arc.configuration_data_component[
878 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 /* printf("reading MSDOS partition from offset 0x%"PRIx64"\n",
951 (uint64_t) offset); */
952
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 "read the disk image, id %i, offset 0x%"PRIx64" ]\n",
958 disk_id, (uint64_t) offset);
959 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 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 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 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 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 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 break;
1346 case 0x30: /* GetConfigurationData(void *configdata, void *node) */
1347 /* 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 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 "0x%016"PRIx64"\n", i, (uint64_t) machine->
1355 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 for (i=0; i<(ssize_t)sizeof(buf); i++) {
1388 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 for (i=0; i<(int32_t)cpu->cd.mips.gpr[MIPS_GPR_A2];
1556 i++) {
1557 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 int disk_type = 0;
1598 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 int disk_type = 0;
1670 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 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
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 for (i=0; i<(int32_t)cpu->cd.mips.gpr[MIPS_GPR_A2]; i++)
1695 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 for (i=0; i<(int32_t)cpu->cd.mips.gpr[MIPS_GPR_A2];
1717 i++) {
1718 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 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
1737 if (cpu->cd.mips.gpr[MIPS_GPR_A2] != 0) {
1738 fatal("[ ARCBIOS Seek(%i,0x%08"PRIx64",%i): "
1739 "UNIMPLEMENTED whence=%i ]\n",
1740 (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 }
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 debug("%016"PRIx64" ]\n", (uint64_t) ofs);
1766 }
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 for (i=0; i<(ssize_t)sizeof(buf); i++)
1774 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 for (j=0; j<(ssize_t)strlen((char *)buf); j++) {
1783 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 if (nmatches == (int)strlen((char *)buf) && ch2=='=') {
1794 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 * 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 * 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 *
2476 * TODO: Refactor; this is too long.
2477 */
2478 void arcbios_init(struct machine *machine, int is64bit, uint64_t sgi_ram_offset,
2479 char *primary_ether_addr, uint8_t *primary_ether_macaddr)
2480 {
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 debug("ARC system @ 0x%"PRIx64" (\"%s\")\n", (uint64_t) system, name);
2727
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 debug("ARC cpu%i @ 0x%"PRIx64, i, (uint64_t) cpuaddr);
2843
2844 if (fpu != 0)
2845 debug(" (fpu @ 0x%"PRIx64")\n", (uint64_t) fpu);
2846 else
2847 debug("\n");
2848
2849 debug(" picache @ 0x%"PRIx64", pdcache @ 0x%"PRIx64"\n",
2850 (uint64_t) picache, (uint64_t) pdcache);
2851
2852 if (machine->cache_secondary >= 12)
2853 debug(" sdcache @ 0x%"PRIx64"\n",
2854 (uint64_t) sdcache);
2855
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 debug("ARC memory @ 0x%"PRIx64"\n", (uint64_t) memory);
2863 }
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
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 } 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
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 }
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
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 }
2969

  ViewVC Help
Powered by ViewVC 1.1.26