/[gxemul]/trunk/src/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/arcbios.c

Parent Directory Parent Directory | Revision Log Revision Log


Revision 12 - (show annotations)
Mon Oct 8 16:18:38 2007 UTC (12 years, 1 month ago) by dpavlin
File MIME type: text/plain
File size: 84958 byte(s)
++ trunk/HISTORY	(local)
$Id: HISTORY,v 1.905 2005/08/16 09:16:24 debug Exp $
20050628	Continuing the work on the ARM translation engine. end_of_page
		works. Experimenting with load/store translation caches
		(virtual -> physical -> host).
20050629	More ARM stuff (memory access translation cache, mostly). This
		might break a lot of stuff elsewhere, probably some MIPS-
		related translation things.
20050630	Many load/stores are now automatically generated and included
		into cpu_arm_instr.c; 1024 functions in total (!).
		Fixes based on feedback from Alec Voropay: only print 8 hex
		digits instead of 16 in some cases when emulating 32-bit
		machines; similar 8 vs 16 digit fix for breakpoint addresses;
		4Kc has 16 TLB entries, not 48; the MIPS config select1
		register is now printed with "reg ,0".
		Also changing many other occurances of 16 vs 8 digit output.
		Adding cache associativity fields to mips_cpu_types.h; updating
		some other cache fields; making the output of
		mips_cpu_dumpinfo() look nicer.
		Generalizing the bintrans stuff for device accesses to also
		work with the new translation system. (This might also break
		some MIPS things.)
		Adding multi-load/store instructions to the ARM disassembler
		and the translator, and some optimizations of various kinds.
20050701	Adding a simple dev_disk (it can read/write sectors from
		disk images).
20050712	Adding dev_ether (a simple ethernet send/receive device).
		Debugger command "ninstrs" for toggling show_nr_of_instructions
		during runtime.
		Removing the framebuffer logo.
20050713	Continuing on dev_ether.
		Adding a dummy cpu_alpha (again).
20050714	More work on cpu_alpha.
20050715	More work on cpu_alpha. Many instructions work, enough to run
		a simple framebuffer fill test (similar to the ARM test).
20050716	More Alpha stuff.
20050717	Minor updates (Alpha stuff).
20050718	Minor updates (Alpha stuff).
20050719	Generalizing some Alpha instructions.
20050720	More Alpha-related updates.
20050721	Continuing on cpu_alpha. Importing rpb.h from NetBSD/alpha.
20050722	Alpha-related updates: userland stuff (Hello World using
		write() compiled statically for FreeBSD/Alpha runs fine), and
		more instructions are now implemented.
20050723	Fixing ldq_u and stq_u.
		Adding more instructions (conditional moves, masks, extracts,
		shifts).
20050724	More FreeBSD/Alpha userland stuff, and adding some more
		instructions (inserts).
20050725	Continuing on the Alpha stuff. (Adding dummy ldt/stt.)
		Adding a -A command line option to turn off alignment checks
		in some cases (for translated code).
		Trying to remove the old bintrans code which updated the pc
		and nr_of_executed_instructions for every instruction.
20050726	Making another attempt att removing the pc/nr of instructions
		code. This time it worked, huge performance increase for
		artificial test code, but performance loss for real-world
		code :-( so I'm scrapping that code for now.
		Tiny performance increase on Alpha (by using ret instead of
		jmp, to play nice with the Alpha's branch prediction) for the
		old MIPS bintrans backend.
20050727	Various minor fixes and cleanups.
20050728	Switching from a 2-level virtual to host/physical translation
		system for ARM emulation, to a 1-level translation.
		Trying to switch from 2-level to 1-level for the MIPS bintrans
		system as well (Alpha only, so far), but there is at least one
		problem: caches and/or how they work with device mappings.
20050730	Doing the 2-level to 1-level conversion for the i386 backend.
		The cache/device bug is still there for R2K/3K :(
		Various other minor updates (Malta etc).
		The mc146818 clock now updates the UIP bit in a way which works
		better with Linux for at least sgimips and Malta emulation.
		Beginning the work on refactoring the dyntrans system.
20050731	Continuing the dyntrans refactoring.
		Fixing a small but serious host alignment bug in memory_rw.
		Adding support for big-endian load/stores to the i386 bintrans
		backend.
		Another minor i386 bintrans backend update: stores from the
		zero register are now one (or two) loads shorter.
		The slt and sltu instructions were incorrectly implemented for
		the i386 backend; only using them for 32-bit mode for now.
20050801	Continuing the dyntrans refactoring.
		Cleanup of the ns16550 serial controller (removing unnecessary
		code).
		Bugfix (memory corruption bug) in dev_gt, and a patch/hack from
		Alec Voropay for Linux/Malta.
20050802	More cleanup/refactoring of the dyntrans subsystem: adding
		phys_page pointers to the lookup tables, for quick jumps
		between translated pages.
		Better fix for the ns16550 device (but still no real FIFO
		functionality).
		Converting cpu_ppc to the new dyntrans system. This means that
		I will have to start from scratch with implementing each
		instruction, and figure out how to implement dual 64/32-bit
		modes etc.
		Removing the URISC CPU family, because it was useless.
20050803	When selecting a machine type, the main type can now be omitted
		if the subtype name is unique. (I.e. -E can be omitted.)
		Fixing a dyntrans/device update bug. (Writes to offset 0 of
		a device could sometimes go unnoticed.)
		Adding an experimental "instruction combination" hack for
		ARM for memset-like byte fill loops.
20050804	Minor progress on cpu_alpha and related things.
		Finally fixing the MIPS dmult/dmultu bugs.
		Fixing some minor TODOs.
20050805	Generalizing the 8259 PIC. It now also works with Cobalt
		and evbmips emulation, in addition to the x86 hack.
		Finally converting the ns16550 device to use devinit.
		Continuing the work on the dyntrans system. Thinking about
		how to add breakpoints.
20050806	More dyntrans updates. Breakpoints seem to work now.
20050807	Minor updates: cpu_alpha and related things; removing
		dev_malta (as it isn't used any more).
		Dyntrans: working on general "show trace tree" support.
		The trace tree stuff now works with both the old MIPS code and
		with newer dyntrans modes. :)
		Continuing on Alpha-related stuff (trying to get *BSD to boot
		a bit further, adding more instructions, etc).
20050808	Adding a dummy IA64 cpu family, and continuing the refactoring
		of the dyntrans system.
		Removing the regression test stuff, because it was more or
		less useless.
		Adding loadlinked/storeconditional type instructions to the
		Alpha emulation. (Needed for Linux/alpha. Not very well tested
		yet.)
20050809	The function call trace tree now prints a per-function nr of
		arguments. (Semi-meaningless, since that data isn't read yet
		from the ELFs; some hardcoded symbols such as memcpy() and
		strlen() work fine, though.)
		More dyntrans refactoring; taking out more of the things that
		are common to all cpu families.
20050810	Working on adding support for "dual mode" for PPC dyntrans
		(i.e. both 64-bit and 32-bit modes).
		(Re)adding some simple PPC instructions.
20050811	Adding a dummy M68K cpu family. The dyntrans system isn't ready
		for variable-length ISAs yet, so it's completely bogus so far.
		Re-adding more PPC instructions.
		Adding a hack to src/file.c which allows OpenBSD/mac68k a.out
		kernels to be loaded.
		Beginning to add PPC loads/stores. So far they only work in
		32-bit mode.
20050812	The configure file option "add_remote" now accepts symbolic
		host names, in addition to numeric IPv4 addresses.
		Re-adding more PPC instructions.
20050814	Continuing to port back more PPC instructions.
		Found and fixed the cache/device write-update bug for 32-bit
		MIPS bintrans. :-)
		Triggered a really weird and annoying bug in Compaq's C
		compiler; ccc sometimes outputs code which loads from an
		address _before_ checking whether the pointer was NULL or not.
		(I'm not sure how to handle this problem.)
20050815	Removing all of the old x86 instruction execution code; adding
		a new (dummy) dyntrans module for x86.
		Taking the first steps to extend the dyntrans system to support
		variable-length instructions.
		Slowly preparing for the next release.
20050816	Adding a dummy SPARC cpu module.
		Minor updates (documentation etc) for the release.

==============  RELEASE 0.3.5  ==============


1 /*
2 * Copyright (C) 2003-2005 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.107 2005/08/09 17:18:22 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_ neccessary, 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%016llx ]\n",
703 (long long)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=%llx echild=%llx eparent=%llx\n",
748 (long long)epeer, (long long)echild,
749 (long long)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%016llx as peer "
756 "to 0x%016llx ]\n", (long long)a,
757 (long long)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%016llx as child "
764 "to 0x%016llx ]\n", (long long)a,
765 (long long)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 int 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%016llx "
873 "component=0x%016llx\n",
874 machine->md.arc.n_configuration_data,
875 (long long)machine->md.arc.configuration_data_configdata[
876 machine->md.arc.n_configuration_data],
877 (long long)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%llx\n",
951 (long long)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%llx ]\n",
958 disk_id, (long long)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%016llx): 0x%016llx ]\n",
1243 (long long)cpu->cd.mips.gpr[MIPS_GPR_A0],
1244 (long long)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%016llx): 0x%016llx ]\n",
1294 (long long)cpu->cd.mips.gpr[MIPS_GPR_A0],
1295 (long long)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%016llx): 0x%016llx ]\n",
1343 (long long)cpu->cd.mips.gpr[MIPS_GPR_A0],
1344 (long long)cpu->cd.mips.gpr[MIPS_GPR_V0]);
1345 break;
1346 case 0x30: /* GetConfigurationData(void *configdata, void *node) */
1347 /* fatal("[ ARCBIOS GetConfigurationData(0x%016llx,"
1348 "0x%016llx) ]\n", (long long)cpu->cd.mips.gpr[MIPS_GPR_A0],
1349 (long long)cpu->cd.mips.gpr[MIPS_GPR_A1]); */
1350 cpu->cd.mips.gpr[MIPS_GPR_V0] = ARCBIOS_EINVAL;
1351 for (i=0; i<machine->md.arc.n_configuration_data; i++) {
1352 /* fatal("configuration_data_component[%i] = "
1353 "0x%016llx\n", i, (long long)machine->
1354 md.arc.configuration_data_component[i]); */
1355 if (cpu->cd.mips.gpr[MIPS_GPR_A1] ==
1356 machine->md.arc.configuration_data_component[i]) {
1357 cpu->cd.mips.gpr[MIPS_GPR_V0] = 0;
1358 for (j=0; j<machine->
1359 md.arc.configuration_data_len[i]; j++) {
1360 unsigned char ch;
1361 cpu->memory_rw(cpu, cpu->mem,
1362 machine->md.arc.
1363 configuration_data_configdata[i] +
1364 j, &ch, 1, MEM_READ, CACHE_NONE);
1365 cpu->memory_rw(cpu, cpu->mem,
1366 cpu->cd.mips.gpr[MIPS_GPR_A0] + j,
1367 &ch, 1, MEM_WRITE, CACHE_NONE);
1368 }
1369 break;
1370 }
1371 }
1372 break;
1373 case 0x3c: /* GetComponent(char *name) */
1374 debug("[ ARCBIOS GetComponent(\"");
1375 dump_mem_string(cpu, cpu->cd.mips.gpr[MIPS_GPR_A0]);
1376 debug("\") ]\n");
1377
1378 if (cpu->cd.mips.gpr[MIPS_GPR_A0] == 0) {
1379 fatal("[ ARCBIOS GetComponent: NULL ptr ]\n");
1380 } else {
1381 unsigned char buf[500];
1382 int match_index = -1;
1383 int match_len = 0;
1384
1385 memset(buf, 0, sizeof(buf));
1386 for (i=0; i<sizeof(buf); i++) {
1387 cpu->memory_rw(cpu, cpu->mem,
1388 cpu->cd.mips.gpr[MIPS_GPR_A0] + i,
1389 &buf[i], 1, MEM_READ, CACHE_NONE);
1390 if (buf[i] == '\0')
1391 i = sizeof(buf);
1392 }
1393 buf[sizeof(buf) - 1] = '\0';
1394
1395 /* "scsi(0)disk(0)rdisk(0)partition(0)" and such. */
1396 /* printf("GetComponent(\"%s\")\n", buf); */
1397
1398 /* Default to NULL return value. */
1399 cpu->cd.mips.gpr[MIPS_GPR_V0] = 0;
1400
1401 /* Scan the string to component table: */
1402 for (i=0; i<machine->md.arc.n_string_to_components;
1403 i++) {
1404 int m = 0;
1405 while (buf[m] && machine->md.arc.
1406 string_to_component[i][m] &&
1407 machine->md.arc.string_to_component[i][m]
1408 == buf[m])
1409 m++;
1410 if (m > match_len) {
1411 match_len = m;
1412 match_index = i;
1413 }
1414 }
1415
1416 if (match_index >= 0) {
1417 /* printf("Longest match: '%s'\n",
1418 machine->md.arc.string_to_component[
1419 match_index]); */
1420 cpu->cd.mips.gpr[MIPS_GPR_V0] =
1421 machine->md.arc.string_to_component_value[
1422 match_index];
1423 }
1424 }
1425 break;
1426 case 0x44: /* GetSystemId() */
1427 debug("[ ARCBIOS GetSystemId() ]\n");
1428 cpu->cd.mips.gpr[MIPS_GPR_V0] = SGI_SYSID_ADDR;
1429 break;
1430 case 0x48: /* void *GetMemoryDescriptor(void *ptr) */
1431 debug("[ ARCBIOS GetMemoryDescriptor(0x%08x) ]\n",
1432 (int)cpu->cd.mips.gpr[MIPS_GPR_A0]);
1433
1434 /* If a0=NULL, then return the first descriptor: */
1435 if ((uint32_t)cpu->cd.mips.gpr[MIPS_GPR_A0] == 0)
1436 cpu->cd.mips.gpr[MIPS_GPR_V0] =
1437 machine->md.arc.memdescriptor_base;
1438 else {
1439 int s = machine->md.arc.arc_64bit?
1440 sizeof(struct arcbios_mem64)
1441 : sizeof(struct arcbios_mem);
1442 int nr = cpu->cd.mips.gpr[MIPS_GPR_A0] -
1443 machine->md.arc.memdescriptor_base;
1444 nr /= s;
1445 nr ++;
1446 cpu->cd.mips.gpr[MIPS_GPR_V0] =
1447 machine->md.arc.memdescriptor_base + s * nr;
1448 if (nr >= machine->md.arc.n_memdescriptors)
1449 cpu->cd.mips.gpr[MIPS_GPR_V0] = 0;
1450 }
1451 break;
1452 case 0x50: /* GetTime() */
1453 debug("[ ARCBIOS GetTime() ]\n");
1454 cpu->cd.mips.gpr[MIPS_GPR_V0] = 0xffffffff80001000ULL;
1455 /* TODO! */
1456 break;
1457 case 0x54: /* GetRelativeTime() */
1458 debug("[ ARCBIOS GetRelativeTime() ]\n");
1459 cpu->cd.mips.gpr[MIPS_GPR_V0] = (int64_t)(int32_t)time(NULL);
1460 break;
1461 case 0x5c: /* Open(char *path, uint32_t mode, uint32_t *fileID) */
1462 debug("[ ARCBIOS Open(\"");
1463 dump_mem_string(cpu, cpu->cd.mips.gpr[MIPS_GPR_A0]);
1464 debug("\",0x%x,0x%x)", (int)cpu->cd.mips.gpr[MIPS_GPR_A0],
1465 (int)cpu->cd.mips.gpr[MIPS_GPR_A1],
1466 (int)cpu->cd.mips.gpr[MIPS_GPR_A2]);
1467
1468 cpu->cd.mips.gpr[MIPS_GPR_V0] = ARCBIOS_ENOENT;
1469
1470 handle = 3;
1471 /* TODO: Starting at 0 would require some updates... */
1472 while (machine->md.arc.file_handle_in_use[handle]) {
1473 handle ++;
1474 if (handle >= ARC_MAX_HANDLES) {
1475 cpu->cd.mips.gpr[MIPS_GPR_V0] = ARCBIOS_EMFILE;
1476 break;
1477 }
1478 }
1479
1480 if (handle >= ARC_MAX_HANDLES) {
1481 fatal("[ ARCBIOS Open: out of file handles ]\n");
1482 } else if (cpu->cd.mips.gpr[MIPS_GPR_A0] == 0) {
1483 fatal("[ ARCBIOS Open: NULL ptr ]\n");
1484 } else {
1485 /*
1486 * TODO: This is hardcoded to successfully open
1487 * anything. It is used by the Windows NT SETUPLDR
1488 * program to load stuff from the boot partition.
1489 */
1490 unsigned char *buf = malloc(MAX_OPEN_STRINGLEN);
1491 if (buf == NULL) {
1492 fprintf(stderr, "out of memory\n");
1493 exit(1);
1494 }
1495 memset(buf, 0, MAX_OPEN_STRINGLEN);
1496 for (i=0; i<MAX_OPEN_STRINGLEN; i++) {
1497 cpu->memory_rw(cpu, cpu->mem,
1498 cpu->cd.mips.gpr[MIPS_GPR_A0] + i,
1499 &buf[i], 1, MEM_READ, CACHE_NONE);
1500 if (buf[i] == '\0')
1501 i = MAX_OPEN_STRINGLEN;
1502 }
1503 buf[MAX_OPEN_STRINGLEN - 1] = '\0';
1504 machine->md.arc.file_handle_string[handle] =
1505 (char *)buf;
1506 machine->md.arc.current_seek_offset[handle] = 0;
1507 cpu->cd.mips.gpr[MIPS_GPR_V0] = ARCBIOS_ESUCCESS;
1508 }
1509
1510 if (cpu->cd.mips.gpr[MIPS_GPR_V0] == ARCBIOS_ESUCCESS) {
1511 debug(" = handle %i ]\n", (int)handle);
1512 store_32bit_word(cpu, cpu->cd.mips.gpr[MIPS_GPR_A2],
1513 handle);
1514 machine->md.arc.file_handle_in_use[handle] = 1;
1515 } else
1516 debug(" = ERROR %i ]\n",
1517 (int)cpu->cd.mips.gpr[MIPS_GPR_V0]);
1518 break;
1519 case 0x60: /* Close(uint32_t handle) */
1520 debug("[ ARCBIOS Close(%i) ]\n",
1521 (int)cpu->cd.mips.gpr[MIPS_GPR_A0]);
1522 if (!machine->md.arc.file_handle_in_use[cpu->cd.mips.gpr[
1523 MIPS_GPR_A0]]) {
1524 fatal("ARCBIOS Close(%i): bad handle\n",
1525 (int)cpu->cd.mips.gpr[MIPS_GPR_A0]);
1526 cpu->cd.mips.gpr[MIPS_GPR_V0] = ARCBIOS_EBADF;
1527 } else {
1528 machine->md.arc.file_handle_in_use[
1529 cpu->cd.mips.gpr[MIPS_GPR_A0]] = 0;
1530 if (machine->md.arc.file_handle_string[
1531 cpu->cd.mips.gpr[MIPS_GPR_A0]] != NULL)
1532 free(machine->md.arc.file_handle_string[
1533 cpu->cd.mips.gpr[MIPS_GPR_A0]]);
1534 machine->md.arc.file_handle_string[cpu->cd.mips.
1535 gpr[MIPS_GPR_A0]] = NULL;
1536 cpu->cd.mips.gpr[MIPS_GPR_V0] = ARCBIOS_ESUCCESS;
1537 }
1538 break;
1539 case 0x64: /* Read(handle, void *buf, length, uint32_t *count) */
1540 if (cpu->cd.mips.gpr[MIPS_GPR_A0] == ARCBIOS_STDIN) {
1541 int i, nread = 0;
1542 /*
1543 * Before going into the loop, make sure stdout
1544 * is flushed. If we're using an X11 VGA console,
1545 * then it needs to be flushed as well.
1546 */
1547 fflush(stdin);
1548 fflush(stdout);
1549 /* NOTE/TODO: This gives a tick to _everything_ */
1550 for (i=0; i<machine->n_tick_entries; i++)
1551 machine->tick_func[i](cpu,
1552 machine->tick_extra[i]);
1553
1554 for (i=0; i<cpu->cd.mips.gpr[MIPS_GPR_A2]; i++) {
1555 int x;
1556 unsigned char ch;
1557
1558 /* Read from STDIN is blocking (at least
1559 that seems to be how NetBSD's arcdiag
1560 wants it) */
1561 x = console_readchar(
1562 machine->main_console_handle);
1563 if (x < 0)
1564 return 0;
1565
1566 /*
1567 * ESC + '[' should be transformed into 0x9b:
1568 *
1569 * NOTE/TODO: This makes the behaviour of just
1570 * pressing ESC a bit harder to define.
1571 */
1572 if (x == 27) {
1573 x = console_readchar(cpu->
1574 machine->main_console_handle);
1575 if (x == '[' || x == 'O')
1576 x = 0x9b;
1577 }
1578
1579 ch = x;
1580 nread ++;
1581 cpu->memory_rw(cpu, cpu->mem,
1582 cpu->cd.mips.gpr[MIPS_GPR_A1] + i,
1583 &ch, 1, MEM_WRITE, CACHE_NONE);
1584
1585 /* NOTE: Only one char, from STDIN: */
1586 i = cpu->cd.mips.gpr[MIPS_GPR_A2]; /* :-) */
1587 }
1588 store_32bit_word(cpu, cpu->cd.mips.gpr[MIPS_GPR_A3],
1589 nread);
1590 /* TODO: not EAGAIN? */
1591 cpu->cd.mips.gpr[MIPS_GPR_V0] =
1592 nread? ARCBIOS_ESUCCESS: ARCBIOS_EAGAIN;
1593 } else {
1594 int handle = cpu->cd.mips.gpr[MIPS_GPR_A0];
1595 int disk_type;
1596 int disk_id = arcbios_handle_to_disk_id_and_type(
1597 machine, handle, &disk_type);
1598 uint64_t partition_offset = 0;
1599 int res;
1600 uint64_t size; /* dummy */
1601 unsigned char *tmp_buf;
1602
1603 arcbios_handle_to_start_and_size(machine, handle,
1604 &partition_offset, &size);
1605
1606 debug("[ ARCBIOS Read(%i,0x%08x,0x%08x,0x%08x) ]\n",
1607 (int)cpu->cd.mips.gpr[MIPS_GPR_A0],
1608 (int)cpu->cd.mips.gpr[MIPS_GPR_A1],
1609 (int)cpu->cd.mips.gpr[MIPS_GPR_A2],
1610 (int)cpu->cd.mips.gpr[MIPS_GPR_A3]);
1611
1612 tmp_buf = malloc(cpu->cd.mips.gpr[MIPS_GPR_A2]);
1613 if (tmp_buf == NULL) {
1614 fprintf(stderr, "[ *** Out of memory in "
1615 "arcbios.c, allocating %i bytes ]\n",
1616 (int)cpu->cd.mips.gpr[MIPS_GPR_A2]);
1617 break;
1618 }
1619
1620 res = diskimage_access(machine, disk_id, disk_type,
1621 0, partition_offset + machine->md.arc.
1622 current_seek_offset[handle], tmp_buf,
1623 cpu->cd.mips.gpr[MIPS_GPR_A2]);
1624
1625 /* If the transfer was successful, transfer the
1626 data to emulated memory: */
1627 if (res) {
1628 uint64_t dst = cpu->cd.mips.gpr[MIPS_GPR_A1];
1629 store_buf(cpu, dst, (char *)tmp_buf,
1630 cpu->cd.mips.gpr[MIPS_GPR_A2]);
1631 store_32bit_word(cpu,
1632 cpu->cd.mips.gpr[MIPS_GPR_A3],
1633 cpu->cd.mips.gpr[MIPS_GPR_A2]);
1634 machine->md.arc.current_seek_offset[handle] +=
1635 cpu->cd.mips.gpr[MIPS_GPR_A2];
1636 cpu->cd.mips.gpr[MIPS_GPR_V0] = 0;
1637 } else
1638 cpu->cd.mips.gpr[MIPS_GPR_V0] = ARCBIOS_EIO;
1639 free(tmp_buf);
1640 }
1641 break;
1642 case 0x68: /* GetReadStatus(handle) */
1643 /*
1644 * According to arcbios_tty_getchar() in NetBSD's
1645 * dev/arcbios/arcbios_tty.c, GetReadStatus should
1646 * return 0 if there is something available.
1647 *
1648 * TODO: Error codes are things like ARCBIOS_EAGAIN.
1649 */
1650 if (cpu->cd.mips.gpr[MIPS_GPR_A0] == ARCBIOS_STDIN) {
1651 cpu->cd.mips.gpr[MIPS_GPR_V0] = console_charavail(
1652 machine->main_console_handle)? 0 : 1;
1653 } else {
1654 fatal("[ ARCBIOS GetReadStatus(%i) from "
1655 "something other than STDIN: TODO ]\n",
1656 (int)cpu->cd.mips.gpr[MIPS_GPR_A0]);
1657 /* TODO */
1658 cpu->cd.mips.gpr[MIPS_GPR_V0] = 1;
1659 }
1660 break;
1661 case 0x6c: /* Write(handle, buf, len, &returnlen) */
1662 if (cpu->cd.mips.gpr[MIPS_GPR_A0] != ARCBIOS_STDOUT) {
1663 /*
1664 * TODO: this is just a test
1665 */
1666 int handle = cpu->cd.mips.gpr[MIPS_GPR_A0];
1667 int disk_type;
1668 int disk_id = arcbios_handle_to_disk_id_and_type(
1669 machine, handle, &disk_type);
1670 uint64_t partition_offset = 0;
1671 int res, i;
1672 uint64_t size; /* dummy */
1673 unsigned char *tmp_buf;
1674
1675 arcbios_handle_to_start_and_size(machine,
1676 handle, &partition_offset, &size);
1677
1678 debug("[ ARCBIOS Write(%i,0x%08llx,%i,0x%08llx) ]\n",
1679 (int)cpu->cd.mips.gpr[MIPS_GPR_A0],
1680 (long long)cpu->cd.mips.gpr[MIPS_GPR_A1],
1681 (int)cpu->cd.mips.gpr[MIPS_GPR_A2],
1682 (long long)cpu->cd.mips.gpr[MIPS_GPR_A3]);
1683
1684 tmp_buf = malloc(cpu->cd.mips.gpr[MIPS_GPR_A2]);
1685 if (tmp_buf == NULL) {
1686 fprintf(stderr, "[ *** Out of memory in"
1687 " arcbios.c, allocating %i bytes ]\n",
1688 (int)cpu->cd.mips.gpr[MIPS_GPR_A2]);
1689 break;
1690 }
1691
1692 for (i=0; i<cpu->cd.mips.gpr[MIPS_GPR_A2]; i++)
1693 cpu->memory_rw(cpu, cpu->mem,
1694 cpu->cd.mips.gpr[MIPS_GPR_A1] + i,
1695 &tmp_buf[i], sizeof(char), MEM_READ,
1696 CACHE_NONE);
1697
1698 res = diskimage_access(machine, disk_id, disk_type,
1699 1, partition_offset + machine->md.arc.
1700 current_seek_offset[handle], tmp_buf,
1701 cpu->cd.mips.gpr[MIPS_GPR_A2]);
1702
1703 if (res) {
1704 store_32bit_word(cpu,
1705 cpu->cd.mips.gpr[MIPS_GPR_A3],
1706 cpu->cd.mips.gpr[MIPS_GPR_A2]);
1707 machine->md.arc.current_seek_offset[handle] +=
1708 cpu->cd.mips.gpr[MIPS_GPR_A2];
1709 cpu->cd.mips.gpr[MIPS_GPR_V0] = 0;
1710 } else
1711 cpu->cd.mips.gpr[MIPS_GPR_V0] = ARCBIOS_EIO;
1712 free(tmp_buf);
1713 } else {
1714 for (i=0; i<cpu->cd.mips.gpr[MIPS_GPR_A2]; i++) {
1715 unsigned char ch = '\0';
1716 cpu->memory_rw(cpu, cpu->mem,
1717 cpu->cd.mips.gpr[MIPS_GPR_A1] + i,
1718 &ch, sizeof(ch), MEM_READ, CACHE_NONE);
1719
1720 arcbios_putchar(cpu, ch);
1721 }
1722 }
1723 store_32bit_word(cpu, cpu->cd.mips.gpr[MIPS_GPR_A3],
1724 cpu->cd.mips.gpr[MIPS_GPR_A2]);
1725 cpu->cd.mips.gpr[MIPS_GPR_V0] = 0; /* Success. */
1726 break;
1727 case 0x70: /* Seek(uint32_t handle, int64_t *ofs,
1728 uint32_t whence): uint32_t */
1729 debug("[ ARCBIOS Seek(%i,0x%08llx,%i): ",
1730 (int)cpu->cd.mips.gpr[MIPS_GPR_A0],
1731 (long long)cpu->cd.mips.gpr[MIPS_GPR_A1],
1732 (int)cpu->cd.mips.gpr[MIPS_GPR_A2]);
1733
1734 if (cpu->cd.mips.gpr[MIPS_GPR_A2] != 0) {
1735 fatal("[ ARCBIOS Seek(%i,0x%08llx,%i): "
1736 "UNIMPLEMENTED whence=%i ]\n",
1737 (int)cpu->cd.mips.gpr[MIPS_GPR_A0],
1738 (long long)cpu->cd.mips.gpr[MIPS_GPR_A1],
1739 (int)cpu->cd.mips.gpr[MIPS_GPR_A2],
1740 (int)cpu->cd.mips.gpr[MIPS_GPR_A2]);
1741 }
1742
1743 {
1744 unsigned char buf[8];
1745 uint64_t ofs;
1746 cpu->memory_rw(cpu, cpu->mem,
1747 cpu->cd.mips.gpr[MIPS_GPR_A1], &buf[0],
1748 sizeof(buf), MEM_READ, CACHE_NONE);
1749 if (cpu->byte_order == EMUL_BIG_ENDIAN) {
1750 unsigned char tmp;
1751 tmp = buf[0]; buf[0] = buf[7]; buf[7] = tmp;
1752 tmp = buf[1]; buf[1] = buf[6]; buf[6] = tmp;
1753 tmp = buf[2]; buf[2] = buf[5]; buf[5] = tmp;
1754 tmp = buf[3]; buf[3] = buf[4]; buf[4] = tmp;
1755 }
1756 ofs = buf[0] + (buf[1] << 8) + (buf[2] << 16) +
1757 (buf[3] << 24) + ((uint64_t)buf[4] << 32) +
1758 ((uint64_t)buf[5] << 40) + ((uint64_t)buf[6] << 48)
1759 + ((uint64_t)buf[7] << 56);
1760 machine->md.arc.current_seek_offset[
1761 cpu->cd.mips.gpr[MIPS_GPR_A0]] = ofs;
1762 debug("%016llx ]\n", (long long)ofs);
1763 }
1764
1765 cpu->cd.mips.gpr[MIPS_GPR_V0] = 0; /* Success. */
1766
1767 break;
1768 case 0x78: /* GetEnvironmentVariable(char *) */
1769 /* Find the environment variable given by a0: */
1770 for (i=0; i<sizeof(buf); i++)
1771 cpu->memory_rw(cpu, cpu->mem,
1772 cpu->cd.mips.gpr[MIPS_GPR_A0] + i,
1773 &buf[i], sizeof(char), MEM_READ, CACHE_NONE);
1774 buf[sizeof(buf)-1] = '\0';
1775 debug("[ ARCBIOS GetEnvironmentVariable(\"%s\") ]\n", buf);
1776 for (i=0; i<0x1000; i++) {
1777 /* Matching string at offset i? */
1778 int nmatches = 0;
1779 for (j=0; j<strlen((char *)buf); j++) {
1780 cpu->memory_rw(cpu, cpu->mem,
1781 (uint64_t)(ARC_ENV_STRINGS + i + j),
1782 &ch2, sizeof(char), MEM_READ, CACHE_NONE);
1783 if (ch2 == buf[j])
1784 nmatches++;
1785 }
1786 cpu->memory_rw(cpu, cpu->mem,
1787 (uint64_t)(ARC_ENV_STRINGS + i +
1788 strlen((char *)buf)), &ch2, sizeof(char),
1789 MEM_READ, CACHE_NONE);
1790 if (nmatches == strlen((char *)buf) && ch2 == '=') {
1791 cpu->cd.mips.gpr[MIPS_GPR_V0] =
1792 ARC_ENV_STRINGS + i +
1793 strlen((char *)buf) + 1;
1794 return 1;
1795 }
1796 }
1797 /* Return NULL if string wasn't found. */
1798 cpu->cd.mips.gpr[MIPS_GPR_V0] = 0;
1799 break;
1800 case 0x7c: /* SetEnvironmentVariable(char *, char *) */
1801 debug("[ ARCBIOS SetEnvironmentVariable(\"");
1802 dump_mem_string(cpu, cpu->cd.mips.gpr[MIPS_GPR_A0]);
1803 debug("\",\"");
1804 dump_mem_string(cpu, cpu->cd.mips.gpr[MIPS_GPR_A1]);
1805 debug("\") ]\n");
1806 /* TODO: This is a dummy. */
1807 cpu->cd.mips.gpr[MIPS_GPR_V0] = ARCBIOS_ESUCCESS;
1808 break;
1809 case 0x80: /* GetFileInformation() */
1810 debug("[ ARCBIOS GetFileInformation(%i,0x%x): ",
1811 (int)cpu->cd.mips.gpr[MIPS_GPR_A0],
1812 (int)cpu->cd.mips.gpr[MIPS_GPR_A1]);
1813
1814 if (cpu->cd.mips.gpr[MIPS_GPR_A0] >= ARC_MAX_HANDLES) {
1815 debug("invalid file handle ]\n");
1816 cpu->cd.mips.gpr[MIPS_GPR_V0] = ARCBIOS_EINVAL;
1817 } else if (!machine->md.arc.file_handle_in_use[cpu->cd.
1818 mips.gpr[MIPS_GPR_A0]]) {
1819 debug("file handle not in use! ]\n");
1820 cpu->cd.mips.gpr[MIPS_GPR_V0] = ARCBIOS_EBADF;
1821 } else {
1822 debug("'%s' ]\n", machine->md.arc.file_handle_string[
1823 cpu->cd.mips.gpr[MIPS_GPR_A0]]);
1824 cpu->cd.mips.gpr[MIPS_GPR_V0] =
1825 arcbios_getfileinformation(cpu);
1826 }
1827 break;
1828 case 0x88: /* FlushAllCaches() */
1829 debug("[ ARCBIOS FlushAllCaches(): TODO ]\n");
1830 cpu->cd.mips.gpr[MIPS_GPR_V0] = 0;
1831 break;
1832 case 0x90: /* void *GetDisplayStatus(handle) */
1833 debug("[ ARCBIOS GetDisplayStatus(%i) ]\n",
1834 (int)cpu->cd.mips.gpr[MIPS_GPR_A0]);
1835 /* TODO: handle different values of 'handle'? */
1836 cpu->cd.mips.gpr[MIPS_GPR_V0] = ARC_DSPSTAT_ADDR;
1837 break;
1838 case 0x100:
1839 /*
1840 * Undocumented, used by IRIX.
1841 */
1842 debug("[ ARCBIOS: IRIX 0x100 (?) ]\n");
1843 /* TODO */
1844 cpu->cd.mips.gpr[MIPS_GPR_V0] = 0;
1845 break;
1846 case 0x888:
1847 /*
1848 * Magical crash if there is no exception handling code.
1849 */
1850 fatal("EXCEPTION, but no exception handler installed yet.\n");
1851 quiet_mode = 0;
1852 cpu_register_dump(machine, cpu, 1, 0x1);
1853 cpu->running = 0;
1854 cpu->dead = 1;
1855 break;
1856 default:
1857 quiet_mode = 0;
1858 cpu_register_dump(machine, cpu, 1, 0x1);
1859 debug("a0 points to: ");
1860 dump_mem_string(cpu, cpu->cd.mips.gpr[MIPS_GPR_A0]);
1861 debug("\n");
1862 fatal("ARCBIOS: unimplemented vector 0x%x\n", vector);
1863 cpu->running = 0;
1864 cpu->dead = 1;
1865 }
1866
1867 return 1;
1868 }
1869
1870
1871 /*
1872 * arcbios_set_default_exception_handler():
1873 */
1874 void arcbios_set_default_exception_handler(struct cpu *cpu)
1875 {
1876 /*
1877 * The default exception handlers simply jump to 0xbfc88888,
1878 * which is then taken care of in arcbios_emul() above.
1879 *
1880 * 3c1abfc8 lui k0,0xbfc8
1881 * 375a8888 ori k0,k0,0x8888
1882 * 03400008 jr k0
1883 * 00000000 nop
1884 */
1885 store_32bit_word(cpu, 0xffffffff80000000ULL, 0x3c1abfc8);
1886 store_32bit_word(cpu, 0xffffffff80000004ULL, 0x375a8888);
1887 store_32bit_word(cpu, 0xffffffff80000008ULL, 0x03400008);
1888 store_32bit_word(cpu, 0xffffffff8000000cULL, 0x00000000);
1889
1890 store_32bit_word(cpu, 0xffffffff80000080ULL, 0x3c1abfc8);
1891 store_32bit_word(cpu, 0xffffffff80000084ULL, 0x375a8888);
1892 store_32bit_word(cpu, 0xffffffff80000088ULL, 0x03400008);
1893 store_32bit_word(cpu, 0xffffffff8000008cULL, 0x00000000);
1894
1895 store_32bit_word(cpu, 0xffffffff80000180ULL, 0x3c1abfc8);
1896 store_32bit_word(cpu, 0xffffffff80000184ULL, 0x375a8888);
1897 store_32bit_word(cpu, 0xffffffff80000188ULL, 0x03400008);
1898 store_32bit_word(cpu, 0xffffffff8000018cULL, 0x00000000);
1899 }
1900
1901
1902 /*
1903 * arcbios_add_other_components():
1904 *
1905 * TODO: How should this be synched with the hardware devices
1906 * added in machine.c?
1907 */
1908 static void arcbios_add_other_components(struct machine *machine,
1909 uint64_t system)
1910 {
1911 struct cpu *cpu = machine->cpus[0];
1912
1913 if (machine->machine_type == MACHINE_ARC &&
1914 ( machine->machine_subtype == MACHINE_ARC_NEC_RD94 ||
1915 machine->machine_subtype == MACHINE_ARC_NEC_R94 ||
1916 machine->machine_subtype == MACHINE_ARC_NEC_R96 )) {
1917 uint64_t jazzbus, eisa, other;
1918
1919 jazzbus = arcbios_addchild_manual(cpu,
1920 COMPONENT_CLASS_AdapterClass,
1921 COMPONENT_TYPE_MultiFunctionAdapter,
1922 0, 1, 2, 0, 0xffffffff, "Jazz-Internal Bus",
1923 system, NULL, 0);
1924
1925 switch (machine->machine_subtype) {
1926 case MACHINE_ARC_NEC_RD94:
1927 case MACHINE_ARC_NEC_R94:
1928 if (machine->use_x11)
1929 arcbios_addchild_manual(cpu,
1930 COMPONENT_CLASS_ControllerClass,
1931 COMPONENT_TYPE_DisplayController,
1932 0, 1, 2, 0, 0x0, "10110004",
1933 system, NULL, 0);
1934 break;
1935 case MACHINE_ARC_NEC_R96:
1936 if (machine->use_x11) {
1937 uint64_t x;
1938 x = arcbios_addchild_manual(cpu,
1939 COMPONENT_CLASS_ControllerClass,
1940 COMPONENT_TYPE_DisplayController,
1941 COMPONENT_FLAG_ConsoleOut |
1942 COMPONENT_FLAG_Output,
1943 1, 2, 0, 0x0, "necvdfrb",
1944 jazzbus, NULL, 0);
1945 arcbios_addchild_manual(cpu,
1946 COMPONENT_CLASS_PeripheralClass,
1947 COMPONENT_TYPE_MonitorPeripheral,
1948 COMPONENT_FLAG_ConsoleOut |
1949 COMPONENT_FLAG_Output,
1950 1, 2, 0, 0xffffffff, "640x480",
1951 x, NULL, 0);
1952 }
1953
1954 /* TODO: R[D]94 too? */
1955 eisa = arcbios_addchild_manual(cpu,
1956 COMPONENT_CLASS_AdapterClass,
1957 COMPONENT_TYPE_EISAAdapter,
1958 0, 1, 2, 0, 0xffffffff, "EISA",
1959 system, NULL, 0);
1960
1961 other = arcbios_addchild_manual(cpu,
1962 COMPONENT_CLASS_ControllerClass,
1963 COMPONENT_TYPE_OtherController,
1964 0, 1, 2, 0, 0xffffffff, "NEC1C01",
1965 eisa, NULL, 0);
1966 break;
1967 }
1968 }
1969
1970 if (machine->machine_type == MACHINE_ARC &&
1971 (machine->machine_subtype == MACHINE_ARC_JAZZ_PICA
1972 || machine->machine_subtype == MACHINE_ARC_JAZZ_MAGNUM)) {
1973 uint64_t jazzbus, ali_s3, vxl;
1974 uint64_t diskcontroller, floppy, kbdctl, kbd;
1975 uint64_t ptrctl, ptr, paral, audio;
1976 uint64_t eisa, scsi;
1977 /* uint64_t serial1, serial2; */
1978
1979 jazzbus = arcbios_addchild_manual(cpu,
1980 COMPONENT_CLASS_AdapterClass,
1981 COMPONENT_TYPE_MultiFunctionAdapter,
1982 0, 1, 2, 0, 0xffffffff, "Jazz-Internal Bus",
1983 system, NULL, 0);
1984
1985 /*
1986 * DisplayController, needed by NetBSD:
1987 * TODO: NetBSD still doesn't use it :(
1988 */
1989 switch (machine->machine_subtype) {
1990 case MACHINE_ARC_JAZZ_PICA:
1991 /* Default TLB entries on PICA-61: */
1992
1993 /* 7: 256K, asid: 0x0, v: 0xe1000000,
1994 p0: 0xfff00000(2.VG), p1: 0x0(0..G) */
1995 mips_coproc_tlb_set_entry(cpu, 7, 262144,
1996 0xffffffffe1000000ULL,
1997 0x0fff00000ULL, 0, 1, 0, 0, 0, 1, 0, 2, 0);
1998
1999 /* 8: 64K, asid: 0x0, v: 0xe0000000,
2000 p0: 0x80000000(2DVG), p1: 0x0(0..G) */
2001 mips_coproc_tlb_set_entry(cpu, 8, 65536,
2002 0xffffffffe0000000ULL,
2003 0x080000000ULL, 0, 1, 0, 1, 0, 1, 0, 2, 0);
2004
2005 /* 9: 64K, asid: 0x0, v: 0xe00e0000,
2006 p0: 0x800e0000(2DVG), p1: 0x800f0000(2DVG) */
2007 mips_coproc_tlb_set_entry(cpu, 9, 65536,
2008 (uint64_t)0xffffffffe00e0000ULL,
2009 (uint64_t)0x0800e0000ULL,
2010 (uint64_t)0x0800f0000ULL, 1, 1, 1, 1, 1, 0, 2, 2);
2011
2012 /* 10: 4K, asid: 0x0, v: 0xe0100000,
2013 p0: 0xf0000000(2DVG), p1: 0x0(0..G) */
2014 mips_coproc_tlb_set_entry(cpu, 10, 4096,
2015 (uint64_t)0xffffffffe0100000ULL,
2016 (uint64_t)0x0f0000000ULL, 0,1, 0, 1, 0, 1, 0, 2, 0);
2017
2018 /* 11: 1M, asid: 0x0, v: 0xe0200000,
2019 p0: 0x60000000(2DVG), p1: 0x60100000(2DVG) */
2020 mips_coproc_tlb_set_entry(cpu, 11, 1048576,
2021 0xffffffffe0200000ULL,
2022 0x060000000ULL, 0x060100000ULL,1,1,1,1,1, 0, 2, 2);
2023
2024 /* 12: 1M, asid: 0x0, v: 0xe0400000,
2025 p0: 0x60200000(2DVG), p1: 0x60300000(2DVG) */
2026 mips_coproc_tlb_set_entry(cpu, 12, 1048576,
2027 0xffffffffe0400000ULL, 0x060200000ULL,
2028 0x060300000ULL, 1, 1, 1, 1, 1, 0, 2, 2);
2029
2030 /* 13: 4M, asid: 0x0, v: 0xe0800000,
2031 p0: 0x40000000(2DVG), p1: 0x40400000(2DVG) */
2032 mips_coproc_tlb_set_entry(cpu, 13, 1048576*4,
2033 0xffffffffe0800000ULL, 0x040000000ULL,
2034 0x040400000ULL, 1, 1, 1, 1, 1, 0, 2, 2);
2035
2036 /* 14: 16M, asid: 0x0, v: 0xe2000000,
2037 p0: 0x90000000(2DVG), p1: 0x91000000(2DVG) */
2038 mips_coproc_tlb_set_entry(cpu, 14, 1048576*16,
2039 0xffffffffe2000000ULL, 0x090000000ULL,
2040 0x091000000ULL, 1, 1, 1, 1, 1, 0, 2, 2);
2041
2042 if (machine->use_x11) {
2043 ali_s3 = arcbios_addchild_manual(cpu,
2044 COMPONENT_CLASS_ControllerClass,
2045 COMPONENT_TYPE_DisplayController,
2046 COMPONENT_FLAG_ConsoleOut |
2047 COMPONENT_FLAG_Output,
2048 1, 2, 0, 0xffffffff, "ALI_S3",
2049 jazzbus, NULL, 0);
2050
2051 arcbios_addchild_manual(cpu,
2052 COMPONENT_CLASS_PeripheralClass,
2053 COMPONENT_TYPE_MonitorPeripheral,
2054 COMPONENT_FLAG_ConsoleOut |
2055 COMPONENT_FLAG_Output,
2056 1, 2, 0, 0xffffffff, "1024x768",
2057 ali_s3, NULL, 0);
2058 }
2059 break;
2060 case MACHINE_ARC_JAZZ_MAGNUM:
2061 if (machine->use_x11) {
2062 vxl = arcbios_addchild_manual(cpu,
2063 COMPONENT_CLASS_ControllerClass,
2064 COMPONENT_TYPE_DisplayController,
2065 COMPONENT_FLAG_ConsoleOut |
2066 COMPONENT_FLAG_Output,
2067 1, 2, 0, 0xffffffff, "VXL",
2068 jazzbus, NULL, 0);
2069
2070 arcbios_addchild_manual(cpu,
2071 COMPONENT_CLASS_PeripheralClass,
2072 COMPONENT_TYPE_MonitorPeripheral,
2073 COMPONENT_FLAG_ConsoleOut |
2074 COMPONENT_FLAG_Output,
2075 1, 2, 0, 0xffffffff, "1024x768",
2076 vxl, NULL, 0);
2077 }
2078 break;
2079 }
2080
2081 diskcontroller = arcbios_addchild_manual(cpu,
2082 COMPONENT_CLASS_ControllerClass,
2083 COMPONENT_TYPE_DiskController,
2084 COMPONENT_FLAG_Input | COMPONENT_FLAG_Output,
2085 1, 2, 0, 0xffffffff, "I82077", jazzbus, NULL, 0);
2086
2087 floppy = arcbios_addchild_manual(cpu,
2088 COMPONENT_CLASS_PeripheralClass,
2089 COMPONENT_TYPE_FloppyDiskPeripheral,
2090 COMPONENT_FLAG_Removable |
2091 COMPONENT_FLAG_Input | COMPONENT_FLAG_Output,
2092 1, 2, 0, 0xffffffff, NULL, diskcontroller, NULL, 0);
2093
2094 kbdctl = arcbios_addchild_manual(cpu,
2095 COMPONENT_CLASS_ControllerClass,
2096 COMPONENT_TYPE_KeyboardController,
2097 COMPONENT_FLAG_ConsoleIn | COMPONENT_FLAG_Input,
2098 1, 2, 0, 0xffffffff, "I8742", jazzbus, NULL, 0);
2099
2100 kbd = arcbios_addchild_manual(cpu,
2101 COMPONENT_CLASS_PeripheralClass,
2102 COMPONENT_TYPE_KeyboardPeripheral,
2103 COMPONENT_FLAG_ConsoleIn | COMPONENT_FLAG_Input,
2104 1, 2, 0, 0xffffffff, "PCAT_ENHANCED", kbdctl, NULL, 0);
2105
2106 ptrctl = arcbios_addchild_manual(cpu,
2107 COMPONENT_CLASS_ControllerClass,
2108 COMPONENT_TYPE_PointerController, COMPONENT_FLAG_Input,
2109 1, 2, 0, 0xffffffff, "I8742", jazzbus, NULL, 0);
2110
2111 ptr = arcbios_addchild_manual(cpu,
2112 COMPONENT_CLASS_PeripheralClass,
2113 COMPONENT_TYPE_PointerPeripheral, COMPONENT_FLAG_Input,
2114 1, 2, 0, 0xffffffff, "PS2 MOUSE", ptrctl, NULL, 0);
2115
2116 /* These cause Windows NT to bug out. */
2117 #if 0
2118 serial1 = arcbios_addchild_manual(cpu,
2119 COMPONENT_CLASS_ControllerClass,
2120 COMPONENT_TYPE_SerialController,
2121 COMPONENT_FLAG_Input | COMPONENT_FLAG_Output,
2122 1, 2, 0, 0xffffffff, "COM1", jazzbus, NULL, 0);
2123
2124 serial2 = arcbios_addchild_manual(cpu,
2125 COMPONENT_CLASS_ControllerClass,
2126 COMPONENT_TYPE_SerialController,
2127 COMPONENT_FLAG_Input | COMPONENT_FLAG_Output,
2128 1, 2, 0, 0xffffffff, "COM1", jazzbus, NULL, 0);
2129 #endif
2130
2131 paral = arcbios_addchild_manual(cpu,
2132 COMPONENT_CLASS_ControllerClass,
2133 COMPONENT_TYPE_ParallelController,
2134 COMPONENT_FLAG_Input | COMPONENT_FLAG_Output,
2135 1, 2, 0, 0xffffffff, "LPT1", jazzbus, NULL, 0);
2136
2137 audio = arcbios_addchild_manual(cpu,
2138 COMPONENT_CLASS_ControllerClass,
2139 COMPONENT_TYPE_AudioController,
2140 COMPONENT_FLAG_Input | COMPONENT_FLAG_Output,
2141 1, 2, 0, 0xffffffff, "MAGNUM", jazzbus, NULL, 0);
2142
2143 eisa = arcbios_addchild_manual(cpu,
2144 COMPONENT_CLASS_AdapterClass, COMPONENT_TYPE_EISAAdapter,
2145 0, 1, 2, 0, 0xffffffff, "EISA", system, NULL, 0);
2146
2147 {
2148 unsigned char config[78];
2149 memset(config, 0, sizeof(config));
2150
2151 /* config data version: 1, revision: 2, count: 4 */
2152 config[0] = 0x01; config[1] = 0x00;
2153 config[2] = 0x02; config[3] = 0x00;
2154 config[4] = 0x04; config[5] = 0x00; config[6] = 0x00; config[7] = 0x00;
2155
2156 /*
2157 type: Interrupt
2158 share_disposition: DeviceExclusive, flags: LevelSensitive
2159 level: 4, vector: 22, reserved1: 0
2160 */
2161 config[8] = arc_CmResourceTypeInterrupt;
2162 config[9] = arc_CmResourceShareDeviceExclusive;
2163 config[10] = arc_CmResourceInterruptLevelSensitive;
2164 config[12] = 4;
2165 config[16] = 22;
2166 config[20] = 0;
2167
2168 /*
2169 type: Memory
2170 share_disposition: DeviceExclusive, flags: ReadWrite
2171 start: 0x 0 80002000, length: 0x1000
2172 */
2173 config[24] = arc_CmResourceTypeMemory;
2174 config[25] = arc_CmResourceShareDeviceExclusive;
2175 config[26] = arc_CmResourceMemoryReadWrite;
2176 config[28] = 0x00; config[29] = 0x20; config[30] = 0x00; config[31] = 0x80;
2177 config[32] = 0x00; config[33] = 0x00; config[34] = 0x00; config[35] = 0x00;
2178 config[36] = 0x00; config[37] = 0x10; config[38] = 0x00; config[39] = 0x00;
2179
2180 /*
2181 type: DMA
2182 share_disposition: DeviceExclusive, flags: 0x0
2183 channel: 0, port: 0, reserved1: 0
2184 */
2185 config[40] = arc_CmResourceTypeDMA;
2186 config[41] = arc_CmResourceShareDeviceExclusive;
2187 /* 42..43 = flags, 44,45,46,47 = channel, 48,49,50,51 = port, 52,53,54,55
2188 = reserved */
2189
2190 /* type: DeviceSpecific
2191 share_disposition: DeviceExclusive, flags: 0x0
2192 datasize: 6, reserved1: 0, reserved2: 0
2193 data: [0x1:0x0:0x2:0x0:0x7:0x30]
2194 */
2195 config[56] = arc_CmResourceTypeDeviceSpecific;
2196 config[57] = arc_CmResourceShareDeviceExclusive;
2197 /* 58,59 = flags 60,61,62,63 = data size, 64..71 = reserved */
2198 config[60] = 6;
2199 /* 72..77 = the data */
2200 config[72] = 0x01; config[73] = 0x00; config[74] = 0x02;
2201 config[75] = 0x00; config[76] = 0x07; config[77] = 0x30;
2202 scsi = arcbios_addchild_manual(cpu,
2203 COMPONENT_CLASS_AdapterClass,
2204 COMPONENT_TYPE_SCSIAdapter,
2205 0, 1, 2, 0, 0xffffffff, "ESP216",
2206 system, config, sizeof(config));
2207
2208 arcbios_register_scsicontroller(machine, scsi);
2209 }
2210 }
2211 }
2212
2213
2214 /*
2215 * arcbios_console_init():
2216 *
2217 * Called from machine.c whenever an ARC-based machine is running with
2218 * a graphical VGA-style framebuffer, which can be used as console.
2219 */
2220 void arcbios_console_init(struct machine *machine,
2221 uint64_t vram, uint64_t ctrlregs)
2222 {
2223 machine->md.arc.vgaconsole = 1;
2224
2225 machine->md.arc.console_vram = vram;
2226 machine->md.arc.console_ctrlregs = ctrlregs;
2227 machine->md.arc.console_maxx = ARC_CONSOLE_MAX_X;
2228 machine->md.arc.console_maxy = ARC_CONSOLE_MAX_Y;
2229 machine->md.arc.in_escape_sequence = 0;
2230 machine->md.arc.escape_sequence[0] = '\0';
2231 }
2232
2233
2234 /*
2235 * arcbios_init():
2236 *
2237 * Should be called before any other arcbios function is used. An exception
2238 * is arcbios_console_init(), which may be called before this function.
2239 */
2240 void arcbios_init(struct machine *machine, int is64bit,
2241 uint64_t sgi_ram_offset)
2242 {
2243 int i, alloclen = 20;
2244 char *name;
2245 uint64_t arc_reserved, mem_base, mem_count;
2246 struct cpu *cpu = machine->cpus[0];
2247 struct arcbios_sysid arcbios_sysid;
2248 struct arcbios_dsp_stat arcbios_dsp_stat;
2249 uint64_t system = 0;
2250 struct arcbios_spb arcbios_spb;
2251 struct arcbios_spb_64 arcbios_spb_64;
2252
2253 machine->md.arc.arc_64bit = is64bit;
2254 machine->md.arc.wordlen = is64bit? sizeof(uint64_t) : sizeof(uint32_t);
2255
2256 machine->md.arc.next_component_address = FIRST_ARC_COMPONENT;
2257 machine->md.arc.configuration_data_next_addr = ARC_CONFIG_DATA_ADDR;
2258
2259 if (machine->physical_ram_in_mb < 16)
2260 fprintf(stderr, "WARNING! The ARC platform specification "
2261 "doesn't allow less than 16 MB of RAM. Continuing "
2262 "anyway.\n");
2263
2264 /* File handles 0, 1, and 2 are stdin, stdout, and stderr. */
2265 for (i=0; i<ARC_MAX_HANDLES; i++) {
2266 machine->md.arc.file_handle_in_use[i] = i<3? 1 : 0;
2267 machine->md.arc.file_handle_string[i] = i>=3? NULL :
2268 (i==0? "(stdin)" : (i==1? "(stdout)" : "(stderr)"));
2269 machine->md.arc.current_seek_offset[i] = 0;
2270 }
2271
2272 if (!machine->use_x11)
2273 machine->md.arc.vgaconsole = 0;
2274
2275 if (machine->md.arc.vgaconsole) {
2276 char tmpstr[100];
2277 int x, y;
2278
2279 machine->md.arc.console_curcolor = 0x1f;
2280 for (y=0; y<machine->md.arc.console_maxy; y++)
2281 for (x=0; x<machine->md.arc.console_maxx; x++)
2282 arcbios_putcell(cpu, ' ', x, y);
2283
2284 machine->md.arc.console_curx = 0;
2285 machine->md.arc.console_cury = 0;
2286
2287 arcbios_putstring(cpu, "GXemul");
2288 #ifdef VERSION
2289 arcbios_putstring(cpu, " "VERSION);
2290 #endif
2291 arcbios_putstring(cpu, " ARCBIOS emulation\n");
2292
2293 snprintf(tmpstr, sizeof(tmpstr), "%i cpu%s (%s), %i MB "
2294 "memory\n\n", machine->ncpus, machine->ncpus > 1? "s" : "",
2295 cpu->cd.mips.cpu_type.name,
2296 machine->physical_ram_in_mb);
2297 arcbios_putstring(cpu, tmpstr);
2298 }
2299
2300 arcbios_set_default_exception_handler(cpu);
2301
2302 memset(&arcbios_sysid, 0, sizeof(arcbios_sysid));
2303 if (machine->machine_type == MACHINE_SGI) {
2304 /* Vendor ID, max 8 chars: */
2305 strncpy(arcbios_sysid.VendorId, "SGI", 3);
2306 switch (machine->machine_subtype) {
2307 case 22:
2308 strncpy(arcbios_sysid.ProductId,
2309 "87654321", 8); /* some kind of ID? */
2310 break;
2311 case 32:
2312 strncpy(arcbios_sysid.ProductId, "8", 1);
2313 /* 6 or 8 (?) */
2314 break;
2315 default:
2316 snprintf(arcbios_sysid.ProductId, 8, "IP%i",
2317 machine->machine_subtype);
2318 }
2319 } else {
2320 switch (machine->machine_subtype) {
2321 case MACHINE_ARC_NEC_RD94:
2322 strncpy(arcbios_sysid.VendorId, "NEC W&S", 8);
2323 strncpy(arcbios_sysid.ProductId, "RD94", 4);
2324 break;
2325 case MACHINE_ARC_NEC_R94:
2326 strncpy(arcbios_sysid.VendorId, "NEC W&S", 8);
2327 strncpy(arcbios_sysid.ProductId, "ijkl", 4);
2328 break;
2329 case MACHINE_ARC_NEC_R96:
2330 strncpy(arcbios_sysid.VendorId, "MIPS DUO", 8);
2331 strncpy(arcbios_sysid.ProductId, "blahblah", 8);
2332 break;
2333 case MACHINE_ARC_NEC_R98:
2334 strncpy(arcbios_sysid.VendorId, "NEC W&S", 8);
2335 strncpy(arcbios_sysid.ProductId, "R98", 4);
2336 break;
2337 case MACHINE_ARC_JAZZ_PICA:
2338 strncpy(arcbios_sysid.VendorId, "MIPS MAG", 8);
2339 strncpy(arcbios_sysid.ProductId, "ijkl", 4);
2340 break;
2341 case MACHINE_ARC_JAZZ_MAGNUM:
2342 strncpy(arcbios_sysid.VendorId, "MIPS MAG", 8);
2343 strncpy(arcbios_sysid.ProductId, "ijkl", 4);
2344 break;
2345 case MACHINE_ARC_JAZZ_M700:
2346 strncpy(arcbios_sysid.VendorId, "OLI00000", 8);
2347 strncpy(arcbios_sysid.ProductId, "ijkl", 4);
2348 break;
2349 case MACHINE_ARC_DESKTECH_TYNE:
2350 strncpy(arcbios_sysid.VendorId, "DESKTECH", 8);
2351 strncpy(arcbios_sysid.ProductId, "ijkl", 4);
2352 break;
2353 default:
2354 fatal("error in machine.c sysid\n");
2355 exit(1);
2356 }
2357 }
2358
2359 store_buf(cpu, SGI_SYSID_ADDR, (char *)&arcbios_sysid,
2360 sizeof(arcbios_sysid));
2361
2362 arcbios_get_dsp_stat(cpu, &arcbios_dsp_stat);
2363 store_buf(cpu, ARC_DSPSTAT_ADDR, (char *)&arcbios_dsp_stat,
2364 sizeof(arcbios_dsp_stat));
2365
2366 /*
2367 * The first 12 MBs of RAM are simply reserved... this simplifies
2368 * things a lot. If there's more than 512MB of RAM, it has to be
2369 * split in two, according to the ARC spec. This code creates a
2370 * number of chunks of at most 512MB each.
2371 *
2372 * NOTE: The region of physical address space between 0x10000000 and
2373 * 0x1fffffff (256 - 512 MB) is usually occupied by memory mapped
2374 * devices, so that portion is "lost".
2375 */
2376 machine->md.arc.memdescriptor_base = ARC_MEMDESC_ADDR;
2377
2378 arc_reserved = 0x2000;
2379 if (machine->machine_type == MACHINE_SGI)
2380 arc_reserved = 0x4000;
2381
2382 arcbios_add_memory_descriptor(cpu, 0, arc_reserved,
2383 ARCBIOS_MEM_FirmwarePermanent);
2384 arcbios_add_memory_descriptor(cpu, sgi_ram_offset + arc_reserved,
2385 0x60000-arc_reserved, ARCBIOS_MEM_FirmwareTemporary);
2386
2387 mem_base = 12;
2388 mem_base += sgi_ram_offset / 1048576;
2389
2390 while (mem_base < machine->physical_ram_in_mb+sgi_ram_offset/1048576) {
2391 mem_count = machine->physical_ram_in_mb+sgi_ram_offset/1048576
2392 - mem_base;
2393
2394 /* Skip the 256-512MB region (for devices) */
2395 if (mem_base < 256 && mem_base + mem_count > 256) {
2396 mem_count = 256-mem_base;
2397 }
2398
2399 /* At most 512MB per descriptor (at least the first 512MB
2400 must be separated this way, according to the ARC spec) */
2401 if (mem_count > 512)
2402 mem_count = 512;
2403
2404 arcbios_add_memory_descriptor(cpu, mem_base * 1048576,
2405 mem_count * 1048576, ARCBIOS_MEM_FreeMemory);
2406
2407 mem_base += mem_count;
2408
2409 /* Skip the devices: */
2410 if (mem_base == 256)
2411 mem_base = 512;
2412 }
2413
2414 /*
2415 * Components: (this is an example of what a system could look like)
2416 *
2417 * [System]
2418 * [CPU] (one for each cpu)
2419 * [FPU] (one for each cpu)
2420 * [CPU Caches]
2421 * [Memory]
2422 * [Ethernet]
2423 * [Serial]
2424 * [SCSI]
2425 * [Disk]
2426 *
2427 * Here's a good list of what hardware is in different IP-models:
2428 * http://www.linux-mips.org/archives/linux-mips/2001-03/msg00101.html
2429 */
2430
2431 if (machine->machine_name == NULL)
2432 fatal("ERROR: machine_name == NULL\n");
2433
2434 /* Add the root node: */
2435 switch (machine->machine_type) {
2436 case MACHINE_SGI:
2437 name = malloc(alloclen);
2438 if (name == NULL) {
2439 fprintf(stderr, "out of memory\n");
2440 exit(1);
2441 }
2442 snprintf(name, alloclen, "SGI-IP%i",
2443 machine->machine_subtype);
2444
2445 /* A very special case for IP24 (which identifies itself
2446 as an IP22): */
2447 if (machine->machine_subtype == 24)
2448 snprintf(name, alloclen, "SGI-IP22");
2449 break;
2450 case MACHINE_ARC:
2451 /* ARC: */
2452 switch (machine->machine_subtype) {
2453 case MACHINE_ARC_NEC_RD94:
2454 name = "NEC-RD94";
2455 break;
2456 case MACHINE_ARC_NEC_R94:
2457 name = "NEC-R94";
2458 break;
2459 case MACHINE_ARC_NEC_R96:
2460 name = "NEC-R96";
2461 break;
2462 case MACHINE_ARC_NEC_R98:
2463 name = "NEC-R98";
2464 break;
2465 case MACHINE_ARC_JAZZ_PICA:
2466 name = "PICA-61";
2467 break;
2468 case MACHINE_ARC_JAZZ_MAGNUM:
2469 case MACHINE_ARC_JAZZ_M700:
2470 name = "Microsoft-Jazz";
2471 break;
2472 case MACHINE_ARC_DESKTECH_TYNE:
2473 name = "DESKTECH-TYNE";
2474 break;
2475 default:
2476 fatal("Unimplemented ARC machine type %i\n",
2477 machine->machine_subtype);
2478 exit(1);
2479 }
2480 break;
2481 default:
2482 fatal("ERROR: non-SGI and non-ARC?\n");
2483 exit(1);
2484 }
2485
2486 system = arcbios_addchild_manual(cpu, COMPONENT_CLASS_SystemClass,
2487 COMPONENT_TYPE_ARC, 0,1,2,0, 0xffffffff, name, 0/*ROOT*/, NULL, 0);
2488 debug("ARC system @ 0x%llx (\"%s\")\n", (long long)system, name);
2489
2490
2491 /*
2492 * Add tree nodes for CPUs and their caches:
2493 */
2494
2495 for (i=0; i<machine->ncpus; i++) {
2496 uint64_t cpuaddr, fpu=0, picache, pdcache, sdcache=0;
2497 int cache_size, cache_line_size;
2498 unsigned int jj;
2499 char arc_cpu_name[100];
2500 char arc_fpc_name[105];
2501
2502 snprintf(arc_cpu_name, sizeof(arc_cpu_name),
2503 "MIPS-%s", machine->cpu_name);
2504
2505 if (machine->machine_type == MACHINE_ARC &&
2506 machine->machine_subtype == MACHINE_ARC_NEC_R96)
2507 snprintf(arc_cpu_name, sizeof(arc_cpu_name),
2508 "MIPS-%s - Pr 4/5.0, Fp 5/0", machine->cpu_name);
2509
2510 arc_cpu_name[sizeof(arc_cpu_name)-1] = 0;
2511 for (jj=0; jj<strlen(arc_cpu_name); jj++)
2512 if (arc_cpu_name[jj] >= 'a' && arc_cpu_name[jj] <= 'z')
2513 arc_cpu_name[jj] += ('A' - 'a');
2514
2515 strlcpy(arc_fpc_name, arc_cpu_name, sizeof(arc_fpc_name));
2516 strlcat(arc_fpc_name, "FPC", sizeof(arc_fpc_name));
2517
2518 cpuaddr = arcbios_addchild_manual(cpu,
2519 COMPONENT_CLASS_ProcessorClass, COMPONENT_TYPE_CPU,
2520 0, 1, 2, i, 0xffffffff, arc_cpu_name, system, NULL, 0);
2521
2522 /*
2523 * TODO: This was in the ARC specs, but it isn't really used
2524 * by ARC implementations? At least SGI-IP32 uses it.
2525 */
2526 if (machine->machine_type == MACHINE_SGI)
2527 fpu = arcbios_addchild_manual(cpu,
2528 COMPONENT_CLASS_ProcessorClass, COMPONENT_TYPE_FPU,
2529 0, 1, 2, 0, 0xffffffff, arc_fpc_name, cpuaddr,
2530 NULL, 0);
2531
2532 cache_size = DEFAULT_PCACHE_SIZE - 12;
2533 if (machine->cache_picache)
2534 cache_size = machine->cache_picache - 12;
2535 if (cache_size < 0)
2536 cache_size = 0;
2537
2538 cache_line_size = DEFAULT_PCACHE_LINESIZE;
2539 if (machine->cache_picache_linesize)
2540 cache_line_size = machine->cache_picache_linesize;
2541 if (cache_line_size < 0)
2542 cache_line_size = 0;
2543
2544 picache = arcbios_addchild_manual(cpu,
2545 COMPONENT_CLASS_CacheClass, COMPONENT_TYPE_PrimaryICache,
2546 0, 1, 2,
2547 /*
2548 * Key bits: 0xXXYYZZZZ
2549 * XX is refill-size.
2550 * Cache line size is 1 << YY,
2551 * Cache size is 4KB << ZZZZ.
2552 */
2553 0x01000000 + (cache_line_size << 16) + cache_size,
2554 /* 32 bytes per line, default = 32 KB total */
2555 0xffffffff, NULL, cpuaddr, NULL, 0);
2556
2557 cache_size = DEFAULT_PCACHE_SIZE - 12;
2558 if (machine->cache_pdcache)
2559 cache_size = machine->cache_pdcache - 12;
2560 if (cache_size < 0)
2561 cache_size = 0;
2562
2563 cache_line_size = DEFAULT_PCACHE_LINESIZE;
2564 if (machine->cache_pdcache_linesize)
2565 cache_line_size = machine->cache_pdcache_linesize;
2566 if (cache_line_size < 0)
2567 cache_line_size = 0;
2568
2569 pdcache = arcbios_addchild_manual(cpu,
2570 COMPONENT_CLASS_CacheClass,
2571 COMPONENT_TYPE_PrimaryDCache, 0, 1, 2,
2572 /*
2573 * Key bits: 0xYYZZZZ
2574 * Cache line size is 1 << YY,
2575 * Cache size is 4KB << ZZZZ.
2576 */
2577 0x01000000 + (cache_line_size << 16) + cache_size,
2578 /* 32 bytes per line, default = 32 KB total */
2579 0xffffffff, NULL, cpuaddr, NULL, 0);
2580
2581 if (machine->cache_secondary >= 12) {
2582 cache_size = machine->cache_secondary - 12;
2583
2584 cache_line_size = 6; /* 64 bytes default */
2585 if (machine->cache_secondary_linesize)
2586 cache_line_size = machine->
2587 cache_secondary_linesize;
2588 if (cache_line_size < 0)
2589 cache_line_size = 0;
2590
2591 sdcache = arcbios_addchild_manual(cpu,
2592 COMPONENT_CLASS_CacheClass,
2593 COMPONENT_TYPE_SecondaryDCache, 0, 1, 2,
2594 /*
2595 * Key bits: 0xYYZZZZ
2596 * Cache line size is 1 << YY,
2597 * Cache size is 4KB << ZZZZ.
2598 */
2599 0x01000000 + (cache_line_size << 16) + cache_size,
2600 /* 64 bytes per line, default = 1 MB total */
2601 0xffffffff, NULL, cpuaddr, NULL, 0);
2602 }
2603
2604 debug("ARC cpu%i @ 0x%llx", i, (long long)cpuaddr);
2605
2606 if (fpu != 0)
2607 debug(" (fpu @ 0x%llx)\n", (long long)fpu);
2608 else
2609 debug("\n");
2610
2611 debug(" picache @ 0x%llx, pdcache @ 0x%llx\n",
2612 (long long)picache, (long long)pdcache);
2613
2614 if (machine->cache_secondary >= 12)
2615 debug(" sdcache @ 0x%llx\n",
2616 (long long)sdcache);
2617
2618 if (machine->machine_type == MACHINE_SGI) {
2619 /* TODO: Memory amount (and base address?)! */
2620 uint64_t memory = arcbios_addchild_manual(cpu,
2621 COMPONENT_CLASS_MemoryClass,
2622 COMPONENT_TYPE_MemoryUnit, 0, 1, 2, 0,
2623 0xffffffff, "memory", cpuaddr, NULL, 0);
2624 debug("ARC memory @ 0x%llx\n", (long long)memory);
2625 }
2626 }
2627
2628
2629 /*
2630 * Add other components:
2631 *
2632 * TODO: How should this be synched with the hardware devices
2633 * added in machine.c?
2634 */
2635
2636 arcbios_add_other_components(machine, system);
2637
2638
2639 /*
2640 * Defalt TLB entry for 64-bit SGI machines:
2641 */
2642 if (machine->machine_type == MACHINE_SGI &&
2643 machine->machine_subtype != 12 /* TODO: ugly */ ) {
2644 /* TODO: On which models is this required? */
2645 mips_coproc_tlb_set_entry(cpu, 0, 1048576*16,
2646 0xc000000000000000ULL, 0, 1048576*16, 1,1,1,1,1, 0, 2, 2);
2647 }
2648
2649
2650 /*
2651 * Set up Firmware Vectors:
2652 */
2653 add_symbol_name(&machine->symbol_context,
2654 ARC_FIRMWARE_ENTRIES, 0x10000, "[ARCBIOS entry]", 0, 1);
2655
2656 for (i=0; i<100; i++) {
2657 if (is64bit) {
2658 store_64bit_word(cpu, ARC_FIRMWARE_VECTORS + i*8,
2659 ARC_FIRMWARE_ENTRIES + i*8);
2660 store_64bit_word(cpu, ARC_PRIVATE_VECTORS + i*8,
2661 ARC_PRIVATE_ENTRIES + i*8);
2662 } else {
2663 store_32bit_word(cpu, ARC_FIRMWARE_VECTORS + i*4,
2664 ARC_FIRMWARE_ENTRIES + i*4);
2665 store_32bit_word(cpu, ARC_PRIVATE_VECTORS + i*4,
2666 ARC_PRIVATE_ENTRIES + i*4);
2667 }
2668 }
2669
2670
2671 /*
2672 * Set up the ARC SPD:
2673 */
2674 if (is64bit) {
2675 /* ARCS64 SPD (TODO: This is just a guess) */
2676 memset(&arcbios_spb_64, 0, sizeof(arcbios_spb_64));
2677 store_64bit_word_in_host(cpu, (unsigned char *)
2678 &arcbios_spb_64.SPBSignature, ARCBIOS_SPB_SIGNATURE);
2679 store_16bit_word_in_host(cpu, (unsigned char *)
2680 &arcbios_spb_64.Version, 64);
2681 store_16bit_word_in_host(cpu, (unsigned char *)
2682 &arcbios_spb_64.Revision, 0);
2683 store_64bit_word_in_host(cpu, (unsigned char *)
2684 &arcbios_spb_64.FirmwareVector, ARC_FIRMWARE_VECTORS);
2685 store_buf(cpu, SGI_SPB_ADDR, (char *)&arcbios_spb_64,
2686 sizeof(arcbios_spb_64));
2687 } else {
2688 /* ARCBIOS SPB: (For ARC and 32-bit SGI modes) */
2689 memset(&arcbios_spb, 0, sizeof(arcbios_spb));
2690 store_32bit_word_in_host(cpu, (unsigned char *)
2691 &arcbios_spb.SPBSignature, ARCBIOS_SPB_SIGNATURE);
2692 store_32bit_word_in_host(cpu, (unsigned char *)
2693 &arcbios_spb.SPBLength, sizeof(arcbios_spb));
2694 store_16bit_word_in_host(cpu, (unsigned char *)
2695 &arcbios_spb.Version, 1);
2696 store_16bit_word_in_host(cpu, (unsigned char *)
2697 &arcbios_spb.Revision, machine->machine_type ==
2698 MACHINE_SGI? 10 : 2);
2699 store_32bit_word_in_host(cpu, (unsigned char *)
2700 &arcbios_spb.FirmwareVector, ARC_FIRMWARE_VECTORS);
2701 store_32bit_word_in_host(cpu, (unsigned char *)
2702 &arcbios_spb.FirmwareVectorLength, 100 * 4); /* ? */
2703 store_32bit_word_in_host(cpu, (unsigned char *)
2704 &arcbios_spb.PrivateVector, ARC_PRIVATE_VECTORS);
2705 store_32bit_word_in_host(cpu, (unsigned char *)
2706 &arcbios_spb.PrivateVectorLength, 100 * 4); /* ? */
2707 store_buf(cpu, SGI_SPB_ADDR, (char *)&arcbios_spb,
2708 sizeof(arcbios_spb));
2709 }
2710 }
2711

  ViewVC Help
Powered by ViewVC 1.1.26