/[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

Annotation of /upstream/0.3.2/src/arcbios.c

Parent Directory Parent Directory | Revision Log Revision Log


Revision 5 - (hide 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 dpavlin 2 /*
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