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

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

Parent Directory Parent Directory | Revision Log Revision Log


Revision 34 - (show annotations)
Mon Oct 8 16:21:17 2007 UTC (16 years, 5 months ago) by dpavlin
File MIME type: text/plain
File size: 94172 byte(s)
++ trunk/HISTORY	(local)
$Id: HISTORY,v 1.1480 2007/02/19 01:34:42 debug Exp $
20061029	Changing usleep(1) calls in the debugger to usleep(10000)
20061107	Adding a new disk image option (-d o...) which sets the ISO9660
		filesystem base offset; also making some other hacks to allow
		NetBSD/dreamcast and homebrew demos/games to boot directly
		from a filesystem image.
		Moving Dreamcast-specific stuff in the documentation to its
		own page (dreamcast.html).
		Adding a border to the Dreamcast PVR framebuffer.
20061108	Adding a -T command line option (again?), for halting the
		emulator on unimplemented memory accesses.
20061109	Continuing on various SH4 and Dreamcast related things.
		The emulator should now halt on more unimplemented device
		accesses, instead of just printing a warning, forcing me to
		actually implement missing stuff :)
20061111	Continuing on SH4 and Dreamcast stuff.
		Adding a bogus Landisk (SH4) machine mode.
20061112	Implementing some parts of the Dreamcast GDROM device. With
		some ugly hacks, NetBSD can (barely) mount an ISO image.
20061113	NetBSD/dreamcast now starts booting from the Live CD image,
		but crashes randomly quite early on in the boot process.
20061122	Beginning on a skeleton interrupt.h and interrupt.c for the
		new interrupt subsystem.
20061124	Continuing on the new interrupt system; taking the first steps
		to attempt to connect CPUs (SuperH and MIPS) and devices
		(dev_cons and SH4 timer interrupts) to it. Many things will
		probably break from now on.
20061125	Converting dev_ns16550, dev_8253 to the new interrupt system.
		Attempting to begin to convert the ISA bus.
20061130	Incorporating a patch from Brian Foley for the configure
		script, which checks for X11 libs in /usr/X11R6/lib64 (which
		is used on some Linux systems).
20061227	Adding a note in the man page about booting from Dreamcast
		CDROM images (i.e. that no external kernel is needed).
20061229	Continuing on the interrupt system rewrite: beginning to
		convert more devices, adding abort() calls for legacy interrupt
		system calls so that everything now _has_ to be rewritten!
		Almost all machine modes are now completely broken.
20061230	More progress on removing old interrupt code, mostly related
		to the ISA bus + devices, the LCA bus (on AlphaBook1), and
		the Footbridge bus (for CATS). And some minor PCI stuff.
		Connecting the ARM cpu to the new interrupt system.
		The CATS, NetWinder, and QEMU_MIPS machine modes now work with
		the new interrupt system :)
20061231	Connecting PowerPC CPUs to the new interrupt system.
		Making PReP machines (IBM 6050) work again.
		Beginning to convert the GT PCI controller (for e.g. Malta
		and Cobalt emulation). Some things work, but not everything.
		Updating Copyright notices for 2007.
20070101	Converting dev_kn02 from legacy style to devinit; the 3max
		machine mode now works with the new interrupt system :-]
20070105	Beginning to convert the SGI O2 machine to the new interrupt
		system; finally converting O2 (IP32) devices to devinit, etc.
20070106	Continuing on the interrupt system redesign/rewrite; KN01
		(PMAX), KN230, and Dreamcast ASIC interrupts should work again,
		moving out stuff from machine.h and devices.h into the
		corresponding devices, beginning the rewrite of i80321
		interrupts, etc.
20070107	Beginning on the rewrite of Eagle interrupt stuff (PReP, etc).
20070117	Beginning the rewrite of Algor (V3) interrupts (finally
		changing dev_v3 into devinit style).
20070118	Removing the "bus" registry concept from machine.h, because
		it was practically meaningless.
		Continuing on the rewrite of Algor V3 ISA interrupts.
20070121	More work on Algor interrupts; they are now working again,
		well enough to run NetBSD/algor. :-)
20070122	Converting VR41xx (HPCmips) interrupts. NetBSD/hpcmips
		can be installed using the new interrupt system :-)
20070123	Making the testmips mode work with the new interrupt system.
20070127	Beginning to convert DEC5800 devices to devinit, and to the
		new interrupt system.
		Converting Playstation 2 devices to devinit, and converting
		the interrupt system. Also fixing a severe bug: the interrupt
		mask register on Playstation 2 is bitwise _toggled_ on writes.
20070128	Removing the dummy NetGear machine mode and the 8250 device
		(which was only used by the NetGear machine).
		Beginning to convert the MacPPC GC (Grand Central) interrupt
		controller to the new interrupt system.
		Converting Jazz interrupts (PICA61 etc.) to the new interrupt
		system. NetBSD/arc can be installed again :-)
		Fixing the JAZZ timer (hardcoding it at 100 Hz, works with
		NetBSD and it is better than a completely dummy timer as it
		was before).
		Converting dev_mp to the new interrupt system, although I
		haven't had time to actually test it yet.
		Completely removing src/machines/interrupts.c, cpu_interrupt
		and cpu_interrupt_ack in src/cpu.c, and
		src/include/machine_interrupts.h! Adding fatal error messages
		+ abort() in the few places that are left to fix.
		Converting dev_z8530 to the new interrupt system.
		FINALLY removing the md_int struct completely from the
		machine struct.
		SH4 fixes (adding a PADDR invalidation in the ITLB replacement
		code in memory_sh.c); the NetBSD/dreamcast LiveCD now runs
		all the way to the login prompt, and can be interacted with :-)
		Converting the CPC700 controller (PCI and interrupt controller
		for PM/PPC) to the new interrupt system.
20070129	Fixing MACE ISA interrupts (SGI IP32 emulation). Both NetBSD/
		sgimips' and OpenBSD/sgi's ramdisk kernels can now be
		interacted with again.
20070130	Moving out the MIPS multi_lw and _sw instruction combinations
		so that they are auto-generated at compile time instead.
20070131	Adding detection of amd64/x86_64 hosts in the configure script,
		for doing initial experiments (again :-) with native code
		generation.
		Adding a -k command line option to set the size of the dyntrans
		cache, and a -B command line option to disable native code
		generation, even if GXemul was compiled with support for
		native code generation for the specific host CPU architecture.
20070201	Experimenting with a skeleton for native code generation.
		Changing the default behaviour, so that native code generation
		is now disabled by default, and has to be enabled by using
		-b on the command line.
20070202	Continuing the native code generation experiments.
		Making PCI interrupts work for Footbridge again.
20070203	More native code generation experiments.
		Removing most of the native code generation experimental code,
		it does not make sense to include any quick hacks like this.
		Minor cleanup/removal of some more legacy MIPS interrupt code.
20070204	Making i80321 interrupts work again (for NetBSD/evbarm etc.),
		and fixing the timer at 100 Hz.
20070206	Experimenting with removing the wdc interrupt slowness hack.
20070207	Lowering the number of dyntrans TLB entries for MIPS from
		192 to 128, resulting in a minor speed improvement.
		Minor optimization to the code invalidation routine in
		cpu_dyntrans.c.
20070208	Increasing (experimentally) the nr of dyntrans instructions per
		loop from 60 to 120.
20070210	Commenting out (experimentally) the dyntrans_device_danger
		detection in memory_rw.c.
		Changing the testmips and baremips machines to use a revision 2
		MIPS64 CPU by default, instead of revision 1.
		Removing the dummy i960, IA64, x86, AVR32, and HP PA-RISC
		files, the PC bios emulation, and the Olivetti M700 (ARC) and
		db64360 emulation modes.
20070211	Adding an "mp" demo to the demos directory, which tests the
		SMP functionality of the testmips machine.
		Fixing PReP interrupts some more. NetBSD/prep now boots again.
20070216	Adding a "nop workaround" for booting Mach/PMAX to the
		documentation; thanks to Artur Bujdoso for the values.
		Converting more of the MacPPC interrupt stuff to the new
		system.
		Beginning to convert BeBox interrupts to the new system.
		PPC603e should NOT have the PPC_NO_DEC flag! Removing it.
		Correcting BeBox clock speed (it was set to 100 in the NetBSD
		bootinfo block, but should be 33000000/4), allowing NetBSD
		to start without using the (incorrect) PPC_NO_DEC hack.
20070217	Implementing (slow) AltiVec vector loads and stores, allowing
		NetBSD/macppc to finally boot using the GENERIC kernel :-)
		Updating the documentation with install instructions for
		NetBSD/macppc.
20070218-19	Regression testing for the release.

==============  RELEASE 0.4.4  ==============


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

  ViewVC Help
Powered by ViewVC 1.1.26