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

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

Parent Directory Parent Directory | Revision Log Revision Log


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

  ViewVC Help
Powered by ViewVC 1.1.26