/[gxemul]/upstream/0.3.4/src/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 /upstream/0.3.4/src/arcbios.c

Parent Directory Parent Directory | Revision Log Revision Log


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

  ViewVC Help
Powered by ViewVC 1.1.26