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

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

Parent Directory Parent Directory | Revision Log Revision Log


Revision 9 - (hide annotations)
Mon Oct 8 16:18:22 2007 UTC (16 years, 7 months ago) by dpavlin
File MIME type: text/plain
File size: 84821 byte(s)
0.3.3.2
1 dpavlin 2 /*
2     * Copyright (C) 2003-2005 Anders Gavare. All rights reserved.
3     *
4     * Redistribution and use in source and binary forms, with or without
5     * modification, are permitted provided that the following conditions are met:
6     *
7     * 1. Redistributions of source code must retain the above copyright
8     * notice, this list of conditions and the following disclaimer.
9     * 2. Redistributions in binary form must reproduce the above copyright
10     * notice, this list of conditions and the following disclaimer in the
11     * documentation and/or other materials provided with the distribution.
12     * 3. The name of the author may not be used to endorse or promote products
13     * derived from this software without specific prior written permission.
14     *
15     * THIS SOFTWARE IS PROVIDED BY THE AUTHOR AND CONTRIBUTORS ``AS IS'' AND
16     * ANY EXPRESS OR IMPLIED WARRANTIES, INCLUDING, BUT NOT LIMITED TO, THE
17     * IMPLIED WARRANTIES OF MERCHANTABILITY AND FITNESS FOR A PARTICULAR PURPOSE
18     * ARE DISCLAIMED. IN NO EVENT SHALL THE AUTHOR OR CONTRIBUTORS BE LIABLE
19     * FOR ANY DIRECT, INDIRECT, INCIDENTAL, SPECIAL, EXEMPLARY, OR CONSEQUENTIAL
20     * DAMAGES (INCLUDING, BUT NOT LIMITED TO, PROCUREMENT OF SUBSTITUTE GOODS
21     * OR SERVICES; LOSS OF USE, DATA, OR PROFITS; OR BUSINESS INTERRUPTION)
22     * HOWEVER CAUSED AND ON ANY THEORY OF LIABILITY, WHETHER IN CONTRACT, STRICT
23     * LIABILITY, OR TORT (INCLUDING NEGLIGENCE OR OTHERWISE) ARISING IN ANY WAY
24     * OUT OF THE USE OF THIS SOFTWARE, EVEN IF ADVISED OF THE POSSIBILITY OF
25     * SUCH DAMAGE.
26     *
27     *
28 dpavlin 6 * $Id: arcbios.c,v 1.103 2005/05/23 12:21:45 debug Exp $
29 dpavlin 2 *
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 dpavlin 6 #include "arcbios_other.h"
44 dpavlin 2 #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 dpavlin 6 void arcbios_add_string_to_component(struct machine *machine,
60     char *string, uint64_t component)
61 dpavlin 2 {
62 dpavlin 6 if (machine->md.arc.n_string_to_components >= MAX_STRING_TO_COMPONENT) {
63 dpavlin 2 printf("Too many string-to-component mappings.\n");
64     exit(1);
65     }
66    
67 dpavlin 6 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 dpavlin 2 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 dpavlin 6 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 dpavlin 2 }
83    
84    
85     /*
86     * arcbios_get_dsp_stat():
87     *
88     * Fills in an arcbios_dsp_stat struct with valid data.
89     */
90 dpavlin 6 static void arcbios_get_dsp_stat(struct cpu *cpu,
91     struct arcbios_dsp_stat *dspstat)
92 dpavlin 2 {
93     memset(dspstat, 0, sizeof(struct arcbios_dsp_stat));
94    
95     store_16bit_word_in_host(cpu, (unsigned char *)&dspstat->
96 dpavlin 6 CursorXPosition, cpu->machine->md.arc.console_curx + 1);
97 dpavlin 2 store_16bit_word_in_host(cpu, (unsigned char *)&dspstat->
98 dpavlin 6 CursorYPosition, cpu->machine->md.arc.console_cury + 1);
99 dpavlin 2 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 dpavlin 6 dspstat->ForegroundColor = cpu->machine->md.arc.console_curcolor;
104     dspstat->HighIntensity = cpu->machine->md.arc.console_curcolor ^ 0x08;
105 dpavlin 2 }
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 dpavlin 6 buf[1] = cpu->machine->md.arc.console_curcolor;
116     if (cpu->machine->md.arc.console_reverse)
117 dpavlin 2 buf[1] = ((buf[1] & 0x70) >> 4) | ((buf[1] & 7) << 4)
118     | (buf[1] & 0x88);
119 dpavlin 6 cpu->memory_rw(cpu, cpu->mem, cpu->machine->md.arc.console_vram +
120     2*(x + cpu->machine->md.arc.console_maxx * y),
121 dpavlin 2 &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 dpavlin 6 int i, len = strlen(cpu->machine->md.arc.escape_sequence);
134 dpavlin 2 int row, col, color, code, start, stop;
135     char *p;
136    
137 dpavlin 6 if (cpu->machine->md.arc.escape_sequence[0] != '[')
138 dpavlin 2 return;
139    
140 dpavlin 6 code = cpu->machine->md.arc.escape_sequence[len-1];
141     cpu->machine->md.arc.escape_sequence[len-1] = '\0';
142 dpavlin 2
143     switch (code) {
144     case 'm':
145 dpavlin 6 color = atoi(cpu->machine->md.arc.escape_sequence + 1);
146 dpavlin 2 switch (color) {
147     case 0: /* Default. */
148 dpavlin 6 cpu->machine->md.arc.console_curcolor = 0x1f;
149     cpu->machine->md.arc.console_reverse = 0; break;
150 dpavlin 2 case 1: /* "Bold". */
151 dpavlin 6 cpu->machine->md.arc.console_curcolor |= 0x08; break;
152 dpavlin 2 case 7: /* "Reverse". */
153 dpavlin 6 cpu->machine->md.arc.console_reverse = 1; break;
154 dpavlin 2 case 30: /* Black foreground. */
155 dpavlin 6 cpu->machine->md.arc.console_curcolor &= 0xf0;
156     cpu->machine->md.arc.console_curcolor |= 0x00; break;
157 dpavlin 2 case 31: /* Red foreground. */
158 dpavlin 6 cpu->machine->md.arc.console_curcolor &= 0xf0;
159     cpu->machine->md.arc.console_curcolor |= 0x04; break;
160 dpavlin 2 case 32: /* Green foreground. */
161 dpavlin 6 cpu->machine->md.arc.console_curcolor &= 0xf0;
162     cpu->machine->md.arc.console_curcolor |= 0x02; break;
163 dpavlin 2 case 33: /* Yellow foreground. */
164 dpavlin 6 cpu->machine->md.arc.console_curcolor &= 0xf0;
165     cpu->machine->md.arc.console_curcolor |= 0x06; break;
166 dpavlin 2 case 34: /* Blue foreground. */
167 dpavlin 6 cpu->machine->md.arc.console_curcolor &= 0xf0;
168     cpu->machine->md.arc.console_curcolor |= 0x01; break;
169 dpavlin 2 case 35: /* Red-blue foreground. */
170 dpavlin 6 cpu->machine->md.arc.console_curcolor &= 0xf0;
171     cpu->machine->md.arc.console_curcolor |= 0x05; break;
172 dpavlin 2 case 36: /* Green-blue foreground. */
173 dpavlin 6 cpu->machine->md.arc.console_curcolor &= 0xf0;
174     cpu->machine->md.arc.console_curcolor |= 0x03; break;
175 dpavlin 2 case 37: /* White foreground. */
176 dpavlin 6 cpu->machine->md.arc.console_curcolor &= 0xf0;
177     cpu->machine->md.arc.console_curcolor |= 0x07; break;
178 dpavlin 2 case 40: /* Black background. */
179 dpavlin 6 cpu->machine->md.arc.console_curcolor &= 0x0f;
180     cpu->machine->md.arc.console_curcolor |= 0x00; break;
181 dpavlin 2 case 41: /* Red background. */
182 dpavlin 6 cpu->machine->md.arc.console_curcolor &= 0x0f;
183     cpu->machine->md.arc.console_curcolor |= 0x40; break;
184 dpavlin 2 case 42: /* Green background. */
185 dpavlin 6 cpu->machine->md.arc.console_curcolor &= 0x0f;
186     cpu->machine->md.arc.console_curcolor |= 0x20; break;
187 dpavlin 2 case 43: /* Yellow background. */
188 dpavlin 6 cpu->machine->md.arc.console_curcolor &= 0x0f;
189     cpu->machine->md.arc.console_curcolor |= 0x60; break;
190 dpavlin 2 case 44: /* Blue background. */
191 dpavlin 6 cpu->machine->md.arc.console_curcolor &= 0x0f;
192     cpu->machine->md.arc.console_curcolor |= 0x10; break;
193 dpavlin 2 case 45: /* Red-blue background. */
194 dpavlin 6 cpu->machine->md.arc.console_curcolor &= 0x0f;
195     cpu->machine->md.arc.console_curcolor |= 0x50; break;
196 dpavlin 2 case 46: /* Green-blue background. */
197 dpavlin 6 cpu->machine->md.arc.console_curcolor &= 0x0f;
198     cpu->machine->md.arc.console_curcolor |= 0x30; break;
199 dpavlin 2 case 47: /* White background. */
200 dpavlin 6 cpu->machine->md.arc.console_curcolor &= 0x0f;
201     cpu->machine->md.arc.console_curcolor |= 0x70; break;
202 dpavlin 2 default:fatal("{ handle_esc_seq: color %i }\n", color);
203     }
204     return;
205     case 'H':
206 dpavlin 6 p = strchr(cpu->machine->md.arc.escape_sequence, ';');
207 dpavlin 2 if (p == NULL)
208     return; /* TODO */
209 dpavlin 6 row = atoi(cpu->machine->md.arc.escape_sequence + 1);
210 dpavlin 2 col = atoi(p + 1);
211     if (col < 1)
212     col = 1;
213     if (row < 1)
214     row = 1;
215 dpavlin 6 cpu->machine->md.arc.console_curx = col - 1;
216     cpu->machine->md.arc.console_cury = row - 1;
217 dpavlin 2 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 dpavlin 6 i = atoi(cpu->machine->md.arc.escape_sequence + 1);
225 dpavlin 2 if (i != 0 && i != 2)
226     fatal("{ handle_esc_seq(): %iJ }\n", i);
227     if (i == 0)
228 dpavlin 6 for (col = cpu->machine->md.arc.console_curx;
229     col < cpu->machine->md.arc.console_maxx; col++)
230 dpavlin 2 arcbios_putcell(cpu, ' ', col,
231 dpavlin 6 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 dpavlin 2 arcbios_putcell(cpu, ' ', col, row);
236     return;
237     case 'K':
238 dpavlin 6 col = atoi(cpu->machine->md.arc.escape_sequence + 1);
239 dpavlin 2 /* 2 = clear line to the right. 1 = to the left (?) */
240 dpavlin 6 start = 0; stop = cpu->machine->md.arc.console_curx;
241 dpavlin 2 if (col == 2) {
242 dpavlin 6 start = cpu->machine->md.arc.console_curx;
243     stop = cpu->machine->md.arc.console_maxx - 1;
244 dpavlin 2 }
245     for (i=start; i<=stop; i++)
246 dpavlin 6 arcbios_putcell(cpu, ' ', i,
247     cpu->machine->md.arc.console_cury);
248 dpavlin 2
249     return;
250     }
251    
252     fatal("{ handle_esc_seq(): unimplemented escape sequence: ");
253     for (i=0; i<len; i++) {
254 dpavlin 6 int x = cpu->machine->md.arc.escape_sequence[i];
255 dpavlin 2 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 dpavlin 6 if (cpu->machine->md.arc.console_cury >=
274     cpu->machine->md.arc.console_maxy) {
275 dpavlin 2 unsigned char buf[2];
276     int x, y;
277 dpavlin 6 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 dpavlin 2 cpu->memory_rw(cpu, cpu->mem,
281 dpavlin 6 cpu->machine->md.arc.console_vram +
282     2*(x + cpu->machine->md.arc.
283     console_maxx * (y+1)),
284 dpavlin 2 &buf[0], sizeof(buf), MEM_READ,
285     CACHE_NONE | PHYSICAL);
286     cpu->memory_rw(cpu, cpu->mem,
287 dpavlin 6 cpu->machine->md.arc.console_vram +
288     2*(x + cpu->machine->md.arc.
289     console_maxx * y),
290 dpavlin 2 &buf[0], sizeof(buf), MEM_WRITE,
291     CACHE_NONE | PHYSICAL);
292     }
293    
294 dpavlin 6 cpu->machine->md.arc.console_cury =
295     cpu->machine->md.arc.console_maxy - 1;
296 dpavlin 2
297 dpavlin 6 for (x=0; x<cpu->machine->md.arc.console_maxx; x++)
298     arcbios_putcell(cpu, ' ', x,
299     cpu->machine->md.arc.console_cury);
300 dpavlin 2 }
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 dpavlin 6 if (!cpu->machine->md.arc.vgaconsole) {
316 dpavlin 2 /* 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 dpavlin 6 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 dpavlin 2 len++;
331 dpavlin 6 if (len >= ARC_MAX_ESC)
332     len = ARC_MAX_ESC;
333     cpu->machine->md.arc.escape_sequence[len] = '\0';
334 dpavlin 2 if ((ch >= 'a' && ch <= 'z') ||
335 dpavlin 6 (ch >= 'A' && ch <= 'Z') || len >= ARC_MAX_ESC) {
336 dpavlin 2 handle_esc_seq(cpu);
337 dpavlin 6 cpu->machine->md.arc.in_escape_sequence = 0;
338 dpavlin 2 }
339     } else {
340     if (ch == 27) {
341 dpavlin 6 cpu->machine->md.arc.in_escape_sequence = 1;
342     cpu->machine->md.arc.escape_sequence[0] = '\0';
343 dpavlin 2 } else if (ch == 0x9b) {
344 dpavlin 6 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 dpavlin 2 } else if (ch == '\b') {
348 dpavlin 6 if (cpu->machine->md.arc.console_curx > 0)
349     cpu->machine->md.arc.console_curx --;
350 dpavlin 2 } else if (ch == '\r') {
351 dpavlin 6 cpu->machine->md.arc.console_curx = 0;
352 dpavlin 2 } else if (ch == '\n') {
353 dpavlin 6 cpu->machine->md.arc.console_cury ++;
354 dpavlin 2 } else if (ch == '\t') {
355 dpavlin 6 cpu->machine->md.arc.console_curx =
356     ((cpu->machine->md.arc.console_curx - 1)
357     | 7) + 1;
358 dpavlin 2 /* TODO: Print spaces? */
359     } else {
360     /* Put char: */
361 dpavlin 6 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 dpavlin 2 scroll_if_necessary(cpu);
366     }
367 dpavlin 6 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 dpavlin 2 }
372     }
373    
374     scroll_if_necessary(cpu);
375    
376     /* Update cursor position: */
377 dpavlin 6 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 dpavlin 2 byte = 0x0e;
384 dpavlin 6 cpu->memory_rw(cpu, cpu->mem, cpu->machine->md.arc.
385     console_ctrlregs + 0x14,
386 dpavlin 2 &byte, sizeof(byte), MEM_WRITE, CACHE_NONE | PHYSICAL);
387     byte = (addr >> 8) & 255;
388 dpavlin 6 cpu->memory_rw(cpu, cpu->mem, cpu->machine->md.arc.
389     console_ctrlregs + 0x15,
390 dpavlin 2 &byte, sizeof(byte), MEM_WRITE, CACHE_NONE | PHYSICAL);
391     byte = 0x0f;
392 dpavlin 6 cpu->memory_rw(cpu, cpu->mem, cpu->machine->md.arc.
393     console_ctrlregs + 0x14,
394 dpavlin 2 &byte, sizeof(byte), MEM_WRITE, CACHE_NONE | PHYSICAL);
395     byte = addr & 255;
396 dpavlin 6 cpu->memory_rw(cpu, cpu->mem, cpu->machine->md.arc.
397     console_ctrlregs + 0x15,
398 dpavlin 2 &byte, sizeof(byte), MEM_WRITE, CACHE_NONE | PHYSICAL);
399     }
400    
401    
402     /*
403 dpavlin 6 * 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 dpavlin 2 * arcbios_register_scsicontroller():
417     */
418 dpavlin 6 void arcbios_register_scsicontroller(struct machine *machine,
419     uint64_t scsicontroller_component)
420 dpavlin 2 {
421 dpavlin 6 machine->md.arc.scsicontroller = scsicontroller_component;
422 dpavlin 2 }
423    
424    
425     /*
426     * arcbios_get_scsicontroller():
427     */
428 dpavlin 6 uint64_t arcbios_get_scsicontroller(struct machine *machine)
429 dpavlin 2 {
430 dpavlin 6 return machine->md.arc.scsicontroller;
431 dpavlin 2 }
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_ neccessary, 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 dpavlin 6 if (cpu->machine->md.arc.arc_64bit)
475 dpavlin 2 s = sizeof(arcbios_mem64);
476     else
477     s = sizeof(arcbios_mem);
478    
479 dpavlin 6 memdesc_addr = cpu->machine->md.arc.memdescriptor_base +
480     cpu->machine->md.arc.n_memdescriptors * s;
481 dpavlin 2
482 dpavlin 6 if (cpu->machine->md.arc.arc_64bit) {
483 dpavlin 2 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 dpavlin 6 cpu->machine->md.arc.n_memdescriptors ++;
503 dpavlin 2 }
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 dpavlin 6 struct machine *machine = cpu->machine;
523     uint64_t a = machine->md.arc.next_component_address;
524 dpavlin 2 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 dpavlin 6 n_left = machine->md.arc.n_components;
547 dpavlin 2 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 dpavlin 6 peeraddr + 0 * machine->md.arc.wordlen, &buf[0],
557     sizeof(eparent), MEM_READ, CACHE_NONE);
558 dpavlin 2 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 dpavlin 6 cpu->memory_rw(cpu, cpu->mem, peeraddr + 1 *
566     machine->md.arc.wordlen,
567 dpavlin 2 &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 dpavlin 6 cpu->memory_rw(cpu, cpu->mem, peeraddr + 2 *
576     machine->md.arc.wordlen,
577 dpavlin 2 &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 dpavlin 6 machine->md.arc.next_component_address += 0x30;
635 dpavlin 2
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 dpavlin 6 machine->md.arc.next_component_address +=
641 dpavlin 2 strlen(identifier) + 1;
642     }
643    
644 dpavlin 6 machine->md.arc.next_component_address ++;
645 dpavlin 2
646     /* Round up to next 0x4 bytes: */
647 dpavlin 6 machine->md.arc.next_component_address =
648     ((machine->md.arc.next_component_address - 1) | 3) + 1;
649 dpavlin 2
650 dpavlin 6 machine->md.arc.n_components ++;
651 dpavlin 2
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 dpavlin 6 struct machine *machine = cpu->machine;
673     uint64_t a = machine->md.arc.next_component_address;
674 dpavlin 2 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 dpavlin 6 n_left = machine->md.arc.n_components;
697 dpavlin 2 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%016llx ]\n",
703     (long long)peeraddr); */
704    
705     cpu->memory_rw(cpu, cpu->mem,
706 dpavlin 6 peeraddr + 0 * machine->md.arc.wordlen, &buf[0],
707     sizeof(eparent), MEM_READ, CACHE_NONE);
708 dpavlin 2 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 dpavlin 6 cpu->memory_rw(cpu, cpu->mem, peeraddr + 1 *
720     machine->md.arc.wordlen,
721 dpavlin 2 &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 dpavlin 6 cpu->memory_rw(cpu, cpu->mem, peeraddr + 2 *
734     machine->md.arc.wordlen,
735 dpavlin 2 &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=%llx echild=%llx eparent=%llx\n",
748     (long long)epeer, (long long)echild,
749     (long long)eparent); */
750    
751     if (eparent == parent && epeer == 0) {
752     epeer = a;
753 dpavlin 6 store_64bit_word(cpu, peeraddr + 0 *
754     machine->md.arc.wordlen, epeer);
755 dpavlin 2 /* debug("[ addchild: adding 0x%016llx as peer "
756     "to 0x%016llx ]\n", (long long)a,
757     (long long)peeraddr); */
758     }
759     if (peeraddr == parent && echild == 0) {
760     echild = a;
761 dpavlin 6 store_64bit_word(cpu, peeraddr + 1 *
762     machine->md.arc.wordlen, echild);
763 dpavlin 2 /* debug("[ addchild: adding 0x%016llx as child "
764     "to 0x%016llx ]\n", (long long)a,
765     (long long)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 dpavlin 6 machine->md.arc.next_component_address += 0x50;
805 dpavlin 2
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 dpavlin 6 machine->md.arc.next_component_address +=
811 dpavlin 2 strlen(identifier) + 1;
812     }
813    
814 dpavlin 6 machine->md.arc.next_component_address ++;
815 dpavlin 2
816     /* Round up to next 0x8 bytes: */
817 dpavlin 6 machine->md.arc.next_component_address =
818     ((machine->md.arc.next_component_address - 1) | 7) + 1;
819 dpavlin 2
820 dpavlin 6 machine->md.arc.n_components ++;
821 dpavlin 2 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 dpavlin 6 struct machine *machine = cpu->machine;
840 dpavlin 2 /* 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     int i;
847    
848 dpavlin 6 if (machine->md.arc.n_configuration_data >= MAX_CONFIG_DATA) {
849 dpavlin 2 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 dpavlin 6 machine->md.arc.configuration_data_next_addr + i,
858 dpavlin 2 &ch, 1, MEM_WRITE, CACHE_NONE);
859     }
860    
861 dpavlin 6 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 dpavlin 2
872     /* printf("& ADDING %i: configdata=0x%016llx "
873 dpavlin 6 "component=0x%016llx\n",
874     machine->md.arc.n_configuration_data,
875     (long long)machine->md.arc.configuration_data_configdata[
876     machine->md.arc.n_configuration_data],
877     (long long)machine->md.arc.configuration_data_component[
878     machine->md.arc.n_configuration_data]); */
879 dpavlin 2
880 dpavlin 6 machine->md.arc.n_configuration_data ++;
881 dpavlin 2 }
882    
883 dpavlin 6 if (!cpu->machine->md.arc.arc_64bit) {
884 dpavlin 2 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 dpavlin 6 int disk_id, int disk_type, int partition_nr, uint64_t *start,
934     uint64_t *size)
935 dpavlin 2 {
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 dpavlin 6 *size = diskimage_getsize(machine, disk_id, disk_type);
944 dpavlin 2 if (partition_nr == 0)
945     return;
946    
947     ugly_goto:
948     *start = 0; *size = 0;
949    
950     /* printf("reading MSDOS partition from offset 0x%llx\n",
951     (long long)offset); */
952    
953 dpavlin 6 res = diskimage_access(machine, disk_id, disk_type, 0, offset,
954 dpavlin 2 sector, sizeof(sector));
955     if (!res) {
956     fatal("[ arcbios_get_msdos_partition_size(): couldn't "
957     "read the disk image, id %i, offset 0x%llx ]\n",
958 dpavlin 6 disk_id, (long long)offset);
959 dpavlin 2 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 dpavlin 6 * arcbios_handle_to_disk_id_and_type():
1013 dpavlin 2 */
1014 dpavlin 6 static int arcbios_handle_to_disk_id_and_type(struct machine *machine,
1015     int handle, int *typep)
1016 dpavlin 2 {
1017     int id, cdrom;
1018     char *s;
1019    
1020 dpavlin 6 if (handle < 0 || handle >= ARC_MAX_HANDLES)
1021 dpavlin 2 return -1;
1022    
1023 dpavlin 6 s = machine->md.arc.file_handle_string[handle];
1024 dpavlin 2 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 dpavlin 6 *typep = DISKIMAGE_SCSI;
1036    
1037 dpavlin 2 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 dpavlin 6 char *s = machine->md.arc.file_handle_string[handle];
1051 dpavlin 2 char *s2;
1052 dpavlin 6 int disk_id, disk_type;
1053 dpavlin 2
1054 dpavlin 6 disk_id = arcbios_handle_to_disk_id_and_type(machine,
1055     handle, &disk_type);
1056    
1057     if (disk_id < 0)
1058 dpavlin 2 return;
1059    
1060     /* This works for "partition(0)": */
1061     *start = 0;
1062 dpavlin 6 *size = diskimage_getsize(machine, disk_id, disk_type);
1063 dpavlin 2
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 dpavlin 6 disk_id, disk_type, partition_nr, start, size);
1071 dpavlin 2 }
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     cpu->dead = 1;
1127     }
1128     }
1129    
1130    
1131     /*
1132     * arcbios_emul(): ARCBIOS emulation
1133     *
1134     * 0x0c Halt()
1135     * 0x10 PowerDown()
1136     * 0x14 Restart()
1137     * 0x18 Reboot()
1138     * 0x1c EnterInteractiveMode()
1139     * 0x20 ReturnFromMain()
1140     * 0x24 GetPeer(node)
1141     * 0x28 GetChild(node)
1142     * 0x2c GetParent(node)
1143     * 0x30 GetConfigurationData(config_data, node)
1144     * 0x3c GetComponent(name)
1145     * 0x44 GetSystemId()
1146     * 0x48 GetMemoryDescriptor(void *)
1147     * 0x50 GetTime()
1148     * 0x54 GetRelativeTime()
1149     * 0x5c Open(path, mode, &fileid)
1150     * 0x60 Close(handle)
1151     * 0x64 Read(handle, &buf, len, &actuallen)
1152     * 0x6c Write(handle, buf, len, &returnlen)
1153     * 0x70 Seek(handle, &offset, len)
1154     * 0x78 GetEnvironmentVariable(char *)
1155     * 0x7c SetEnvironmentVariable(char *, char *)
1156     * 0x80 GetFileInformation(handle, buf)
1157     * 0x88 FlushAllCaches()
1158     * 0x90 GetDisplayStatus(uint32_t handle)
1159     * 0x100 undocumented IRIX (?)
1160     */
1161     int arcbios_emul(struct cpu *cpu)
1162     {
1163 dpavlin 6 struct machine *machine = cpu->machine;
1164 dpavlin 2 int vector = cpu->pc & 0xfff;
1165     int i, j, handle;
1166     unsigned char ch2;
1167     unsigned char buf[40];
1168    
1169     if (cpu->pc >= ARC_PRIVATE_ENTRIES &&
1170     cpu->pc < ARC_PRIVATE_ENTRIES + 100*sizeof(uint32_t)) {
1171     arcbios_private_emul(cpu);
1172     return 1;
1173     }
1174    
1175 dpavlin 6 if (machine->md.arc.arc_64bit)
1176 dpavlin 2 vector /= 2;
1177    
1178     /* Special case for reboot by jumping to 0xbfc00000: */
1179     if (vector == 0 && (cpu->pc & 0xffffffffULL) == 0xbfc00000ULL)
1180     vector = 0x18;
1181    
1182     switch (vector) {
1183     case 0x0c: /* Halt() */
1184     case 0x10: /* PowerDown() */
1185     case 0x14: /* Restart() */
1186     case 0x18: /* Reboot() */
1187     case 0x1c: /* EnterInteractiveMode() */
1188     case 0x20: /* ReturnFromMain() */
1189     debug("[ ARCBIOS Halt() or similar ]\n");
1190     /* Halt all CPUs. */
1191 dpavlin 6 for (i=0; i<machine->ncpus; i++) {
1192     machine->cpus[i]->running = 0;
1193     machine->cpus[i]->dead = 1;
1194 dpavlin 2 }
1195 dpavlin 6 machine->exit_without_entering_debugger = 1;
1196 dpavlin 2 break;
1197     case 0x24: /* GetPeer(node) */
1198     if (cpu->cd.mips.gpr[MIPS_GPR_A0] == 0) {
1199     /* NULL ptr argument: return NULL. */
1200     cpu->cd.mips.gpr[MIPS_GPR_V0] = 0;
1201     } else {
1202     uint64_t peer;
1203     cpu->memory_rw(cpu, cpu->mem,
1204 dpavlin 6 cpu->cd.mips.gpr[MIPS_GPR_A0] - 3 *
1205     machine->md.arc.wordlen, &buf[0],
1206     machine->md.arc.wordlen, MEM_READ, CACHE_NONE);
1207     if (machine->md.arc.arc_64bit) {
1208 dpavlin 2 if (cpu->byte_order == EMUL_BIG_ENDIAN) {
1209     unsigned char tmp; tmp = buf[0];
1210     buf[0] = buf[7]; buf[7] = tmp;
1211     tmp = buf[1]; buf[1] = buf[6];
1212     buf[6] = tmp;
1213     tmp = buf[2]; buf[2] = buf[5];
1214     buf[5] = tmp;
1215     tmp = buf[3]; buf[3] = buf[4];
1216     buf[4] = tmp;
1217     }
1218     peer = (uint64_t)buf[0] + ((uint64_t)buf[1]<<8)
1219     + ((uint64_t)buf[2]<<16)
1220     + ((uint64_t)buf[3]<<24)
1221     + ((uint64_t)buf[4]<<32)
1222     + ((uint64_t)buf[5]<<40)
1223     + ((uint64_t)buf[6]<<48)
1224     + ((uint64_t)buf[7]<<56);
1225     } else {
1226     if (cpu->byte_order == EMUL_BIG_ENDIAN) {
1227     unsigned char tmp; tmp = buf[0];
1228     buf[0] = buf[3]; buf[3] = tmp;
1229     tmp = buf[1]; buf[1] = buf[2];
1230     buf[2] = tmp;
1231     }
1232     peer = buf[0] + (buf[1]<<8) + (buf[2]<<16)
1233     + (buf[3]<<24);
1234     }
1235    
1236     cpu->cd.mips.gpr[MIPS_GPR_V0] = peer?
1237 dpavlin 6 (peer + 3 * machine->md.arc.wordlen) : 0;
1238     if (!machine->md.arc.arc_64bit)
1239 dpavlin 2 cpu->cd.mips.gpr[MIPS_GPR_V0] = (int64_t)
1240     (int32_t) cpu->cd.mips.gpr[MIPS_GPR_V0];
1241     }
1242     debug("[ ARCBIOS GetPeer(node 0x%016llx): 0x%016llx ]\n",
1243     (long long)cpu->cd.mips.gpr[MIPS_GPR_A0],
1244     (long long)cpu->cd.mips.gpr[MIPS_GPR_V0]);
1245     break;
1246     case 0x28: /* GetChild(node) */
1247     /* 0 for the root, non-0 for children: */
1248     if (cpu->cd.mips.gpr[MIPS_GPR_A0] == 0)
1249 dpavlin 6 cpu->cd.mips.gpr[MIPS_GPR_V0] = FIRST_ARC_COMPONENT
1250     + machine->md.arc.wordlen * 3;
1251 dpavlin 2 else {
1252     uint64_t child = 0;
1253     cpu->memory_rw(cpu, cpu->mem,
1254 dpavlin 6 cpu->cd.mips.gpr[MIPS_GPR_A0] - 2 *
1255     machine->md.arc.wordlen, &buf[0], machine->
1256     md.arc.wordlen, MEM_READ, CACHE_NONE);
1257     if (machine->md.arc.arc_64bit) {
1258 dpavlin 2 if (cpu->byte_order == EMUL_BIG_ENDIAN) {
1259     unsigned char tmp; tmp = buf[0];
1260     buf[0] = buf[7]; buf[7] = tmp;
1261     tmp = buf[1]; buf[1] = buf[6];
1262     buf[6] = tmp;
1263     tmp = buf[2]; buf[2] = buf[5];
1264     buf[5] = tmp;
1265     tmp = buf[3]; buf[3] = buf[4];
1266     buf[4] = tmp;
1267     }
1268     child = (uint64_t)buf[0] +
1269     ((uint64_t)buf[1]<<8) +
1270     ((uint64_t)buf[2]<<16) +
1271     ((uint64_t)buf[3]<<24) +
1272     ((uint64_t)buf[4]<<32) +
1273     ((uint64_t)buf[5]<<40) +
1274     ((uint64_t)buf[6]<<48) +
1275     ((uint64_t)buf[7]<<56);
1276     } else {
1277     if (cpu->byte_order == EMUL_BIG_ENDIAN) {
1278     unsigned char tmp; tmp = buf[0];
1279     buf[0] = buf[3]; buf[3] = tmp;
1280     tmp = buf[1]; buf[1] = buf[2];
1281     buf[2] = tmp;
1282     }
1283     child = buf[0] + (buf[1]<<8) + (buf[2]<<16) +
1284     (buf[3]<<24);
1285     }
1286    
1287     cpu->cd.mips.gpr[MIPS_GPR_V0] = child?
1288 dpavlin 6 (child + 3 * machine->md.arc.wordlen) : 0;
1289     if (!machine->md.arc.arc_64bit)
1290 dpavlin 2 cpu->cd.mips.gpr[MIPS_GPR_V0] = (int64_t)
1291     (int32_t)cpu->cd.mips.gpr[MIPS_GPR_V0];
1292     }
1293     debug("[ ARCBIOS GetChild(node 0x%016llx): 0x%016llx ]\n",
1294     (long long)cpu->cd.mips.gpr[MIPS_GPR_A0],
1295     (long long)cpu->cd.mips.gpr[MIPS_GPR_V0]);
1296     break;
1297     case 0x2c: /* GetParent(node) */
1298     {
1299     uint64_t parent;
1300    
1301     cpu->memory_rw(cpu, cpu->mem,
1302 dpavlin 6 cpu->cd.mips.gpr[MIPS_GPR_A0] - 1 * machine->
1303     md.arc.wordlen, &buf[0], machine->md.arc.wordlen,
1304     MEM_READ, CACHE_NONE);
1305 dpavlin 2
1306 dpavlin 6 if (machine->md.arc.arc_64bit) {
1307 dpavlin 2 if (cpu->byte_order == EMUL_BIG_ENDIAN) {
1308     unsigned char tmp; tmp = buf[0];
1309     buf[0] = buf[7]; buf[7] = tmp;
1310     tmp = buf[1]; buf[1] = buf[6];
1311     buf[6] = tmp;
1312     tmp = buf[2]; buf[2] = buf[5];
1313     buf[5] = tmp;
1314     tmp = buf[3]; buf[3] = buf[4];
1315     buf[4] = tmp;
1316     }
1317     parent = (uint64_t)buf[0] +
1318     ((uint64_t)buf[1]<<8) +
1319     ((uint64_t)buf[2]<<16) +
1320     ((uint64_t)buf[3]<<24) +
1321     ((uint64_t)buf[4]<<32) +
1322     ((uint64_t)buf[5]<<40) +
1323     ((uint64_t)buf[6]<<48) +
1324     ((uint64_t)buf[7]<<56);
1325     } else {
1326     if (cpu->byte_order == EMUL_BIG_ENDIAN) {
1327     unsigned char tmp; tmp = buf[0];
1328     buf[0] = buf[3]; buf[3] = tmp;
1329     tmp = buf[1]; buf[1] = buf[2];
1330     buf[2] = tmp;
1331     }
1332     parent = buf[0] + (buf[1]<<8) +
1333     (buf[2]<<16) + (buf[3]<<24);
1334     }
1335    
1336     cpu->cd.mips.gpr[MIPS_GPR_V0] = parent?
1337 dpavlin 6 (parent + 3 * machine->md.arc.wordlen) : 0;
1338     if (!machine->md.arc.arc_64bit)
1339 dpavlin 2 cpu->cd.mips.gpr[MIPS_GPR_V0] = (int64_t)
1340     (int32_t) cpu->cd.mips.gpr[MIPS_GPR_V0];
1341     }
1342     debug("[ ARCBIOS GetParent(node 0x%016llx): 0x%016llx ]\n",
1343     (long long)cpu->cd.mips.gpr[MIPS_GPR_A0],
1344     (long long)cpu->cd.mips.gpr[MIPS_GPR_V0]);
1345     break;
1346     case 0x30: /* GetConfigurationData(void *configdata, void *node) */
1347     /* fatal("[ ARCBIOS GetConfigurationData(0x%016llx,"
1348     "0x%016llx) ]\n", (long long)cpu->cd.mips.gpr[MIPS_GPR_A0],
1349     (long long)cpu->cd.mips.gpr[MIPS_GPR_A1]); */
1350     cpu->cd.mips.gpr[MIPS_GPR_V0] = ARCBIOS_EINVAL;
1351 dpavlin 6 for (i=0; i<machine->md.arc.n_configuration_data; i++) {
1352 dpavlin 2 /* fatal("configuration_data_component[%i] = "
1353 dpavlin 6 "0x%016llx\n", i, (long long)machine->
1354     md.arc.configuration_data_component[i]); */
1355 dpavlin 2 if (cpu->cd.mips.gpr[MIPS_GPR_A1] ==
1356 dpavlin 6 machine->md.arc.configuration_data_component[i]) {
1357 dpavlin 2 cpu->cd.mips.gpr[MIPS_GPR_V0] = 0;
1358 dpavlin 6 for (j=0; j<machine->
1359     md.arc.configuration_data_len[i]; j++) {
1360 dpavlin 2 unsigned char ch;
1361     cpu->memory_rw(cpu, cpu->mem,
1362 dpavlin 6 machine->md.arc.
1363 dpavlin 2 configuration_data_configdata[i] +
1364     j, &ch, 1, MEM_READ, CACHE_NONE);
1365     cpu->memory_rw(cpu, cpu->mem,
1366     cpu->cd.mips.gpr[MIPS_GPR_A0] + j,
1367     &ch, 1, MEM_WRITE, CACHE_NONE);
1368     }
1369     break;
1370     }
1371     }
1372     break;
1373     case 0x3c: /* GetComponent(char *name) */
1374     debug("[ ARCBIOS GetComponent(\"");
1375     dump_mem_string(cpu, cpu->cd.mips.gpr[MIPS_GPR_A0]);
1376     debug("\") ]\n");
1377    
1378     if (cpu->cd.mips.gpr[MIPS_GPR_A0] == 0) {
1379     fatal("[ ARCBIOS GetComponent: NULL ptr ]\n");
1380     } else {
1381     unsigned char buf[500];
1382     int match_index = -1;
1383     int match_len = 0;
1384    
1385     memset(buf, 0, sizeof(buf));
1386     for (i=0; i<sizeof(buf); i++) {
1387     cpu->memory_rw(cpu, cpu->mem,
1388     cpu->cd.mips.gpr[MIPS_GPR_A0] + i,
1389     &buf[i], 1, MEM_READ, CACHE_NONE);
1390     if (buf[i] == '\0')
1391     i = sizeof(buf);
1392     }
1393     buf[sizeof(buf) - 1] = '\0';
1394    
1395     /* "scsi(0)disk(0)rdisk(0)partition(0)" and such. */
1396     /* printf("GetComponent(\"%s\")\n", buf); */
1397    
1398     /* Default to NULL return value. */
1399     cpu->cd.mips.gpr[MIPS_GPR_V0] = 0;
1400    
1401     /* Scan the string to component table: */
1402 dpavlin 6 for (i=0; i<machine->md.arc.n_string_to_components;
1403     i++) {
1404 dpavlin 2 int m = 0;
1405 dpavlin 6 while (buf[m] && machine->md.arc.
1406     string_to_component[i][m] &&
1407     machine->md.arc.string_to_component[i][m]
1408 dpavlin 2 == buf[m])
1409     m++;
1410     if (m > match_len) {
1411     match_len = m;
1412     match_index = i;
1413     }
1414     }
1415    
1416     if (match_index >= 0) {
1417     /* printf("Longest match: '%s'\n",
1418 dpavlin 6 machine->md.arc.string_to_component[
1419 dpavlin 2 match_index]); */
1420     cpu->cd.mips.gpr[MIPS_GPR_V0] =
1421 dpavlin 6 machine->md.arc.string_to_component_value[
1422 dpavlin 2 match_index];
1423     }
1424     }
1425     break;
1426     case 0x44: /* GetSystemId() */
1427     debug("[ ARCBIOS GetSystemId() ]\n");
1428     cpu->cd.mips.gpr[MIPS_GPR_V0] = SGI_SYSID_ADDR;
1429     break;
1430     case 0x48: /* void *GetMemoryDescriptor(void *ptr) */
1431     debug("[ ARCBIOS GetMemoryDescriptor(0x%08x) ]\n",
1432     (int)cpu->cd.mips.gpr[MIPS_GPR_A0]);
1433    
1434     /* If a0=NULL, then return the first descriptor: */
1435     if ((uint32_t)cpu->cd.mips.gpr[MIPS_GPR_A0] == 0)
1436     cpu->cd.mips.gpr[MIPS_GPR_V0] =
1437 dpavlin 6 machine->md.arc.memdescriptor_base;
1438 dpavlin 2 else {
1439 dpavlin 6 int s = machine->md.arc.arc_64bit?
1440     sizeof(struct arcbios_mem64)
1441 dpavlin 2 : sizeof(struct arcbios_mem);
1442     int nr = cpu->cd.mips.gpr[MIPS_GPR_A0] -
1443 dpavlin 6 machine->md.arc.memdescriptor_base;
1444 dpavlin 2 nr /= s;
1445     nr ++;
1446     cpu->cd.mips.gpr[MIPS_GPR_V0] =
1447 dpavlin 6 machine->md.arc.memdescriptor_base + s * nr;
1448     if (nr >= machine->md.arc.n_memdescriptors)
1449 dpavlin 2 cpu->cd.mips.gpr[MIPS_GPR_V0] = 0;
1450     }
1451     break;
1452     case 0x50: /* GetTime() */
1453     debug("[ ARCBIOS GetTime() ]\n");
1454     cpu->cd.mips.gpr[MIPS_GPR_V0] = 0xffffffff80001000ULL;
1455     /* TODO! */
1456     break;
1457     case 0x54: /* GetRelativeTime() */
1458     debug("[ ARCBIOS GetRelativeTime() ]\n");
1459     cpu->cd.mips.gpr[MIPS_GPR_V0] = (int64_t)(int32_t)time(NULL);
1460     break;
1461     case 0x5c: /* Open(char *path, uint32_t mode, uint32_t *fileID) */
1462     debug("[ ARCBIOS Open(\"");
1463     dump_mem_string(cpu, cpu->cd.mips.gpr[MIPS_GPR_A0]);
1464     debug("\",0x%x,0x%x)", (int)cpu->cd.mips.gpr[MIPS_GPR_A0],
1465     (int)cpu->cd.mips.gpr[MIPS_GPR_A1],
1466     (int)cpu->cd.mips.gpr[MIPS_GPR_A2]);
1467    
1468     cpu->cd.mips.gpr[MIPS_GPR_V0] = ARCBIOS_ENOENT;
1469    
1470     handle = 3;
1471     /* TODO: Starting at 0 would require some updates... */
1472 dpavlin 6 while (machine->md.arc.file_handle_in_use[handle]) {
1473 dpavlin 2 handle ++;
1474 dpavlin 6 if (handle >= ARC_MAX_HANDLES) {
1475 dpavlin 2 cpu->cd.mips.gpr[MIPS_GPR_V0] = ARCBIOS_EMFILE;
1476     break;
1477     }
1478     }
1479    
1480 dpavlin 6 if (handle >= ARC_MAX_HANDLES) {
1481 dpavlin 2 fatal("[ ARCBIOS Open: out of file handles ]\n");
1482     } else if (cpu->cd.mips.gpr[MIPS_GPR_A0] == 0) {
1483     fatal("[ ARCBIOS Open: NULL ptr ]\n");
1484     } else {
1485     /*
1486     * TODO: This is hardcoded to successfully open
1487     * anything. It is used by the Windows NT SETUPLDR
1488     * program to load stuff from the boot partition.
1489     */
1490     unsigned char *buf = malloc(MAX_OPEN_STRINGLEN);
1491     if (buf == NULL) {
1492     fprintf(stderr, "out of memory\n");
1493     exit(1);
1494     }
1495     memset(buf, 0, MAX_OPEN_STRINGLEN);
1496     for (i=0; i<MAX_OPEN_STRINGLEN; i++) {
1497     cpu->memory_rw(cpu, cpu->mem,
1498     cpu->cd.mips.gpr[MIPS_GPR_A0] + i,
1499     &buf[i], 1, MEM_READ, CACHE_NONE);
1500     if (buf[i] == '\0')
1501     i = MAX_OPEN_STRINGLEN;
1502     }
1503     buf[MAX_OPEN_STRINGLEN - 1] = '\0';
1504 dpavlin 6 machine->md.arc.file_handle_string[handle] =
1505     (char *)buf;
1506     machine->md.arc.current_seek_offset[handle] = 0;
1507 dpavlin 2 cpu->cd.mips.gpr[MIPS_GPR_V0] = ARCBIOS_ESUCCESS;
1508     }
1509    
1510     if (cpu->cd.mips.gpr[MIPS_GPR_V0] == ARCBIOS_ESUCCESS) {
1511     debug(" = handle %i ]\n", (int)handle);
1512     store_32bit_word(cpu, cpu->cd.mips.gpr[MIPS_GPR_A2],
1513     handle);
1514 dpavlin 6 machine->md.arc.file_handle_in_use[handle] = 1;
1515 dpavlin 2 } else
1516     debug(" = ERROR %i ]\n",
1517     (int)cpu->cd.mips.gpr[MIPS_GPR_V0]);
1518     break;
1519     case 0x60: /* Close(uint32_t handle) */
1520     debug("[ ARCBIOS Close(%i) ]\n",
1521     (int)cpu->cd.mips.gpr[MIPS_GPR_A0]);
1522 dpavlin 6 if (!machine->md.arc.file_handle_in_use[cpu->cd.mips.gpr[
1523     MIPS_GPR_A0]]) {
1524 dpavlin 2 fatal("ARCBIOS Close(%i): bad handle\n",
1525     (int)cpu->cd.mips.gpr[MIPS_GPR_A0]);
1526     cpu->cd.mips.gpr[MIPS_GPR_V0] = ARCBIOS_EBADF;
1527     } else {
1528 dpavlin 6 machine->md.arc.file_handle_in_use[
1529     cpu->cd.mips.gpr[MIPS_GPR_A0]] = 0;
1530     if (machine->md.arc.file_handle_string[
1531     cpu->cd.mips.gpr[MIPS_GPR_A0]] != NULL)
1532     free(machine->md.arc.file_handle_string[
1533     cpu->cd.mips.gpr[MIPS_GPR_A0]]);
1534     machine->md.arc.file_handle_string[cpu->cd.mips.
1535     gpr[MIPS_GPR_A0]] = NULL;
1536 dpavlin 2 cpu->cd.mips.gpr[MIPS_GPR_V0] = ARCBIOS_ESUCCESS;
1537     }
1538     break;
1539     case 0x64: /* Read(handle, void *buf, length, uint32_t *count) */
1540     if (cpu->cd.mips.gpr[MIPS_GPR_A0] == ARCBIOS_STDIN) {
1541     int i, nread = 0;
1542     /*
1543     * Before going into the loop, make sure stdout
1544     * is flushed. If we're using an X11 VGA console,
1545     * then it needs to be flushed as well.
1546     */
1547     fflush(stdin);
1548     fflush(stdout);
1549     /* NOTE/TODO: This gives a tick to _everything_ */
1550 dpavlin 6 for (i=0; i<machine->n_tick_entries; i++)
1551     machine->tick_func[i](cpu,
1552     machine->tick_extra[i]);
1553 dpavlin 2
1554     for (i=0; i<cpu->cd.mips.gpr[MIPS_GPR_A2]; 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 dpavlin 6 x = console_readchar(
1562     machine->main_console_handle);
1563 dpavlin 2 if (x < 0)
1564     return 0;
1565    
1566     /*
1567     * ESC + '[' should be transformed into 0x9b:
1568     *
1569     * NOTE/TODO: This makes the behaviour of just
1570     * pressing ESC a bit harder to define.
1571     */
1572     if (x == 27) {
1573     x = console_readchar(cpu->
1574     machine->main_console_handle);
1575     if (x == '[' || x == 'O')
1576     x = 0x9b;
1577     }
1578    
1579     ch = x;
1580     nread ++;
1581     cpu->memory_rw(cpu, cpu->mem,
1582     cpu->cd.mips.gpr[MIPS_GPR_A1] + i,
1583     &ch, 1, MEM_WRITE, CACHE_NONE);
1584    
1585     /* NOTE: Only one char, from STDIN: */
1586     i = cpu->cd.mips.gpr[MIPS_GPR_A2]; /* :-) */
1587     }
1588     store_32bit_word(cpu, cpu->cd.mips.gpr[MIPS_GPR_A3],
1589     nread);
1590     /* TODO: not EAGAIN? */
1591     cpu->cd.mips.gpr[MIPS_GPR_V0] =
1592     nread? ARCBIOS_ESUCCESS: ARCBIOS_EAGAIN;
1593     } else {
1594     int handle = cpu->cd.mips.gpr[MIPS_GPR_A0];
1595 dpavlin 6 int disk_type;
1596     int disk_id = arcbios_handle_to_disk_id_and_type(
1597     machine, handle, &disk_type);
1598 dpavlin 2 uint64_t partition_offset = 0;
1599     int res;
1600     uint64_t size; /* dummy */
1601     unsigned char *tmp_buf;
1602    
1603 dpavlin 6 arcbios_handle_to_start_and_size(machine, handle,
1604     &partition_offset, &size);
1605 dpavlin 2
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 dpavlin 6 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 dpavlin 2
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 dpavlin 6 machine->md.arc.current_seek_offset[handle] +=
1635 dpavlin 2 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 dpavlin 6 machine->main_console_handle)? 0 : 1;
1653 dpavlin 2 } else {
1654     fatal("[ ARCBIOS GetReadStatus(%i) from "
1655     "something other than STDIN: TODO ]\n",
1656     (int)cpu->cd.mips.gpr[MIPS_GPR_A0]);
1657     /* TODO */
1658     cpu->cd.mips.gpr[MIPS_GPR_V0] = 1;
1659     }
1660     break;
1661     case 0x6c: /* Write(handle, buf, len, &returnlen) */
1662     if (cpu->cd.mips.gpr[MIPS_GPR_A0] != ARCBIOS_STDOUT) {
1663     /*
1664     * TODO: this is just a test
1665     */
1666     int handle = cpu->cd.mips.gpr[MIPS_GPR_A0];
1667 dpavlin 6 int disk_type;
1668     int disk_id = arcbios_handle_to_disk_id_and_type(
1669     machine, handle, &disk_type);
1670 dpavlin 2 uint64_t partition_offset = 0;
1671     int res, i;
1672     uint64_t size; /* dummy */
1673     unsigned char *tmp_buf;
1674    
1675 dpavlin 6 arcbios_handle_to_start_and_size(machine,
1676 dpavlin 2 handle, &partition_offset, &size);
1677    
1678     debug("[ ARCBIOS Write(%i,0x%08llx,%i,0x%08llx) ]\n",
1679     (int)cpu->cd.mips.gpr[MIPS_GPR_A0],
1680     (long long)cpu->cd.mips.gpr[MIPS_GPR_A1],
1681     (int)cpu->cd.mips.gpr[MIPS_GPR_A2],
1682     (long long)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<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 dpavlin 6 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 dpavlin 2
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 dpavlin 6 machine->md.arc.current_seek_offset[handle] +=
1708 dpavlin 2 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<cpu->cd.mips.gpr[MIPS_GPR_A2]; i++) {
1715     unsigned char ch = '\0';
1716     cpu->memory_rw(cpu, cpu->mem,
1717     cpu->cd.mips.gpr[MIPS_GPR_A1] + i,
1718     &ch, sizeof(ch), MEM_READ, CACHE_NONE);
1719    
1720     arcbios_putchar(cpu, ch);
1721     }
1722     }
1723     store_32bit_word(cpu, cpu->cd.mips.gpr[MIPS_GPR_A3],
1724     cpu->cd.mips.gpr[MIPS_GPR_A2]);
1725     cpu->cd.mips.gpr[MIPS_GPR_V0] = 0; /* Success. */
1726     break;
1727     case 0x70: /* Seek(uint32_t handle, int64_t *ofs,
1728     uint32_t whence): uint32_t */
1729     debug("[ ARCBIOS Seek(%i,0x%08llx,%i): ",
1730     (int)cpu->cd.mips.gpr[MIPS_GPR_A0],
1731     (long long)cpu->cd.mips.gpr[MIPS_GPR_A1],
1732     (int)cpu->cd.mips.gpr[MIPS_GPR_A2]);
1733    
1734     if (cpu->cd.mips.gpr[MIPS_GPR_A2] != 0) {
1735     fatal("[ ARCBIOS Seek(%i,0x%08llx,%i): "
1736     "UNIMPLEMENTED whence=%i ]\n",
1737     (int)cpu->cd.mips.gpr[MIPS_GPR_A0],
1738     (long long)cpu->cd.mips.gpr[MIPS_GPR_A1],
1739     (int)cpu->cd.mips.gpr[MIPS_GPR_A2],
1740     (int)cpu->cd.mips.gpr[MIPS_GPR_A2]);
1741     }
1742    
1743     {
1744     unsigned char buf[8];
1745     uint64_t ofs;
1746     cpu->memory_rw(cpu, cpu->mem,
1747     cpu->cd.mips.gpr[MIPS_GPR_A1], &buf[0],
1748     sizeof(buf), MEM_READ, CACHE_NONE);
1749     if (cpu->byte_order == EMUL_BIG_ENDIAN) {
1750     unsigned char tmp;
1751     tmp = buf[0]; buf[0] = buf[7]; buf[7] = tmp;
1752     tmp = buf[1]; buf[1] = buf[6]; buf[6] = tmp;
1753     tmp = buf[2]; buf[2] = buf[5]; buf[5] = tmp;
1754     tmp = buf[3]; buf[3] = buf[4]; buf[4] = tmp;
1755     }
1756     ofs = buf[0] + (buf[1] << 8) + (buf[2] << 16) +
1757     (buf[3] << 24) + ((uint64_t)buf[4] << 32) +
1758     ((uint64_t)buf[5] << 40) + ((uint64_t)buf[6] << 48)
1759     + ((uint64_t)buf[7] << 56);
1760 dpavlin 6 machine->md.arc.current_seek_offset[
1761 dpavlin 2 cpu->cd.mips.gpr[MIPS_GPR_A0]] = ofs;
1762     debug("%016llx ]\n", (long long)ofs);
1763     }
1764    
1765     cpu->cd.mips.gpr[MIPS_GPR_V0] = 0; /* Success. */
1766    
1767     break;
1768     case 0x78: /* GetEnvironmentVariable(char *) */
1769     /* Find the environment variable given by a0: */
1770     for (i=0; i<sizeof(buf); i++)
1771     cpu->memory_rw(cpu, cpu->mem,
1772     cpu->cd.mips.gpr[MIPS_GPR_A0] + i,
1773     &buf[i], sizeof(char), MEM_READ, CACHE_NONE);
1774     buf[sizeof(buf)-1] = '\0';
1775     debug("[ ARCBIOS GetEnvironmentVariable(\"%s\") ]\n", buf);
1776     for (i=0; i<0x1000; i++) {
1777     /* Matching string at offset i? */
1778     int nmatches = 0;
1779     for (j=0; j<strlen((char *)buf); j++) {
1780     cpu->memory_rw(cpu, cpu->mem,
1781     (uint64_t)(ARC_ENV_STRINGS + i + j),
1782     &ch2, sizeof(char), MEM_READ, CACHE_NONE);
1783     if (ch2 == buf[j])
1784     nmatches++;
1785     }
1786     cpu->memory_rw(cpu, cpu->mem,
1787     (uint64_t)(ARC_ENV_STRINGS + i +
1788     strlen((char *)buf)), &ch2, sizeof(char),
1789     MEM_READ, CACHE_NONE);
1790     if (nmatches == strlen((char *)buf) && ch2 == '=') {
1791     cpu->cd.mips.gpr[MIPS_GPR_V0] =
1792     ARC_ENV_STRINGS + i +
1793     strlen((char *)buf) + 1;
1794     return 1;
1795     }
1796     }
1797     /* Return NULL if string wasn't found. */
1798     cpu->cd.mips.gpr[MIPS_GPR_V0] = 0;
1799     break;
1800     case 0x7c: /* SetEnvironmentVariable(char *, char *) */
1801     debug("[ ARCBIOS SetEnvironmentVariable(\"");
1802     dump_mem_string(cpu, cpu->cd.mips.gpr[MIPS_GPR_A0]);
1803     debug("\",\"");
1804     dump_mem_string(cpu, cpu->cd.mips.gpr[MIPS_GPR_A1]);
1805     debug("\") ]\n");
1806     /* TODO: This is a dummy. */
1807     cpu->cd.mips.gpr[MIPS_GPR_V0] = ARCBIOS_ESUCCESS;
1808     break;
1809     case 0x80: /* GetFileInformation() */
1810     debug("[ ARCBIOS GetFileInformation(%i,0x%x): ",
1811     (int)cpu->cd.mips.gpr[MIPS_GPR_A0],
1812     (int)cpu->cd.mips.gpr[MIPS_GPR_A1]);
1813    
1814 dpavlin 6 if (cpu->cd.mips.gpr[MIPS_GPR_A0] >= ARC_MAX_HANDLES) {
1815 dpavlin 2 debug("invalid file handle ]\n");
1816     cpu->cd.mips.gpr[MIPS_GPR_V0] = ARCBIOS_EINVAL;
1817 dpavlin 6 } else if (!machine->md.arc.file_handle_in_use[cpu->cd.
1818     mips.gpr[MIPS_GPR_A0]]) {
1819 dpavlin 2 debug("file handle not in use! ]\n");
1820     cpu->cd.mips.gpr[MIPS_GPR_V0] = ARCBIOS_EBADF;
1821     } else {
1822 dpavlin 6 debug("'%s' ]\n", machine->md.arc.file_handle_string[
1823 dpavlin 2 cpu->cd.mips.gpr[MIPS_GPR_A0]]);
1824     cpu->cd.mips.gpr[MIPS_GPR_V0] =
1825     arcbios_getfileinformation(cpu);
1826     }
1827     break;
1828     case 0x88: /* FlushAllCaches() */
1829     debug("[ ARCBIOS FlushAllCaches(): TODO ]\n");
1830     cpu->cd.mips.gpr[MIPS_GPR_V0] = 0;
1831     break;
1832     case 0x90: /* void *GetDisplayStatus(handle) */
1833     debug("[ ARCBIOS GetDisplayStatus(%i) ]\n",
1834     (int)cpu->cd.mips.gpr[MIPS_GPR_A0]);
1835     /* TODO: handle different values of 'handle'? */
1836     cpu->cd.mips.gpr[MIPS_GPR_V0] = ARC_DSPSTAT_ADDR;
1837     break;
1838     case 0x100:
1839     /*
1840     * Undocumented, used by IRIX.
1841     */
1842     debug("[ ARCBIOS: IRIX 0x100 (?) ]\n");
1843     /* TODO */
1844     cpu->cd.mips.gpr[MIPS_GPR_V0] = 0;
1845     break;
1846     case 0x888:
1847     /*
1848     * Magical crash if there is no exception handling code.
1849     */
1850     fatal("EXCEPTION, but no exception handler installed yet.\n");
1851     quiet_mode = 0;
1852 dpavlin 6 cpu_register_dump(machine, cpu, 1, 0x1);
1853 dpavlin 2 cpu->running = 0;
1854     cpu->dead = 1;
1855     break;
1856     default:
1857     quiet_mode = 0;
1858 dpavlin 6 cpu_register_dump(machine, cpu, 1, 0x1);
1859 dpavlin 2 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     cpu->dead = 1;
1865     }
1866    
1867     return 1;
1868     }
1869    
1870    
1871     /*
1872     * arcbios_set_default_exception_handler():
1873     */
1874     void arcbios_set_default_exception_handler(struct cpu *cpu)
1875     {
1876     /*
1877     * The default exception handlers simply jump to 0xbfc88888,
1878     * which is then taken care of in arcbios_emul() above.
1879     *
1880     * 3c1abfc8 lui k0,0xbfc8
1881     * 375a8888 ori k0,k0,0x8888
1882     * 03400008 jr k0
1883     * 00000000 nop
1884     */
1885     store_32bit_word(cpu, 0xffffffff80000000ULL, 0x3c1abfc8);
1886     store_32bit_word(cpu, 0xffffffff80000004ULL, 0x375a8888);
1887     store_32bit_word(cpu, 0xffffffff80000008ULL, 0x03400008);
1888     store_32bit_word(cpu, 0xffffffff8000000cULL, 0x00000000);
1889    
1890     store_32bit_word(cpu, 0xffffffff80000080ULL, 0x3c1abfc8);
1891     store_32bit_word(cpu, 0xffffffff80000084ULL, 0x375a8888);
1892     store_32bit_word(cpu, 0xffffffff80000088ULL, 0x03400008);
1893     store_32bit_word(cpu, 0xffffffff8000008cULL, 0x00000000);
1894    
1895     store_32bit_word(cpu, 0xffffffff80000180ULL, 0x3c1abfc8);
1896     store_32bit_word(cpu, 0xffffffff80000184ULL, 0x375a8888);
1897     store_32bit_word(cpu, 0xffffffff80000188ULL, 0x03400008);
1898     store_32bit_word(cpu, 0xffffffff8000018cULL, 0x00000000);
1899     }
1900    
1901    
1902     /*
1903 dpavlin 6 * arcbios_add_other_components():
1904     *
1905     * TODO: How should this be synched with the hardware devices
1906     * added in machine.c?
1907     */
1908     static void arcbios_add_other_components(struct machine *machine,
1909     uint64_t system)
1910     {
1911     struct cpu *cpu = machine->cpus[0];
1912    
1913     if (machine->machine_type == MACHINE_ARC &&
1914     ( machine->machine_subtype == MACHINE_ARC_NEC_RD94 ||
1915     machine->machine_subtype == MACHINE_ARC_NEC_R94 ||
1916     machine->machine_subtype == MACHINE_ARC_NEC_R96 )) {
1917     uint64_t jazzbus, eisa, other;
1918    
1919     jazzbus = arcbios_addchild_manual(cpu,
1920     COMPONENT_CLASS_AdapterClass,
1921     COMPONENT_TYPE_MultiFunctionAdapter,
1922     0, 1, 2, 0, 0xffffffff, "Jazz-Internal Bus",
1923     system, NULL, 0);
1924    
1925     switch (machine->machine_subtype) {
1926     case MACHINE_ARC_NEC_RD94:
1927     case MACHINE_ARC_NEC_R94:
1928     if (machine->use_x11)
1929     arcbios_addchild_manual(cpu,
1930     COMPONENT_CLASS_ControllerClass,
1931     COMPONENT_TYPE_DisplayController,
1932     0, 1, 2, 0, 0x0, "10110004",
1933     system, NULL, 0);
1934     break;
1935     case MACHINE_ARC_NEC_R96:
1936     if (machine->use_x11) {
1937     uint64_t x;
1938     x = arcbios_addchild_manual(cpu,
1939     COMPONENT_CLASS_ControllerClass,
1940     COMPONENT_TYPE_DisplayController,
1941     COMPONENT_FLAG_ConsoleOut |
1942     COMPONENT_FLAG_Output,
1943     1, 2, 0, 0x0, "necvdfrb",
1944     jazzbus, NULL, 0);
1945     arcbios_addchild_manual(cpu,
1946     COMPONENT_CLASS_PeripheralClass,
1947     COMPONENT_TYPE_MonitorPeripheral,
1948     COMPONENT_FLAG_ConsoleOut |
1949     COMPONENT_FLAG_Output,
1950     1, 2, 0, 0xffffffff, "640x480",
1951     x, NULL, 0);
1952     }
1953    
1954     /* TODO: R[D]94 too? */
1955     eisa = arcbios_addchild_manual(cpu,
1956     COMPONENT_CLASS_AdapterClass,
1957     COMPONENT_TYPE_EISAAdapter,
1958     0, 1, 2, 0, 0xffffffff, "EISA",
1959     system, NULL, 0);
1960    
1961     other = arcbios_addchild_manual(cpu,
1962     COMPONENT_CLASS_ControllerClass,
1963     COMPONENT_TYPE_OtherController,
1964     0, 1, 2, 0, 0xffffffff, "NEC1C01",
1965     eisa, NULL, 0);
1966     break;
1967     }
1968     }
1969    
1970     if (machine->machine_type == MACHINE_ARC &&
1971     (machine->machine_subtype == MACHINE_ARC_JAZZ_PICA
1972     || machine->machine_subtype == MACHINE_ARC_JAZZ_MAGNUM)) {
1973     uint64_t jazzbus, ali_s3, vxl;
1974     uint64_t diskcontroller, floppy, kbdctl, kbd;
1975     uint64_t ptrctl, ptr, paral, audio;
1976     uint64_t eisa, scsi;
1977     /* uint64_t serial1, serial2; */
1978    
1979     jazzbus = arcbios_addchild_manual(cpu,
1980     COMPONENT_CLASS_AdapterClass,
1981     COMPONENT_TYPE_MultiFunctionAdapter,
1982     0, 1, 2, 0, 0xffffffff, "Jazz-Internal Bus",
1983     system, NULL, 0);
1984    
1985     /*
1986     * DisplayController, needed by NetBSD:
1987     * TODO: NetBSD still doesn't use it :(
1988     */
1989     switch (machine->machine_subtype) {
1990     case MACHINE_ARC_JAZZ_PICA:
1991     /* Default TLB entries on PICA-61: */
1992    
1993     /* 7: 256K, asid: 0x0, v: 0xe1000000,
1994     p0: 0xfff00000(2.VG), p1: 0x0(0..G) */
1995     mips_coproc_tlb_set_entry(cpu, 7, 262144,
1996     0xffffffffe1000000ULL,
1997     0x0fff00000ULL, 0, 1, 0, 0, 0, 1, 0, 2, 0);
1998    
1999     /* 8: 64K, asid: 0x0, v: 0xe0000000,
2000     p0: 0x80000000(2DVG), p1: 0x0(0..G) */
2001     mips_coproc_tlb_set_entry(cpu, 8, 65536,
2002     0xffffffffe0000000ULL,
2003     0x080000000ULL, 0, 1, 0, 1, 0, 1, 0, 2, 0);
2004    
2005     /* 9: 64K, asid: 0x0, v: 0xe00e0000,
2006     p0: 0x800e0000(2DVG), p1: 0x800f0000(2DVG) */
2007     mips_coproc_tlb_set_entry(cpu, 9, 65536,
2008     (uint64_t)0xffffffffe00e0000ULL,
2009     (uint64_t)0x0800e0000ULL,
2010     (uint64_t)0x0800f0000ULL, 1, 1, 1, 1, 1, 0, 2, 2);
2011    
2012     /* 10: 4K, asid: 0x0, v: 0xe0100000,
2013     p0: 0xf0000000(2DVG), p1: 0x0(0..G) */
2014     mips_coproc_tlb_set_entry(cpu, 10, 4096,
2015     (uint64_t)0xffffffffe0100000ULL,
2016     (uint64_t)0x0f0000000ULL, 0,1, 0, 1, 0, 1, 0, 2, 0);
2017    
2018     /* 11: 1M, asid: 0x0, v: 0xe0200000,
2019     p0: 0x60000000(2DVG), p1: 0x60100000(2DVG) */
2020     mips_coproc_tlb_set_entry(cpu, 11, 1048576,
2021     0xffffffffe0200000ULL,
2022     0x060000000ULL, 0x060100000ULL,1,1,1,1,1, 0, 2, 2);
2023    
2024     /* 12: 1M, asid: 0x0, v: 0xe0400000,
2025     p0: 0x60200000(2DVG), p1: 0x60300000(2DVG) */
2026     mips_coproc_tlb_set_entry(cpu, 12, 1048576,
2027     0xffffffffe0400000ULL, 0x060200000ULL,
2028     0x060300000ULL, 1, 1, 1, 1, 1, 0, 2, 2);
2029    
2030     /* 13: 4M, asid: 0x0, v: 0xe0800000,
2031     p0: 0x40000000(2DVG), p1: 0x40400000(2DVG) */
2032     mips_coproc_tlb_set_entry(cpu, 13, 1048576*4,
2033     0xffffffffe0800000ULL, 0x040000000ULL,
2034     0x040400000ULL, 1, 1, 1, 1, 1, 0, 2, 2);
2035    
2036     /* 14: 16M, asid: 0x0, v: 0xe2000000,
2037     p0: 0x90000000(2DVG), p1: 0x91000000(2DVG) */
2038     mips_coproc_tlb_set_entry(cpu, 14, 1048576*16,
2039     0xffffffffe2000000ULL, 0x090000000ULL,
2040     0x091000000ULL, 1, 1, 1, 1, 1, 0, 2, 2);
2041    
2042     if (machine->use_x11) {
2043     ali_s3 = arcbios_addchild_manual(cpu,
2044     COMPONENT_CLASS_ControllerClass,
2045     COMPONENT_TYPE_DisplayController,
2046     COMPONENT_FLAG_ConsoleOut |
2047     COMPONENT_FLAG_Output,
2048     1, 2, 0, 0xffffffff, "ALI_S3",
2049     jazzbus, NULL, 0);
2050    
2051     arcbios_addchild_manual(cpu,
2052     COMPONENT_CLASS_PeripheralClass,
2053     COMPONENT_TYPE_MonitorPeripheral,
2054     COMPONENT_FLAG_ConsoleOut |
2055     COMPONENT_FLAG_Output,
2056     1, 2, 0, 0xffffffff, "1024x768",
2057     ali_s3, NULL, 0);
2058     }
2059     break;
2060     case MACHINE_ARC_JAZZ_MAGNUM:
2061     if (machine->use_x11) {
2062     vxl = arcbios_addchild_manual(cpu,
2063     COMPONENT_CLASS_ControllerClass,
2064     COMPONENT_TYPE_DisplayController,
2065     COMPONENT_FLAG_ConsoleOut |
2066     COMPONENT_FLAG_Output,
2067     1, 2, 0, 0xffffffff, "VXL",
2068     jazzbus, NULL, 0);
2069    
2070     arcbios_addchild_manual(cpu,
2071     COMPONENT_CLASS_PeripheralClass,
2072     COMPONENT_TYPE_MonitorPeripheral,
2073     COMPONENT_FLAG_ConsoleOut |
2074     COMPONENT_FLAG_Output,
2075     1, 2, 0, 0xffffffff, "1024x768",
2076     vxl, NULL, 0);
2077     }
2078     break;
2079     }
2080    
2081     diskcontroller = arcbios_addchild_manual(cpu,
2082     COMPONENT_CLASS_ControllerClass,
2083     COMPONENT_TYPE_DiskController,
2084     COMPONENT_FLAG_Input | COMPONENT_FLAG_Output,
2085     1, 2, 0, 0xffffffff, "I82077", jazzbus, NULL, 0);
2086    
2087     floppy = arcbios_addchild_manual(cpu,
2088     COMPONENT_CLASS_PeripheralClass,
2089     COMPONENT_TYPE_FloppyDiskPeripheral,
2090     COMPONENT_FLAG_Removable |
2091     COMPONENT_FLAG_Input | COMPONENT_FLAG_Output,
2092     1, 2, 0, 0xffffffff, NULL, diskcontroller, NULL, 0);
2093    
2094     kbdctl = arcbios_addchild_manual(cpu,
2095     COMPONENT_CLASS_ControllerClass,
2096     COMPONENT_TYPE_KeyboardController,
2097     COMPONENT_FLAG_ConsoleIn | COMPONENT_FLAG_Input,
2098     1, 2, 0, 0xffffffff, "I8742", jazzbus, NULL, 0);
2099    
2100     kbd = arcbios_addchild_manual(cpu,
2101     COMPONENT_CLASS_PeripheralClass,
2102     COMPONENT_TYPE_KeyboardPeripheral,
2103     COMPONENT_FLAG_ConsoleIn | COMPONENT_FLAG_Input,
2104     1, 2, 0, 0xffffffff, "PCAT_ENHANCED", kbdctl, NULL, 0);
2105    
2106     ptrctl = arcbios_addchild_manual(cpu,
2107     COMPONENT_CLASS_ControllerClass,
2108     COMPONENT_TYPE_PointerController, COMPONENT_FLAG_Input,
2109     1, 2, 0, 0xffffffff, "I8742", jazzbus, NULL, 0);
2110    
2111     ptr = arcbios_addchild_manual(cpu,
2112     COMPONENT_CLASS_PeripheralClass,
2113     COMPONENT_TYPE_PointerPeripheral, COMPONENT_FLAG_Input,
2114     1, 2, 0, 0xffffffff, "PS2 MOUSE", ptrctl, NULL, 0);
2115    
2116     /* These cause Windows NT to bug out. */
2117     #if 0
2118     serial1 = arcbios_addchild_manual(cpu,
2119     COMPONENT_CLASS_ControllerClass,
2120     COMPONENT_TYPE_SerialController,
2121     COMPONENT_FLAG_Input | COMPONENT_FLAG_Output,
2122     1, 2, 0, 0xffffffff, "COM1", jazzbus, NULL, 0);
2123    
2124     serial2 = arcbios_addchild_manual(cpu,
2125     COMPONENT_CLASS_ControllerClass,
2126     COMPONENT_TYPE_SerialController,
2127     COMPONENT_FLAG_Input | COMPONENT_FLAG_Output,
2128     1, 2, 0, 0xffffffff, "COM1", jazzbus, NULL, 0);
2129     #endif
2130    
2131     paral = arcbios_addchild_manual(cpu,
2132     COMPONENT_CLASS_ControllerClass,
2133     COMPONENT_TYPE_ParallelController,
2134     COMPONENT_FLAG_Input | COMPONENT_FLAG_Output,
2135     1, 2, 0, 0xffffffff, "LPT1", jazzbus, NULL, 0);
2136    
2137     audio = arcbios_addchild_manual(cpu,
2138     COMPONENT_CLASS_ControllerClass,
2139     COMPONENT_TYPE_AudioController,
2140     COMPONENT_FLAG_Input | COMPONENT_FLAG_Output,
2141     1, 2, 0, 0xffffffff, "MAGNUM", jazzbus, NULL, 0);
2142    
2143     eisa = arcbios_addchild_manual(cpu,
2144     COMPONENT_CLASS_AdapterClass, COMPONENT_TYPE_EISAAdapter,
2145     0, 1, 2, 0, 0xffffffff, "EISA", system, NULL, 0);
2146    
2147     {
2148     unsigned char config[78];
2149     memset(config, 0, sizeof(config));
2150    
2151     /* config data version: 1, revision: 2, count: 4 */
2152     config[0] = 0x01; config[1] = 0x00;
2153     config[2] = 0x02; config[3] = 0x00;
2154     config[4] = 0x04; config[5] = 0x00; config[6] = 0x00; config[7] = 0x00;
2155    
2156     /*
2157     type: Interrupt
2158     share_disposition: DeviceExclusive, flags: LevelSensitive
2159     level: 4, vector: 22, reserved1: 0
2160     */
2161     config[8] = arc_CmResourceTypeInterrupt;
2162     config[9] = arc_CmResourceShareDeviceExclusive;
2163     config[10] = arc_CmResourceInterruptLevelSensitive;
2164     config[12] = 4;
2165     config[16] = 22;
2166     config[20] = 0;
2167    
2168     /*
2169     type: Memory
2170     share_disposition: DeviceExclusive, flags: ReadWrite
2171     start: 0x 0 80002000, length: 0x1000
2172     */
2173     config[24] = arc_CmResourceTypeMemory;
2174     config[25] = arc_CmResourceShareDeviceExclusive;
2175     config[26] = arc_CmResourceMemoryReadWrite;
2176     config[28] = 0x00; config[29] = 0x20; config[30] = 0x00; config[31] = 0x80;
2177     config[32] = 0x00; config[33] = 0x00; config[34] = 0x00; config[35] = 0x00;
2178     config[36] = 0x00; config[37] = 0x10; config[38] = 0x00; config[39] = 0x00;
2179    
2180     /*
2181     type: DMA
2182     share_disposition: DeviceExclusive, flags: 0x0
2183     channel: 0, port: 0, reserved1: 0
2184     */
2185     config[40] = arc_CmResourceTypeDMA;
2186     config[41] = arc_CmResourceShareDeviceExclusive;
2187     /* 42..43 = flags, 44,45,46,47 = channel, 48,49,50,51 = port, 52,53,54,55
2188     = reserved */
2189    
2190     /* type: DeviceSpecific
2191     share_disposition: DeviceExclusive, flags: 0x0
2192     datasize: 6, reserved1: 0, reserved2: 0
2193     data: [0x1:0x0:0x2:0x0:0x7:0x30]
2194     */
2195     config[56] = arc_CmResourceTypeDeviceSpecific;
2196     config[57] = arc_CmResourceShareDeviceExclusive;
2197     /* 58,59 = flags 60,61,62,63 = data size, 64..71 = reserved */
2198     config[60] = 6;
2199     /* 72..77 = the data */
2200     config[72] = 0x01; config[73] = 0x00; config[74] = 0x02;
2201     config[75] = 0x00; config[76] = 0x07; config[77] = 0x30;
2202     scsi = arcbios_addchild_manual(cpu,
2203     COMPONENT_CLASS_AdapterClass,
2204     COMPONENT_TYPE_SCSIAdapter,
2205     0, 1, 2, 0, 0xffffffff, "ESP216",
2206     system, config, sizeof(config));
2207    
2208     arcbios_register_scsicontroller(machine, scsi);
2209     }
2210     }
2211     }
2212    
2213    
2214     /*
2215     * arcbios_console_init():
2216     *
2217     * Called from machine.c whenever an ARC-based machine is running with
2218     * a graphical VGA-style framebuffer, which can be used as console.
2219     */
2220     void arcbios_console_init(struct machine *machine,
2221     uint64_t vram, uint64_t ctrlregs)
2222     {
2223     machine->md.arc.vgaconsole = 1;
2224    
2225     machine->md.arc.console_vram = vram;
2226     machine->md.arc.console_ctrlregs = ctrlregs;
2227     machine->md.arc.console_maxx = ARC_CONSOLE_MAX_X;
2228     machine->md.arc.console_maxy = ARC_CONSOLE_MAX_Y;
2229     machine->md.arc.in_escape_sequence = 0;
2230     machine->md.arc.escape_sequence[0] = '\0';
2231     }
2232    
2233    
2234     /*
2235 dpavlin 2 * arcbios_init():
2236     *
2237 dpavlin 6 * Should be called before any other arcbios function is used. An exception
2238     * is arcbios_console_init(), which may be called before this function.
2239 dpavlin 2 */
2240 dpavlin 6 void arcbios_init(struct machine *machine, int is64bit,
2241     uint64_t sgi_ram_offset)
2242 dpavlin 2 {
2243 dpavlin 6 int i, alloclen = 20;
2244     char *name;
2245     uint64_t arc_reserved, mem_base, mem_count;
2246     struct cpu *cpu = machine->cpus[0];
2247     struct arcbios_sysid arcbios_sysid;
2248     struct arcbios_dsp_stat arcbios_dsp_stat;
2249     uint64_t system = 0;
2250     struct arcbios_spb arcbios_spb;
2251     struct arcbios_spb_64 arcbios_spb_64;
2252 dpavlin 2
2253 dpavlin 6 machine->md.arc.arc_64bit = is64bit;
2254     machine->md.arc.wordlen = is64bit? sizeof(uint64_t) : sizeof(uint32_t);
2255    
2256     machine->md.arc.next_component_address = FIRST_ARC_COMPONENT;
2257     machine->md.arc.configuration_data_next_addr = ARC_CONFIG_DATA_ADDR;
2258    
2259     if (machine->physical_ram_in_mb < 16)
2260     fprintf(stderr, "WARNING! The ARC platform specification "
2261     "doesn't allow less than 16 MB of RAM. Continuing "
2262     "anyway.\n");
2263    
2264 dpavlin 2 /* File handles 0, 1, and 2 are stdin, stdout, and stderr. */
2265 dpavlin 6 for (i=0; i<ARC_MAX_HANDLES; i++) {
2266     machine->md.arc.file_handle_in_use[i] = i<3? 1 : 0;
2267     machine->md.arc.file_handle_string[i] = i>=3? NULL :
2268     (i==0? "(stdin)" : (i==1? "(stdout)" : "(stderr)"));
2269     machine->md.arc.current_seek_offset[i] = 0;
2270 dpavlin 2 }
2271 dpavlin 6
2272     if (!machine->use_x11)
2273     machine->md.arc.vgaconsole = 0;
2274    
2275     if (machine->md.arc.vgaconsole) {
2276     char tmpstr[100];
2277     int x, y;
2278    
2279     machine->md.arc.console_curcolor = 0x1f;
2280     for (y=0; y<machine->md.arc.console_maxy; y++)
2281     for (x=0; x<machine->md.arc.console_maxx; x++)
2282     arcbios_putcell(cpu, ' ', x, y);
2283    
2284     machine->md.arc.console_curx = 0;
2285     machine->md.arc.console_cury = 0;
2286    
2287     arcbios_putstring(cpu, "GXemul");
2288     #ifdef VERSION
2289     arcbios_putstring(cpu, " "VERSION);
2290     #endif
2291     arcbios_putstring(cpu, " ARCBIOS emulation\n");
2292    
2293     sprintf(tmpstr, "%i cpu%s (%s), %i MB memory\n\n",
2294     machine->ncpus, machine->ncpus > 1? "s" : "",
2295     cpu->cd.mips.cpu_type.name,
2296     machine->physical_ram_in_mb);
2297     arcbios_putstring(cpu, tmpstr);
2298     }
2299    
2300     arcbios_set_default_exception_handler(cpu);
2301    
2302     memset(&arcbios_sysid, 0, sizeof(arcbios_sysid));
2303     if (machine->machine_type == MACHINE_SGI) {
2304     /* Vendor ID, max 8 chars: */
2305     strncpy(arcbios_sysid.VendorId, "SGI", 3);
2306     switch (machine->machine_subtype) {
2307     case 22:
2308     strncpy(arcbios_sysid.ProductId,
2309     "87654321", 8); /* some kind of ID? */
2310     break;
2311     case 32:
2312     strncpy(arcbios_sysid.ProductId, "8", 1);
2313     /* 6 or 8 (?) */
2314     break;
2315     default:
2316     snprintf(arcbios_sysid.ProductId, 8, "IP%i",
2317     machine->machine_subtype);
2318     }
2319     } else {
2320     switch (machine->machine_subtype) {
2321     case MACHINE_ARC_NEC_RD94:
2322     strncpy(arcbios_sysid.VendorId, "NEC W&S", 8);
2323     strncpy(arcbios_sysid.ProductId, "RD94", 4);
2324     break;
2325     case MACHINE_ARC_NEC_R94:
2326     strncpy(arcbios_sysid.VendorId, "NEC W&S", 8);
2327     strncpy(arcbios_sysid.ProductId, "ijkl", 4);
2328     break;
2329     case MACHINE_ARC_NEC_R96:
2330     strncpy(arcbios_sysid.VendorId, "MIPS DUO", 8);
2331     strncpy(arcbios_sysid.ProductId, "blahblah", 8);
2332     break;
2333     case MACHINE_ARC_NEC_R98:
2334     strncpy(arcbios_sysid.VendorId, "NEC W&S", 8);
2335     strncpy(arcbios_sysid.ProductId, "R98", 4);
2336     break;
2337     case MACHINE_ARC_JAZZ_PICA:
2338     strncpy(arcbios_sysid.VendorId, "MIPS MAG", 8);
2339     strncpy(arcbios_sysid.ProductId, "ijkl", 4);
2340     break;
2341     case MACHINE_ARC_JAZZ_MAGNUM:
2342     strncpy(arcbios_sysid.VendorId, "MIPS MAG", 8);
2343     strncpy(arcbios_sysid.ProductId, "ijkl", 4);
2344     break;
2345     case MACHINE_ARC_JAZZ_M700:
2346     strncpy(arcbios_sysid.VendorId, "OLI00000", 8);
2347     strncpy(arcbios_sysid.ProductId, "ijkl", 4);
2348     break;
2349     case MACHINE_ARC_DESKTECH_TYNE:
2350     strncpy(arcbios_sysid.VendorId, "DESKTECH", 8);
2351     strncpy(arcbios_sysid.ProductId, "ijkl", 4);
2352     break;
2353     default:
2354     fatal("error in machine.c sysid\n");
2355     exit(1);
2356     }
2357     }
2358    
2359     store_buf(cpu, SGI_SYSID_ADDR, (char *)&arcbios_sysid,
2360     sizeof(arcbios_sysid));
2361    
2362     arcbios_get_dsp_stat(cpu, &arcbios_dsp_stat);
2363     store_buf(cpu, ARC_DSPSTAT_ADDR, (char *)&arcbios_dsp_stat,
2364     sizeof(arcbios_dsp_stat));
2365    
2366     /*
2367     * The first 12 MBs of RAM are simply reserved... this simplifies
2368     * things a lot. If there's more than 512MB of RAM, it has to be
2369     * split in two, according to the ARC spec. This code creates a
2370     * number of chunks of at most 512MB each.
2371     *
2372     * NOTE: The region of physical address space between 0x10000000 and
2373     * 0x1fffffff (256 - 512 MB) is usually occupied by memory mapped
2374     * devices, so that portion is "lost".
2375     */
2376     machine->md.arc.memdescriptor_base = ARC_MEMDESC_ADDR;
2377    
2378     arc_reserved = 0x2000;
2379     if (machine->machine_type == MACHINE_SGI)
2380     arc_reserved = 0x4000;
2381    
2382     arcbios_add_memory_descriptor(cpu, 0, arc_reserved,
2383     ARCBIOS_MEM_FirmwarePermanent);
2384     arcbios_add_memory_descriptor(cpu, sgi_ram_offset + arc_reserved,
2385     0x60000-arc_reserved, ARCBIOS_MEM_FirmwareTemporary);
2386    
2387     mem_base = 12;
2388     mem_base += sgi_ram_offset / 1048576;
2389    
2390     while (mem_base < machine->physical_ram_in_mb+sgi_ram_offset/1048576) {
2391     mem_count = machine->physical_ram_in_mb+sgi_ram_offset/1048576
2392     - mem_base;
2393    
2394     /* Skip the 256-512MB region (for devices) */
2395     if (mem_base < 256 && mem_base + mem_count > 256) {
2396     mem_count = 256-mem_base;
2397     }
2398    
2399     /* At most 512MB per descriptor (at least the first 512MB
2400     must be separated this way, according to the ARC spec) */
2401     if (mem_count > 512)
2402     mem_count = 512;
2403    
2404     arcbios_add_memory_descriptor(cpu, mem_base * 1048576,
2405     mem_count * 1048576, ARCBIOS_MEM_FreeMemory);
2406    
2407     mem_base += mem_count;
2408    
2409     /* Skip the devices: */
2410     if (mem_base == 256)
2411     mem_base = 512;
2412     }
2413    
2414     /*
2415     * Components: (this is an example of what a system could look like)
2416     *
2417     * [System]
2418     * [CPU] (one for each cpu)
2419     * [FPU] (one for each cpu)
2420     * [CPU Caches]
2421     * [Memory]
2422     * [Ethernet]
2423     * [Serial]
2424     * [SCSI]
2425     * [Disk]
2426     *
2427     * Here's a good list of what hardware is in different IP-models:
2428     * http://www.linux-mips.org/archives/linux-mips/2001-03/msg00101.html
2429     */
2430    
2431     if (machine->machine_name == NULL)
2432     fatal("ERROR: machine_name == NULL\n");
2433    
2434     /* Add the root node: */
2435     switch (machine->machine_type) {
2436     case MACHINE_SGI:
2437     name = malloc(alloclen);
2438     if (name == NULL) {
2439     fprintf(stderr, "out of memory\n");
2440     exit(1);
2441     }
2442     snprintf(name, alloclen, "SGI-IP%i",
2443     machine->machine_subtype);
2444    
2445     /* A very special case for IP24 (which identifies itself
2446     as an IP22): */
2447     if (machine->machine_subtype == 24)
2448     sprintf(name, "SGI-IP22");
2449     break;
2450     case MACHINE_ARC:
2451     /* ARC: */
2452     switch (machine->machine_subtype) {
2453     case MACHINE_ARC_NEC_RD94:
2454     name = "NEC-RD94";
2455     break;
2456     case MACHINE_ARC_NEC_R94:
2457     name = "NEC-R94";
2458     break;
2459     case MACHINE_ARC_NEC_R96:
2460     name = "NEC-R96";
2461     break;
2462     case MACHINE_ARC_NEC_R98:
2463     name = "NEC-R98";
2464     break;
2465     case MACHINE_ARC_JAZZ_PICA:
2466     name = "PICA-61";
2467     break;
2468     case MACHINE_ARC_JAZZ_MAGNUM:
2469     case MACHINE_ARC_JAZZ_M700:
2470     name = "Microsoft-Jazz";
2471     break;
2472     case MACHINE_ARC_DESKTECH_TYNE:
2473     name = "DESKTECH-TYNE";
2474     break;
2475     default:
2476     fatal("Unimplemented ARC machine type %i\n",
2477     machine->machine_subtype);
2478     exit(1);
2479     }
2480     break;
2481     default:
2482     fatal("ERROR: non-SGI and non-ARC?\n");
2483     exit(1);
2484     }
2485    
2486     system = arcbios_addchild_manual(cpu, COMPONENT_CLASS_SystemClass,
2487     COMPONENT_TYPE_ARC, 0,1,2,0, 0xffffffff, name, 0/*ROOT*/, NULL, 0);
2488     debug("ARC system @ 0x%llx (\"%s\")\n", (long long)system, name);
2489    
2490    
2491     /*
2492     * Add tree nodes for CPUs and their caches:
2493     */
2494    
2495     for (i=0; i<machine->ncpus; i++) {
2496     uint64_t cpuaddr, fpu=0, picache, pdcache, sdcache=0;
2497     int cache_size, cache_line_size;
2498     unsigned int jj;
2499     char arc_cpu_name[100];
2500     char arc_fpc_name[105];
2501    
2502     snprintf(arc_cpu_name, sizeof(arc_cpu_name),
2503     "MIPS-%s", machine->cpu_name);
2504    
2505     if (machine->machine_type == MACHINE_ARC &&
2506     machine->machine_subtype == MACHINE_ARC_NEC_R96)
2507     snprintf(arc_cpu_name, sizeof(arc_cpu_name),
2508     "MIPS-%s - Pr 4/5.0, Fp 5/0", machine->cpu_name);
2509    
2510     arc_cpu_name[sizeof(arc_cpu_name)-1] = 0;
2511     for (jj=0; jj<strlen(arc_cpu_name); jj++)
2512     if (arc_cpu_name[jj] >= 'a' && arc_cpu_name[jj] <= 'z')
2513     arc_cpu_name[jj] += ('A' - 'a');
2514    
2515     strcpy(arc_fpc_name, arc_cpu_name);
2516     strcat(arc_fpc_name, "FPC");
2517    
2518     cpuaddr = arcbios_addchild_manual(cpu,
2519     COMPONENT_CLASS_ProcessorClass, COMPONENT_TYPE_CPU,
2520     0, 1, 2, i, 0xffffffff, arc_cpu_name, system, NULL, 0);
2521    
2522     /*
2523     * TODO: This was in the ARC specs, but it isn't really used
2524     * by ARC implementations? At least SGI-IP32 uses it.
2525     */
2526     if (machine->machine_type == MACHINE_SGI)
2527     fpu = arcbios_addchild_manual(cpu,
2528     COMPONENT_CLASS_ProcessorClass, COMPONENT_TYPE_FPU,
2529     0, 1, 2, 0, 0xffffffff, arc_fpc_name, cpuaddr,
2530     NULL, 0);
2531    
2532     cache_size = DEFAULT_PCACHE_SIZE - 12;
2533     if (machine->cache_picache)
2534     cache_size = machine->cache_picache - 12;
2535     if (cache_size < 0)
2536     cache_size = 0;
2537    
2538     cache_line_size = DEFAULT_PCACHE_LINESIZE;
2539     if (machine->cache_picache_linesize)
2540     cache_line_size = machine->cache_picache_linesize;
2541     if (cache_line_size < 0)
2542     cache_line_size = 0;
2543    
2544     picache = arcbios_addchild_manual(cpu,
2545     COMPONENT_CLASS_CacheClass, COMPONENT_TYPE_PrimaryICache,
2546     0, 1, 2,
2547     /*
2548     * Key bits: 0xXXYYZZZZ
2549     * XX is refill-size.
2550     * Cache line size is 1 << YY,
2551     * Cache size is 4KB << ZZZZ.
2552     */
2553     0x01000000 + (cache_line_size << 16) + cache_size,
2554     /* 32 bytes per line, default = 32 KB total */
2555     0xffffffff, NULL, cpuaddr, NULL, 0);
2556    
2557     cache_size = DEFAULT_PCACHE_SIZE - 12;
2558     if (machine->cache_pdcache)
2559     cache_size = machine->cache_pdcache - 12;
2560     if (cache_size < 0)
2561     cache_size = 0;
2562    
2563     cache_line_size = DEFAULT_PCACHE_LINESIZE;
2564     if (machine->cache_pdcache_linesize)
2565     cache_line_size = machine->cache_pdcache_linesize;
2566     if (cache_line_size < 0)
2567     cache_line_size = 0;
2568    
2569     pdcache = arcbios_addchild_manual(cpu,
2570     COMPONENT_CLASS_CacheClass,
2571     COMPONENT_TYPE_PrimaryDCache, 0, 1, 2,
2572     /*
2573     * Key bits: 0xYYZZZZ
2574     * Cache line size is 1 << YY,
2575     * Cache size is 4KB << ZZZZ.
2576     */
2577     0x01000000 + (cache_line_size << 16) + cache_size,
2578     /* 32 bytes per line, default = 32 KB total */
2579     0xffffffff, NULL, cpuaddr, NULL, 0);
2580    
2581     if (machine->cache_secondary >= 12) {
2582     cache_size = machine->cache_secondary - 12;
2583    
2584     cache_line_size = 6; /* 64 bytes default */
2585     if (machine->cache_secondary_linesize)
2586     cache_line_size = machine->
2587     cache_secondary_linesize;
2588     if (cache_line_size < 0)
2589     cache_line_size = 0;
2590    
2591     sdcache = arcbios_addchild_manual(cpu,
2592     COMPONENT_CLASS_CacheClass,
2593     COMPONENT_TYPE_SecondaryDCache, 0, 1, 2,
2594     /*
2595     * Key bits: 0xYYZZZZ
2596     * Cache line size is 1 << YY,
2597     * Cache size is 4KB << ZZZZ.
2598     */
2599     0x01000000 + (cache_line_size << 16) + cache_size,
2600     /* 64 bytes per line, default = 1 MB total */
2601     0xffffffff, NULL, cpuaddr, NULL, 0);
2602     }
2603    
2604     debug("ARC cpu%i @ 0x%llx", i, (long long)cpuaddr);
2605    
2606     if (fpu != 0)
2607     debug(" (fpu @ 0x%llx)\n", (long long)fpu);
2608     else
2609     debug("\n");
2610    
2611     debug(" picache @ 0x%llx, pdcache @ 0x%llx\n",
2612     (long long)picache, (long long)pdcache);
2613    
2614     if (machine->cache_secondary >= 12)
2615     debug(" sdcache @ 0x%llx\n",
2616     (long long)sdcache);
2617    
2618     if (machine->machine_type == MACHINE_SGI) {
2619     /* TODO: Memory amount (and base address?)! */
2620     uint64_t memory = arcbios_addchild_manual(cpu,
2621     COMPONENT_CLASS_MemoryClass,
2622     COMPONENT_TYPE_MemoryUnit, 0, 1, 2, 0,
2623     0xffffffff, "memory", cpuaddr, NULL, 0);
2624     debug("ARC memory @ 0x%llx\n", (long long)memory);
2625     }
2626     }
2627    
2628    
2629     /*
2630     * Add other components:
2631     *
2632     * TODO: How should this be synched with the hardware devices
2633     * added in machine.c?
2634     */
2635    
2636     arcbios_add_other_components(machine, system);
2637    
2638    
2639     /*
2640     * Defalt TLB entry for 64-bit SGI machines:
2641     */
2642     if (machine->machine_type == MACHINE_SGI) {
2643     /* TODO: On which models is this required? */
2644     mips_coproc_tlb_set_entry(cpu, 0, 1048576*16,
2645     0xc000000000000000ULL, 0, 1048576*16, 1,1,1,1,1, 0, 2, 2);
2646     }
2647    
2648    
2649     /*
2650     * Set up Firmware Vectors:
2651     */
2652     add_symbol_name(&machine->symbol_context,
2653     ARC_FIRMWARE_ENTRIES, 0x10000, "[ARCBIOS entry]", 0);
2654    
2655     for (i=0; i<100; i++) {
2656     if (is64bit) {
2657     store_64bit_word(cpu, ARC_FIRMWARE_VECTORS + i*8,
2658     ARC_FIRMWARE_ENTRIES + i*8);
2659     store_64bit_word(cpu, ARC_PRIVATE_VECTORS + i*8,
2660     ARC_PRIVATE_ENTRIES + i*8);
2661     } else {
2662     store_32bit_word(cpu, ARC_FIRMWARE_VECTORS + i*4,
2663     ARC_FIRMWARE_ENTRIES + i*4);
2664     store_32bit_word(cpu, ARC_PRIVATE_VECTORS + i*4,
2665     ARC_PRIVATE_ENTRIES + i*4);
2666     }
2667     }
2668    
2669    
2670     /*
2671     * Set up the ARC SPD:
2672     */
2673     if (is64bit) {
2674     /* ARCS64 SPD (TODO: This is just a guess) */
2675     memset(&arcbios_spb_64, 0, sizeof(arcbios_spb_64));
2676     store_64bit_word_in_host(cpu, (unsigned char *)
2677     &arcbios_spb_64.SPBSignature, ARCBIOS_SPB_SIGNATURE);
2678     store_16bit_word_in_host(cpu, (unsigned char *)
2679     &arcbios_spb_64.Version, 64);
2680     store_16bit_word_in_host(cpu, (unsigned char *)
2681     &arcbios_spb_64.Revision, 0);
2682     store_64bit_word_in_host(cpu, (unsigned char *)
2683     &arcbios_spb_64.FirmwareVector, ARC_FIRMWARE_VECTORS);
2684     store_buf(cpu, SGI_SPB_ADDR, (char *)&arcbios_spb_64,
2685     sizeof(arcbios_spb_64));
2686     } else {
2687     /* ARCBIOS SPB: (For ARC and 32-bit SGI modes) */
2688     memset(&arcbios_spb, 0, sizeof(arcbios_spb));
2689     store_32bit_word_in_host(cpu, (unsigned char *)
2690     &arcbios_spb.SPBSignature, ARCBIOS_SPB_SIGNATURE);
2691     store_32bit_word_in_host(cpu, (unsigned char *)
2692     &arcbios_spb.SPBLength, sizeof(arcbios_spb));
2693     store_16bit_word_in_host(cpu, (unsigned char *)
2694     &arcbios_spb.Version, 1);
2695     store_16bit_word_in_host(cpu, (unsigned char *)
2696     &arcbios_spb.Revision, machine->machine_type ==
2697     MACHINE_SGI? 10 : 2);
2698     store_32bit_word_in_host(cpu, (unsigned char *)
2699     &arcbios_spb.FirmwareVector, ARC_FIRMWARE_VECTORS);
2700     store_32bit_word_in_host(cpu, (unsigned char *)
2701     &arcbios_spb.FirmwareVectorLength, 100 * 4); /* ? */
2702     store_32bit_word_in_host(cpu, (unsigned char *)
2703     &arcbios_spb.PrivateVector, ARC_PRIVATE_VECTORS);
2704     store_32bit_word_in_host(cpu, (unsigned char *)
2705     &arcbios_spb.PrivateVectorLength, 100 * 4); /* ? */
2706     store_buf(cpu, SGI_SPB_ADDR, (char *)&arcbios_spb,
2707     sizeof(arcbios_spb));
2708     }
2709 dpavlin 2 }
2710    

  ViewVC Help
Powered by ViewVC 1.1.26