/[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 28 - (show annotations)
Mon Oct 8 16:20:26 2007 UTC (16 years, 6 months ago) by dpavlin
File MIME type: text/plain
File size: 94253 byte(s)
++ trunk/HISTORY	(local)
$Id: HISTORY,v 1.1298 2006/07/22 11:27:46 debug Exp $
20060626	Continuing on SPARC emulation (beginning on the 'save'
		instruction, register windows, etc).
20060629	Planning statistics gathering (new -s command line option),
		and renaming speed_tricks to allow_instruction_combinations.
20060630	Some minor manual page updates.
		Various cleanups.
		Implementing the -s command line option.
20060701	FINALLY found the bug which prevented Linux and Ultrix from
		running without the ugly hack in the R2000/R3000 cache isol
		code; it was the phystranslation hint array which was buggy.
		Removing the phystranslation hint code completely, for now.
20060702	Minor dyntrans cleanups; invalidation of physpages now only
		invalidate those parts of a page that have actually been
		translated. (32 parts per page.)
		Some MIPS non-R3000 speed fixes.
		Experimenting with MIPS instruction combination for some
		addiu+bne+sw loops, and sw+sw+sw.
		Adding support (again) for larger-than-4KB pages in MIPS tlbw*.
		Continuing on SPARC emulation: adding load/store instructions.
20060704	Fixing a virtual vs physical page shift bug in the new tlbw*
		implementation. Problem noticed by Jakub Jermar. (Many thanks.)
		Moving rfe and eret to cpu_mips_instr.c, since that is the
		only place that uses them nowadays.
20060705	Removing the BSD license from the "testmachine" include files,
		placing them in the public domain instead; this enables the
		testmachine stuff to be used from projects which are
		incompatible with the BSD license for some reason.
20060707	Adding instruction combinations for the R2000/R3000 L1
		I-cache invalidation code used by NetBSD/pmax 3.0, lui+addiu,
		various branches followed by addiu or nop, and jr ra followed
		by addiu. The time it takes to perform a full NetBSD/pmax R3000
		install on the laptop has dropped from 573 seconds to 539. :-)
20060708	Adding a framebuffer controller device (dev_fbctrl), which so
		far can be used to change the fb resolution during runtime, but
		in the future will also be useful for accelerated block fill/
		copy, and possibly also simplified character output.
		Adding an instruction combination for NetBSD/pmax' strlen.
20060709	Minor fixes: reading raw files in src/file.c wasn't memblock
		aligned, removing buggy multi_sw MIPS instruction combination,
		etc.
20060711	Adding a machine_qemu.c, which contains a "qemu_mips" machine.
		(It mimics QEMU's MIPS machine mode, so that a test kernel
		made for QEMU_MIPS also can run in GXemul... at least to some
		extent.)  Adding a short section about how to run this mode to
		doc/guestoses.html.
20060714	Misc. minor code cleanups.
20060715	Applying a patch which adds getchar() to promemul/yamon.c
		(from Oleksandr Tymoshenko).
		Adding yamon.h from NetBSD, and rewriting yamon.c to use it
		(instead of ugly hardcoded numbers) + some cleanup.
20060716	Found and fixed the bug which broke single-stepping of 64-bit
		programs between 0.4.0 and 0.4.0.1 (caused by too quick
		refactoring and no testing). Hopefully this fix will not
		break too many other things.
20060718	Continuing on the 8253 PIT; it now works with Linux/QEMU_MIPS.
		Re-adding the sw+sw+sw instr comb (the problem was that I had
		ignored endian issues); however, it doesn't seem to give any
		big performance gain.
20060720	Adding a dummy Transputer mode (T414, T800 etc) skeleton (only
		the 'j' and 'ldc' instructions are implemented so far). :-}
20060721	Adding gtreg.h from NetBSD, updating dev_gt.c to use it, plus
		misc. other updates to get Linux 2.6 for evbmips/malta working
		(thanks to Alec Voropay for the details).
		FINALLY found and fixed the bug which made tlbw* for non-R3000
		buggy; it was a reference count problem in the dyntrans core.
20060722	Testing stuff; things seem stable enough for a new release.

==============  RELEASE 0.4.1  ==============


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

  ViewVC Help
Powered by ViewVC 1.1.26