/[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 22 - (show annotations)
Mon Oct 8 16:19:37 2007 UTC (16 years, 5 months ago) by dpavlin
File MIME type: text/plain
File size: 93728 byte(s)
++ trunk/HISTORY	(local)
$Id: HISTORY,v 1.1121 2006/02/18 21:03:08 debug Exp $
20051126	Cobalt and PReP now work with the 21143 NIC.
		Continuing on Alpha dyntrans things.
		Fixing some more left-shift-by-24 to unsigned.
20051127	Working on OpenFirmware emulation; major cleanup/redesign.
		Progress on MacPPC emulation: NetBSD detects two CPUs (when
		running with -n 2), framebuffer output (for text) works.
		Adding quick-hack Bandit PCI controller and "gc" interrupt
		controller for MacPPC.
20051128	Changing from a Bandit to a Uni-North controller for macppc.
		Continuing on OpenFirmware and MacPPC emulation in general
		(obio controller, and wdc attached to the obio seems to work).
20051129	More work on MacPPC emulation (adding a dummy ADB controller).
		Continuing the PCI bus cleanup (endianness and tag composition)
		and rewriting all PCI controllers' access functions.
20051130	Various minor PPC dyntrans optimizations.
		Manually inlining some parts of the framebuffer redraw routine.
		Slowly beginning the conversion of the old MIPS emulation into
		dyntrans (but this will take quite some time to get right).
		Generalizing quick_pc_to_pointers.
20051201	Documentation update (David Muse has made available a kernel
		which simplifies Debian/DECstation installation).
		Continuing on the ADB bus controller.
20051202	Beginning a rewrite of the Zilog serial controller (dev_zs).
20051203	Continuing on the zs rewrite (now called dev_z8530); conversion
		to devinit style.
		Reworking some of the input-only vs output-only vs input-output
		details of src/console.c, better warning messages, and adding
		a debug dump.
		Removing the concept of "device state"; it wasn't really used.
		Changing some debug output (-vv should now be used to show all
		details about devices and busses; not shown during normal
		startup anymore).
		Beginning on some SPARC instruction disassembly support.
20051204	Minor PPC updates (WALNUT skeleton stuff).
		Continuing on the MIPS dyntrans rewrite.
		More progress on the ADB controller (a keyboard is "detected"
		by NetBSD and OpenBSD).
		Downgrading OpenBSD/arc as a guest OS from "working" to
		"almost working" in the documentation.
		Progress on Algor emulation ("v3" PCI controller).
20051205	Minor updates.
20051207	Sorting devices according to address; this reduces complexity
		of device lookups from O(n) to O(log n) in memory_rw (but no
		real performance increase (yet) in experiments).
20051210	Beginning the work on native dyntrans backends (by making a
		simple skeleton; so far only for Alpha hosts).
20051211	Some very minor SPARC updates.
20051215	Fixing a bug in the MIPS mul (note: not mult) instruction,
		so it also works with non-64-bit emulation. (Thanks to Alec
		Voropay for noticing the problem.)
20051216	More work on the fake/empty/simple/skeleton/whatever backend;
		performance doesn't increase, so this isn't really worth it,
		but it was probably worth it to prepare for a real backend
		later.
20051219	More instr call statistics gathering and analysis stuff.
20051220	Another fix for MIPS 'mul'. Also converting mul and {d,}cl{o,z}
		to dyntrans.
		memory_ppc.c syntax error fix (noticed by Peter Valchev).
		Beginning to move out machines from src/machine.c into
		individual files in src/machines (in a way similar to the
		autodev system for devices).
20051222	Updating the documentation regarding NetBSD/pmax 3.0.
20051223	- " - NetBSD/cats 3.0.
20051225	- " - NetBSD/hpcmips 3.0.
20051226	Continuing on the machine registry redesign.
		Adding support for ARM rrx (33-bit rotate).
		Fixing some signed/unsigned issues (exposed by gcc -W).
20051227	Fixing the bug which prevented a NetBSD/prep 3.0 install kernel
		from starting (triggered when an mtmsr was the last instruction
		on a page). Unfortunately not enough to get the kernel to run
		as well as the 2.1 kernels did.
20051230	Some dyntrans refactoring.
20051231	Continuing on the machine registry redesign.
20060101-10	Continuing... moving more machines. Moving MD interrupt stuff
		from machine.c into a new src/machines/interrupts.c.
20060114	Adding various mvmeppc machine skeletons.
20060115	Continuing on mvme* stuff. NetBSD/mvmeppc prints boot messages
		(for MVME1600) and reaches the root device prompt, but no
		specific hardware devices are emulated yet.
20060116	Minor updates to the mvme1600 emulation mode; the Eagle PCI bus
		seems to work without much modification, and a 21143 can be
		detected, interrupts might work (but untested so far).
		Adding a fake MK48Txx (mkclock) device, for NetBSD/mvmeppc.
20060121	Adding an aux control register for ARM. (A BIG thank you to
		Olivier Houchard for tracking down this bug.)
20060122	Adding more ARM instructions (smulXY), and dev_iq80321_7seg.
20060124	Adding disassembly of more ARM instructions (mia*, mra/mar),
		and some semi-bogus XScale and i80321 registers.
20060201-02	Various minor updates. Moving the last machines out of
		machine.c.
20060204	Adding a -c command line option, for running debugger commands
		before the simulation starts, but after all files have been
		loaded.
		Minor iq80321-related updates.
20060209	Minor hacks (DEVINIT macro, etc).
		Preparing for the generalization of the 64-bit dyntrans address
		translation subsystem.
20060216	Adding ARM ldrd (double-register load).
20060217	Continuing on various ARM-related stuff.
20060218	More progress on the ATA/wdc emulation for NetBSD/iq80321.
		NetBSD/evbarm can now be installed :-)  Updating the docs, etc.
		Continuing on Algor emulation.

==============  RELEASE 0.3.8  ==============


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

  ViewVC Help
Powered by ViewVC 1.1.26