arcbios.cc Source File

Back to the index.

arcbios.cc
Go to the documentation of this file.
1 /*
2  * Copyright (C) 2003-2018 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 and ARCS 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  uint64_t envptr = machine->machine_type == MACHINE_SGI ? ARC_ENV_STRINGS_SGI : ARC_ENV_STRINGS;
1773  for (j=0; j<(ssize_t)strlen((char *)buf); j++) {
1774  cpu->memory_rw(cpu, cpu->mem,
1775  (uint64_t)(envptr + i + j),
1776  &ch2, sizeof(char), MEM_READ, CACHE_NONE);
1777  if (ch2 == buf[j])
1778  nmatches++;
1779  }
1780  cpu->memory_rw(cpu, cpu->mem,
1781  (uint64_t)(envptr + i +
1782  strlen((char *)buf)), &ch2, sizeof(char),
1783  MEM_READ, CACHE_NONE);
1784  if (nmatches == (int)strlen((char *)buf) && ch2=='=') {
1785  cpu->cd.mips.gpr[MIPS_GPR_V0] =
1786  envptr + i +
1787  strlen((char *)buf) + 1;
1788  return 1;
1789  }
1790  }
1791  /* Return NULL if string wasn't found. */
1792  cpu->cd.mips.gpr[MIPS_GPR_V0] = 0;
1793  break;
1794  case 0x7c: /* SetEnvironmentVariable(char *, char *) */
1795  debug("[ ARCBIOS SetEnvironmentVariable(\"");
1796  dump_mem_string(cpu, cpu->cd.mips.gpr[MIPS_GPR_A0]);
1797  debug("\",\"");
1798  dump_mem_string(cpu, cpu->cd.mips.gpr[MIPS_GPR_A1]);
1799  debug("\") ]\n");
1800  /* TODO: This is a dummy. */
1802  break;
1803  case 0x80: /* GetFileInformation() */
1804  debug("[ ARCBIOS GetFileInformation(%i,0x%x): ",
1805  (int)cpu->cd.mips.gpr[MIPS_GPR_A0],
1806  (int)cpu->cd.mips.gpr[MIPS_GPR_A1]);
1807 
1808  if (cpu->cd.mips.gpr[MIPS_GPR_A0] >= ARC_MAX_HANDLES) {
1809  debug("invalid file handle ]\n");
1811  } else if (!machine->md.arc->file_handle_in_use[cpu->cd.
1812  mips.gpr[MIPS_GPR_A0]]) {
1813  debug("file handle not in use! ]\n");
1815  } else {
1816  debug("'%s' ]\n", machine->md.arc->file_handle_string[
1817  cpu->cd.mips.gpr[MIPS_GPR_A0]]);
1818  cpu->cd.mips.gpr[MIPS_GPR_V0] =
1819  arcbios_getfileinformation(cpu);
1820  }
1821  break;
1822  case 0x88: /* FlushAllCaches() */
1823  debug("[ ARCBIOS FlushAllCaches(): TODO ]\n");
1824  cpu->cd.mips.gpr[MIPS_GPR_V0] = 0;
1825  break;
1826  case 0x90: /* void *GetDisplayStatus(handle) */
1827  debug("[ ARCBIOS GetDisplayStatus(%i) ]\n",
1828  (int)cpu->cd.mips.gpr[MIPS_GPR_A0]);
1829  /* TODO: handle different values of 'handle'? */
1831  break;
1832  case 0x100:
1833  /*
1834  * Undocumented, used by IRIX.
1835  */
1836  debug("[ ARCBIOS: IRIX 0x100 (?) ]\n");
1837  /* TODO */
1838  cpu->cd.mips.gpr[MIPS_GPR_V0] = 0;
1839  break;
1840  case 0x888:
1841  /*
1842  * Magical crash if there is no exception handling code.
1843  */
1844  fatal("EXCEPTION, but no exception handler installed yet.\n");
1845  quiet_mode = 0;
1846  cpu_register_dump(machine, cpu, 1, 0x1);
1847  cpu->running = 0;
1848  break;
1849  default:
1850  quiet_mode = 0;
1851  cpu_register_dump(machine, cpu, 1, 0x1);
1852  debug("a0 points to: ");
1853  dump_mem_string(cpu, cpu->cd.mips.gpr[MIPS_GPR_A0]);
1854  debug("\n");
1855  fatal("ARCBIOS: unimplemented vector 0x%x\n", vector);
1856  cpu->running = 0;
1857  }
1858 
1859  return 1;
1860 }
1861 
1862 
1863 /*
1864  * arcbios_set_default_exception_handler():
1865  */
1867 {
1868  /*
1869  * The default exception handlers simply jump to 0xbfc88888,
1870  * which is then taken care of in arcbios_emul() above.
1871  *
1872  * 3c1abfc8 lui k0,0xbfc8
1873  * 375a8888 ori k0,k0,0x8888
1874  * 03400008 jr k0
1875  * 00000000 nop
1876  */
1877  store_32bit_word(cpu, 0xffffffff80000000ULL, 0x3c1abfc8);
1878  store_32bit_word(cpu, 0xffffffff80000004ULL, 0x375a8888);
1879  store_32bit_word(cpu, 0xffffffff80000008ULL, 0x03400008);
1880  store_32bit_word(cpu, 0xffffffff8000000cULL, 0x00000000);
1881 
1882  store_32bit_word(cpu, 0xffffffff80000080ULL, 0x3c1abfc8);
1883  store_32bit_word(cpu, 0xffffffff80000084ULL, 0x375a8888);
1884  store_32bit_word(cpu, 0xffffffff80000088ULL, 0x03400008);
1885  store_32bit_word(cpu, 0xffffffff8000008cULL, 0x00000000);
1886 
1887  store_32bit_word(cpu, 0xffffffff80000180ULL, 0x3c1abfc8);
1888  store_32bit_word(cpu, 0xffffffff80000184ULL, 0x375a8888);
1889  store_32bit_word(cpu, 0xffffffff80000188ULL, 0x03400008);
1890  store_32bit_word(cpu, 0xffffffff8000018cULL, 0x00000000);
1891 }
1892 
1893 
1894 /*
1895  * arcbios_add_other_components():
1896  *
1897  * TODO: How should this be synched with the hardware devices
1898  * added in machine.c?
1899  */
1900 static void arcbios_add_other_components(struct machine *machine,
1901  uint64_t system)
1902 {
1903  struct cpu *cpu = machine->cpus[0];
1904 
1905  if (machine->machine_type == MACHINE_ARC &&
1907  || machine->machine_subtype == MACHINE_ARC_JAZZ_MAGNUM)) {
1908  uint64_t jazzbus, ali_s3, vxl;
1909  uint64_t diskcontroller, floppy, kbdctl, kbd;
1910  uint64_t ptrctl, ptr, paral, audio;
1911  uint64_t eisa, scsi;
1912  /* uint64_t serial1, serial2; */
1913 
1914  jazzbus = arcbios_addchild_manual(cpu,
1917  0, 1, 2, 0, 0xffffffff, "Jazz-Internal Bus",
1918  system, NULL, 0);
1919 
1920  /*
1921  * DisplayController, needed by NetBSD:
1922  * TODO: NetBSD still doesn't use it :(
1923  */
1924  switch (machine->machine_subtype) {
1925  case MACHINE_ARC_JAZZ_PICA:
1926  /* Default TLB entries on PICA-61: */
1927 
1928  /* 7: 256K, asid: 0x0, v: 0xe1000000,
1929  p0: 0xfff00000(2.VG), p1: 0x0(0..G) */
1930  mips_coproc_tlb_set_entry(cpu, 7, 262144,
1931  0xffffffffe1000000ULL,
1932  0x0fff00000ULL, 0, 1, 0, 0, 0, 1, 0, 2, 0);
1933 
1934  /* 8: 64K, asid: 0x0, v: 0xe0000000,
1935  p0: 0x80000000(2DVG), p1: 0x0(0..G) */
1936  mips_coproc_tlb_set_entry(cpu, 8, 65536,
1937  0xffffffffe0000000ULL,
1938  0x080000000ULL, 0, 1, 0, 1, 0, 1, 0, 2, 0);
1939 
1940  /* 9: 64K, asid: 0x0, v: 0xe00e0000,
1941  p0: 0x800e0000(2DVG), p1: 0x800f0000(2DVG) */
1942  mips_coproc_tlb_set_entry(cpu, 9, 65536,
1943  (uint64_t)0xffffffffe00e0000ULL,
1944  (uint64_t)0x0800e0000ULL,
1945  (uint64_t)0x0800f0000ULL, 1, 1, 1, 1, 1, 0, 2, 2);
1946 
1947  /* 10: 4K, asid: 0x0, v: 0xe0100000,
1948  p0: 0xf0000000(2DVG), p1: 0x0(0..G) */
1949  mips_coproc_tlb_set_entry(cpu, 10, 4096,
1950  (uint64_t)0xffffffffe0100000ULL,
1951  (uint64_t)0x0f0000000ULL, 0,1, 0, 1, 0, 1, 0, 2, 0);
1952 
1953  /* 11: 1M, asid: 0x0, v: 0xe0200000,
1954  p0: 0x60000000(2DVG), p1: 0x60100000(2DVG) */
1955  mips_coproc_tlb_set_entry(cpu, 11, 1048576,
1956  0xffffffffe0200000ULL,
1957  0x060000000ULL, 0x060100000ULL,1,1,1,1,1, 0, 2, 2);
1958 
1959  /* 12: 1M, asid: 0x0, v: 0xe0400000,
1960  p0: 0x60200000(2DVG), p1: 0x60300000(2DVG) */
1961  mips_coproc_tlb_set_entry(cpu, 12, 1048576,
1962  0xffffffffe0400000ULL, 0x060200000ULL,
1963  0x060300000ULL, 1, 1, 1, 1, 1, 0, 2, 2);
1964 
1965  /* 13: 4M, asid: 0x0, v: 0xe0800000,
1966  p0: 0x40000000(2DVG), p1: 0x40400000(2DVG) */
1967  mips_coproc_tlb_set_entry(cpu, 13, 1048576*4,
1968  0xffffffffe0800000ULL, 0x040000000ULL,
1969  0x040400000ULL, 1, 1, 1, 1, 1, 0, 2, 2);
1970 
1971  /* 14: 16M, asid: 0x0, v: 0xe2000000,
1972  p0: 0x90000000(2DVG), p1: 0x91000000(2DVG) */
1973  mips_coproc_tlb_set_entry(cpu, 14, 1048576*16,
1974  0xffffffffe2000000ULL, 0x090000000ULL,
1975  0x091000000ULL, 1, 1, 1, 1, 1, 0, 2, 2);
1976 
1977  if (machine->x11_md.in_use) {
1978  ali_s3 = arcbios_addchild_manual(cpu,
1983  1, 2, 0, 0xffffffff, "ALI_S3",
1984  jazzbus, NULL, 0);
1985 
1991  1, 2, 0, 0xffffffff, "1024x768",
1992  ali_s3, NULL, 0);
1993  }
1994  break;
1996  if (machine->x11_md.in_use) {
1997  vxl = arcbios_addchild_manual(cpu,
2002  1, 2, 0, 0xffffffff, "VXL",
2003  jazzbus, NULL, 0);
2004 
2010  1, 2, 0, 0xffffffff, "1024x768",
2011  vxl, NULL, 0);
2012  }
2013  break;
2014  }
2015 
2016  diskcontroller = arcbios_addchild_manual(cpu,
2020  1, 2, 0, 0xffffffff, "I82077", jazzbus, NULL, 0);
2021 
2022  floppy = arcbios_addchild_manual(cpu,
2027  1, 2, 0, 0xffffffff, NULL, diskcontroller, NULL, 0);
2028 
2029  kbdctl = arcbios_addchild_manual(cpu,
2033  1, 2, 0, 0xffffffff, "I8742", jazzbus, NULL, 0);
2034 
2035  kbd = arcbios_addchild_manual(cpu,
2039  1, 2, 0, 0xffffffff, "PCAT_ENHANCED", kbdctl, NULL, 0);
2040 
2041  ptrctl = arcbios_addchild_manual(cpu,
2044  1, 2, 0, 0xffffffff, "I8742", jazzbus, NULL, 0);
2045 
2046  ptr = arcbios_addchild_manual(cpu,
2049  1, 2, 0, 0xffffffff, "PS2 MOUSE", ptrctl, NULL, 0);
2050 
2051 /* These cause Windows NT to bug out. */
2052 #if 0
2053  serial1 = arcbios_addchild_manual(cpu,
2057  1, 2, 0, 0xffffffff, "COM1", jazzbus, NULL, 0);
2058 
2059  serial2 = arcbios_addchild_manual(cpu,
2063  1, 2, 0, 0xffffffff, "COM1", jazzbus, NULL, 0);
2064 #endif
2065 
2066  paral = arcbios_addchild_manual(cpu,
2070  1, 2, 0, 0xffffffff, "LPT1", jazzbus, NULL, 0);
2071 
2072  audio = arcbios_addchild_manual(cpu,
2076  1, 2, 0, 0xffffffff, "MAGNUM", jazzbus, NULL, 0);
2077 
2078  eisa = arcbios_addchild_manual(cpu,
2080  0, 1, 2, 0, 0xffffffff, "EISA", system, NULL, 0);
2081 
2082  {
2083  unsigned char config[78];
2084  memset(config, 0, sizeof(config));
2085 
2086 /* config data version: 1, revision: 2, count: 4 */
2087 config[0] = 0x01; config[1] = 0x00;
2088 config[2] = 0x02; config[3] = 0x00;
2089 config[4] = 0x04; config[5] = 0x00; config[6] = 0x00; config[7] = 0x00;
2090 
2091 /*
2092  type: Interrupt
2093  share_disposition: DeviceExclusive, flags: LevelSensitive
2094  level: 4, vector: 22, reserved1: 0
2095 */
2096  config[8] = arc_CmResourceTypeInterrupt;
2099  config[12] = 4;
2100  config[16] = 22;
2101  config[20] = 0;
2102 
2103 /*
2104  type: Memory
2105  share_disposition: DeviceExclusive, flags: ReadWrite
2106  start: 0x 0 80002000, length: 0x1000
2107 */
2108  config[24] = arc_CmResourceTypeMemory;
2110  config[26] = arc_CmResourceMemoryReadWrite;
2111 config[28] = 0x00; config[29] = 0x20; config[30] = 0x00; config[31] = 0x80;
2112  config[32] = 0x00; config[33] = 0x00; config[34] = 0x00; config[35] = 0x00;
2113 config[36] = 0x00; config[37] = 0x10; config[38] = 0x00; config[39] = 0x00;
2114 
2115 /*
2116  type: DMA
2117  share_disposition: DeviceExclusive, flags: 0x0
2118  channel: 0, port: 0, reserved1: 0
2119 */
2120  config[40] = arc_CmResourceTypeDMA;
2122 /* 42..43 = flags, 44,45,46,47 = channel, 48,49,50,51 = port, 52,53,54,55
2123  = reserved */
2124 
2125 /* type: DeviceSpecific
2126  share_disposition: DeviceExclusive, flags: 0x0
2127  datasize: 6, reserved1: 0, reserved2: 0
2128  data: [0x1:0x0:0x2:0x0:0x7:0x30]
2129 */
2130  config[56] = arc_CmResourceTypeDeviceSpecific;
2132 /* 58,59 = flags 60,61,62,63 = data size, 64..71 = reserved */
2133  config[60] = 6;
2134 /* 72..77 = the data */
2135  config[72] = 0x01; config[73] = 0x00; config[74] = 0x02;
2136  config[75] = 0x00; config[76] = 0x07; config[77] = 0x30;
2137  scsi = arcbios_addchild_manual(cpu,
2140  0, 1, 2, 0, 0xffffffff, "ESP216",
2141  system, config, sizeof(config));
2142 
2143  arcbios_register_scsicontroller(machine, scsi);
2144  }
2145  }
2146 }
2147 
2148 
2149 /*
2150  * arcbios_console_init():
2151  *
2152  * Called from machine.c whenever an ARC-based machine is running with
2153  * a graphical VGA-style framebuffer, which can be used as console.
2154  */
2155 void arcbios_console_init(struct machine *machine,
2156  uint64_t vram, uint64_t ctrlregs)
2157 {
2158  if (machine->md.arc == NULL) {
2159  CHECK_ALLOCATION(machine->md.arc = (struct machine_arcbios *)
2160  malloc(sizeof(struct machine_arcbios)));
2161  memset(machine->md.arc, 0, sizeof(struct machine_arcbios));
2162  }
2163 
2164  machine->md.arc->vgaconsole = 1;
2165 
2166  machine->md.arc->console_vram = vram;
2167  machine->md.arc->console_ctrlregs = ctrlregs;
2168  machine->md.arc->console_maxx = ARC_CONSOLE_MAX_X;
2169  machine->md.arc->console_maxy = ARC_CONSOLE_MAX_Y;
2170  machine->md.arc->in_escape_sequence = 0;
2171  machine->md.arc->escape_sequence[0] = '\0';
2172 }
2173 
2174 
2175 /*
2176  * arc_environment_setup():
2177  *
2178  * Initialize the emulated environment variables.
2179  */
2180 static void arc_environment_setup(struct machine *machine, int is64bit,
2181  const char *primary_ether_addr)
2182 {
2183  size_t bootpath_len = 500;
2184  char *init_bootpath;
2185  uint64_t addr, addr2;
2186  struct cpu *cpu = machine->cpus[0];
2187 
2188  /*
2189  * Boot string in ARC format:
2190  *
2191  * TODO: How about floppies? multi()disk()fdisk()
2192  * Is tftp() good for netbooting?
2193  */
2194  CHECK_ALLOCATION(init_bootpath = (char *) malloc(bootpath_len));
2195  init_bootpath[0] = '\0';
2196 
2197  if (machine->bootdev_id < 0 || machine->force_netboot) {
2198  snprintf(init_bootpath, bootpath_len, "tftp()");
2199  } else {
2200  /* TODO: Make this nicer. */
2201  if (machine->machine_type == MACHINE_SGI) {
2202  if (machine->machine_subtype == 30)
2203  strlcat(init_bootpath, "xio(0)pci(15)",
2204  bootpath_len);
2205  if (machine->machine_subtype == 32)
2206  strlcat(init_bootpath, "pci(0)",
2207  bootpath_len);
2208  }
2209 
2210  if (diskimage_is_a_cdrom(machine, machine->bootdev_id,
2211  machine->bootdev_type))
2212  snprintf(init_bootpath + strlen(init_bootpath),
2213  bootpath_len - strlen(init_bootpath),
2214  "scsi(0)cdrom(%i)fdisk(0)", machine->bootdev_id);
2215  else
2216  snprintf(init_bootpath + strlen(init_bootpath),
2217  bootpath_len - strlen(init_bootpath),
2218  "scsi(0)disk(%i)rdisk(0)partition(1)",
2219  machine->bootdev_id);
2220  }
2221 
2222  if (machine->machine_type == MACHINE_ARC)
2223  strlcat(init_bootpath, "\\", bootpath_len);
2224 
2225  CHECK_ALLOCATION(machine->bootstr = (char *) malloc(ARC_BOOTSTR_BUFLEN));
2226 
2227  strlcpy(machine->bootstr, init_bootpath, ARC_BOOTSTR_BUFLEN);
2228  if (strlcat(machine->bootstr, machine->boot_kernel_filename,
2230  fprintf(stderr, "boot string too long?\n");
2231  exit(1);
2232  }
2233 
2234  /* Boot args., eg "-a" */
2235  machine->bootarg = machine->boot_string_argument;
2236 
2237  /* argc, argv, envp in a0, a1, a2: */
2238  cpu->cd.mips.gpr[MIPS_GPR_A0] = 0; /* note: argc is increased later */
2239 
2240  /* TODO: not needed? */
2241  cpu->cd.mips.gpr[MIPS_GPR_SP] = (int64_t)(int32_t)
2242  (machine->physical_ram_in_mb * 1048576 + 0x80000000 - 0x2080);
2243 
2244  /* Set up argc/argv: */
2245  addr = ARC_ENV_STRINGS;
2246  addr2 = ARC_ARGV_START;
2247  cpu->cd.mips.gpr[MIPS_GPR_A1] = addr2;
2248 
2249  /* bootstr: */
2250  store_pointer_and_advance(cpu, &addr2, addr, is64bit);
2251  add_environment_string(cpu, machine->bootstr, &addr);
2252  cpu->cd.mips.gpr[MIPS_GPR_A0] ++;
2253 
2254  /* bootarg: */
2255  if (machine->bootarg[0] != '\0') {
2256  store_pointer_and_advance(cpu, &addr2, addr, is64bit);
2257  add_environment_string(cpu, machine->bootarg, &addr);
2258  cpu->cd.mips.gpr[MIPS_GPR_A0] ++;
2259  }
2260 
2261  store_pointer_and_advance(cpu, &addr2, 0, is64bit);
2262 
2263  cpu->cd.mips.gpr[MIPS_GPR_A2] = addr2;
2264 
2265  if (machine->machine_type == MACHINE_SGI) {
2266  /*
2267  * The SGI O2 PROM contains an "env" section header like this:
2268  *
2269  * 00004000 00 00 00 00 00 00 00 00 53 48 44 52 00 00 04 00 |........SHDR....|
2270  * 00004010 03 03 00 00 65 6e 76 00 00 00 00 00 00 00 00 00 |....env.........|
2271  * 00004020 00 00 00 00 00 00 00 00 00 00 00 00 00 00 00 00 |................|
2272  * 00004030 00 00 00 00 31 2e 30 00 00 00 00 00 13 18 11 ae |....1.0.........|
2273  *
2274  * followed by environment variables at 0x4000. It is not required
2275  * by NetBSD/OpenBSD/Linux, but Irix seems to hardcodedly look into
2276  * the PROM address space for this header.
2277  */
2278  store_32bit_word(cpu, ARC_ENV_SGI + 0x08, 0x53484452);
2279  store_32bit_word(cpu, ARC_ENV_SGI + 0x0c, 0x00000400);
2280  store_32bit_word(cpu, ARC_ENV_SGI + 0x10, 0x03030000);
2281  store_32bit_word(cpu, ARC_ENV_SGI + 0x14, 0x656e7600);
2282  store_32bit_word(cpu, ARC_ENV_SGI + 0x34, 0x312e3000);
2283  store_32bit_word(cpu, ARC_ENV_SGI + 0x3c, 0x131811ae);
2284  addr = ARC_ENV_STRINGS_SGI;
2285  }
2286 
2287  /*
2288  * Add environment variables. For each variable, add it
2289  * as a string using add_environment_string(), and add a
2290  * pointer to it to the ARC_ENV_POINTERS array.
2291  */
2292  if (machine->machine_type == MACHINE_SGI) {
2293  if (machine->x11_md.in_use) {
2294  store_pointer_and_advance(cpu, &addr2, addr, is64bit);
2295  add_environment_string(cpu, "ConsoleIn=keyboard()",
2296  &addr);
2297  store_pointer_and_advance(cpu, &addr2, addr, is64bit);
2298  add_environment_string(cpu, "ConsoleOut=video()",
2299  &addr);
2300 
2301  /* g for graphical mode. G for graphical mode
2302  with SGI logo visible on Irix? */
2303  store_pointer_and_advance(cpu, &addr2, addr, is64bit);
2304  add_environment_string(cpu, "console=g", &addr);
2305 
2306  store_pointer_and_advance(cpu, &addr2, addr, is64bit);
2307  add_environment_string(cpu, "gfx=alive", &addr);
2308  } else {
2309  store_pointer_and_advance(cpu, &addr2, addr, is64bit);
2310  add_environment_string(cpu, "ConsoleIn=serial(0)",
2311  &addr);
2312  store_pointer_and_advance(cpu, &addr2, addr, is64bit);
2313  add_environment_string(cpu, "ConsoleOut=serial(0)",
2314  &addr);
2315 
2316  /* 'd' or 'd2' in Irix, 'ttyS0' in Linux? */
2317  store_pointer_and_advance(cpu, &addr2, addr, is64bit);
2318  add_environment_string(cpu, "console=d", &addr);
2319 
2320  store_pointer_and_advance(cpu, &addr2, addr, is64bit);
2321  add_environment_string(cpu, "gfx=dead", &addr);
2322  }
2323 
2324  store_pointer_and_advance(cpu, &addr2, addr, is64bit);
2325  add_environment_string(cpu, "AutoLoad=No", &addr);
2326 
2327  if (machine->bootdev_id < 0 || machine->force_netboot) {
2328  /*
2329  * diskless=1 means boot from network disk? (nfs?)
2330  * diskless=2 means boot from network tape?
2331  */
2332  store_pointer_and_advance(cpu, &addr2, addr, is64bit);
2333  add_environment_string(cpu, "diskless=1", &addr);
2334 
2335  // store_pointer_and_advance(cpu, &addr2, addr, is64bit);
2336  // add_environment_string(cpu, "tapedevice=bootp()10.0.0.2:/dev/tape", &addr);
2337 
2338  store_pointer_and_advance(cpu, &addr2, addr, is64bit);
2339  add_environment_string(cpu, "bootfile=bootp()10.0.0.2:/var/boot/client/unix", &addr);
2340 
2341  store_pointer_and_advance(cpu, &addr2, addr, is64bit);
2343  "SystemPartition=bootp()10.0.0.2:/var/boot/client",
2344  &addr);
2345  store_pointer_and_advance(cpu, &addr2, addr, is64bit);
2347  "root=xyz",
2348  &addr);
2349  store_pointer_and_advance(cpu, &addr2, addr, is64bit);
2351  "OSLoadPartition=bootp()10.0.0.2:/var/boot/client",
2352  &addr);
2353  } else {
2354  store_pointer_and_advance(cpu, &addr2, addr, is64bit);
2355  add_environment_string(cpu, "diskless=0", &addr);
2356 
2357  store_pointer_and_advance(cpu, &addr2, addr, is64bit);
2359  "SystemPartition=pci(0)scsi(0)disk(2)rdisk(0)partition(8)",
2360  &addr);
2361  store_pointer_and_advance(cpu, &addr2, addr, is64bit);
2363  "OSLoadPartition=pci(0)scsi(0)disk(2)rdisk(0)partition(0)",
2364  &addr);
2365  }
2366 
2367  store_pointer_and_advance(cpu, &addr2, addr, is64bit);
2368  add_environment_string(cpu, "volume=80", &addr);
2369  store_pointer_and_advance(cpu, &addr2, addr, is64bit);
2370  add_environment_string(cpu, "sgilogo=y", &addr);
2371 
2372  store_pointer_and_advance(cpu, &addr2, addr, is64bit);
2373  add_environment_string(cpu, "monitor=h", &addr);
2374  store_pointer_and_advance(cpu, &addr2, addr, is64bit);
2375  add_environment_string(cpu, "TimeZone=GMT", &addr);
2376  store_pointer_and_advance(cpu, &addr2, addr, is64bit);
2377  add_environment_string(cpu, "nogfxkbd=1", &addr);
2378 
2379  /* TODO IP30: 'xio(0)pci(15)scsi(0)disk(1)rdisk(0)partition(0)' */
2380 
2381  store_pointer_and_advance(cpu, &addr2, addr, is64bit);
2382  add_environment_string(cpu, "OSLoadFilename=/unix", &addr);
2383  store_pointer_and_advance(cpu, &addr2, addr, is64bit);
2384  add_environment_string(cpu, "OSLoader=sash", &addr);
2385  store_pointer_and_advance(cpu, &addr2, addr, is64bit);
2386  add_environment_string(cpu, "kernname=unix", &addr);
2387 
2388  store_pointer_and_advance(cpu, &addr2, addr, is64bit);
2389  add_environment_string(cpu, "rbaud=9600", &addr);
2390  store_pointer_and_advance(cpu, &addr2, addr, is64bit);
2391  add_environment_string(cpu, "rebound=y", &addr);
2392  store_pointer_and_advance(cpu, &addr2, addr, is64bit);
2393  add_environment_string(cpu, "crt_option=1", &addr);
2394  store_pointer_and_advance(cpu, &addr2, addr, is64bit);
2395  add_environment_string(cpu, "netaddr=10.0.0.1", &addr);
2396  store_pointer_and_advance(cpu, &addr2, addr, is64bit);
2397  add_environment_string(cpu, "netmask=255.0.0.0", &addr);
2398  store_pointer_and_advance(cpu, &addr2, addr, is64bit);
2399  add_environment_string(cpu, "dlserver=10.0.0.2", &addr);
2400  store_pointer_and_advance(cpu, &addr2, addr, is64bit);
2401  add_environment_string(cpu, "srvaddr=10.0.0.2", &addr);
2402 
2403  store_pointer_and_advance(cpu, &addr2, addr, is64bit);
2404  add_environment_string(cpu, "keybd=US", &addr);
2405 
2406  store_pointer_and_advance(cpu, &addr2, addr, is64bit);
2407  add_environment_string(cpu, "cpufreq=3", &addr);
2408  store_pointer_and_advance(cpu, &addr2, addr, is64bit);
2409  add_environment_string(cpu, "dbaud=9600", &addr);
2410  store_pointer_and_advance(cpu, &addr2, addr, is64bit);
2411  add_environment_string(cpu, primary_ether_addr, &addr);
2412 
2413  store_pointer_and_advance(cpu, &addr2, addr, is64bit);
2414  add_environment_string(cpu, "verbose=1", &addr);
2415  store_pointer_and_advance(cpu, &addr2, addr, is64bit);
2416  // showconfig 0 means don't show. 1 means show some.
2417  // 2 means show more. TODO: higher values?
2418  add_environment_string(cpu, "showconfig=255", &addr);
2419  store_pointer_and_advance(cpu, &addr2, addr, is64bit);
2420  add_environment_string(cpu, "diagmode=v", &addr);
2421  store_pointer_and_advance(cpu, &addr2, addr, is64bit);
2422  add_environment_string(cpu, "debug_bigmem=1", &addr);
2423  } else {
2424  char *tmp;
2425  size_t mlen = ARC_BOOTSTR_BUFLEN;
2426  CHECK_ALLOCATION(tmp = (char *) malloc(mlen));
2427  snprintf(tmp, mlen, "OSLOADOPTIONS=%s", machine->bootarg);
2428 
2429  store_pointer_and_advance(cpu, &addr2, addr, is64bit);
2430  add_environment_string(cpu, tmp, &addr);
2431 
2432  store_pointer_and_advance(cpu, &addr2, addr, is64bit);
2433  snprintf(tmp, mlen,
2434  "OSLOADPARTITION=scsi(0)disk(%d)rdisk(0)partition(1)",
2435  machine->bootdev_id);
2436  add_environment_string(cpu, tmp, &addr);
2437  free(tmp);
2438 
2439  if (machine->x11_md.in_use) {
2440  store_pointer_and_advance(cpu, &addr2, addr, is64bit);
2442  "CONSOLEIN=multi()key()keyboard()console()", &addr);
2443  store_pointer_and_advance(cpu, &addr2, addr, is64bit);
2445  "CONSOLEOUT=multi()video()monitor()console()",
2446  &addr);
2447  } else {
2448  /* TODO: serial console for ARC? */
2449  store_pointer_and_advance(cpu, &addr2, addr, is64bit);
2451  "CONSOLEIN=multi()serial(0)", &addr);
2452  store_pointer_and_advance(cpu, &addr2, addr, is64bit);
2454  "CONSOLEOUT=multi()serial(0)", &addr);
2455  }
2456  }
2457 
2458  /* End the environment strings with an empty zero-terminated
2459  string, and the envp array with a NULL pointer. */
2460  add_environment_string(cpu, "", &addr); /* the end */
2461  store_pointer_and_advance(cpu, &addr2, 0, is64bit);
2462 
2463  /* Return address: (0x20 = ReturnFromMain()) */
2464  cpu->cd.mips.gpr[MIPS_GPR_RA] = ARC_FIRMWARE_ENTRIES + 0x20;
2465 }
2466 
2467 
2468 /*
2469  * arcbios_init():
2470  *
2471  * Should be called before any other arcbios function is used. An exception
2472  * is arcbios_console_init(), which may be called before this function.
2473  *
2474  * TODO: Refactor; this is too long.
2475  */
2476 void arcbios_init(struct machine *machine, int is64bit, uint64_t sgi_ram_offset,
2477  const char *primary_ether_addr, uint8_t *primary_ether_macaddr)
2478 {
2479  int i, alloclen = 20;
2480  char *name;
2481  uint64_t arc_reserved, mem_base, mem_count;
2482  struct cpu *cpu = machine->cpus[0];
2483  struct arcbios_sysid arcbios_sysid;
2484  struct arcbios_dsp_stat arcbios_dsp_stat;
2485  uint64_t system = 0;
2486  struct arcbios_spb arcbios_spb;
2487  struct arcbios_spb_64 arcbios_spb_64;
2488 
2489  if (machine->md.arc == NULL) {
2490  CHECK_ALLOCATION(machine->md.arc = (struct machine_arcbios *)
2491  malloc(sizeof(struct machine_arcbios)));
2492  memset(machine->md.arc, 0, sizeof(struct machine_arcbios));
2493  }
2494 
2495  machine->md.arc->arc_64bit = is64bit;
2496  machine->md.arc->wordlen = is64bit? sizeof(uint64_t) : sizeof(uint32_t);
2497 
2500 
2501  if (machine->physical_ram_in_mb < 16)
2502  fprintf(stderr, "WARNING! The ARC platform specification "
2503  "doesn't allow less than 16 MB of RAM. Continuing "
2504  "anyway.\n");
2505 
2506  /* File handles 0, 1, and 2 are stdin, stdout, and stderr. */
2507  for (i=0; i<ARC_MAX_HANDLES; i++) {
2508  machine->md.arc->file_handle_in_use[i] = i<3? 1 : 0;
2509  machine->md.arc->file_handle_string[i] = i>=3? NULL :
2510  (i==0? "(stdin)" : (i==1? "(stdout)" : "(stderr)"));
2511  machine->md.arc->current_seek_offset[i] = 0;
2512  }
2513 
2514  if (!machine->x11_md.in_use)
2515  machine->md.arc->vgaconsole = 0;
2516 
2517  if (machine->md.arc->vgaconsole) {
2518  char tmpstr[100];
2519  int x, y;
2520 
2521  machine->md.arc->console_curcolor = 0x1f;
2522  for (y=0; y<machine->md.arc->console_maxy; y++)
2523  for (x=0; x<machine->md.arc->console_maxx; x++)
2524  arcbios_putcell(cpu, ' ', x, y);
2525 
2526  machine->md.arc->console_curx = 0;
2527  machine->md.arc->console_cury = 0;
2528 
2529  arcbios_putstring(cpu, "GXemul " VERSION" ARCBIOS emulation\n");
2530 
2531  snprintf(tmpstr, sizeof(tmpstr), "%i cpu%s (%s), %i MB "
2532  "memory\n\n", machine->ncpus, machine->ncpus > 1? "s" : "",
2533  cpu->cd.mips.cpu_type.name,
2534  machine->physical_ram_in_mb);
2535  arcbios_putstring(cpu, tmpstr);
2536  }
2537 
2539 
2540  memset(&arcbios_sysid, 0, sizeof(arcbios_sysid));
2541  if (machine->machine_type == MACHINE_SGI) {
2542  /* Vendor ID, max 8 chars: */
2543  strncpy(arcbios_sysid.VendorId, "SGI", 3);
2544  switch (machine->machine_subtype) {
2545  case 22:
2546  strncpy(arcbios_sysid.ProductId,
2547  "87654321", 8); /* some kind of ID? */
2548  break;
2549  case 32:
2550  strncpy(arcbios_sysid.ProductId, "8", 1);
2551  /* 6 or 8 (?) */
2552  break;
2553  default:
2554  snprintf(arcbios_sysid.ProductId, 8, "IP%i",
2555  machine->machine_subtype);
2556  }
2557  } else {
2558  switch (machine->machine_subtype) {
2559  case MACHINE_ARC_JAZZ_PICA:
2560  strncpy(arcbios_sysid.VendorId, "MIPS MAG", 8);
2561  strncpy(arcbios_sysid.ProductId, "ijkl", 4);
2562  break;
2564  strncpy(arcbios_sysid.VendorId, "MIPS MAG", 8);
2565  strncpy(arcbios_sysid.ProductId, "ijkl", 4);
2566  break;
2567  default:
2568  fatal("error in machine.c sysid\n");
2569  exit(1);
2570  }
2571  }
2572 
2573  store_buf(cpu, SGI_SYSID_ADDR, (char *)&arcbios_sysid,
2574  sizeof(arcbios_sysid));
2575 
2576  arcbios_get_dsp_stat(cpu, &arcbios_dsp_stat);
2577  store_buf(cpu, ARC_DSPSTAT_ADDR, (char *)&arcbios_dsp_stat,
2578  sizeof(arcbios_dsp_stat));
2579 
2580  /*
2581  * The first 12 MBs of RAM are simply reserved... this simplifies
2582  * things a lot. If there's more than 512MB of RAM, it has to be
2583  * split in two, according to the ARC spec. This code creates a
2584  * number of chunks of at most 512MB each.
2585  *
2586  * NOTE: The region of physical address space between 0x10000000 and
2587  * 0x1fffffff (256 - 512 MB) is usually occupied by memory mapped
2588  * devices, so that portion is "lost".
2589  */
2591 
2592  arc_reserved = 0x2000;
2593  if (machine->machine_type == MACHINE_SGI)
2594  arc_reserved = 0x4000;
2595 
2596  arcbios_add_memory_descriptor(cpu, 0, arc_reserved,
2598  arcbios_add_memory_descriptor(cpu, sgi_ram_offset + arc_reserved,
2599  0x60000-arc_reserved, ARCBIOS_MEM_FirmwareTemporary);
2600 
2601  mem_base = 12;
2602  mem_base += sgi_ram_offset / 1048576;
2603 
2604  while (mem_base < machine->physical_ram_in_mb+sgi_ram_offset/1048576) {
2605  mem_count = machine->physical_ram_in_mb+sgi_ram_offset/1048576
2606  - mem_base;
2607 
2608  /* Skip the 256-512MB region (for devices) */
2609  if (mem_base < 256 && mem_base + mem_count > 256) {
2610  mem_count = 256-mem_base;
2611  }
2612 
2613  /* At most 512MB per descriptor (at least the first 512MB
2614  must be separated this way, according to the ARC spec) */
2615  if (mem_count > 512)
2616  mem_count = 512;
2617 
2618  arcbios_add_memory_descriptor(cpu, mem_base * 1048576,
2619  mem_count * 1048576, ARCBIOS_MEM_FreeMemory);
2620 
2621  mem_base += mem_count;
2622 
2623  /* Skip the devices: */
2624  if (mem_base == 256)
2625  mem_base = 512;
2626  }
2627 
2628  /*
2629  * Components: (this is an example of what a system could look like)
2630  *
2631  * [System]
2632  * [CPU] (one for each cpu)
2633  * [FPU] (one for each cpu)
2634  * [CPU Caches]
2635  * [Memory]
2636  * [Ethernet]
2637  * [Serial]
2638  * [SCSI]
2639  * [Disk]
2640  *
2641  * Here's a good list of what hardware is in different IP-models:
2642  * http://www.linux-mips.org/archives/linux-mips/2001-03/msg00101.html
2643  */
2644 
2645  if (machine->machine_name == NULL)
2646  fatal("ERROR: machine_name == NULL\n");
2647 
2648  /* Add the root node: */
2649  switch (machine->machine_type) {
2650  case MACHINE_SGI:
2651  CHECK_ALLOCATION(name = (char *) malloc(alloclen));
2652  snprintf(name, alloclen, "SGI-IP%i",
2653  machine->machine_subtype);
2654 
2655  /* A very special case for IP24 (which identifies itself
2656  as an IP22): */
2657  if (machine->machine_subtype == 24)
2658  snprintf(name, alloclen, "SGI-IP22");
2659  break;
2660  case MACHINE_ARC:
2661  /* ARC: */
2662  switch (machine->machine_subtype) {
2663  case MACHINE_ARC_JAZZ_PICA:
2664  name = strdup("PICA-61");
2665  break;
2667  name = strdup("Microsoft-Jazz");
2668  break;
2669  default:
2670  fatal("Unimplemented ARC machine type %i\n",
2671  machine->machine_subtype);
2672  exit(1);
2673  }
2674  break;
2675  default:
2676  fatal("ERROR: non-SGI and non-ARC?\n");
2677  exit(1);
2678  }
2679 
2681  COMPONENT_TYPE_ARC, 0,1,2,0, 0xffffffff, name, 0/*ROOT*/, NULL, 0);
2682  debug("ARC system @ 0x%" PRIx64" (\"%s\")\n", (uint64_t) system, name);
2683 
2684 
2685  /*
2686  * Add tree nodes for CPUs and their caches:
2687  */
2688 
2689  for (i=0; i<machine->ncpus; i++) {
2690  uint64_t cpuaddr, fpu=0, picache, pdcache, sdcache=0;
2691  int cache_size, cache_line_size;
2692  unsigned int jj;
2693  char arc_cpu_name[100];
2694  char arc_fpc_name[105];
2695 
2696  snprintf(arc_cpu_name, sizeof(arc_cpu_name),
2697  "MIPS-%s", machine->cpu_name);
2698 
2699  arc_cpu_name[sizeof(arc_cpu_name)-1] = 0;
2700  for (jj=0; jj<strlen(arc_cpu_name); jj++)
2701  if (arc_cpu_name[jj] >= 'a' && arc_cpu_name[jj] <= 'z')
2702  arc_cpu_name[jj] += ('A' - 'a');
2703 
2704  strlcpy(arc_fpc_name, arc_cpu_name, sizeof(arc_fpc_name));
2705  strlcat(arc_fpc_name, "FPC", sizeof(arc_fpc_name));
2706 
2707  cpuaddr = arcbios_addchild_manual(cpu,
2709  0, 1, 2, i, 0xffffffff, arc_cpu_name, system, NULL, 0);
2710 
2711  /*
2712  * TODO: This was in the ARC specs, but it isn't really used
2713  * by ARC implementations? At least SGI-IP32 uses it.
2714  */
2715  if (machine->machine_type == MACHINE_SGI)
2716  fpu = arcbios_addchild_manual(cpu,
2718  0, 1, 2, 0, 0xffffffff, arc_fpc_name, cpuaddr,
2719  NULL, 0);
2720 
2721  cache_size = DEFAULT_PCACHE_SIZE - 12;
2722  if (cpu->cd.mips.cache_picache)
2723  cache_size = cpu->cd.mips.cache_picache - 12;
2724  if (cache_size < 0)
2725  cache_size = 0;
2726 
2727  cache_line_size = DEFAULT_PCACHE_LINESIZE;
2728  if (cpu->cd.mips.cache_picache_linesize)
2729  cache_line_size = cpu->cd.mips.cache_picache_linesize;
2730  if (cache_line_size < 0)
2731  cache_line_size = 0;
2732 
2733  picache = arcbios_addchild_manual(cpu,
2735  0, 1, 2,
2736  /*
2737  * Key bits: 0xXXYYZZZZ
2738  * XX is refill-size.
2739  * Cache line size is 1 << YY,
2740  * Cache size is 4KB << ZZZZ.
2741  */
2742  0x01000000 + (cache_line_size << 16) + cache_size,
2743  /* 32 bytes per line, default = 32 KB total */
2744  0xffffffff, NULL, cpuaddr, NULL, 0);
2745 
2746  cache_size = DEFAULT_PCACHE_SIZE - 12;
2747  if (cpu->cd.mips.cache_pdcache)
2748  cache_size = cpu->cd.mips.cache_pdcache - 12;
2749  if (cache_size < 0)
2750  cache_size = 0;
2751 
2752  cache_line_size = DEFAULT_PCACHE_LINESIZE;
2753  if (cpu->cd.mips.cache_pdcache_linesize)
2754  cache_line_size = cpu->cd.mips.cache_pdcache_linesize;
2755  if (cache_line_size < 0)
2756  cache_line_size = 0;
2757 
2758  pdcache = arcbios_addchild_manual(cpu,
2761  /*
2762  * Key bits: 0xYYZZZZ
2763  * Cache line size is 1 << YY,
2764  * Cache size is 4KB << ZZZZ.
2765  */
2766  0x01000000 + (cache_line_size << 16) + cache_size,
2767  /* 32 bytes per line, default = 32 KB total */
2768  0xffffffff, NULL, cpuaddr, NULL, 0);
2769 
2770  if (cpu->cd.mips.cache_secondary >= 12) {
2771  cache_size = cpu->cd.mips.cache_secondary - 12;
2772 
2773  cache_line_size = 6; /* 64 bytes default */
2774  if (cpu->cd.mips.cache_secondary_linesize)
2775  cache_line_size = cpu->cd.mips.
2776  cache_secondary_linesize;
2777  if (cache_line_size < 0)
2778  cache_line_size = 0;
2779 
2780  sdcache = arcbios_addchild_manual(cpu,
2783  /*
2784  * Key bits: 0xYYZZZZ
2785  * Cache line size is 1 << YY,
2786  * Cache size is 4KB << ZZZZ.
2787  */
2788  0x01000000 + (cache_line_size << 16) + cache_size,
2789  /* 64 bytes per line, default = 1 MB total */
2790  0xffffffff, NULL, cpuaddr, NULL, 0);
2791  }
2792 
2793  debug("ARC cpu%i @ 0x%" PRIx64, i, (uint64_t) cpuaddr);
2794 
2795  if (fpu != 0)
2796  debug(" (fpu @ 0x%" PRIx64")\n", (uint64_t) fpu);
2797  else
2798  debug("\n");
2799 
2800  debug(" picache @ 0x%" PRIx64", pdcache @ 0x%" PRIx64"\n",
2801  (uint64_t) picache, (uint64_t) pdcache);
2802 
2803  if (cpu->cd.mips.cache_secondary >= 12)
2804  debug(" sdcache @ 0x%" PRIx64"\n",
2805  (uint64_t) sdcache);
2806 
2807  if (machine->machine_type == MACHINE_SGI) {
2808  /* TODO: Memory amount (and base address?)! */
2809  uint64_t memory = arcbios_addchild_manual(cpu,
2811  COMPONENT_TYPE_MemoryUnit, 0, 1, 2, 0,
2812  0xffffffff, "memory", cpuaddr, NULL, 0);
2813  debug("ARC memory @ 0x%" PRIx64"\n", (uint64_t) memory);
2814  }
2815  }
2816 
2817 
2818  /*
2819  * Add other components:
2820  *
2821  * TODO: How should this be synched with the hardware devices
2822  * added in machine.c?
2823  */
2824 
2825  arcbios_add_other_components(machine, system);
2826 
2827 
2828  /*
2829  * Defalt TLB entry for 64-bit SGI machines:
2830  */
2831  if (machine->machine_type == MACHINE_SGI &&
2832  machine->machine_subtype != 12 /* TODO: ugly */ ) {
2833  /* TODO: On which models is this required? */
2834  mips_coproc_tlb_set_entry(cpu, 0, 1048576*16,
2835  0xc000000000000000ULL, 0, 1048576*16, 1,1,1,1,1, 0, 2, 2);
2836  }
2837 
2838 
2839  /*
2840  * Set up Firmware Vectors:
2841  */
2842  add_symbol_name(&machine->symbol_context,
2843  ARC_FIRMWARE_ENTRIES, 0x10000, "[ARCBIOS entry]", 0, 1);
2844 
2845  for (i=0; i<100; i++) {
2846  if (is64bit) {
2848  ARC_FIRMWARE_ENTRIES + i*8);
2850  ARC_PRIVATE_ENTRIES + i*8);
2851 
2852  /* "Magic trap" instruction: */
2854  0x00c0de0c);
2856  0x00c0de0c);
2857  } else {
2859  ARC_FIRMWARE_ENTRIES + i*4);
2861  ARC_PRIVATE_ENTRIES + i*4);
2862 
2863  /* "Magic trap" instruction: */
2865  0x00c0de0c);
2867  0x00c0de0c);
2868  }
2869  }
2870 
2871 
2872  /*
2873  * Set up the ARC SPD:
2874  */
2875  if (is64bit) {
2876  /* ARCS64 SPD (TODO: This is just a guess) */
2877  memset(&arcbios_spb_64, 0, sizeof(arcbios_spb_64));
2878  store_64bit_word_in_host(cpu, (unsigned char *)
2879  &arcbios_spb_64.SPBSignature, ARCBIOS_SPB_SIGNATURE);
2880  store_16bit_word_in_host(cpu, (unsigned char *)
2881  &arcbios_spb_64.Version, 64);
2882  store_16bit_word_in_host(cpu, (unsigned char *)
2883  &arcbios_spb_64.Revision, 0);
2884  store_64bit_word_in_host(cpu, (unsigned char *)
2885  &arcbios_spb_64.FirmwareVector, ARC_FIRMWARE_VECTORS);
2886  store_buf(cpu, SGI_SPB_ADDR, (char *)&arcbios_spb_64,
2887  sizeof(arcbios_spb_64));
2888  } else {
2889  /* ARCBIOS SPB: (For ARC and 32-bit SGI modes) */
2890  memset(&arcbios_spb, 0, sizeof(arcbios_spb));
2891  store_32bit_word_in_host(cpu, (unsigned char *)
2892  &arcbios_spb.SPBSignature, ARCBIOS_SPB_SIGNATURE);
2893  store_32bit_word_in_host(cpu, (unsigned char *)
2894  &arcbios_spb.SPBLength, sizeof(arcbios_spb));
2895  store_16bit_word_in_host(cpu, (unsigned char *)
2896  &arcbios_spb.Version, 1);
2897  store_16bit_word_in_host(cpu, (unsigned char *)
2898  &arcbios_spb.Revision, machine->machine_type ==
2899  MACHINE_SGI? 10 : 2);
2900  store_32bit_word_in_host(cpu, (unsigned char *)
2901  &arcbios_spb.FirmwareVector, ARC_FIRMWARE_VECTORS);
2902  store_32bit_word_in_host(cpu, (unsigned char *)
2903  &arcbios_spb.FirmwareVectorLength, 100 * 4); /* ? */
2904  store_32bit_word_in_host(cpu, (unsigned char *)
2905  &arcbios_spb.PrivateVector, ARC_PRIVATE_VECTORS);
2906  store_32bit_word_in_host(cpu, (unsigned char *)
2907  &arcbios_spb.PrivateVectorLength, 100 * 4); /* ? */
2908  store_buf(cpu, SGI_SPB_ADDR, (char *)&arcbios_spb,
2909  sizeof(arcbios_spb));
2910  }
2911 
2912 
2913  /*
2914  * TODO: How to build the component tree intermixed with
2915  * the rest of device initialization?
2916  */
2917 
2918  arc_environment_setup(machine, is64bit, primary_ether_addr);
2919 }
2920 
const char * file_handle_string[ARC_MAX_HANDLES]
Definition: machine_arc.h:68
void ** extra
Definition: machine.h:77
#define ARC_ENV_STRINGS_SGI
Definition: arcbios.h:99
#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
void(** f)(struct cpu *, void *)
Definition: machine.h:76
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:101
uint64_t console_ctrlregs
Definition: machine_arc.h:56
#define ARC_ENV_SGI
Definition: arcbios.h:98
#define COMPONENT_TYPE_KeyboardPeripheral
Definition: sgi_arcbios.h:303
#define ARC_DSPSTAT_ADDR
Definition: arcbios.h:102
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:2476
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:103
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:2155
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:104
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:1048
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:105
uint32_t SPBLength
Definition: sgi_arcbios.h:105
int bootdev_type
Definition: machine.h:153
#define ARCBIOS_MEM_FreeMemory
Definition: sgi_arcbios.h:368
#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:106
#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:107
#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:1866
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 Fri Dec 7 2018 19:52:23 for GXemul by doxygen 1.8.13