/[gxemul]/upstream/0.4.3/src/promemul/arcbios.c
This is repository of my old source code which isn't updated any more. Go to git.rot13.org for current projects!
ViewVC logotype

Annotation of /upstream/0.4.3/src/promemul/arcbios.c

Parent Directory Parent Directory | Revision Log Revision Log


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

  ViewVC Help
Powered by ViewVC 1.1.26