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

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

Parent Directory Parent Directory | Revision Log Revision Log


Revision 42 - (hide annotations)
Mon Oct 8 16:22:32 2007 UTC (16 years, 8 months ago) by dpavlin
File MIME type: text/plain
File size: 91074 byte(s)
++ trunk/HISTORY	(local)
$Id: HISTORY,v 1.1613 2007/06/15 20:11:26 debug Exp $
20070501	Continuing a little on m88k disassembly (control registers,
		more instructions).
		Adding a dummy mvme88k machine mode.
20070502	Re-adding MIPS load/store alignment exceptions.
20070503	Implementing more of the M88K disassembly code.
20070504	Adding disassembly of some more M88K load/store instructions.
		Implementing some relatively simple M88K instructions (br.n,
		xor[.u] imm, and[.u] imm).
20070505	Implementing M88K three-register and, or, xor, and jmp[.n],
		bsr[.n] including function call trace stuff.
		Applying a patch from Bruce M. Simpson which implements the
		SYSCON_BOARD_CPU_CLOCK_FREQ_ID object of the syscon call in
		the yamon PROM emulation.
20070506	Implementing M88K bb0[.n] and bb1[.n], and skeletons for
		ldcr and stcr (although no control regs are implemented yet).
20070509	Found and fixed the bug which caused Linux for QEMU_MIPS to
		stop working in 0.4.5.1: It was a faulty change to the MIPS
		'sc' and 'scd' instructions I made while going through gcc -W
		warnings on 20070428.
20070510	Updating the Linux/QEMU_MIPS section in guestoses.html to
		use mips-test-0.2.tar.gz instead of 0.1.
		A big thank you to Miod Vallat for sending me M88K manuals.
		Implementing more M88K instructions (addu, subu, div[u], mulu,
		ext[u], clr, set, cmp).
20070511	Fixing bugs in the M88K "and" and "and.u" instructions (found
		by comparing against the manual).
		Implementing more M88K instructions (mask[.u], mak, bcnd (auto-
		generated)) and some more control register details.
		Cleanup: Removing the experimental AVR emulation mode and
		corresponding devices; AVR emulation wasn't really meaningful.
		Implementing autogeneration of most M88K loads/stores. The
		rectangle drawing demo (with -O0) for M88K runs :-)
		Beginning on M88K exception handling.
		More M88K instructions: tb0, tb1, rte, sub, jsr[.n].
		Adding some skeleton MVME PROM ("BUG") emulation.
20070512	Fixing a bug in the M88K cmp instruction.
		Adding the M88K lda (scaled register) instruction.
		Fixing bugs in 64-bit (32-bit pairs) M88K loads/stores.
		Removing the unused tick_hz stuff from the machine struct.
		Implementing the M88K xmem instruction. OpenBSD/mvme88k gets
		far enough to display the Copyright banner :-)
		Implementing subu.co (guess), addu.co, addu.ci, ff0, and ff1.
		Adding a dev_mvme187, for MVME187-specific devices/registers.
		OpenBSD/mvme88k prints more boot messages. :)
20070515	Continuing on MVME187 emulation (adding more devices, beginning
		on the CMMUs, etc).
		Adding the M88K and.c, xor.c, and or.c instructions, and making
		sure that mul, div, etc cause exceptions if executed when SFD1
		is disabled.
20070517	Continuing on M88K and MVME187 emulation in general; moving
		the CMMU registers to the CPU struct, separating dev_pcc2 from
		dev_mvme187, and beginning on memory_m88k.c (BATC and PATC).
		Fixing a bug in 64-bit (32-bit pairs) M88K fast stores.
		Implementing the clock part of dev_mk48txx.
		Implementing the M88K fstcr and xcr instructions.
		Implementing m88k_cpu_tlbdump().
		Beginning on the implementation of a separate address space
		for M88K .usr loads/stores.
20070520	Removing the non-working (skeleton) Sandpoint, SonyNEWS, SHARK
		Dnard, and Zaurus machine modes.
		Experimenting with dyntrans to_be_translated read-ahead. It
		seems to give a very small performance increase for MIPS
		emulation, but a large performance degradation for SuperH. Hm.
20070522	Disabling correct SuperH ITLB emulation; it does not seem to be
		necessary in order to let SH4 guest OSes run, and it slows down
		userspace code.
		Implementing "samepage" branches for SuperH emulation, and some
		other minor speed hacks.
20070525	Continuing on M88K memory-related stuff: exceptions, memory
		transaction register contents, etc.
		Implementing the M88K subu.ci instruction.
		Removing the non-working (skeleton) Iyonix machine mode.
		OpenBSD/mvme88k reaches userland :-), starts executing
		/sbin/init's instructions, and issues a few syscalls, before
		crashing.
20070526	Fixing bugs in dev_mk48txx, so that OpenBSD/mvme88k detects
		the correct time-of-day.
		Implementing a generic IRQ controller for the test machines
		(dev_irqc), similar to a proposed patch from Petr Stepan.
		Experimenting some more with translation read-ahead.
		Adding an "expect" script for automated OpenBSD/landisk
		install regression/performance tests.
20070527	Adding a dummy mmEye (SH3) machine mode skeleton.
		FINALLY found the strange M88K bug I have been hunting: I had
		not emulated the SNIP value for exceptions occurring in
		branch delay slots correctly.
		Implementing correct exceptions for 64-bit M88K loads/stores.
		Address to symbol lookups are now disabled when M88K is
		running in usermode (because usermode addresses don't have
		anything to do with supervisor addresses).
20070531	Removing the mmEye machine mode skeleton.
20070604	Some minor code cleanup.
20070605	Moving src/useremul.c into a subdir (src/useremul/), and
		cleaning up some more legacy constructs.
		Adding -Wstrict-aliasing and -fstrict-aliasing detection to
		the configure script.
20070606	Adding a check for broken GCC on Solaris to the configure
		script. (GCC 3.4.3 on Solaris cannot handle static variables
		which are initialized to 0 or NULL. :-/)
		Removing the old (non-working) ARC emulation modes: NEC RD94,
		R94, R96, and R98, and the last traces of Olivetti M700 and
		Deskstation Tyne.
		Removing the non-working skeleton WDSC device (dev_wdsc).
20070607	Thinking about how to use the host's cc + ld at runtime to
		generate native code. (See experiments/native_cc_ld_test.i
		for an example.)
20070608	Adding a program counter sampling timer, which could be useful
		for native code generation experiments.
		The KN02_CSR_NRMMOD bit in the DECstation 5000/200 (KN02) CSR
		should always be set, to allow a 5000/200 PROM to boot.
20070609	Moving out breakpoint details from the machine struct into
		a helper struct, and removing the limit on max nr of
		breakpoints.
20070610	Moving out tick functions into a helper struct as well (which
		also gets rid of the max limit).
20070612	FINALLY figured out why Debian/DECstation stopped working when
		translation read-ahead was enabled: in src/memory_rw.c, the
		call to invalidate_code_translation was made also if the
		memory access was an instruction load (if the page was mapped
		as writable); it shouldn't be called in that case.
20070613	Implementing some more MIPS32/64 revision 2 instructions: di,
		ei, ext, dext, dextm, dextu, and ins.
20070614	Implementing an instruction combination for the NetBSD/arm
		idle loop (making the host not use any cpu if NetBSD/arm
		inside the emulator is not using any cpu).
		Increasing the nr of ARM VPH entries from 128 to 384.
20070615	Removing the ENABLE_arch stuff from the configure script, so
		that all included architectures are included in both release
		and development builds.
		Moving memory related helper functions from misc.c to memory.c.
		Adding preliminary instructions for netbooting NetBSD/pmppc to
		guestoses.html; it doesn't work yet, there are weird timeouts.
		Beginning a total rewrite of the userland emulation modes
		(removing all emulation modes, beginning from scratch with
		NetBSD/MIPS and FreeBSD/Alpha only).
20070616	After fixing a bug in the DEC21143 NIC (the TDSTAT_OWN bit was
		only cleared for the last segment when transmitting, not all
		segments), NetBSD/pmppc boots with root-on-nfs without the
		timeouts. Updating guestoses.html.
		Removing the skeleton PSP (Playstation Portable) mode.
		Moving X11-related stuff in the machine struct into a helper
		struct.
		Cleanup of out-of-memory checks, to use a new CHECK_ALLOCATION
		macro (which prints a meaningful error message).
		Adding a COMMENT to each machine and device (for automagic
		.index comment generation).
		Doing regression testing for the next release.

==============  RELEASE 0.4.6  ==============


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

  ViewVC Help
Powered by ViewVC 1.1.26