/[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 22 - (hide annotations)
Mon Oct 8 16:19:37 2007 UTC (16 years, 6 months ago) by dpavlin
File MIME type: text/plain
File size: 93728 byte(s)
++ trunk/HISTORY	(local)
$Id: HISTORY,v 1.1121 2006/02/18 21:03:08 debug Exp $
20051126	Cobalt and PReP now work with the 21143 NIC.
		Continuing on Alpha dyntrans things.
		Fixing some more left-shift-by-24 to unsigned.
20051127	Working on OpenFirmware emulation; major cleanup/redesign.
		Progress on MacPPC emulation: NetBSD detects two CPUs (when
		running with -n 2), framebuffer output (for text) works.
		Adding quick-hack Bandit PCI controller and "gc" interrupt
		controller for MacPPC.
20051128	Changing from a Bandit to a Uni-North controller for macppc.
		Continuing on OpenFirmware and MacPPC emulation in general
		(obio controller, and wdc attached to the obio seems to work).
20051129	More work on MacPPC emulation (adding a dummy ADB controller).
		Continuing the PCI bus cleanup (endianness and tag composition)
		and rewriting all PCI controllers' access functions.
20051130	Various minor PPC dyntrans optimizations.
		Manually inlining some parts of the framebuffer redraw routine.
		Slowly beginning the conversion of the old MIPS emulation into
		dyntrans (but this will take quite some time to get right).
		Generalizing quick_pc_to_pointers.
20051201	Documentation update (David Muse has made available a kernel
		which simplifies Debian/DECstation installation).
		Continuing on the ADB bus controller.
20051202	Beginning a rewrite of the Zilog serial controller (dev_zs).
20051203	Continuing on the zs rewrite (now called dev_z8530); conversion
		to devinit style.
		Reworking some of the input-only vs output-only vs input-output
		details of src/console.c, better warning messages, and adding
		a debug dump.
		Removing the concept of "device state"; it wasn't really used.
		Changing some debug output (-vv should now be used to show all
		details about devices and busses; not shown during normal
		startup anymore).
		Beginning on some SPARC instruction disassembly support.
20051204	Minor PPC updates (WALNUT skeleton stuff).
		Continuing on the MIPS dyntrans rewrite.
		More progress on the ADB controller (a keyboard is "detected"
		by NetBSD and OpenBSD).
		Downgrading OpenBSD/arc as a guest OS from "working" to
		"almost working" in the documentation.
		Progress on Algor emulation ("v3" PCI controller).
20051205	Minor updates.
20051207	Sorting devices according to address; this reduces complexity
		of device lookups from O(n) to O(log n) in memory_rw (but no
		real performance increase (yet) in experiments).
20051210	Beginning the work on native dyntrans backends (by making a
		simple skeleton; so far only for Alpha hosts).
20051211	Some very minor SPARC updates.
20051215	Fixing a bug in the MIPS mul (note: not mult) instruction,
		so it also works with non-64-bit emulation. (Thanks to Alec
		Voropay for noticing the problem.)
20051216	More work on the fake/empty/simple/skeleton/whatever backend;
		performance doesn't increase, so this isn't really worth it,
		but it was probably worth it to prepare for a real backend
		later.
20051219	More instr call statistics gathering and analysis stuff.
20051220	Another fix for MIPS 'mul'. Also converting mul and {d,}cl{o,z}
		to dyntrans.
		memory_ppc.c syntax error fix (noticed by Peter Valchev).
		Beginning to move out machines from src/machine.c into
		individual files in src/machines (in a way similar to the
		autodev system for devices).
20051222	Updating the documentation regarding NetBSD/pmax 3.0.
20051223	- " - NetBSD/cats 3.0.
20051225	- " - NetBSD/hpcmips 3.0.
20051226	Continuing on the machine registry redesign.
		Adding support for ARM rrx (33-bit rotate).
		Fixing some signed/unsigned issues (exposed by gcc -W).
20051227	Fixing the bug which prevented a NetBSD/prep 3.0 install kernel
		from starting (triggered when an mtmsr was the last instruction
		on a page). Unfortunately not enough to get the kernel to run
		as well as the 2.1 kernels did.
20051230	Some dyntrans refactoring.
20051231	Continuing on the machine registry redesign.
20060101-10	Continuing... moving more machines. Moving MD interrupt stuff
		from machine.c into a new src/machines/interrupts.c.
20060114	Adding various mvmeppc machine skeletons.
20060115	Continuing on mvme* stuff. NetBSD/mvmeppc prints boot messages
		(for MVME1600) and reaches the root device prompt, but no
		specific hardware devices are emulated yet.
20060116	Minor updates to the mvme1600 emulation mode; the Eagle PCI bus
		seems to work without much modification, and a 21143 can be
		detected, interrupts might work (but untested so far).
		Adding a fake MK48Txx (mkclock) device, for NetBSD/mvmeppc.
20060121	Adding an aux control register for ARM. (A BIG thank you to
		Olivier Houchard for tracking down this bug.)
20060122	Adding more ARM instructions (smulXY), and dev_iq80321_7seg.
20060124	Adding disassembly of more ARM instructions (mia*, mra/mar),
		and some semi-bogus XScale and i80321 registers.
20060201-02	Various minor updates. Moving the last machines out of
		machine.c.
20060204	Adding a -c command line option, for running debugger commands
		before the simulation starts, but after all files have been
		loaded.
		Minor iq80321-related updates.
20060209	Minor hacks (DEVINIT macro, etc).
		Preparing for the generalization of the 64-bit dyntrans address
		translation subsystem.
20060216	Adding ARM ldrd (double-register load).
20060217	Continuing on various ARM-related stuff.
20060218	More progress on the ATA/wdc emulation for NetBSD/iq80321.
		NetBSD/evbarm can now be installed :-)  Updating the docs, etc.
		Continuing on Algor emulation.

==============  RELEASE 0.3.8  ==============


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

  ViewVC Help
Powered by ViewVC 1.1.26