/[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 44 - (show annotations)
Mon Oct 8 16:22:56 2007 UTC (16 years, 6 months ago) by dpavlin
File MIME type: text/plain
File size: 91001 byte(s)
++ trunk/HISTORY	(local)
$Id: HISTORY,v 1.1632 2007/09/11 21:46:35 debug Exp $
20070616	Implementing the MIPS32/64 revision 2 "ror" instruction.
20070617	Adding a struct for each physpage which keeps track of which
		ranges within that page (base offset, length) that are
		continuously translatable. When running with native code
		generation enabled (-b), a range is added after each read-
		ahead loop.
		Experimenting with using the physical program counter sample
		data (implemented 20070608) together with the "translatable
		range" information, to figure out which physical address ranges
		would be worth translating to native code (if the number of
		samples falling within a range is above a certain threshold).
20070618	Adding automagic building of .index comment files for
		src/file/, src/promemul/, src src/useremul/ as well.
		Adding a "has been translated" bit to the ranges, so that only
		not-yet-translated ranges will be sampled.
20070619	Moving src/cpu.c and src/memory_rw.c into src/cpus/,
		src/device.c into src/devices/, and src/machine.c into
		src/machines/.
		Creating a skeleton cc/ld native backend module; beginning on
		the function which will detect cc command line, etc.
20070620	Continuing on the native code generation infrastructure.
20070621	Moving src/x11.c and src/console.c into a new src/console/
		subdir (for everything that is console or framebuffer related).
		Moving src/symbol*.c into a new src/symbol/, which should
		contain anything that is symbol handling related.
20070624	Making the program counter sampling threshold a "settings
		variable" (sampling_threshold), i.e. it can now be changed
		during runtime.
		Switching the RELEASE notes format from plain text to HTML.
		If the TMPDIR environment variable is set, it is used instead
		of "/tmp" for temporary files.
		Continuing on the cc/ld backend: simple .c code is generated,
		the compiler and linker are called, etc.
		Adding detection of host architecture to the configure script
		(again), and adding icache invalidation support (only
		implemented for Alpha hosts so far).
20070625	Simplifying the program counter sampling mechanism.
20070626	Removing the cc/ld native code generation stuff, program
		counter sampling, etc; it would not have worked well in the
		general case.
20070627	Removing everything related to native code generation.
20070629	Removing the (practically unusable) support for multiple
		emulations. (The single emulation allowed now still supports
		multiple simultaneous machines, as before.)
		Beginning on PCCTWO and M88K interrupts.
20070723	Adding a dummy skeleton for emulation of M32R processors.
20070901	Fixing a warning found by "gcc version 4.3.0 20070817
		(experimental)" on amd64.
20070905	Removing some more traces of the old "multiple emulations"
		code.
		Also looking in /usr/local/include and /usr/local/lib for
		X11 libs, when running configure.
20070909	Minor updates to the guest OS install instructions, in
		preparation for the NetBSD 4.0 release.
20070918	More testing of NetBSD 4.0 RC1.

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

  ViewVC Help
Powered by ViewVC 1.1.26