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

Parent Directory Parent Directory | Revision Log Revision Log


Revision 5 - (show annotations)
Mon Oct 8 16:18:06 2007 UTC (16 years, 7 months ago) by dpavlin
File MIME type: text/plain
File size: 58580 byte(s)
0.3.2
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.96 2005/03/20 11:11:39 debug Exp $
29 *
30 * ARCBIOS emulation.
31 *
32 * This whole file is a mess.
33 *
34 * TODO: Fix.
35 *
36 * TODO: FACTOR OUT COMMON PARTS OF THE 64-bit and 32-bit stuff!!
37 */
38
39 #include <stdio.h>
40 #include <stdlib.h>
41 #include <string.h>
42 #include <time.h>
43 #include <unistd.h>
44 #include <sys/time.h>
45 #include <sys/types.h>
46 #include <sys/resource.h>
47
48 #include "arcbios.h"
49 #include "console.h"
50 #include "cpu.h"
51 #include "cpu_mips.h"
52 #include "diskimage.h"
53 #include "machine.h"
54 #include "memory.h"
55 #include "misc.h"
56
57
58 extern int quiet_mode;
59
60
61 /*
62 * TODO: all this should be _per machine_!
63 */
64
65 /* Configuration data: */
66 #define MAX_CONFIG_DATA 50
67 static int n_configuration_data = 0;
68 static uint64_t configuration_data_next_addr = ARC_CONFIG_DATA_ADDR;
69 static uint64_t configuration_data_component[MAX_CONFIG_DATA];
70 static int configuration_data_len[MAX_CONFIG_DATA];
71 static uint64_t configuration_data_configdata[MAX_CONFIG_DATA];
72
73 static int arc_64bit = 0; /* For some SGI modes */
74 static int arc_wordlen = sizeof(uint32_t);
75
76 static uint64_t scsicontroller = 0;
77
78 static int arc_n_memdescriptors = 0;
79 static uint64_t arcbios_memdescriptor_base = ARC_MEMDESC_ADDR;
80
81 static uint64_t arcbios_next_component_address = FIRST_ARC_COMPONENT;
82 static int n_arc_components = 0;
83
84 static uint64_t arcbios_console_vram = 0;
85 static uint64_t arcbios_console_ctrlregs = 0;
86 #define MAX_ESC 16
87 static char arcbios_escape_sequence[MAX_ESC+1];
88 static int arcbios_in_escape_sequence;
89 static int arcbios_console_maxx, arcbios_console_maxy;
90 int arcbios_console_curx = 0, arcbios_console_cury = 0;
91 static int arcbios_console_reverse = 0;
92 int arcbios_console_curcolor = 0x1f;
93
94 /* Open file handles: */
95 #define MAX_OPEN_STRINGLEN 200
96 #define MAX_HANDLES 10
97 static int file_handle_in_use[MAX_HANDLES];
98 static unsigned char *file_handle_string[MAX_HANDLES];
99 static uint64_t arcbios_current_seek_offset[MAX_HANDLES];
100
101 #define MAX_STRING_TO_COMPONENT 20
102 static char *arcbios_string_to_component[MAX_STRING_TO_COMPONENT];
103 static uint64_t arcbios_string_to_component_value[MAX_STRING_TO_COMPONENT];
104 static int arcbios_n_string_to_components = 0;
105
106
107 /*
108 * arcbios_add_string_to_component():
109 */
110 void arcbios_add_string_to_component(char *string, uint64_t component)
111 {
112 if (arcbios_n_string_to_components >= MAX_STRING_TO_COMPONENT) {
113 printf("Too many string-to-component mappings.\n");
114 exit(1);
115 }
116
117 arcbios_string_to_component[arcbios_n_string_to_components] =
118 strdup(string);
119 if (arcbios_string_to_component[arcbios_n_string_to_components] ==
120 NULL) {
121 fprintf(stderr, "out of memory in "
122 "arcbios_add_string_to_component()\n");
123 exit(1);
124 }
125 debug("adding ARC component mapping: 0x%08x = %s\n",
126 (int)component, string);
127
128 arcbios_string_to_component_value[arcbios_n_string_to_components] =
129 component;
130 arcbios_n_string_to_components ++;
131 }
132
133
134 /*
135 * arcbios_get_dsp_stat():
136 *
137 * Fills in an arcbios_dsp_stat struct with valid data.
138 */
139 void arcbios_get_dsp_stat(struct cpu *cpu, struct arcbios_dsp_stat *dspstat)
140 {
141 memset(dspstat, 0, sizeof(struct arcbios_dsp_stat));
142
143 store_16bit_word_in_host(cpu, (unsigned char *)&dspstat->
144 CursorXPosition, arcbios_console_curx + 1);
145 store_16bit_word_in_host(cpu, (unsigned char *)&dspstat->
146 CursorYPosition, arcbios_console_cury + 1);
147 store_16bit_word_in_host(cpu, (unsigned char *)&dspstat->
148 CursorMaxXPosition, ARC_CONSOLE_MAX_X);
149 store_16bit_word_in_host(cpu, (unsigned char *)&dspstat->
150 CursorMaxYPosition, ARC_CONSOLE_MAX_Y);
151 dspstat->ForegroundColor = arcbios_console_curcolor;
152 dspstat->HighIntensity = arcbios_console_curcolor ^ 0x08;
153 }
154
155
156 /*
157 * arcbios_putcell():
158 */
159 static void arcbios_putcell(struct cpu *cpu, int ch, int x, int y)
160 {
161 unsigned char buf[2];
162 buf[0] = ch;
163 buf[1] = arcbios_console_curcolor;
164 if (arcbios_console_reverse)
165 buf[1] = ((buf[1] & 0x70) >> 4) | ((buf[1] & 7) << 4)
166 | (buf[1] & 0x88);
167 cpu->memory_rw(cpu, cpu->mem, arcbios_console_vram +
168 2*(x + arcbios_console_maxx * y),
169 &buf[0], sizeof(buf), MEM_WRITE,
170 CACHE_NONE | PHYSICAL);
171 }
172
173
174 /*
175 * arcbios_console_init():
176 *
177 * Called from machine.c whenever an ARC-based machine is running with
178 * a graphical VGA-style framebuffer, which can be used as console.
179 */
180 void arcbios_console_init(struct cpu *cpu,
181 uint64_t vram, uint64_t ctrlregs, int maxx, int maxy)
182 {
183 int x, y;
184
185 arcbios_console_vram = vram;
186 arcbios_console_ctrlregs = ctrlregs;
187 arcbios_console_maxx = maxx;
188 arcbios_console_maxy = maxy;
189 arcbios_in_escape_sequence = 0;
190 arcbios_escape_sequence[0] = '\0';
191 arcbios_console_curcolor = 0x1f;
192
193 for (y=1; y<arcbios_console_maxy; y++)
194 for (x=0; x<arcbios_console_maxx; x++)
195 arcbios_putcell(cpu, ' ', x, y);
196
197 arcbios_console_curx = 0;
198 arcbios_console_cury = 1;
199 }
200
201
202 /*
203 * handle_esc_seq():
204 *
205 * Used by arcbios_putchar().
206 */
207 static void handle_esc_seq(struct cpu *cpu)
208 {
209 int i, len = strlen(arcbios_escape_sequence);
210 int row, col, color, code, start, stop;
211 char *p;
212
213 if (arcbios_escape_sequence[0] != '[')
214 return;
215
216 code = arcbios_escape_sequence[len-1];
217 arcbios_escape_sequence[len-1] = '\0';
218
219 switch (code) {
220 case 'm':
221 color = atoi(arcbios_escape_sequence + 1);
222 switch (color) {
223 case 0: /* Default. */
224 arcbios_console_curcolor = 0x1f;
225 arcbios_console_reverse = 0; break;
226 case 1: /* "Bold". */
227 arcbios_console_curcolor |= 0x08; break;
228 case 7: /* "Reverse". */
229 arcbios_console_reverse = 1; break;
230 case 30: /* Black foreground. */
231 arcbios_console_curcolor &= 0xf0;
232 arcbios_console_curcolor |= 0x00; break;
233 case 31: /* Red foreground. */
234 arcbios_console_curcolor &= 0xf0;
235 arcbios_console_curcolor |= 0x04; break;
236 case 32: /* Green foreground. */
237 arcbios_console_curcolor &= 0xf0;
238 arcbios_console_curcolor |= 0x02; break;
239 case 33: /* Yellow foreground. */
240 arcbios_console_curcolor &= 0xf0;
241 arcbios_console_curcolor |= 0x06; break;
242 case 34: /* Blue foreground. */
243 arcbios_console_curcolor &= 0xf0;
244 arcbios_console_curcolor |= 0x01; break;
245 case 35: /* Red-blue foreground. */
246 arcbios_console_curcolor &= 0xf0;
247 arcbios_console_curcolor |= 0x05; break;
248 case 36: /* Green-blue foreground. */
249 arcbios_console_curcolor &= 0xf0;
250 arcbios_console_curcolor |= 0x03; break;
251 case 37: /* White foreground. */
252 arcbios_console_curcolor &= 0xf0;
253 arcbios_console_curcolor |= 0x07; break;
254 case 40: /* Black background. */
255 arcbios_console_curcolor &= 0x0f;
256 arcbios_console_curcolor |= 0x00; break;
257 case 41: /* Red background. */
258 arcbios_console_curcolor &= 0x0f;
259 arcbios_console_curcolor |= 0x40; break;
260 case 42: /* Green background. */
261 arcbios_console_curcolor &= 0x0f;
262 arcbios_console_curcolor |= 0x20; break;
263 case 43: /* Yellow background. */
264 arcbios_console_curcolor &= 0x0f;
265 arcbios_console_curcolor |= 0x60; break;
266 case 44: /* Blue background. */
267 arcbios_console_curcolor &= 0x0f;
268 arcbios_console_curcolor |= 0x10; break;
269 case 45: /* Red-blue background. */
270 arcbios_console_curcolor &= 0x0f;
271 arcbios_console_curcolor |= 0x50; break;
272 case 46: /* Green-blue background. */
273 arcbios_console_curcolor &= 0x0f;
274 arcbios_console_curcolor |= 0x30; break;
275 case 47: /* White background. */
276 arcbios_console_curcolor &= 0x0f;
277 arcbios_console_curcolor |= 0x70; break;
278 default:fatal("{ handle_esc_seq: color %i }\n", color);
279 }
280 return;
281 case 'H':
282 p = strchr(arcbios_escape_sequence, ';');
283 if (p == NULL)
284 return; /* TODO */
285 row = atoi(arcbios_escape_sequence + 1);
286 col = atoi(p + 1);
287 if (col < 1)
288 col = 1;
289 if (row < 1)
290 row = 1;
291 arcbios_console_curx = col - 1;
292 arcbios_console_cury = row - 1;
293 return;
294 case 'J':
295 /*
296 * J = clear screen below cursor, and the rest of the
297 * current line,
298 * 2J = clear whole screen.
299 */
300 i = atoi(arcbios_escape_sequence + 1);
301 if (i != 0 && i != 2)
302 fatal("{ handle_esc_seq(): %iJ }\n", i);
303 if (i == 0)
304 for (col = arcbios_console_curx;
305 col < arcbios_console_maxx; col++)
306 arcbios_putcell(cpu, ' ', col,
307 arcbios_console_cury);
308 for (col = 0; col < arcbios_console_maxx; col++)
309 for (row = i? 0 : arcbios_console_cury+1;
310 row < arcbios_console_maxy; row++)
311 arcbios_putcell(cpu, ' ', col, row);
312 return;
313 case 'K':
314 col = atoi(arcbios_escape_sequence + 1);
315 /* 2 = clear line to the right. 1 = to the left (?) */
316 start = 0; stop = arcbios_console_curx;
317 if (col == 2) {
318 start = arcbios_console_curx;
319 stop = arcbios_console_maxx-1;
320 }
321 for (i=start; i<=stop; i++)
322 arcbios_putcell(cpu, ' ', i, arcbios_console_cury);
323
324 return;
325 }
326
327 fatal("{ handle_esc_seq(): unimplemented escape sequence: ");
328 for (i=0; i<len; i++) {
329 int x = arcbios_escape_sequence[i];
330 if (i == len-1)
331 x = code;
332
333 if (x >= ' ' && x < 127)
334 fatal("%c", x);
335 else
336 fatal("[0x%02x]", x);
337 }
338 fatal(" }\n");
339 }
340
341
342 /*
343 * scroll_if_necessary():
344 */
345 static void scroll_if_necessary(struct cpu *cpu)
346 {
347 /* Scroll? */
348 if (arcbios_console_cury >= arcbios_console_maxy) {
349 unsigned char buf[2];
350 int x, y;
351 for (y=0; y<arcbios_console_maxy-1; y++)
352 for (x=0; x<arcbios_console_maxx; x++) {
353 cpu->memory_rw(cpu, cpu->mem,
354 arcbios_console_vram +
355 2*(x + arcbios_console_maxx * (y+1)),
356 &buf[0], sizeof(buf), MEM_READ,
357 CACHE_NONE | PHYSICAL);
358 cpu->memory_rw(cpu, cpu->mem,
359 arcbios_console_vram +
360 2*(x + arcbios_console_maxx * y),
361 &buf[0], sizeof(buf), MEM_WRITE,
362 CACHE_NONE | PHYSICAL);
363 }
364
365 arcbios_console_cury = arcbios_console_maxy - 1;
366
367 for (x=0; x<arcbios_console_maxx; x++)
368 arcbios_putcell(cpu, ' ', x, arcbios_console_cury);
369 }
370 }
371
372
373 /*
374 * arcbios_putchar():
375 *
376 * If we're using X11 with VGA-style console, then output to that console.
377 * Otherwise, use console_putchar().
378 */
379 static void arcbios_putchar(struct cpu *cpu, int ch)
380 {
381 int addr;
382 unsigned char byte;
383
384 if (!cpu->machine->use_x11) {
385 /* Text console output: */
386
387 /* Hack for Windows NT, which uses 0x9b instead of ESC + [ */
388 if (ch == 0x9b) {
389 console_putchar(cpu->machine->main_console_handle, 27);
390 ch = '[';
391 }
392 console_putchar(cpu->machine->main_console_handle, ch);
393 return;
394 }
395
396 if (arcbios_in_escape_sequence) {
397 int len = strlen(arcbios_escape_sequence);
398 arcbios_escape_sequence[len] = ch;
399 len++;
400 if (len >= MAX_ESC)
401 len = MAX_ESC;
402 arcbios_escape_sequence[len] = '\0';
403 if ((ch >= 'a' && ch <= 'z') ||
404 (ch >= 'A' && ch <= 'Z') || len >= MAX_ESC) {
405 handle_esc_seq(cpu);
406 arcbios_in_escape_sequence = 0;
407 }
408 } else {
409 if (ch == 27) {
410 arcbios_in_escape_sequence = 1;
411 arcbios_escape_sequence[0] = '\0';
412 } else if (ch == 0x9b) {
413 arcbios_in_escape_sequence = 1;
414 arcbios_escape_sequence[0] = '[';
415 arcbios_escape_sequence[1] = '\0';
416 } else if (ch == '\b') {
417 if (arcbios_console_curx > 0)
418 arcbios_console_curx --;
419 } else if (ch == '\r') {
420 arcbios_console_curx = 0;
421 } else if (ch == '\n') {
422 arcbios_console_cury ++;
423 } else if (ch == '\t') {
424 arcbios_console_curx =
425 ((arcbios_console_curx - 1) | 7) + 1;
426 /* TODO: Print spaces? */
427 } else {
428 /* Put char: */
429 if (arcbios_console_curx >= arcbios_console_maxx) {
430 arcbios_console_curx = 0;
431 arcbios_console_cury ++;
432 scroll_if_necessary(cpu);
433 }
434 arcbios_putcell(cpu, ch, arcbios_console_curx,
435 arcbios_console_cury);
436 arcbios_console_curx ++;
437 }
438 }
439
440 scroll_if_necessary(cpu);
441
442 /* Update cursor position: */
443 addr = (arcbios_console_curx >= arcbios_console_maxx?
444 arcbios_console_maxx-1 : arcbios_console_curx) +
445 arcbios_console_cury * arcbios_console_maxx;
446 byte = 0x0e;
447 cpu->memory_rw(cpu, cpu->mem, arcbios_console_ctrlregs + 0x14,
448 &byte, sizeof(byte), MEM_WRITE, CACHE_NONE | PHYSICAL);
449 byte = (addr >> 8) & 255;
450 cpu->memory_rw(cpu, cpu->mem, arcbios_console_ctrlregs + 0x15,
451 &byte, sizeof(byte), MEM_WRITE, CACHE_NONE | PHYSICAL);
452 byte = 0x0f;
453 cpu->memory_rw(cpu, cpu->mem, arcbios_console_ctrlregs + 0x14,
454 &byte, sizeof(byte), MEM_WRITE, CACHE_NONE | PHYSICAL);
455 byte = addr & 255;
456 cpu->memory_rw(cpu, cpu->mem, arcbios_console_ctrlregs + 0x15,
457 &byte, sizeof(byte), MEM_WRITE, CACHE_NONE | PHYSICAL);
458 }
459
460
461 /*
462 * arcbios_register_scsicontroller():
463 */
464 void arcbios_register_scsicontroller(uint64_t scsicontroller_component)
465 {
466 scsicontroller = scsicontroller_component;
467 }
468
469
470 /*
471 * arcbios_get_scsicontroller():
472 */
473 uint64_t arcbios_get_scsicontroller(void)
474 {
475 return scsicontroller;
476 }
477
478
479 /*
480 * arcbios_add_memory_descriptor():
481 *
482 * NOTE: arctype is the ARC type, not the SGI type. This function takes
483 * care of converting, when necessary.
484 */
485 void arcbios_add_memory_descriptor(struct cpu *cpu,
486 uint64_t base, uint64_t len, int arctype)
487 {
488 uint64_t memdesc_addr;
489 int s;
490 struct arcbios_mem arcbios_mem;
491 struct arcbios_mem64 arcbios_mem64;
492
493 base /= 4096;
494 len /= 4096;
495
496 /*
497 * TODO: Huh? Why isn't it necessary to convert from arc to sgi types?
498 *
499 * TODO 2: It seems that it _is_ neccessary, but NetBSD's arcdiag
500 * doesn't handle the sgi case separately.
501 */
502 #if 1
503 if (cpu->machine->machine_type == MACHINE_SGI) {
504 /* arctype is SGI style */
505 /* printf("%i => ", arctype); */
506 switch (arctype) {
507 case 0: arctype = 0; break;
508 case 1: arctype = 1; break;
509 case 2: arctype = 3; break;
510 case 3: arctype = 4; break;
511 case 4: arctype = 5; break;
512 case 5: arctype = 6; break;
513 case 6: arctype = 7; break;
514 case 7: arctype = 2; break;
515 }
516 /* printf("%i\n", arctype); */
517 }
518 #endif
519 if (arc_64bit)
520 s = sizeof(arcbios_mem64);
521 else
522 s = sizeof(arcbios_mem);
523
524 memdesc_addr = arcbios_memdescriptor_base +
525 arc_n_memdescriptors * s;
526
527 if (arc_64bit) {
528 memset(&arcbios_mem64, 0, s);
529 store_32bit_word_in_host(cpu,
530 (unsigned char *)&arcbios_mem64.Type, arctype);
531 store_64bit_word_in_host(cpu,
532 (unsigned char *)&arcbios_mem64.BasePage, base);
533 store_64bit_word_in_host(cpu,
534 (unsigned char *)&arcbios_mem64.PageCount, len);
535 store_buf(cpu, memdesc_addr, (char *)&arcbios_mem64, s);
536 } else {
537 memset(&arcbios_mem, 0, s);
538 store_32bit_word_in_host(cpu,
539 (unsigned char *)&arcbios_mem.Type, arctype);
540 store_32bit_word_in_host(cpu,
541 (unsigned char *)&arcbios_mem.BasePage, base);
542 store_32bit_word_in_host(cpu,
543 (unsigned char *)&arcbios_mem.PageCount, len);
544 store_buf(cpu, memdesc_addr, (char *)&arcbios_mem, s);
545 }
546
547 arc_n_memdescriptors ++;
548 }
549
550
551 /*
552 * arcbios_addchild():
553 *
554 * host_tmp_component is a temporary component, with data formated for
555 * the host system. It needs to be translated/copied into emulated RAM.
556 *
557 * Return value is the virtual (emulated) address of the added component.
558 *
559 * TODO: This function doesn't care about memory management, but simply
560 * stores the new child after the last stored child.
561 * TODO: This stuff is really ugly.
562 */
563 static uint64_t arcbios_addchild(struct cpu *cpu,
564 struct arcbios_component *host_tmp_component,
565 char *identifier, uint32_t parent)
566 {
567 uint64_t a = arcbios_next_component_address;
568 uint32_t peer=0;
569 uint32_t child=0;
570 int n_left;
571 uint64_t peeraddr = FIRST_ARC_COMPONENT;
572
573 /*
574 * This component has no children yet, but it may have peers (that is,
575 * other components that share this component's parent) so we have to
576 * set the peer value correctly.
577 *
578 * Also, if this is the first child of some parent, the parent's child
579 * pointer should be set to point to this component. (But only if it
580 * is the first.)
581 *
582 * This is really ugly: scan through all components, starting from
583 * FIRST_ARC_COMPONENT, to find a component with the same parent as
584 * this component will have. If such a component is found, and its
585 * 'peer' value is NULL, then set it to this component's address (a).
586 *
587 * TODO: make this nicer
588 */
589
590 n_left = n_arc_components;
591 while (n_left > 0) {
592 /* Load parent, child, and peer values: */
593 uint32_t eparent, echild, epeer, tmp;
594 unsigned char buf[4];
595
596 /* debug("[ addchild: peeraddr = 0x%08x ]\n",
597 (int)peeraddr); */
598
599 cpu->memory_rw(cpu, cpu->mem,
600 peeraddr + 0 * arc_wordlen, &buf[0], sizeof(eparent),
601 MEM_READ, CACHE_NONE);
602 if (cpu->byte_order == EMUL_BIG_ENDIAN) {
603 unsigned char tmp;
604 tmp = buf[0]; buf[0] = buf[3]; buf[3] = tmp;
605 tmp = buf[1]; buf[1] = buf[2]; buf[2] = tmp;
606 }
607 epeer = buf[0] + (buf[1]<<8) + (buf[2]<<16) + (buf[3]<<24);
608
609 cpu->memory_rw(cpu, cpu->mem, peeraddr + 1 * arc_wordlen,
610 &buf[0], sizeof(eparent), MEM_READ, CACHE_NONE);
611 if (cpu->byte_order == EMUL_BIG_ENDIAN) {
612 unsigned char tmp; tmp = buf[0];
613 buf[0] = buf[3]; buf[3] = tmp;
614 tmp = buf[1]; buf[1] = buf[2]; buf[2] = tmp;
615 }
616 echild = buf[0] + (buf[1]<<8) + (buf[2]<<16) + (buf[3]<<24);
617
618 cpu->memory_rw(cpu, cpu->mem, peeraddr + 2 * arc_wordlen,
619 &buf[0], sizeof(eparent), MEM_READ, CACHE_NONE);
620 if (cpu->byte_order == EMUL_BIG_ENDIAN) {
621 unsigned char tmp; tmp = buf[0];
622 buf[0] = buf[3]; buf[3] = tmp;
623 tmp = buf[1]; buf[1] = buf[2]; buf[2] = tmp;
624 }
625 eparent = buf[0] + (buf[1]<<8) + (buf[2]<<16) + (buf[3]<<24);
626
627 /* debug(" epeer=%x echild=%x eparent=%x\n",
628 (int)epeer,(int)echild,(int)eparent); */
629
630 if ((uint32_t)eparent == (uint32_t)parent &&
631 (uint32_t)epeer == 0) {
632 epeer = a;
633 store_32bit_word(cpu, peeraddr + 0x00, epeer);
634 /* debug("[ addchild: adding 0x%08x as peer "
635 "to 0x%08x ]\n", (int)a, (int)peeraddr); */
636 }
637 if ((uint32_t)peeraddr == (uint32_t)parent &&
638 (uint32_t)echild == 0) {
639 echild = a;
640 store_32bit_word(cpu, peeraddr + 0x04, echild);
641 /* debug("[ addchild: adding 0x%08x as "
642 "child to 0x%08x ]\n", (int)a, (int)peeraddr); */
643 }
644
645 /* Go to the next component: */
646 cpu->memory_rw(cpu, cpu->mem, peeraddr + 0x28, &buf[0],
647 sizeof(eparent), MEM_READ, CACHE_NONE);
648 if (cpu->byte_order == EMUL_BIG_ENDIAN) {
649 unsigned char tmp; tmp = buf[0];
650 buf[0] = buf[3]; buf[3] = tmp;
651 tmp = buf[1]; buf[1] = buf[2]; buf[2] = tmp;
652 }
653 tmp = buf[0] + (buf[1]<<8) + (buf[2]<<16) + (buf[3]<<24);
654 peeraddr += 0x30;
655 peeraddr += tmp + 1;
656 peeraddr = ((peeraddr - 1) | 3) + 1;
657
658 n_left --;
659 }
660
661 store_32bit_word(cpu, a + 0x00, peer);
662 store_32bit_word(cpu, a + 0x04, child);
663 store_32bit_word(cpu, a + 0x08, parent);
664 store_32bit_word(cpu, a+ 0x0c, host_tmp_component->Class);
665 store_32bit_word(cpu, a+ 0x10, host_tmp_component->Type);
666 store_32bit_word(cpu, a+ 0x14, host_tmp_component->Flags +
667 65536 * host_tmp_component->Version);
668 store_32bit_word(cpu, a+ 0x18, host_tmp_component->Revision);
669 store_32bit_word(cpu, a+ 0x1c, host_tmp_component->Key);
670 store_32bit_word(cpu, a+ 0x20, host_tmp_component->AffinityMask);
671 store_32bit_word(cpu, a+ 0x24, host_tmp_component->
672 ConfigurationDataSize);
673 store_32bit_word(cpu, a+ 0x28, host_tmp_component->IdentifierLength);
674 store_32bit_word(cpu, a+ 0x2c, host_tmp_component->Identifier);
675
676 arcbios_next_component_address += 0x30;
677
678 if (host_tmp_component->IdentifierLength != 0) {
679 store_32bit_word(cpu, a + 0x2c, a + 0x30);
680 store_string(cpu, a + 0x30, identifier);
681 if (identifier != NULL)
682 arcbios_next_component_address +=
683 strlen(identifier) + 1;
684 }
685
686 arcbios_next_component_address ++;
687
688 /* Round up to next 0x4 bytes: */
689 arcbios_next_component_address =
690 ((arcbios_next_component_address - 1) | 3) + 1;
691
692 n_arc_components ++;
693
694 return a;
695 }
696
697
698 /*
699 * arcbios_addchild64():
700 *
701 * host_tmp_component is a temporary component, with data formated for
702 * the host system. It needs to be translated/copied into emulated RAM.
703 *
704 * Return value is the virtual (emulated) address of the added component.
705 *
706 * TODO: This function doesn't care about memory management, but simply
707 * stores the new child after the last stored child.
708 * TODO: This stuff is really ugly.
709 */
710 static uint64_t arcbios_addchild64(struct cpu *cpu,
711 struct arcbios_component64 *host_tmp_component,
712 char *identifier, uint64_t parent)
713 {
714 uint64_t a = arcbios_next_component_address;
715 uint64_t peer=0;
716 uint64_t child=0;
717 int n_left;
718 uint64_t peeraddr = FIRST_ARC_COMPONENT;
719
720 /*
721 * This component has no children yet, but it may have peers (that is,
722 * other components that share this component's parent) so we have to
723 * set the peer value correctly.
724 *
725 * Also, if this is the first child of some parent, the parent's child
726 * pointer should be set to point to this component. (But only if it
727 * is the first.)
728 *
729 * This is really ugly: scan through all components, starting from
730 * FIRST_ARC_COMPONENT, to find a component with the same parent as
731 * this component will have. If such a component is found, and its
732 * 'peer' value is NULL, then set it to this component's address (a).
733 *
734 * TODO: make this nicer
735 */
736
737 n_left = n_arc_components;
738 while (n_left > 0) {
739 /* Load parent, child, and peer values: */
740 uint64_t eparent, echild, epeer, tmp;
741 unsigned char buf[8];
742
743 /* debug("[ addchild: peeraddr = 0x%016llx ]\n",
744 (long long)peeraddr); */
745
746 cpu->memory_rw(cpu, cpu->mem,
747 peeraddr + 0 * arc_wordlen, &buf[0], sizeof(eparent),
748 MEM_READ, CACHE_NONE);
749 if (cpu->byte_order == EMUL_BIG_ENDIAN) {
750 unsigned char tmp;
751 tmp = buf[0]; buf[0] = buf[7]; buf[7] = tmp;
752 tmp = buf[1]; buf[1] = buf[6]; buf[6] = tmp;
753 tmp = buf[2]; buf[2] = buf[5]; buf[5] = tmp;
754 tmp = buf[3]; buf[3] = buf[4]; buf[4] = tmp;
755 }
756 epeer = buf[0] + (buf[1]<<8) + (buf[2]<<16) + (buf[3]<<24)
757 + ((uint64_t)buf[4] << 32) + ((uint64_t)buf[5] << 40)
758 + ((uint64_t)buf[6] << 48) + ((uint64_t)buf[7] << 56);
759
760 cpu->memory_rw(cpu, cpu->mem, peeraddr + 1 * arc_wordlen,
761 &buf[0], sizeof(eparent), MEM_READ, CACHE_NONE);
762 if (cpu->byte_order == EMUL_BIG_ENDIAN) {
763 unsigned char tmp;
764 tmp = buf[0]; buf[0] = buf[7]; buf[7] = tmp;
765 tmp = buf[1]; buf[1] = buf[6]; buf[6] = tmp;
766 tmp = buf[2]; buf[2] = buf[5]; buf[5] = tmp;
767 tmp = buf[3]; buf[3] = buf[4]; buf[4] = tmp;
768 }
769 echild = buf[0] + (buf[1]<<8) + (buf[2]<<16) + (buf[3]<<24)
770 + ((uint64_t)buf[4] << 32) + ((uint64_t)buf[5] << 40)
771 + ((uint64_t)buf[6] << 48) + ((uint64_t)buf[7] << 56);
772
773 cpu->memory_rw(cpu, cpu->mem, peeraddr + 2 * arc_wordlen,
774 &buf[0], sizeof(eparent), MEM_READ, CACHE_NONE);
775 if (cpu->byte_order == EMUL_BIG_ENDIAN) {
776 unsigned char tmp;
777 tmp = buf[0]; buf[0] = buf[7]; buf[7] = tmp;
778 tmp = buf[1]; buf[1] = buf[6]; buf[6] = tmp;
779 tmp = buf[2]; buf[2] = buf[5]; buf[5] = tmp;
780 tmp = buf[3]; buf[3] = buf[4]; buf[4] = tmp;
781 }
782 eparent = buf[0] + (buf[1]<<8) + (buf[2]<<16) + (buf[3]<<24)
783 + ((uint64_t)buf[4] << 32) + ((uint64_t)buf[5] << 40)
784 + ((uint64_t)buf[6] << 48) + ((uint64_t)buf[7] << 56);
785
786 /* debug(" epeer=%llx echild=%llx eparent=%llx\n",
787 (long long)epeer, (long long)echild,
788 (long long)eparent); */
789
790 if (eparent == parent && epeer == 0) {
791 epeer = a;
792 store_64bit_word(cpu, peeraddr + 0 * arc_wordlen,
793 epeer);
794 /* debug("[ addchild: adding 0x%016llx as peer "
795 "to 0x%016llx ]\n", (long long)a,
796 (long long)peeraddr); */
797 }
798 if (peeraddr == parent && echild == 0) {
799 echild = a;
800 store_64bit_word(cpu, peeraddr + 1 * arc_wordlen,
801 echild);
802 /* debug("[ addchild: adding 0x%016llx as child "
803 "to 0x%016llx ]\n", (long long)a,
804 (long long)peeraddr); */
805 }
806
807 /* Go to the next component: */
808 cpu->memory_rw(cpu, cpu->mem, peeraddr + 0x34,
809 &buf[0], sizeof(uint32_t), MEM_READ, CACHE_NONE);
810 if (cpu->byte_order == EMUL_BIG_ENDIAN) {
811 unsigned char tmp;
812 tmp = buf[0]; buf[0] = buf[3]; buf[3] = tmp;
813 tmp = buf[1]; buf[1] = buf[2]; buf[2] = tmp;
814 }
815 tmp = buf[0] + (buf[1]<<8) + (buf[2]<<16) + (buf[3]<<24);
816
817 tmp &= 0xfffff;
818
819 peeraddr += 0x50;
820 peeraddr += tmp + 1;
821 peeraddr = ((peeraddr - 1) | 3) + 1;
822
823 n_left --;
824 }
825
826 store_64bit_word(cpu, a + 0x00, peer);
827 store_64bit_word(cpu, a + 0x08, child);
828 store_64bit_word(cpu, a + 0x10, parent);
829 store_32bit_word(cpu, a+ 0x18, host_tmp_component->Class);
830 store_32bit_word(cpu, a+ 0x1c, host_tmp_component->Type);
831 store_32bit_word(cpu, a+ 0x20, host_tmp_component->Flags);
832 store_32bit_word(cpu, a+ 0x24, host_tmp_component->Version +
833 ((uint64_t)host_tmp_component->Revision << 16));
834 store_32bit_word(cpu, a+ 0x28, host_tmp_component->Key);
835 store_64bit_word(cpu, a+ 0x30, host_tmp_component->AffinityMask);
836 store_64bit_word(cpu, a+ 0x38, host_tmp_component->
837 ConfigurationDataSize);
838 store_64bit_word(cpu, a+ 0x40, host_tmp_component->IdentifierLength);
839 store_64bit_word(cpu, a+ 0x48, host_tmp_component->Identifier);
840
841 /* TODO: Find out how a REAL ARCS64 implementation does it. */
842
843 arcbios_next_component_address += 0x50;
844
845 if (host_tmp_component->IdentifierLength != 0) {
846 store_64bit_word(cpu, a + 0x48, a + 0x50);
847 store_string(cpu, a + 0x50, identifier);
848 if (identifier != NULL)
849 arcbios_next_component_address +=
850 strlen(identifier) + 1;
851 }
852
853 arcbios_next_component_address ++;
854
855 /* Round up to next 0x8 bytes: */
856 arcbios_next_component_address =
857 ((arcbios_next_component_address - 1) | 7) + 1;
858
859 n_arc_components ++;
860 return a;
861 }
862
863
864 /*
865 * arcbios_addchild_manual():
866 *
867 * Used internally to set up component structures.
868 * Parent may only be NULL for the first (system) component.
869 *
870 * Return value is the virtual (emulated) address of the added component.
871 */
872 uint64_t arcbios_addchild_manual(struct cpu *cpu,
873 uint64_t class, uint64_t type, uint64_t flags,
874 uint64_t version, uint64_t revision, uint64_t key,
875 uint64_t affinitymask, char *identifier, uint64_t parent,
876 void *config_data, size_t config_len)
877 {
878 /* This component is only for temporary use: */
879 struct arcbios_component component;
880 struct arcbios_component64 component64;
881
882 if (config_data != NULL) {
883 unsigned char *p = config_data;
884 int i;
885
886 if (n_configuration_data >= MAX_CONFIG_DATA) {
887 printf("fatal error: you need to increase "
888 "MAX_CONFIG_DATA\n");
889 exit(1);
890 }
891
892 for (i=0; i<config_len; i++) {
893 unsigned char ch = p[i];
894 cpu->memory_rw(cpu, cpu->mem,
895 configuration_data_next_addr + i,
896 &ch, 1, MEM_WRITE, CACHE_NONE);
897 }
898
899 configuration_data_len[n_configuration_data] = config_len;
900 configuration_data_configdata[n_configuration_data] =
901 configuration_data_next_addr;
902 configuration_data_next_addr += config_len;
903 configuration_data_component[n_configuration_data] =
904 arcbios_next_component_address + (arc_64bit? 0x18 : 0x0c);
905
906 /* printf("& ADDING %i: configdata=0x%016llx "
907 "component=0x%016llx\n", n_configuration_data,
908 (long long)configuration_data_configdata[
909 n_configuration_data],
910 (long long)configuration_data_component[
911 n_configuration_data]); */
912
913 n_configuration_data ++;
914 }
915
916 if (!arc_64bit) {
917 component.Class = class;
918 component.Type = type;
919 component.Flags = flags;
920 component.Version = version;
921 component.Revision = revision;
922 component.Key = key;
923 component.AffinityMask = affinitymask;
924 component.ConfigurationDataSize = config_len;
925 component.IdentifierLength = 0;
926 component.Identifier = 0;
927 if (identifier != NULL) {
928 component.IdentifierLength = strlen(identifier) + 1;
929 }
930 return arcbios_addchild(cpu, &component, identifier, parent);
931 } else {
932 component64.Class = class;
933 component64.Type = type;
934 component64.Flags = flags;
935 component64.Version = version;
936 component64.Revision = revision;
937 component64.Key = key;
938 component64.AffinityMask = affinitymask;
939 component64.ConfigurationDataSize = config_len;
940 component64.IdentifierLength = 0;
941 component64.Identifier = 0;
942 if (identifier != NULL) {
943 component64.IdentifierLength = strlen(identifier) + 1;
944 }
945 return arcbios_addchild64(cpu, &component64, identifier,
946 parent);
947 }
948 }
949
950
951 /*
952 * arcbios_get_msdos_partition_size():
953 *
954 * This function tries to parse MSDOS-style partition tables on a disk
955 * image, and return the starting offset (counted in bytes), and the
956 * size, of a specific partition.
957 *
958 * NOTE: partition_nr is 1-based!
959 *
960 * TODO: This is buggy, it doesn't really handle extended partitions.
961 *
962 * See http://www.nondot.org/sabre/os/files/Partitions/Partitions.html
963 * for more info.
964 */
965 static void arcbios_get_msdos_partition_size(struct machine *machine,
966 int scsi_id, int partition_nr, uint64_t *start, uint64_t *size)
967 {
968 int res, i, partition_type, cur_partition = 0;
969 unsigned char sector[512];
970 unsigned char buf[16];
971 uint64_t offset = 0, st;
972
973 /* Partition 0 is the entire disk image: */
974 *start = 0;
975 *size = diskimage_getsize(machine, scsi_id);
976 if (partition_nr == 0)
977 return;
978
979 ugly_goto:
980 *start = 0; *size = 0;
981
982 /* printf("reading MSDOS partition from offset 0x%llx\n",
983 (long long)offset); */
984
985 res = diskimage_access(machine, scsi_id, 0, offset,
986 sector, sizeof(sector));
987 if (!res) {
988 fatal("[ arcbios_get_msdos_partition_size(): couldn't "
989 "read the disk image, id %i, offset 0x%llx ]\n",
990 scsi_id, (long long)offset);
991 return;
992 }
993
994 if (sector[510] != 0x55 || sector[511] != 0xaa) {
995 fatal("[ arcbios_get_msdos_partition_size(): not an "
996 "MSDOS partition table ]\n");
997 }
998
999 #if 0
1000 /* Debug dump: */
1001 for (i=0; i<4; i++) {
1002 int j;
1003 printf(" partition %i: ", i+1);
1004 for (j=0; j<16; j++)
1005 printf(" %02x", sector[446 + i*16 + j]);
1006 printf("\n");
1007 }
1008 #endif
1009
1010 for (i=0; i<4; i++) {
1011 memmove(buf, sector + 446 + 16*i, 16);
1012
1013 partition_type = buf[4];
1014
1015 if (partition_type == 0)
1016 continue;
1017
1018 st = (buf[8] + (buf[9] << 8) + (buf[10] << 16) +
1019 (buf[11] << 24)) * 512;
1020
1021 if (start != NULL)
1022 *start = st;
1023 if (size != NULL)
1024 *size = (buf[12] + (buf[13] << 8) + (buf[14] << 16) +
1025 (buf[15] << 24)) * 512;
1026
1027 /* Extended DOS partition: */
1028 if (partition_type == 5) {
1029 offset += st;
1030 goto ugly_goto;
1031 }
1032
1033 /* Found the right partition? Then return. */
1034 cur_partition ++;
1035 if (cur_partition == partition_nr)
1036 return;
1037 }
1038
1039 fatal("[ partition(%i) NOT found ]\n", partition_nr);
1040 }
1041
1042
1043 /*
1044 * arcbios_handle_to_scsi_id():
1045 */
1046 static int arcbios_handle_to_scsi_id(int handle)
1047 {
1048 int id, cdrom;
1049 char *s;
1050
1051 if (handle < 0 || handle >= MAX_HANDLES)
1052 return -1;
1053
1054 s = (char *)file_handle_string[handle];
1055 if (s == NULL)
1056 return -1;
1057
1058 /*
1059 * s is something like "scsi(0)disk(0)rdisk(0)partition(0)".
1060 * TODO: This is really ugly and hardcoded.
1061 */
1062
1063 if (strncmp(s, "scsi(", 5) != 0 || strlen(s) < 13)
1064 return -1;
1065
1066 cdrom = (s[7] == 'c');
1067 id = cdrom? atoi(s + 13) : atoi(s + 12);
1068
1069 return id;
1070 }
1071
1072
1073 /*
1074 * arcbios_handle_to_start_and_size():
1075 */
1076 static void arcbios_handle_to_start_and_size(struct machine *machine,
1077 int handle, uint64_t *start, uint64_t *size)
1078 {
1079 char *s = (char *)file_handle_string[handle];
1080 char *s2;
1081 int scsi_id = arcbios_handle_to_scsi_id(handle);
1082
1083 if (scsi_id < 0)
1084 return;
1085
1086 /* This works for "partition(0)": */
1087 *start = 0;
1088 *size = diskimage_getsize(machine, scsi_id);
1089
1090 s2 = strstr(s, "partition(");
1091 if (s2 != NULL) {
1092 int partition_nr = atoi(s2 + 10);
1093 /* printf("partition_nr = %i\n", partition_nr); */
1094 if (partition_nr != 0)
1095 arcbios_get_msdos_partition_size(machine,
1096 scsi_id, partition_nr, start, size);
1097 }
1098 }
1099
1100
1101 /*
1102 * arcbios_getfileinformation():
1103 *
1104 * Fill in a GetFileInformation struct in emulated memory,
1105 * for a specific file handle. (This is used to get the size
1106 * and offsets of partitions on disk images.)
1107 */
1108 static int arcbios_getfileinformation(struct cpu *cpu)
1109 {
1110 int handle = cpu->cd.mips.gpr[MIPS_GPR_A0];
1111 uint64_t addr = cpu->cd.mips.gpr[MIPS_GPR_A1];
1112 uint64_t start, size;
1113
1114 arcbios_handle_to_start_and_size(cpu->machine, handle, &start, &size);
1115
1116 store_64bit_word(cpu, addr + 0, 0);
1117 store_64bit_word(cpu, addr + 8, size);
1118 store_64bit_word(cpu, addr + 16, 0);
1119 store_32bit_word(cpu, addr + 24, 1);
1120 store_32bit_word(cpu, addr + 28, 0);
1121 store_32bit_word(cpu, addr + 32, 0);
1122
1123 /* printf("\n!!! size=0x%x start=0x%x\n", (int)size, (int)start); */
1124
1125 return ARCBIOS_ESUCCESS;
1126 }
1127
1128
1129 /*
1130 * arcbios_private_emul():
1131 *
1132 * TODO: This is probably SGI specific. (?)
1133 *
1134 * 0x04 get nvram table
1135 */
1136 void arcbios_private_emul(struct cpu *cpu)
1137 {
1138 int vector = cpu->pc & 0xfff;
1139
1140 switch (vector) {
1141 case 0x04:
1142 debug("[ ARCBIOS PRIVATE get nvram table(): TODO ]\n");
1143 cpu->cd.mips.gpr[MIPS_GPR_V0] = 0;
1144 break;
1145 default:
1146 cpu_register_dump(cpu->machine, cpu, 1, 0x1);
1147 debug("a0 points to: ");
1148 dump_mem_string(cpu, cpu->cd.mips.gpr[MIPS_GPR_A0]);
1149 debug("\n");
1150 fatal("ARCBIOS: unimplemented PRIVATE vector 0x%x\n", vector);
1151 cpu->running = 0;
1152 cpu->dead = 1;
1153 }
1154 }
1155
1156
1157 /*
1158 * arcbios_emul(): ARCBIOS emulation
1159 *
1160 * 0x0c Halt()
1161 * 0x10 PowerDown()
1162 * 0x14 Restart()
1163 * 0x18 Reboot()
1164 * 0x1c EnterInteractiveMode()
1165 * 0x20 ReturnFromMain()
1166 * 0x24 GetPeer(node)
1167 * 0x28 GetChild(node)
1168 * 0x2c GetParent(node)
1169 * 0x30 GetConfigurationData(config_data, node)
1170 * 0x3c GetComponent(name)
1171 * 0x44 GetSystemId()
1172 * 0x48 GetMemoryDescriptor(void *)
1173 * 0x50 GetTime()
1174 * 0x54 GetRelativeTime()
1175 * 0x5c Open(path, mode, &fileid)
1176 * 0x60 Close(handle)
1177 * 0x64 Read(handle, &buf, len, &actuallen)
1178 * 0x6c Write(handle, buf, len, &returnlen)
1179 * 0x70 Seek(handle, &offset, len)
1180 * 0x78 GetEnvironmentVariable(char *)
1181 * 0x7c SetEnvironmentVariable(char *, char *)
1182 * 0x80 GetFileInformation(handle, buf)
1183 * 0x88 FlushAllCaches()
1184 * 0x90 GetDisplayStatus(uint32_t handle)
1185 * 0x100 undocumented IRIX (?)
1186 */
1187 int arcbios_emul(struct cpu *cpu)
1188 {
1189 int vector = cpu->pc & 0xfff;
1190 int i, j, handle;
1191 unsigned char ch2;
1192 unsigned char buf[40];
1193
1194 if (cpu->pc >= ARC_PRIVATE_ENTRIES &&
1195 cpu->pc < ARC_PRIVATE_ENTRIES + 100*sizeof(uint32_t)) {
1196 arcbios_private_emul(cpu);
1197 return 1;
1198 }
1199
1200 if (arc_64bit)
1201 vector /= 2;
1202
1203 /* Special case for reboot by jumping to 0xbfc00000: */
1204 if (vector == 0 && (cpu->pc & 0xffffffffULL) == 0xbfc00000ULL)
1205 vector = 0x18;
1206
1207 switch (vector) {
1208 case 0x0c: /* Halt() */
1209 case 0x10: /* PowerDown() */
1210 case 0x14: /* Restart() */
1211 case 0x18: /* Reboot() */
1212 case 0x1c: /* EnterInteractiveMode() */
1213 case 0x20: /* ReturnFromMain() */
1214 debug("[ ARCBIOS Halt() or similar ]\n");
1215 /* Halt all CPUs. */
1216 for (i=0; i<cpu->machine->ncpus; i++) {
1217 cpu->machine->cpus[i]->running = 0;
1218 cpu->machine->cpus[i]->dead = 1;
1219 }
1220 cpu->machine->exit_without_entering_debugger = 1;
1221 break;
1222 case 0x24: /* GetPeer(node) */
1223 if (cpu->cd.mips.gpr[MIPS_GPR_A0] == 0) {
1224 /* NULL ptr argument: return NULL. */
1225 cpu->cd.mips.gpr[MIPS_GPR_V0] = 0;
1226 } else {
1227 uint64_t peer;
1228 cpu->memory_rw(cpu, cpu->mem,
1229 cpu->cd.mips.gpr[MIPS_GPR_A0] - 3 * arc_wordlen,
1230 &buf[0], arc_wordlen, MEM_READ, CACHE_NONE);
1231 if (arc_64bit) {
1232 if (cpu->byte_order == EMUL_BIG_ENDIAN) {
1233 unsigned char tmp; tmp = buf[0];
1234 buf[0] = buf[7]; buf[7] = tmp;
1235 tmp = buf[1]; buf[1] = buf[6];
1236 buf[6] = tmp;
1237 tmp = buf[2]; buf[2] = buf[5];
1238 buf[5] = tmp;
1239 tmp = buf[3]; buf[3] = buf[4];
1240 buf[4] = tmp;
1241 }
1242 peer = (uint64_t)buf[0] + ((uint64_t)buf[1]<<8)
1243 + ((uint64_t)buf[2]<<16)
1244 + ((uint64_t)buf[3]<<24)
1245 + ((uint64_t)buf[4]<<32)
1246 + ((uint64_t)buf[5]<<40)
1247 + ((uint64_t)buf[6]<<48)
1248 + ((uint64_t)buf[7]<<56);
1249 } else {
1250 if (cpu->byte_order == EMUL_BIG_ENDIAN) {
1251 unsigned char tmp; tmp = buf[0];
1252 buf[0] = buf[3]; buf[3] = tmp;
1253 tmp = buf[1]; buf[1] = buf[2];
1254 buf[2] = tmp;
1255 }
1256 peer = buf[0] + (buf[1]<<8) + (buf[2]<<16)
1257 + (buf[3]<<24);
1258 }
1259
1260 cpu->cd.mips.gpr[MIPS_GPR_V0] = peer?
1261 (peer + 3 * arc_wordlen) : 0;
1262 if (!arc_64bit)
1263 cpu->cd.mips.gpr[MIPS_GPR_V0] = (int64_t)
1264 (int32_t) cpu->cd.mips.gpr[MIPS_GPR_V0];
1265 }
1266 debug("[ ARCBIOS GetPeer(node 0x%016llx): 0x%016llx ]\n",
1267 (long long)cpu->cd.mips.gpr[MIPS_GPR_A0],
1268 (long long)cpu->cd.mips.gpr[MIPS_GPR_V0]);
1269 break;
1270 case 0x28: /* GetChild(node) */
1271 /* 0 for the root, non-0 for children: */
1272 if (cpu->cd.mips.gpr[MIPS_GPR_A0] == 0)
1273 cpu->cd.mips.gpr[MIPS_GPR_V0] =
1274 FIRST_ARC_COMPONENT + arc_wordlen * 3;
1275 else {
1276 uint64_t child = 0;
1277 cpu->memory_rw(cpu, cpu->mem,
1278 cpu->cd.mips.gpr[MIPS_GPR_A0] - 2 * arc_wordlen,
1279 &buf[0], arc_wordlen, MEM_READ, CACHE_NONE);
1280 if (arc_64bit) {
1281 if (cpu->byte_order == EMUL_BIG_ENDIAN) {
1282 unsigned char tmp; tmp = buf[0];
1283 buf[0] = buf[7]; buf[7] = tmp;
1284 tmp = buf[1]; buf[1] = buf[6];
1285 buf[6] = tmp;
1286 tmp = buf[2]; buf[2] = buf[5];
1287 buf[5] = tmp;
1288 tmp = buf[3]; buf[3] = buf[4];
1289 buf[4] = tmp;
1290 }
1291 child = (uint64_t)buf[0] +
1292 ((uint64_t)buf[1]<<8) +
1293 ((uint64_t)buf[2]<<16) +
1294 ((uint64_t)buf[3]<<24) +
1295 ((uint64_t)buf[4]<<32) +
1296 ((uint64_t)buf[5]<<40) +
1297 ((uint64_t)buf[6]<<48) +
1298 ((uint64_t)buf[7]<<56);
1299 } else {
1300 if (cpu->byte_order == EMUL_BIG_ENDIAN) {
1301 unsigned char tmp; tmp = buf[0];
1302 buf[0] = buf[3]; buf[3] = tmp;
1303 tmp = buf[1]; buf[1] = buf[2];
1304 buf[2] = tmp;
1305 }
1306 child = buf[0] + (buf[1]<<8) + (buf[2]<<16) +
1307 (buf[3]<<24);
1308 }
1309
1310 cpu->cd.mips.gpr[MIPS_GPR_V0] = child?
1311 (child + 3 * arc_wordlen) : 0;
1312 if (!arc_64bit)
1313 cpu->cd.mips.gpr[MIPS_GPR_V0] = (int64_t)
1314 (int32_t)cpu->cd.mips.gpr[MIPS_GPR_V0];
1315 }
1316 debug("[ ARCBIOS GetChild(node 0x%016llx): 0x%016llx ]\n",
1317 (long long)cpu->cd.mips.gpr[MIPS_GPR_A0],
1318 (long long)cpu->cd.mips.gpr[MIPS_GPR_V0]);
1319 break;
1320 case 0x2c: /* GetParent(node) */
1321 {
1322 uint64_t parent;
1323
1324 cpu->memory_rw(cpu, cpu->mem,
1325 cpu->cd.mips.gpr[MIPS_GPR_A0] - 1 * arc_wordlen,
1326 &buf[0], arc_wordlen, MEM_READ, CACHE_NONE);
1327
1328 if (arc_64bit) {
1329 if (cpu->byte_order == EMUL_BIG_ENDIAN) {
1330 unsigned char tmp; tmp = buf[0];
1331 buf[0] = buf[7]; buf[7] = tmp;
1332 tmp = buf[1]; buf[1] = buf[6];
1333 buf[6] = tmp;
1334 tmp = buf[2]; buf[2] = buf[5];
1335 buf[5] = tmp;
1336 tmp = buf[3]; buf[3] = buf[4];
1337 buf[4] = tmp;
1338 }
1339 parent = (uint64_t)buf[0] +
1340 ((uint64_t)buf[1]<<8) +
1341 ((uint64_t)buf[2]<<16) +
1342 ((uint64_t)buf[3]<<24) +
1343 ((uint64_t)buf[4]<<32) +
1344 ((uint64_t)buf[5]<<40) +
1345 ((uint64_t)buf[6]<<48) +
1346 ((uint64_t)buf[7]<<56);
1347 } else {
1348 if (cpu->byte_order == EMUL_BIG_ENDIAN) {
1349 unsigned char tmp; tmp = buf[0];
1350 buf[0] = buf[3]; buf[3] = tmp;
1351 tmp = buf[1]; buf[1] = buf[2];
1352 buf[2] = tmp;
1353 }
1354 parent = buf[0] + (buf[1]<<8) +
1355 (buf[2]<<16) + (buf[3]<<24);
1356 }
1357
1358 cpu->cd.mips.gpr[MIPS_GPR_V0] = parent?
1359 (parent + 3 * arc_wordlen) : 0;
1360 if (!arc_64bit)
1361 cpu->cd.mips.gpr[MIPS_GPR_V0] = (int64_t)
1362 (int32_t) cpu->cd.mips.gpr[MIPS_GPR_V0];
1363 }
1364 debug("[ ARCBIOS GetParent(node 0x%016llx): 0x%016llx ]\n",
1365 (long long)cpu->cd.mips.gpr[MIPS_GPR_A0],
1366 (long long)cpu->cd.mips.gpr[MIPS_GPR_V0]);
1367 break;
1368 case 0x30: /* GetConfigurationData(void *configdata, void *node) */
1369 /* fatal("[ ARCBIOS GetConfigurationData(0x%016llx,"
1370 "0x%016llx) ]\n", (long long)cpu->cd.mips.gpr[MIPS_GPR_A0],
1371 (long long)cpu->cd.mips.gpr[MIPS_GPR_A1]); */
1372 cpu->cd.mips.gpr[MIPS_GPR_V0] = ARCBIOS_EINVAL;
1373 for (i=0; i<n_configuration_data; i++) {
1374 /* fatal("configuration_data_component[%i] = "
1375 "0x%016llx\n", i,
1376 (long long)configuration_data_component[i]); */
1377 if (cpu->cd.mips.gpr[MIPS_GPR_A1] ==
1378 configuration_data_component[i]) {
1379 cpu->cd.mips.gpr[MIPS_GPR_V0] = 0;
1380 for (j=0; j<configuration_data_len[i]; j++) {
1381 unsigned char ch;
1382 cpu->memory_rw(cpu, cpu->mem,
1383 configuration_data_configdata[i] +
1384 j, &ch, 1, MEM_READ, CACHE_NONE);
1385 cpu->memory_rw(cpu, cpu->mem,
1386 cpu->cd.mips.gpr[MIPS_GPR_A0] + j,
1387 &ch, 1, MEM_WRITE, CACHE_NONE);
1388 }
1389 break;
1390 }
1391 }
1392 break;
1393 case 0x3c: /* GetComponent(char *name) */
1394 debug("[ ARCBIOS GetComponent(\"");
1395 dump_mem_string(cpu, cpu->cd.mips.gpr[MIPS_GPR_A0]);
1396 debug("\") ]\n");
1397
1398 if (cpu->cd.mips.gpr[MIPS_GPR_A0] == 0) {
1399 fatal("[ ARCBIOS GetComponent: NULL ptr ]\n");
1400 } else {
1401 unsigned char buf[500];
1402 int match_index = -1;
1403 int match_len = 0;
1404
1405 memset(buf, 0, sizeof(buf));
1406 for (i=0; i<sizeof(buf); i++) {
1407 cpu->memory_rw(cpu, cpu->mem,
1408 cpu->cd.mips.gpr[MIPS_GPR_A0] + i,
1409 &buf[i], 1, MEM_READ, CACHE_NONE);
1410 if (buf[i] == '\0')
1411 i = sizeof(buf);
1412 }
1413 buf[sizeof(buf) - 1] = '\0';
1414
1415 /* "scsi(0)disk(0)rdisk(0)partition(0)" and such. */
1416 /* printf("GetComponent(\"%s\")\n", buf); */
1417
1418 /* Default to NULL return value. */
1419 cpu->cd.mips.gpr[MIPS_GPR_V0] = 0;
1420
1421 /* Scan the string to component table: */
1422 for (i=0; i<arcbios_n_string_to_components; i++) {
1423 int m = 0;
1424 while (buf[m] && arcbios_string_to_component
1425 [i][m] && arcbios_string_to_component[i][m]
1426 == buf[m])
1427 m++;
1428 if (m > match_len) {
1429 match_len = m;
1430 match_index = i;
1431 }
1432 }
1433
1434 if (match_index >= 0) {
1435 /* printf("Longest match: '%s'\n",
1436 arcbios_string_to_component[
1437 match_index]); */
1438 cpu->cd.mips.gpr[MIPS_GPR_V0] =
1439 arcbios_string_to_component_value[
1440 match_index];
1441 }
1442 }
1443 break;
1444 case 0x44: /* GetSystemId() */
1445 debug("[ ARCBIOS GetSystemId() ]\n");
1446 cpu->cd.mips.gpr[MIPS_GPR_V0] = SGI_SYSID_ADDR;
1447 break;
1448 case 0x48: /* void *GetMemoryDescriptor(void *ptr) */
1449 debug("[ ARCBIOS GetMemoryDescriptor(0x%08x) ]\n",
1450 (int)cpu->cd.mips.gpr[MIPS_GPR_A0]);
1451
1452 /* If a0=NULL, then return the first descriptor: */
1453 if ((uint32_t)cpu->cd.mips.gpr[MIPS_GPR_A0] == 0)
1454 cpu->cd.mips.gpr[MIPS_GPR_V0] =
1455 arcbios_memdescriptor_base;
1456 else {
1457 int s = arc_64bit? sizeof(struct arcbios_mem64)
1458 : sizeof(struct arcbios_mem);
1459 int nr = cpu->cd.mips.gpr[MIPS_GPR_A0] -
1460 arcbios_memdescriptor_base;
1461 nr /= s;
1462 nr ++;
1463 cpu->cd.mips.gpr[MIPS_GPR_V0] =
1464 arcbios_memdescriptor_base + s * nr;
1465 if (nr >= arc_n_memdescriptors)
1466 cpu->cd.mips.gpr[MIPS_GPR_V0] = 0;
1467 }
1468 break;
1469 case 0x50: /* GetTime() */
1470 debug("[ ARCBIOS GetTime() ]\n");
1471 cpu->cd.mips.gpr[MIPS_GPR_V0] = 0xffffffff80001000ULL;
1472 /* TODO! */
1473 break;
1474 case 0x54: /* GetRelativeTime() */
1475 debug("[ ARCBIOS GetRelativeTime() ]\n");
1476 cpu->cd.mips.gpr[MIPS_GPR_V0] = (int64_t)(int32_t)time(NULL);
1477 break;
1478 case 0x5c: /* Open(char *path, uint32_t mode, uint32_t *fileID) */
1479 debug("[ ARCBIOS Open(\"");
1480 dump_mem_string(cpu, cpu->cd.mips.gpr[MIPS_GPR_A0]);
1481 debug("\",0x%x,0x%x)", (int)cpu->cd.mips.gpr[MIPS_GPR_A0],
1482 (int)cpu->cd.mips.gpr[MIPS_GPR_A1],
1483 (int)cpu->cd.mips.gpr[MIPS_GPR_A2]);
1484
1485 cpu->cd.mips.gpr[MIPS_GPR_V0] = ARCBIOS_ENOENT;
1486
1487 handle = 3;
1488 /* TODO: Starting at 0 would require some updates... */
1489 while (file_handle_in_use[handle]) {
1490 handle ++;
1491 if (handle >= MAX_HANDLES) {
1492 cpu->cd.mips.gpr[MIPS_GPR_V0] = ARCBIOS_EMFILE;
1493 break;
1494 }
1495 }
1496
1497 if (handle >= MAX_HANDLES) {
1498 fatal("[ ARCBIOS Open: out of file handles ]\n");
1499 } else if (cpu->cd.mips.gpr[MIPS_GPR_A0] == 0) {
1500 fatal("[ ARCBIOS Open: NULL ptr ]\n");
1501 } else {
1502 /*
1503 * TODO: This is hardcoded to successfully open
1504 * anything. It is used by the Windows NT SETUPLDR
1505 * program to load stuff from the boot partition.
1506 */
1507 unsigned char *buf = malloc(MAX_OPEN_STRINGLEN);
1508 if (buf == NULL) {
1509 fprintf(stderr, "out of memory\n");
1510 exit(1);
1511 }
1512 memset(buf, 0, MAX_OPEN_STRINGLEN);
1513 for (i=0; i<MAX_OPEN_STRINGLEN; i++) {
1514 cpu->memory_rw(cpu, cpu->mem,
1515 cpu->cd.mips.gpr[MIPS_GPR_A0] + i,
1516 &buf[i], 1, MEM_READ, CACHE_NONE);
1517 if (buf[i] == '\0')
1518 i = MAX_OPEN_STRINGLEN;
1519 }
1520 buf[MAX_OPEN_STRINGLEN - 1] = '\0';
1521 file_handle_string[handle] = buf;
1522 arcbios_current_seek_offset[handle] = 0;
1523 cpu->cd.mips.gpr[MIPS_GPR_V0] = ARCBIOS_ESUCCESS;
1524 }
1525
1526 if (cpu->cd.mips.gpr[MIPS_GPR_V0] == ARCBIOS_ESUCCESS) {
1527 debug(" = handle %i ]\n", (int)handle);
1528 store_32bit_word(cpu, cpu->cd.mips.gpr[MIPS_GPR_A2],
1529 handle);
1530 file_handle_in_use[handle] = 1;
1531 } else
1532 debug(" = ERROR %i ]\n",
1533 (int)cpu->cd.mips.gpr[MIPS_GPR_V0]);
1534 break;
1535 case 0x60: /* Close(uint32_t handle) */
1536 debug("[ ARCBIOS Close(%i) ]\n",
1537 (int)cpu->cd.mips.gpr[MIPS_GPR_A0]);
1538 if (!file_handle_in_use[cpu->cd.mips.gpr[MIPS_GPR_A0]]) {
1539 fatal("ARCBIOS Close(%i): bad handle\n",
1540 (int)cpu->cd.mips.gpr[MIPS_GPR_A0]);
1541 cpu->cd.mips.gpr[MIPS_GPR_V0] = ARCBIOS_EBADF;
1542 } else {
1543 file_handle_in_use[cpu->cd.mips.gpr[MIPS_GPR_A0]] = 0;
1544 if (file_handle_string[cpu->cd.mips.gpr[MIPS_GPR_A0]]
1545 != NULL)
1546 free(file_handle_string[cpu->cd.mips.gpr[
1547 MIPS_GPR_A0]]);
1548 file_handle_string[cpu->cd.mips.gpr[MIPS_GPR_A0]] =
1549 NULL;
1550 cpu->cd.mips.gpr[MIPS_GPR_V0] = ARCBIOS_ESUCCESS;
1551 }
1552 break;
1553 case 0x64: /* Read(handle, void *buf, length, uint32_t *count) */
1554 if (cpu->cd.mips.gpr[MIPS_GPR_A0] == ARCBIOS_STDIN) {
1555 int i, nread = 0;
1556 /*
1557 * Before going into the loop, make sure stdout
1558 * is flushed. If we're using an X11 VGA console,
1559 * then it needs to be flushed as well.
1560 */
1561 fflush(stdin);
1562 fflush(stdout);
1563 /* NOTE/TODO: This gives a tick to _everything_ */
1564 for (i=0; i<cpu->machine->n_tick_entries; i++)
1565 cpu->machine->tick_func[i](cpu,
1566 cpu->machine->tick_extra[i]);
1567
1568 for (i=0; i<cpu->cd.mips.gpr[MIPS_GPR_A2]; i++) {
1569 int x;
1570 unsigned char ch;
1571
1572 /* Read from STDIN is blocking (at least
1573 that seems to be how NetBSD's arcdiag
1574 wants it) */
1575 x = console_readchar(cpu->machine->
1576 main_console_handle);
1577 if (x < 0)
1578 return 0;
1579
1580 /*
1581 * ESC + '[' should be transformed into 0x9b:
1582 *
1583 * NOTE/TODO: This makes the behaviour of just
1584 * pressing ESC a bit harder to define.
1585 */
1586 if (x == 27) {
1587 x = console_readchar(cpu->
1588 machine->main_console_handle);
1589 if (x == '[' || x == 'O')
1590 x = 0x9b;
1591 }
1592
1593 ch = x;
1594 nread ++;
1595 cpu->memory_rw(cpu, cpu->mem,
1596 cpu->cd.mips.gpr[MIPS_GPR_A1] + i,
1597 &ch, 1, MEM_WRITE, CACHE_NONE);
1598
1599 /* NOTE: Only one char, from STDIN: */
1600 i = cpu->cd.mips.gpr[MIPS_GPR_A2]; /* :-) */
1601 }
1602 store_32bit_word(cpu, cpu->cd.mips.gpr[MIPS_GPR_A3],
1603 nread);
1604 /* TODO: not EAGAIN? */
1605 cpu->cd.mips.gpr[MIPS_GPR_V0] =
1606 nread? ARCBIOS_ESUCCESS: ARCBIOS_EAGAIN;
1607 } else {
1608 int handle = cpu->cd.mips.gpr[MIPS_GPR_A0];
1609 int disk_id = arcbios_handle_to_scsi_id(handle);
1610 uint64_t partition_offset = 0;
1611 int res;
1612 uint64_t size; /* dummy */
1613 unsigned char *tmp_buf;
1614
1615 arcbios_handle_to_start_and_size(cpu->machine,
1616 handle, &partition_offset, &size);
1617
1618 debug("[ ARCBIOS Read(%i,0x%08x,0x%08x,0x%08x) ]\n",
1619 (int)cpu->cd.mips.gpr[MIPS_GPR_A0],
1620 (int)cpu->cd.mips.gpr[MIPS_GPR_A1],
1621 (int)cpu->cd.mips.gpr[MIPS_GPR_A2],
1622 (int)cpu->cd.mips.gpr[MIPS_GPR_A3]);
1623
1624 tmp_buf = malloc(cpu->cd.mips.gpr[MIPS_GPR_A2]);
1625 if (tmp_buf == NULL) {
1626 fprintf(stderr, "[ *** Out of memory in "
1627 "arcbios.c, allocating %i bytes ]\n",
1628 (int)cpu->cd.mips.gpr[MIPS_GPR_A2]);
1629 break;
1630 }
1631
1632 res = diskimage_access(cpu->machine, disk_id, 0,
1633 partition_offset + arcbios_current_seek_offset[
1634 handle], tmp_buf, cpu->cd.mips.gpr[MIPS_GPR_A2]);
1635
1636 /* If the transfer was successful, transfer the
1637 data to emulated memory: */
1638 if (res) {
1639 uint64_t dst = cpu->cd.mips.gpr[MIPS_GPR_A1];
1640 store_buf(cpu, dst, (char *)tmp_buf,
1641 cpu->cd.mips.gpr[MIPS_GPR_A2]);
1642 store_32bit_word(cpu,
1643 cpu->cd.mips.gpr[MIPS_GPR_A3],
1644 cpu->cd.mips.gpr[MIPS_GPR_A2]);
1645 arcbios_current_seek_offset[handle] +=
1646 cpu->cd.mips.gpr[MIPS_GPR_A2];
1647 cpu->cd.mips.gpr[MIPS_GPR_V0] = 0;
1648 } else
1649 cpu->cd.mips.gpr[MIPS_GPR_V0] = ARCBIOS_EIO;
1650 free(tmp_buf);
1651 }
1652 break;
1653 case 0x68: /* GetReadStatus(handle) */
1654 /*
1655 * According to arcbios_tty_getchar() in NetBSD's
1656 * dev/arcbios/arcbios_tty.c, GetReadStatus should
1657 * return 0 if there is something available.
1658 *
1659 * TODO: Error codes are things like ARCBIOS_EAGAIN.
1660 */
1661 if (cpu->cd.mips.gpr[MIPS_GPR_A0] == ARCBIOS_STDIN) {
1662 cpu->cd.mips.gpr[MIPS_GPR_V0] = console_charavail(
1663 cpu->machine->main_console_handle)? 0 : 1;
1664 } else {
1665 fatal("[ ARCBIOS GetReadStatus(%i) from "
1666 "something other than STDIN: TODO ]\n",
1667 (int)cpu->cd.mips.gpr[MIPS_GPR_A0]);
1668 /* TODO */
1669 cpu->cd.mips.gpr[MIPS_GPR_V0] = 1;
1670 }
1671 break;
1672 case 0x6c: /* Write(handle, buf, len, &returnlen) */
1673 if (cpu->cd.mips.gpr[MIPS_GPR_A0] != ARCBIOS_STDOUT) {
1674 /*
1675 * TODO: this is just a test
1676 */
1677 int handle = cpu->cd.mips.gpr[MIPS_GPR_A0];
1678 int disk_id = arcbios_handle_to_scsi_id(handle);
1679 uint64_t partition_offset = 0;
1680 int res, i;
1681 uint64_t size; /* dummy */
1682 unsigned char *tmp_buf;
1683
1684 arcbios_handle_to_start_and_size(cpu->machine,
1685 handle, &partition_offset, &size);
1686
1687 debug("[ ARCBIOS Write(%i,0x%08llx,%i,0x%08llx) ]\n",
1688 (int)cpu->cd.mips.gpr[MIPS_GPR_A0],
1689 (long long)cpu->cd.mips.gpr[MIPS_GPR_A1],
1690 (int)cpu->cd.mips.gpr[MIPS_GPR_A2],
1691 (long long)cpu->cd.mips.gpr[MIPS_GPR_A3]);
1692
1693 tmp_buf = malloc(cpu->cd.mips.gpr[MIPS_GPR_A2]);
1694 if (tmp_buf == NULL) {
1695 fprintf(stderr, "[ *** Out of memory in"
1696 " arcbios.c, allocating %i bytes ]\n",
1697 (int)cpu->cd.mips.gpr[MIPS_GPR_A2]);
1698 break;
1699 }
1700
1701 for (i=0; i<cpu->cd.mips.gpr[MIPS_GPR_A2]; i++)
1702 cpu->memory_rw(cpu, cpu->mem,
1703 cpu->cd.mips.gpr[MIPS_GPR_A1] + i,
1704 &tmp_buf[i], sizeof(char), MEM_READ,
1705 CACHE_NONE);
1706
1707 res = diskimage_access(cpu->machine, disk_id, 1,
1708 partition_offset + arcbios_current_seek_offset[
1709 handle], tmp_buf, cpu->cd.mips.gpr[MIPS_GPR_A2]);
1710
1711 if (res) {
1712 store_32bit_word(cpu,
1713 cpu->cd.mips.gpr[MIPS_GPR_A3],
1714 cpu->cd.mips.gpr[MIPS_GPR_A2]);
1715 arcbios_current_seek_offset[handle] +=
1716 cpu->cd.mips.gpr[MIPS_GPR_A2];
1717 cpu->cd.mips.gpr[MIPS_GPR_V0] = 0;
1718 } else
1719 cpu->cd.mips.gpr[MIPS_GPR_V0] = ARCBIOS_EIO;
1720 free(tmp_buf);
1721 } else {
1722 for (i=0; i<cpu->cd.mips.gpr[MIPS_GPR_A2]; i++) {
1723 unsigned char ch = '\0';
1724 cpu->memory_rw(cpu, cpu->mem,
1725 cpu->cd.mips.gpr[MIPS_GPR_A1] + i,
1726 &ch, sizeof(ch), MEM_READ, CACHE_NONE);
1727
1728 arcbios_putchar(cpu, ch);
1729 }
1730 }
1731 store_32bit_word(cpu, cpu->cd.mips.gpr[MIPS_GPR_A3],
1732 cpu->cd.mips.gpr[MIPS_GPR_A2]);
1733 cpu->cd.mips.gpr[MIPS_GPR_V0] = 0; /* Success. */
1734 break;
1735 case 0x70: /* Seek(uint32_t handle, int64_t *ofs,
1736 uint32_t whence): uint32_t */
1737 debug("[ ARCBIOS Seek(%i,0x%08llx,%i): ",
1738 (int)cpu->cd.mips.gpr[MIPS_GPR_A0],
1739 (long long)cpu->cd.mips.gpr[MIPS_GPR_A1],
1740 (int)cpu->cd.mips.gpr[MIPS_GPR_A2]);
1741
1742 if (cpu->cd.mips.gpr[MIPS_GPR_A2] != 0) {
1743 fatal("[ ARCBIOS Seek(%i,0x%08llx,%i): "
1744 "UNIMPLEMENTED whence=%i ]\n",
1745 (int)cpu->cd.mips.gpr[MIPS_GPR_A0],
1746 (long long)cpu->cd.mips.gpr[MIPS_GPR_A1],
1747 (int)cpu->cd.mips.gpr[MIPS_GPR_A2],
1748 (int)cpu->cd.mips.gpr[MIPS_GPR_A2]);
1749 }
1750
1751 {
1752 unsigned char buf[8];
1753 uint64_t ofs;
1754 cpu->memory_rw(cpu, cpu->mem,
1755 cpu->cd.mips.gpr[MIPS_GPR_A1], &buf[0],
1756 sizeof(buf), MEM_READ, CACHE_NONE);
1757 if (cpu->byte_order == EMUL_BIG_ENDIAN) {
1758 unsigned char tmp;
1759 tmp = buf[0]; buf[0] = buf[7]; buf[7] = tmp;
1760 tmp = buf[1]; buf[1] = buf[6]; buf[6] = tmp;
1761 tmp = buf[2]; buf[2] = buf[5]; buf[5] = tmp;
1762 tmp = buf[3]; buf[3] = buf[4]; buf[4] = tmp;
1763 }
1764 ofs = buf[0] + (buf[1] << 8) + (buf[2] << 16) +
1765 (buf[3] << 24) + ((uint64_t)buf[4] << 32) +
1766 ((uint64_t)buf[5] << 40) + ((uint64_t)buf[6] << 48)
1767 + ((uint64_t)buf[7] << 56);
1768 arcbios_current_seek_offset[
1769 cpu->cd.mips.gpr[MIPS_GPR_A0]] = ofs;
1770 debug("%016llx ]\n", (long long)ofs);
1771 }
1772
1773 cpu->cd.mips.gpr[MIPS_GPR_V0] = 0; /* Success. */
1774
1775 break;
1776 case 0x78: /* GetEnvironmentVariable(char *) */
1777 /* Find the environment variable given by a0: */
1778 for (i=0; i<sizeof(buf); i++)
1779 cpu->memory_rw(cpu, cpu->mem,
1780 cpu->cd.mips.gpr[MIPS_GPR_A0] + i,
1781 &buf[i], sizeof(char), MEM_READ, CACHE_NONE);
1782 buf[sizeof(buf)-1] = '\0';
1783 debug("[ ARCBIOS GetEnvironmentVariable(\"%s\") ]\n", buf);
1784 for (i=0; i<0x1000; i++) {
1785 /* Matching string at offset i? */
1786 int nmatches = 0;
1787 for (j=0; j<strlen((char *)buf); j++) {
1788 cpu->memory_rw(cpu, cpu->mem,
1789 (uint64_t)(ARC_ENV_STRINGS + i + j),
1790 &ch2, sizeof(char), MEM_READ, CACHE_NONE);
1791 if (ch2 == buf[j])
1792 nmatches++;
1793 }
1794 cpu->memory_rw(cpu, cpu->mem,
1795 (uint64_t)(ARC_ENV_STRINGS + i +
1796 strlen((char *)buf)), &ch2, sizeof(char),
1797 MEM_READ, CACHE_NONE);
1798 if (nmatches == strlen((char *)buf) && ch2 == '=') {
1799 cpu->cd.mips.gpr[MIPS_GPR_V0] =
1800 ARC_ENV_STRINGS + i +
1801 strlen((char *)buf) + 1;
1802 return 1;
1803 }
1804 }
1805 /* Return NULL if string wasn't found. */
1806 cpu->cd.mips.gpr[MIPS_GPR_V0] = 0;
1807 break;
1808 case 0x7c: /* SetEnvironmentVariable(char *, char *) */
1809 debug("[ ARCBIOS SetEnvironmentVariable(\"");
1810 dump_mem_string(cpu, cpu->cd.mips.gpr[MIPS_GPR_A0]);
1811 debug("\",\"");
1812 dump_mem_string(cpu, cpu->cd.mips.gpr[MIPS_GPR_A1]);
1813 debug("\") ]\n");
1814 /* TODO: This is a dummy. */
1815 cpu->cd.mips.gpr[MIPS_GPR_V0] = ARCBIOS_ESUCCESS;
1816 break;
1817 case 0x80: /* GetFileInformation() */
1818 debug("[ ARCBIOS GetFileInformation(%i,0x%x): ",
1819 (int)cpu->cd.mips.gpr[MIPS_GPR_A0],
1820 (int)cpu->cd.mips.gpr[MIPS_GPR_A1]);
1821
1822 if (cpu->cd.mips.gpr[MIPS_GPR_A0] >= MAX_HANDLES) {
1823 debug("invalid file handle ]\n");
1824 cpu->cd.mips.gpr[MIPS_GPR_V0] = ARCBIOS_EINVAL;
1825 } else if (!file_handle_in_use[cpu->cd.mips.gpr[MIPS_GPR_A0]]) {
1826 debug("file handle not in use! ]\n");
1827 cpu->cd.mips.gpr[MIPS_GPR_V0] = ARCBIOS_EBADF;
1828 } else {
1829 debug("'%s' ]\n", file_handle_string[
1830 cpu->cd.mips.gpr[MIPS_GPR_A0]]);
1831 cpu->cd.mips.gpr[MIPS_GPR_V0] =
1832 arcbios_getfileinformation(cpu);
1833 }
1834 break;
1835 case 0x88: /* FlushAllCaches() */
1836 debug("[ ARCBIOS FlushAllCaches(): TODO ]\n");
1837 cpu->cd.mips.gpr[MIPS_GPR_V0] = 0;
1838 break;
1839 case 0x90: /* void *GetDisplayStatus(handle) */
1840 debug("[ ARCBIOS GetDisplayStatus(%i) ]\n",
1841 (int)cpu->cd.mips.gpr[MIPS_GPR_A0]);
1842 /* TODO: handle different values of 'handle'? */
1843 cpu->cd.mips.gpr[MIPS_GPR_V0] = ARC_DSPSTAT_ADDR;
1844 break;
1845 case 0x100:
1846 /*
1847 * Undocumented, used by IRIX.
1848 */
1849 debug("[ ARCBIOS: IRIX 0x100 (?) ]\n");
1850 /* TODO */
1851 cpu->cd.mips.gpr[MIPS_GPR_V0] = 0;
1852 break;
1853 case 0x888:
1854 /*
1855 * Magical crash if there is no exception handling code.
1856 */
1857 fatal("EXCEPTION, but no exception handler installed yet.\n");
1858 quiet_mode = 0;
1859 cpu_register_dump(cpu->machine, cpu, 1, 0x1);
1860 cpu->running = 0;
1861 cpu->dead = 1;
1862 break;
1863 default:
1864 quiet_mode = 0;
1865 cpu_register_dump(cpu->machine, cpu, 1, 0x1);
1866 debug("a0 points to: ");
1867 dump_mem_string(cpu, cpu->cd.mips.gpr[MIPS_GPR_A0]);
1868 debug("\n");
1869 fatal("ARCBIOS: unimplemented vector 0x%x\n", vector);
1870 cpu->running = 0;
1871 cpu->dead = 1;
1872 }
1873
1874 return 1;
1875 }
1876
1877
1878 /*
1879 * arcbios_set_64bit_mode():
1880 *
1881 * Should be used for some SGI modes.
1882 */
1883 void arcbios_set_64bit_mode(int enable)
1884 {
1885 arc_64bit = enable;
1886 arc_wordlen = arc_64bit? sizeof(uint64_t) : sizeof(uint32_t);
1887 }
1888
1889
1890 /*
1891 * arcbios_set_default_exception_handler():
1892 */
1893 void arcbios_set_default_exception_handler(struct cpu *cpu)
1894 {
1895 /*
1896 * The default exception handlers simply jump to 0xbfc88888,
1897 * which is then taken care of in arcbios_emul() above.
1898 *
1899 * 3c1abfc8 lui k0,0xbfc8
1900 * 375a8888 ori k0,k0,0x8888
1901 * 03400008 jr k0
1902 * 00000000 nop
1903 */
1904 store_32bit_word(cpu, 0xffffffff80000000ULL, 0x3c1abfc8);
1905 store_32bit_word(cpu, 0xffffffff80000004ULL, 0x375a8888);
1906 store_32bit_word(cpu, 0xffffffff80000008ULL, 0x03400008);
1907 store_32bit_word(cpu, 0xffffffff8000000cULL, 0x00000000);
1908
1909 store_32bit_word(cpu, 0xffffffff80000080ULL, 0x3c1abfc8);
1910 store_32bit_word(cpu, 0xffffffff80000084ULL, 0x375a8888);
1911 store_32bit_word(cpu, 0xffffffff80000088ULL, 0x03400008);
1912 store_32bit_word(cpu, 0xffffffff8000008cULL, 0x00000000);
1913
1914 store_32bit_word(cpu, 0xffffffff80000180ULL, 0x3c1abfc8);
1915 store_32bit_word(cpu, 0xffffffff80000184ULL, 0x375a8888);
1916 store_32bit_word(cpu, 0xffffffff80000188ULL, 0x03400008);
1917 store_32bit_word(cpu, 0xffffffff8000018cULL, 0x00000000);
1918 }
1919
1920
1921 /*
1922 * arcbios_init():
1923 *
1924 * Should be called before any other arcbios function is used.
1925 */
1926 void arcbios_init(void)
1927 {
1928 int i;
1929
1930 /* File handles 0, 1, and 2 are stdin, stdout, and stderr. */
1931 for (i=0; i<MAX_HANDLES; i++) {
1932 file_handle_in_use[i] = i<3? 1 : 0;
1933 file_handle_string[i] = NULL;
1934 arcbios_current_seek_offset[i] = 0;
1935 }
1936 }
1937

  ViewVC Help
Powered by ViewVC 1.1.26