/[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 44 - (hide annotations)
Mon Oct 8 16:22:56 2007 UTC (16 years, 6 months ago) by dpavlin
File MIME type: text/plain
File size: 91001 byte(s)
++ trunk/HISTORY	(local)
$Id: HISTORY,v 1.1632 2007/09/11 21:46:35 debug Exp $
20070616	Implementing the MIPS32/64 revision 2 "ror" instruction.
20070617	Adding a struct for each physpage which keeps track of which
		ranges within that page (base offset, length) that are
		continuously translatable. When running with native code
		generation enabled (-b), a range is added after each read-
		ahead loop.
		Experimenting with using the physical program counter sample
		data (implemented 20070608) together with the "translatable
		range" information, to figure out which physical address ranges
		would be worth translating to native code (if the number of
		samples falling within a range is above a certain threshold).
20070618	Adding automagic building of .index comment files for
		src/file/, src/promemul/, src src/useremul/ as well.
		Adding a "has been translated" bit to the ranges, so that only
		not-yet-translated ranges will be sampled.
20070619	Moving src/cpu.c and src/memory_rw.c into src/cpus/,
		src/device.c into src/devices/, and src/machine.c into
		src/machines/.
		Creating a skeleton cc/ld native backend module; beginning on
		the function which will detect cc command line, etc.
20070620	Continuing on the native code generation infrastructure.
20070621	Moving src/x11.c and src/console.c into a new src/console/
		subdir (for everything that is console or framebuffer related).
		Moving src/symbol*.c into a new src/symbol/, which should
		contain anything that is symbol handling related.
20070624	Making the program counter sampling threshold a "settings
		variable" (sampling_threshold), i.e. it can now be changed
		during runtime.
		Switching the RELEASE notes format from plain text to HTML.
		If the TMPDIR environment variable is set, it is used instead
		of "/tmp" for temporary files.
		Continuing on the cc/ld backend: simple .c code is generated,
		the compiler and linker are called, etc.
		Adding detection of host architecture to the configure script
		(again), and adding icache invalidation support (only
		implemented for Alpha hosts so far).
20070625	Simplifying the program counter sampling mechanism.
20070626	Removing the cc/ld native code generation stuff, program
		counter sampling, etc; it would not have worked well in the
		general case.
20070627	Removing everything related to native code generation.
20070629	Removing the (practically unusable) support for multiple
		emulations. (The single emulation allowed now still supports
		multiple simultaneous machines, as before.)
		Beginning on PCCTWO and M88K interrupts.
20070723	Adding a dummy skeleton for emulation of M32R processors.
20070901	Fixing a warning found by "gcc version 4.3.0 20070817
		(experimental)" on amd64.
20070905	Removing some more traces of the old "multiple emulations"
		code.
		Also looking in /usr/local/include and /usr/local/lib for
		X11 libs, when running configure.
20070909	Minor updates to the guest OS install instructions, in
		preparation for the NetBSD 4.0 release.
20070918	More testing of NetBSD 4.0 RC1.

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

  ViewVC Help
Powered by ViewVC 1.1.26