arcbios.cc Source File

Back to the index.

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

Generated on Sun Sep 30 2018 16:05:18 for GXemul by doxygen 1.8.13