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

Annotation of /trunk/src/arcbios.c

Parent Directory Parent Directory | Revision Log Revision Log


Revision 12 - (hide annotations)
Mon Oct 8 16:18:38 2007 UTC (16 years, 6 months 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 dpavlin 2 /*
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 dpavlin 12 * $Id: arcbios.c,v 1.107 2005/08/09 17:18:22 debug Exp $
29 dpavlin 2 *
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 dpavlin 6 #include "arcbios_other.h"
44 dpavlin 2 #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 dpavlin 6 void arcbios_add_string_to_component(struct machine *machine,
60     char *string, uint64_t component)
61 dpavlin 2 {
62 dpavlin 6 if (machine->md.arc.n_string_to_components >= MAX_STRING_TO_COMPONENT) {
63 dpavlin 2 printf("Too many string-to-component mappings.\n");
64     exit(1);
65     }
66    
67 dpavlin 6 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 dpavlin 2 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 dpavlin 6 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 dpavlin 2 }
83    
84    
85     /*
86     * arcbios_get_dsp_stat():
87     *
88     * Fills in an arcbios_dsp_stat struct with valid data.
89     */
90 dpavlin 6 static void arcbios_get_dsp_stat(struct cpu *cpu,
91     struct arcbios_dsp_stat *dspstat)
92 dpavlin 2 {
93     memset(dspstat, 0, sizeof(struct arcbios_dsp_stat));
94    
95     store_16bit_word_in_host(cpu, (unsigned char *)&dspstat->
96 dpavlin 6 CursorXPosition, cpu->machine->md.arc.console_curx + 1);
97 dpavlin 2 store_16bit_word_in_host(cpu, (unsigned char *)&dspstat->
98 dpavlin 6 CursorYPosition, cpu->machine->md.arc.console_cury + 1);
99 dpavlin 2 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 dpavlin 6 dspstat->ForegroundColor = cpu->machine->md.arc.console_curcolor;
104     dspstat->HighIntensity = cpu->machine->md.arc.console_curcolor ^ 0x08;
105 dpavlin 2 }
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 dpavlin 6 buf[1] = cpu->machine->md.arc.console_curcolor;
116     if (cpu->machine->md.arc.console_reverse)
117 dpavlin 2 buf[1] = ((buf[1] & 0x70) >> 4) | ((buf[1] & 7) << 4)
118     | (buf[1] & 0x88);
119 dpavlin 6 cpu->memory_rw(cpu, cpu->mem, cpu->machine->md.arc.console_vram +
120     2*(x + cpu->machine->md.arc.console_maxx * y),
121 dpavlin 2 &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 dpavlin 6 int i, len = strlen(cpu->machine->md.arc.escape_sequence);
134 dpavlin 2 int row, col, color, code, start, stop;
135     char *p;
136    
137 dpavlin 6 if (cpu->machine->md.arc.escape_sequence[0] != '[')
138 dpavlin 2 return;
139    
140 dpavlin 6 code = cpu->machine->md.arc.escape_sequence[len-1];
141     cpu->machine->md.arc.escape_sequence[len-1] = '\0';
142 dpavlin 2
143     switch (code) {
144     case 'm':
145 dpavlin 6 color = atoi(cpu->machine->md.arc.escape_sequence + 1);
146 dpavlin 2 switch (color) {
147     case 0: /* Default. */
148 dpavlin 6 cpu->machine->md.arc.console_curcolor = 0x1f;
149     cpu->machine->md.arc.console_reverse = 0; break;
150 dpavlin 2 case 1: /* "Bold". */
151 dpavlin 6 cpu->machine->md.arc.console_curcolor |= 0x08; break;
152 dpavlin 2 case 7: /* "Reverse". */
153 dpavlin 6 cpu->machine->md.arc.console_reverse = 1; break;
154 dpavlin 2 case 30: /* Black foreground. */
155 dpavlin 6 cpu->machine->md.arc.console_curcolor &= 0xf0;
156     cpu->machine->md.arc.console_curcolor |= 0x00; break;
157 dpavlin 2 case 31: /* Red foreground. */
158 dpavlin 6 cpu->machine->md.arc.console_curcolor &= 0xf0;
159     cpu->machine->md.arc.console_curcolor |= 0x04; break;
160 dpavlin 2 case 32: /* Green foreground. */
161 dpavlin 6 cpu->machine->md.arc.console_curcolor &= 0xf0;
162     cpu->machine->md.arc.console_curcolor |= 0x02; break;
163 dpavlin 2 case 33: /* Yellow foreground. */
164 dpavlin 6 cpu->machine->md.arc.console_curcolor &= 0xf0;
165     cpu->machine->md.arc.console_curcolor |= 0x06; break;
166 dpavlin 2 case 34: /* Blue foreground. */
167 dpavlin 6 cpu->machine->md.arc.console_curcolor &= 0xf0;
168     cpu->machine->md.arc.console_curcolor |= 0x01; break;
169 dpavlin 2 case 35: /* Red-blue foreground. */
170 dpavlin 6 cpu->machine->md.arc.console_curcolor &= 0xf0;
171     cpu->machine->md.arc.console_curcolor |= 0x05; break;
172 dpavlin 2 case 36: /* Green-blue foreground. */
173 dpavlin 6 cpu->machine->md.arc.console_curcolor &= 0xf0;
174     cpu->machine->md.arc.console_curcolor |= 0x03; break;
175 dpavlin 2 case 37: /* White foreground. */
176 dpavlin 6 cpu->machine->md.arc.console_curcolor &= 0xf0;
177     cpu->machine->md.arc.console_curcolor |= 0x07; break;
178 dpavlin 2 case 40: /* Black background. */
179 dpavlin 6 cpu->machine->md.arc.console_curcolor &= 0x0f;
180     cpu->machine->md.arc.console_curcolor |= 0x00; break;
181 dpavlin 2 case 41: /* Red background. */
182 dpavlin 6 cpu->machine->md.arc.console_curcolor &= 0x0f;
183     cpu->machine->md.arc.console_curcolor |= 0x40; break;
184 dpavlin 2 case 42: /* Green background. */
185 dpavlin 6 cpu->machine->md.arc.console_curcolor &= 0x0f;
186     cpu->machine->md.arc.console_curcolor |= 0x20; break;
187 dpavlin 2 case 43: /* Yellow background. */
188 dpavlin 6 cpu->machine->md.arc.console_curcolor &= 0x0f;
189     cpu->machine->md.arc.console_curcolor |= 0x60; break;
190 dpavlin 2 case 44: /* Blue background. */
191 dpavlin 6 cpu->machine->md.arc.console_curcolor &= 0x0f;
192     cpu->machine->md.arc.console_curcolor |= 0x10; break;
193 dpavlin 2 case 45: /* Red-blue background. */
194 dpavlin 6 cpu->machine->md.arc.console_curcolor &= 0x0f;
195     cpu->machine->md.arc.console_curcolor |= 0x50; break;
196 dpavlin 2 case 46: /* Green-blue background. */
197 dpavlin 6 cpu->machine->md.arc.console_curcolor &= 0x0f;
198     cpu->machine->md.arc.console_curcolor |= 0x30; break;
199 dpavlin 2 case 47: /* White background. */
200 dpavlin 6 cpu->machine->md.arc.console_curcolor &= 0x0f;
201     cpu->machine->md.arc.console_curcolor |= 0x70; break;
202 dpavlin 2 default:fatal("{ handle_esc_seq: color %i }\n", color);
203     }
204     return;
205     case 'H':
206 dpavlin 6 p = strchr(cpu->machine->md.arc.escape_sequence, ';');
207 dpavlin 2 if (p == NULL)
208     return; /* TODO */
209 dpavlin 6 row = atoi(cpu->machine->md.arc.escape_sequence + 1);
210 dpavlin 2 col = atoi(p + 1);
211     if (col < 1)
212     col = 1;
213     if (row < 1)
214     row = 1;
215 dpavlin 6 cpu->machine->md.arc.console_curx = col - 1;
216     cpu->machine->md.arc.console_cury = row - 1;
217 dpavlin 2 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 dpavlin 6 i = atoi(cpu->machine->md.arc.escape_sequence + 1);
225 dpavlin 2 if (i != 0 && i != 2)
226     fatal("{ handle_esc_seq(): %iJ }\n", i);
227     if (i == 0)
228 dpavlin 6 for (col = cpu->machine->md.arc.console_curx;
229     col < cpu->machine->md.arc.console_maxx; col++)
230 dpavlin 2 arcbios_putcell(cpu, ' ', col,
231 dpavlin 6 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 dpavlin 2 arcbios_putcell(cpu, ' ', col, row);
236     return;
237     case 'K':
238 dpavlin 6 col = atoi(cpu->machine->md.arc.escape_sequence + 1);
239 dpavlin 2 /* 2 = clear line to the right. 1 = to the left (?) */
240 dpavlin 6 start = 0; stop = cpu->machine->md.arc.console_curx;
241 dpavlin 2 if (col == 2) {
242 dpavlin 6 start = cpu->machine->md.arc.console_curx;
243     stop = cpu->machine->md.arc.console_maxx - 1;
244 dpavlin 2 }
245     for (i=start; i<=stop; i++)
246 dpavlin 6 arcbios_putcell(cpu, ' ', i,
247     cpu->machine->md.arc.console_cury);
248 dpavlin 2
249     return;
250     }
251    
252     fatal("{ handle_esc_seq(): unimplemented escape sequence: ");
253     for (i=0; i<len; i++) {
254 dpavlin 6 int x = cpu->machine->md.arc.escape_sequence[i];
255 dpavlin 2 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 dpavlin 6 if (cpu->machine->md.arc.console_cury >=
274     cpu->machine->md.arc.console_maxy) {
275 dpavlin 2 unsigned char buf[2];
276     int x, y;
277 dpavlin 6 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 dpavlin 2 cpu->memory_rw(cpu, cpu->mem,
281 dpavlin 6 cpu->machine->md.arc.console_vram +
282     2*(x + cpu->machine->md.arc.
283     console_maxx * (y+1)),
284 dpavlin 2 &buf[0], sizeof(buf), MEM_READ,
285     CACHE_NONE | PHYSICAL);
286     cpu->memory_rw(cpu, cpu->mem,
287 dpavlin 6 cpu->machine->md.arc.console_vram +
288     2*(x + cpu->machine->md.arc.
289     console_maxx * y),
290 dpavlin 2 &buf[0], sizeof(buf), MEM_WRITE,
291     CACHE_NONE | PHYSICAL);
292     }
293    
294 dpavlin 6 cpu->machine->md.arc.console_cury =
295     cpu->machine->md.arc.console_maxy - 1;
296 dpavlin 2
297 dpavlin 6 for (x=0; x<cpu->machine->md.arc.console_maxx; x++)
298     arcbios_putcell(cpu, ' ', x,
299     cpu->machine->md.arc.console_cury);
300 dpavlin 2 }
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 dpavlin 6 if (!cpu->machine->md.arc.vgaconsole) {
316 dpavlin 2 /* 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 dpavlin 6 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 dpavlin 2 len++;
331 dpavlin 6 if (len >= ARC_MAX_ESC)
332     len = ARC_MAX_ESC;
333     cpu->machine->md.arc.escape_sequence[len] = '\0';
334 dpavlin 2 if ((ch >= 'a' && ch <= 'z') ||
335 dpavlin 6 (ch >= 'A' && ch <= 'Z') || len >= ARC_MAX_ESC) {
336 dpavlin 2 handle_esc_seq(cpu);
337 dpavlin 6 cpu->machine->md.arc.in_escape_sequence = 0;
338 dpavlin 2 }
339     } else {
340     if (ch == 27) {
341 dpavlin 6 cpu->machine->md.arc.in_escape_sequence = 1;
342     cpu->machine->md.arc.escape_sequence[0] = '\0';
343 dpavlin 2 } else if (ch == 0x9b) {
344 dpavlin 6 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 dpavlin 2 } else if (ch == '\b') {
348 dpavlin 6 if (cpu->machine->md.arc.console_curx > 0)
349     cpu->machine->md.arc.console_curx --;
350 dpavlin 2 } else if (ch == '\r') {
351 dpavlin 6 cpu->machine->md.arc.console_curx = 0;
352 dpavlin 2 } else if (ch == '\n') {
353 dpavlin 6 cpu->machine->md.arc.console_cury ++;
354 dpavlin 2 } else if (ch == '\t') {
355 dpavlin 6 cpu->machine->md.arc.console_curx =
356     ((cpu->machine->md.arc.console_curx - 1)
357     | 7) + 1;
358 dpavlin 2 /* TODO: Print spaces? */
359     } else {
360     /* Put char: */
361 dpavlin 6 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 dpavlin 2 scroll_if_necessary(cpu);
366     }
367 dpavlin 6 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 dpavlin 2 }
372     }
373    
374     scroll_if_necessary(cpu);
375    
376     /* Update cursor position: */
377 dpavlin 6 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 dpavlin 2 byte = 0x0e;
384 dpavlin 6 cpu->memory_rw(cpu, cpu->mem, cpu->machine->md.arc.
385     console_ctrlregs + 0x14,
386 dpavlin 2 &byte, sizeof(byte), MEM_WRITE, CACHE_NONE | PHYSICAL);
387     byte = (addr >> 8) & 255;
388 dpavlin 6 cpu->memory_rw(cpu, cpu->mem, cpu->machine->md.arc.
389     console_ctrlregs + 0x15,
390 dpavlin 2 &byte, sizeof(byte), MEM_WRITE, CACHE_NONE | PHYSICAL);
391     byte = 0x0f;
392 dpavlin 6 cpu->memory_rw(cpu, cpu->mem, cpu->machine->md.arc.
393     console_ctrlregs + 0x14,
394 dpavlin 2 &byte, sizeof(byte), MEM_WRITE, CACHE_NONE | PHYSICAL);
395     byte = addr & 255;
396 dpavlin 6 cpu->memory_rw(cpu, cpu->mem, cpu->machine->md.arc.
397     console_ctrlregs + 0x15,
398 dpavlin 2 &byte, sizeof(byte), MEM_WRITE, CACHE_NONE | PHYSICAL);
399     }
400    
401    
402     /*
403 dpavlin 6 * 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 dpavlin 2 * arcbios_register_scsicontroller():
417     */
418 dpavlin 6 void arcbios_register_scsicontroller(struct machine *machine,
419     uint64_t scsicontroller_component)
420 dpavlin 2 {
421 dpavlin 6 machine->md.arc.scsicontroller = scsicontroller_component;
422 dpavlin 2 }
423    
424    
425     /*
426     * arcbios_get_scsicontroller():
427     */
428 dpavlin 6 uint64_t arcbios_get_scsicontroller(struct machine *machine)
429 dpavlin 2 {
430 dpavlin 6 return machine->md.arc.scsicontroller;
431 dpavlin 2 }
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 dpavlin 6 if (cpu->machine->md.arc.arc_64bit)
475 dpavlin 2 s = sizeof(arcbios_mem64);
476     else
477     s = sizeof(arcbios_mem);
478    
479 dpavlin 6 memdesc_addr = cpu->machine->md.arc.memdescriptor_base +
480     cpu->machine->md.arc.n_memdescriptors * s;
481 dpavlin 2
482 dpavlin 6 if (cpu->machine->md.arc.arc_64bit) {
483 dpavlin 2 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 dpavlin 6 cpu->machine->md.arc.n_memdescriptors ++;
503 dpavlin 2 }
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 dpavlin 6 struct machine *machine = cpu->machine;
523     uint64_t a = machine->md.arc.next_component_address;
524 dpavlin 2 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 dpavlin 6 n_left = machine->md.arc.n_components;
547 dpavlin 2 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 dpavlin 6 peeraddr + 0 * machine->md.arc.wordlen, &buf[0],
557     sizeof(eparent), MEM_READ, CACHE_NONE);
558 dpavlin 2 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 dpavlin 6 cpu->memory_rw(cpu, cpu->mem, peeraddr + 1 *
566     machine->md.arc.wordlen,
567 dpavlin 2 &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 dpavlin 6 cpu->memory_rw(cpu, cpu->mem, peeraddr + 2 *
576     machine->md.arc.wordlen,
577 dpavlin 2 &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 dpavlin 6 machine->md.arc.next_component_address += 0x30;
635 dpavlin 2
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 dpavlin 6 machine->md.arc.next_component_address +=
641 dpavlin 2 strlen(identifier) + 1;
642     }
643    
644 dpavlin 6 machine->md.arc.next_component_address ++;
645 dpavlin 2
646     /* Round up to next 0x4 bytes: */
647 dpavlin 6 machine->md.arc.next_component_address =
648     ((machine->md.arc.next_component_address - 1) | 3) + 1;
649 dpavlin 2
650 dpavlin 6 machine->md.arc.n_components ++;
651 dpavlin 2
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 dpavlin 6 struct machine *machine = cpu->machine;
673     uint64_t a = machine->md.arc.next_component_address;
674 dpavlin 2 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 dpavlin 6 n_left = machine->md.arc.n_components;
697 dpavlin 2 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 dpavlin 6 peeraddr + 0 * machine->md.arc.wordlen, &buf[0],
707     sizeof(eparent), MEM_READ, CACHE_NONE);
708 dpavlin 2 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 dpavlin 6 cpu->memory_rw(cpu, cpu->mem, peeraddr + 1 *
720     machine->md.arc.wordlen,
721 dpavlin 2 &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 dpavlin 6 cpu->memory_rw(cpu, cpu->mem, peeraddr + 2 *
734     machine->md.arc.wordlen,
735 dpavlin 2 &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 dpavlin 6 store_64bit_word(cpu, peeraddr + 0 *
754     machine->md.arc.wordlen, epeer);
755 dpavlin 2 /* 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 dpavlin 6 store_64bit_word(cpu, peeraddr + 1 *
762     machine->md.arc.wordlen, echild);
763 dpavlin 2 /* 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 dpavlin 6 machine->md.arc.next_component_address += 0x50;
805 dpavlin 2
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 dpavlin 6 machine->md.arc.next_component_address +=
811 dpavlin 2 strlen(identifier) + 1;
812     }
813    
814 dpavlin 6 machine->md.arc.next_component_address ++;
815 dpavlin 2
816     /* Round up to next 0x8 bytes: */
817 dpavlin 6 machine->md.arc.next_component_address =
818     ((machine->md.arc.next_component_address - 1) | 7) + 1;
819 dpavlin 2
820 dpavlin 6 machine->md.arc.n_components ++;
821 dpavlin 2 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 dpavlin 6 struct machine *machine = cpu->machine;
840 dpavlin 2 /* 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 dpavlin 6 if (machine->md.arc.n_configuration_data >= MAX_CONFIG_DATA) {
849 dpavlin 2 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 dpavlin 6 machine->md.arc.configuration_data_next_addr + i,
858 dpavlin 2 &ch, 1, MEM_WRITE, CACHE_NONE);
859     }
860    
861 dpavlin 6 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 dpavlin 2
872     /* printf("& ADDING %i: configdata=0x%016llx "
873 dpavlin 6 "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 dpavlin 2
880 dpavlin 6 machine->md.arc.n_configuration_data ++;
881 dpavlin 2 }
882    
883 dpavlin 6 if (!cpu->machine->md.arc.arc_64bit) {
884 dpavlin 2 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 dpavlin 6 int disk_id, int disk_type, int partition_nr, uint64_t *start,
934     uint64_t *size)
935 dpavlin 2 {
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 dpavlin 6 *size = diskimage_getsize(machine, disk_id, disk_type);
944 dpavlin 2 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 dpavlin 6 res = diskimage_access(machine, disk_id, disk_type, 0, offset,
954 dpavlin 2 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 dpavlin 6 disk_id, (long long)offset);
959 dpavlin 2 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 dpavlin 6 * arcbios_handle_to_disk_id_and_type():
1013 dpavlin 2 */
1014 dpavlin 6 static int arcbios_handle_to_disk_id_and_type(struct machine *machine,
1015     int handle, int *typep)
1016 dpavlin 2 {
1017     int id, cdrom;
1018     char *s;
1019    
1020 dpavlin 6 if (handle < 0 || handle >= ARC_MAX_HANDLES)
1021 dpavlin 2 return -1;
1022    
1023 dpavlin 6 s = machine->md.arc.file_handle_string[handle];
1024 dpavlin 2 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 dpavlin 6 *typep = DISKIMAGE_SCSI;
1036    
1037 dpavlin 2 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 dpavlin 6 char *s = machine->md.arc.file_handle_string[handle];
1051 dpavlin 2 char *s2;
1052 dpavlin 6 int disk_id, disk_type;
1053 dpavlin 2
1054 dpavlin 6 disk_id = arcbios_handle_to_disk_id_and_type(machine,
1055     handle, &disk_type);
1056    
1057     if (disk_id < 0)
1058 dpavlin 2 return;
1059    
1060     /* This works for "partition(0)": */
1061     *start = 0;
1062 dpavlin 6 *size = diskimage_getsize(machine, disk_id, disk_type);
1063 dpavlin 2
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 dpavlin 6 disk_id, disk_type, partition_nr, start, size);
1071 dpavlin 2 }
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 dpavlin 6 struct machine *machine = cpu->machine;
1164 dpavlin 2 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 dpavlin 6 if (machine->md.arc.arc_64bit)
1176 dpavlin 2 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 dpavlin 6 for (i=0; i<machine->ncpus; i++) {
1192     machine->cpus[i]->running = 0;
1193     machine->cpus[i]->dead = 1;
1194 dpavlin 2 }
1195 dpavlin 6 machine->exit_without_entering_debugger = 1;
1196 dpavlin 2 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 dpavlin 6 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 dpavlin 2 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 dpavlin 6 (peer + 3 * machine->md.arc.wordlen) : 0;
1238     if (!machine->md.arc.arc_64bit)
1239 dpavlin 2 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 dpavlin 6 cpu->cd.mips.gpr[MIPS_GPR_V0] = FIRST_ARC_COMPONENT
1250     + machine->md.arc.wordlen * 3;
1251 dpavlin 2 else {
1252     uint64_t child = 0;
1253     cpu->memory_rw(cpu, cpu->mem,
1254 dpavlin 6 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 dpavlin 2 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 dpavlin 6 (child + 3 * machine->md.arc.wordlen) : 0;
1289     if (!machine->md.arc.arc_64bit)
1290 dpavlin 2 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 dpavlin 6 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 dpavlin 2
1306 dpavlin 6 if (machine->md.arc.arc_64bit) {
1307 dpavlin 2 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 dpavlin 6 (parent + 3 * machine->md.arc.wordlen) : 0;
1338     if (!machine->md.arc.arc_64bit)
1339 dpavlin 2 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 dpavlin 6 for (i=0; i<machine->md.arc.n_configuration_data; i++) {
1352 dpavlin 2 /* fatal("configuration_data_component[%i] = "
1353 dpavlin 6 "0x%016llx\n", i, (long long)machine->
1354     md.arc.configuration_data_component[i]); */
1355 dpavlin 2 if (cpu->cd.mips.gpr[MIPS_GPR_A1] ==
1356 dpavlin 6 machine->md.arc.configuration_data_component[i]) {
1357 dpavlin 2 cpu->cd.mips.gpr[MIPS_GPR_V0] = 0;
1358 dpavlin 6 for (j=0; j<machine->
1359     md.arc.configuration_data_len[i]; j++) {
1360 dpavlin 2 unsigned char ch;
1361     cpu->memory_rw(cpu, cpu->mem,
1362 dpavlin 6 machine->md.arc.
1363 dpavlin 2 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 dpavlin 6 for (i=0; i<machine->md.arc.n_string_to_components;
1403     i++) {
1404 dpavlin 2 int m = 0;
1405 dpavlin 6 while (buf[m] && machine->md.arc.
1406     string_to_component[i][m] &&
1407     machine->md.arc.string_to_component[i][m]
1408 dpavlin 2 == 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 dpavlin 6 machine->md.arc.string_to_component[
1419 dpavlin 2 match_index]); */
1420     cpu->cd.mips.gpr[MIPS_GPR_V0] =
1421 dpavlin 6 machine->md.arc.string_to_component_value[
1422 dpavlin 2 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 dpavlin 6 machine->md.arc.memdescriptor_base;
1438 dpavlin 2 else {
1439 dpavlin 6 int s = machine->md.arc.arc_64bit?
1440     sizeof(struct arcbios_mem64)
1441 dpavlin 2 : sizeof(struct arcbios_mem);
1442     int nr = cpu->cd.mips.gpr[MIPS_GPR_A0] -
1443 dpavlin 6 machine->md.arc.memdescriptor_base;
1444 dpavlin 2 nr /= s;
1445     nr ++;
1446     cpu->cd.mips.gpr[MIPS_GPR_V0] =
1447 dpavlin 6 machine->md.arc.memdescriptor_base + s * nr;
1448     if (nr >= machine->md.arc.n_memdescriptors)
1449 dpavlin 2 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 dpavlin 6 while (machine->md.arc.file_handle_in_use[handle]) {
1473 dpavlin 2 handle ++;
1474 dpavlin 6 if (handle >= ARC_MAX_HANDLES) {
1475 dpavlin 2 cpu->cd.mips.gpr[MIPS_GPR_V0] = ARCBIOS_EMFILE;
1476     break;
1477     }
1478     }
1479    
1480 dpavlin 6 if (handle >= ARC_MAX_HANDLES) {
1481 dpavlin 2 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 dpavlin 6 machine->md.arc.file_handle_string[handle] =
1505     (char *)buf;
1506     machine->md.arc.current_seek_offset[handle] = 0;
1507 dpavlin 2 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 dpavlin 6 machine->md.arc.file_handle_in_use[handle] = 1;
1515 dpavlin 2 } 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 dpavlin 6 if (!machine->md.arc.file_handle_in_use[cpu->cd.mips.gpr[
1523     MIPS_GPR_A0]]) {
1524 dpavlin 2 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 dpavlin 6 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 dpavlin 2 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 dpavlin 6 for (i=0; i<machine->n_tick_entries; i++)
1551     machine->tick_func[i](cpu,
1552     machine->tick_extra[i]);
1553 dpavlin 2
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 dpavlin 6 x = console_readchar(
1562     machine->main_console_handle);
1563 dpavlin 2 if (x < 0)
1564     return 0;
1565    
1566     /*
1567     * ESC + '[' should be transformed into 0x9b:
1568     *
1569     * NOTE/TODO: This makes the behaviour of just
1570     * pressing ESC a bit harder to define.
1571     */
1572     if (x == 27) {
1573     x = console_readchar(cpu->
1574     machine->main_console_handle);
1575     if (x == '[' || x == 'O')
1576     x = 0x9b;
1577     }
1578    
1579     ch = x;
1580     nread ++;
1581     cpu->memory_rw(cpu, cpu->mem,
1582     cpu->cd.mips.gpr[MIPS_GPR_A1] + i,
1583     &ch, 1, MEM_WRITE, CACHE_NONE);
1584    
1585     /* NOTE: Only one char, from STDIN: */
1586     i = cpu->cd.mips.gpr[MIPS_GPR_A2]; /* :-) */
1587     }
1588     store_32bit_word(cpu, cpu->cd.mips.gpr[MIPS_GPR_A3],
1589     nread);
1590     /* TODO: not EAGAIN? */
1591     cpu->cd.mips.gpr[MIPS_GPR_V0] =
1592     nread? ARCBIOS_ESUCCESS: ARCBIOS_EAGAIN;
1593     } else {
1594     int handle = cpu->cd.mips.gpr[MIPS_GPR_A0];
1595 dpavlin 6 int disk_type;
1596     int disk_id = arcbios_handle_to_disk_id_and_type(
1597     machine, handle, &disk_type);
1598 dpavlin 2 uint64_t partition_offset = 0;
1599     int res;
1600     uint64_t size; /* dummy */
1601     unsigned char *tmp_buf;
1602    
1603 dpavlin 6 arcbios_handle_to_start_and_size(machine, handle,
1604     &partition_offset, &size);
1605 dpavlin 2
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 dpavlin 6 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 dpavlin 2
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 dpavlin 6 machine->md.arc.current_seek_offset[handle] +=
1635 dpavlin 2 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 dpavlin 6 machine->main_console_handle)? 0 : 1;
1653 dpavlin 2 } else {
1654     fatal("[ ARCBIOS GetReadStatus(%i) from "
1655     "something other than STDIN: TODO ]\n",
1656     (int)cpu->cd.mips.gpr[MIPS_GPR_A0]);
1657     /* TODO */
1658     cpu->cd.mips.gpr[MIPS_GPR_V0] = 1;
1659     }
1660     break;
1661     case 0x6c: /* Write(handle, buf, len, &returnlen) */
1662     if (cpu->cd.mips.gpr[MIPS_GPR_A0] != ARCBIOS_STDOUT) {
1663     /*
1664     * TODO: this is just a test
1665     */
1666     int handle = cpu->cd.mips.gpr[MIPS_GPR_A0];
1667 dpavlin 6 int disk_type;
1668     int disk_id = arcbios_handle_to_disk_id_and_type(
1669     machine, handle, &disk_type);
1670 dpavlin 2 uint64_t partition_offset = 0;
1671     int res, i;
1672     uint64_t size; /* dummy */
1673     unsigned char *tmp_buf;
1674    
1675 dpavlin 6 arcbios_handle_to_start_and_size(machine,
1676 dpavlin 2 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 dpavlin 6 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 dpavlin 2
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 dpavlin 6 machine->md.arc.current_seek_offset[handle] +=
1708 dpavlin 2 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 dpavlin 6 machine->md.arc.current_seek_offset[
1761 dpavlin 2 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 dpavlin 6 if (cpu->cd.mips.gpr[MIPS_GPR_A0] >= ARC_MAX_HANDLES) {
1815 dpavlin 2 debug("invalid file handle ]\n");
1816     cpu->cd.mips.gpr[MIPS_GPR_V0] = ARCBIOS_EINVAL;
1817 dpavlin 6 } else if (!machine->md.arc.file_handle_in_use[cpu->cd.
1818     mips.gpr[MIPS_GPR_A0]]) {
1819 dpavlin 2 debug("file handle not in use! ]\n");
1820     cpu->cd.mips.gpr[MIPS_GPR_V0] = ARCBIOS_EBADF;
1821     } else {
1822 dpavlin 6 debug("'%s' ]\n", machine->md.arc.file_handle_string[
1823 dpavlin 2 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 dpavlin 6 cpu_register_dump(machine, cpu, 1, 0x1);
1853 dpavlin 2 cpu->running = 0;
1854     cpu->dead = 1;
1855     break;
1856     default:
1857     quiet_mode = 0;
1858 dpavlin 6 cpu_register_dump(machine, cpu, 1, 0x1);
1859 dpavlin 2 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 dpavlin 6 * 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 dpavlin 2 * arcbios_init():
2236     *
2237 dpavlin 6 * 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 dpavlin 2 */
2240 dpavlin 6 void arcbios_init(struct machine *machine, int is64bit,
2241     uint64_t sgi_ram_offset)
2242 dpavlin 2 {
2243 dpavlin 6 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 dpavlin 2
2253 dpavlin 6 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 dpavlin 2 /* File handles 0, 1, and 2 are stdin, stdout, and stderr. */
2265 dpavlin 6 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 dpavlin 2 }
2271 dpavlin 6
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 dpavlin 10 snprintf(tmpstr, sizeof(tmpstr), "%i cpu%s (%s), %i MB "
2294     "memory\n\n", machine->ncpus, machine->ncpus > 1? "s" : "",
2295 dpavlin 6 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 dpavlin 10 snprintf(name, alloclen, "SGI-IP22");
2449 dpavlin 6 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 dpavlin 10 strlcpy(arc_fpc_name, arc_cpu_name, sizeof(arc_fpc_name));
2516     strlcat(arc_fpc_name, "FPC", sizeof(arc_fpc_name));
2517 dpavlin 6
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 dpavlin 12 if (machine->machine_type == MACHINE_SGI &&
2643     machine->machine_subtype != 12 /* TODO: ugly */ ) {
2644 dpavlin 6 /* 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 dpavlin 12 ARC_FIRMWARE_ENTRIES, 0x10000, "[ARCBIOS entry]", 0, 1);
2655 dpavlin 6
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 dpavlin 2 }
2711    

  ViewVC Help
Powered by ViewVC 1.1.26