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

Annotation of /trunk/src/promemul/arcbios.c

Parent Directory Parent Directory | Revision Log Revision Log


Revision 28 - (hide annotations)
Mon Oct 8 16:20:26 2007 UTC (16 years, 6 months ago) by dpavlin
File MIME type: text/plain
File size: 94253 byte(s)
++ trunk/HISTORY	(local)
$Id: HISTORY,v 1.1298 2006/07/22 11:27:46 debug Exp $
20060626	Continuing on SPARC emulation (beginning on the 'save'
		instruction, register windows, etc).
20060629	Planning statistics gathering (new -s command line option),
		and renaming speed_tricks to allow_instruction_combinations.
20060630	Some minor manual page updates.
		Various cleanups.
		Implementing the -s command line option.
20060701	FINALLY found the bug which prevented Linux and Ultrix from
		running without the ugly hack in the R2000/R3000 cache isol
		code; it was the phystranslation hint array which was buggy.
		Removing the phystranslation hint code completely, for now.
20060702	Minor dyntrans cleanups; invalidation of physpages now only
		invalidate those parts of a page that have actually been
		translated. (32 parts per page.)
		Some MIPS non-R3000 speed fixes.
		Experimenting with MIPS instruction combination for some
		addiu+bne+sw loops, and sw+sw+sw.
		Adding support (again) for larger-than-4KB pages in MIPS tlbw*.
		Continuing on SPARC emulation: adding load/store instructions.
20060704	Fixing a virtual vs physical page shift bug in the new tlbw*
		implementation. Problem noticed by Jakub Jermar. (Many thanks.)
		Moving rfe and eret to cpu_mips_instr.c, since that is the
		only place that uses them nowadays.
20060705	Removing the BSD license from the "testmachine" include files,
		placing them in the public domain instead; this enables the
		testmachine stuff to be used from projects which are
		incompatible with the BSD license for some reason.
20060707	Adding instruction combinations for the R2000/R3000 L1
		I-cache invalidation code used by NetBSD/pmax 3.0, lui+addiu,
		various branches followed by addiu or nop, and jr ra followed
		by addiu. The time it takes to perform a full NetBSD/pmax R3000
		install on the laptop has dropped from 573 seconds to 539. :-)
20060708	Adding a framebuffer controller device (dev_fbctrl), which so
		far can be used to change the fb resolution during runtime, but
		in the future will also be useful for accelerated block fill/
		copy, and possibly also simplified character output.
		Adding an instruction combination for NetBSD/pmax' strlen.
20060709	Minor fixes: reading raw files in src/file.c wasn't memblock
		aligned, removing buggy multi_sw MIPS instruction combination,
		etc.
20060711	Adding a machine_qemu.c, which contains a "qemu_mips" machine.
		(It mimics QEMU's MIPS machine mode, so that a test kernel
		made for QEMU_MIPS also can run in GXemul... at least to some
		extent.)  Adding a short section about how to run this mode to
		doc/guestoses.html.
20060714	Misc. minor code cleanups.
20060715	Applying a patch which adds getchar() to promemul/yamon.c
		(from Oleksandr Tymoshenko).
		Adding yamon.h from NetBSD, and rewriting yamon.c to use it
		(instead of ugly hardcoded numbers) + some cleanup.
20060716	Found and fixed the bug which broke single-stepping of 64-bit
		programs between 0.4.0 and 0.4.0.1 (caused by too quick
		refactoring and no testing). Hopefully this fix will not
		break too many other things.
20060718	Continuing on the 8253 PIT; it now works with Linux/QEMU_MIPS.
		Re-adding the sw+sw+sw instr comb (the problem was that I had
		ignored endian issues); however, it doesn't seem to give any
		big performance gain.
20060720	Adding a dummy Transputer mode (T414, T800 etc) skeleton (only
		the 'j' and 'ldc' instructions are implemented so far). :-}
20060721	Adding gtreg.h from NetBSD, updating dev_gt.c to use it, plus
		misc. other updates to get Linux 2.6 for evbmips/malta working
		(thanks to Alec Voropay for the details).
		FINALLY found and fixed the bug which made tlbw* for non-R3000
		buggy; it was a reference count problem in the dyntrans core.
20060722	Testing stuff; things seem stable enough for a new release.

==============  RELEASE 0.4.1  ==============


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

  ViewVC Help
Powered by ViewVC 1.1.26