/[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 14 - (hide annotations)
Mon Oct 8 16:18:51 2007 UTC (16 years, 6 months ago) by dpavlin
File MIME type: text/plain
File size: 84956 byte(s)
++ trunk/HISTORY	(local)
$Id: HISTORY,v 1.982 2005/10/07 22:45:32 debug Exp $
20050816	Some success in decoding the way the SGI O2 PROM draws graphics
		during bootup; lines/rectangles and bitmaps work, enough to
		show the bootlogo etc. :-)
		Adding more PPC instructions, and (dummy) BAT registers.
20050817	Updating the pckbc to support scancode type 3 keyboards
		(required in order to interact with the SGI O2 PROM).
		Adding more PPC instructions.
20050818	Adding more ARM instructions; general register forms.
		Importing armreg.h from NetBSD (ARM cpu ids). Adding a (dummy)
		CATS machine mode (using SA110 as the default CPU).
		Continuing on general dyntrans related stuff.
20050819	Register forms for ARM load/stores. Gaah! The Compaq C Compiler
		bug is triggered for ARM loads as well, not just PPC :-(
		Adding full support for ARM PC-relative load/stores, and load/
		stores where the PC register is the destination register.
		Adding support for ARM a.out binaries.
20050820	Continuing to add more ARM instructions, and correcting some
		bugs. Continuing on CATS emulation.
		More work on the PPC stuff.
20050821	Minor PPC and ARM updates. Adding more machine types.
20050822	All ARM "data processing instructions" are now generated
		automatically.
20050824	Beginning the work on the ARM system control coprocessor.
		Adding support for ARM halfword load/stores, and signed loads.
20050825	Fixing an important bug related to the ARM condition codes.
		OpenBSD/zaurus and NetBSD/netwinder now print some boot
		messages. :)
		Adding a dummy SH (Hitachi SuperH) cpu family.
		Beginning to add some ARM virtual address translation.
		MIPS bugfixes: unaligned PC now cause an ADEL exception (at
		least for non-bintrans execution), and ADEL/ADES (not
		TLBL/TLBS) are used if userland tries to access kernel space.
		(Thanks to Joshua Wise for making me aware of these bugs.)
20050827	More work on the ARM emulation, and various other updates.
20050828	More ARM updates.
		Finally taking the time to work on translation invalidation
		(i.e. invalidating translated code mappings when memory is
		written to). Hopefully this doesn't break anything.
20050829	Moving CPU related files from src/ to a new subdir, src/cpus/.
		Moving PROM emulation stuff from src/ to src/promemul/.
		Better debug instruction trace for ARM loads and stores.
20050830	Various ARM updates (correcting CMP flag calculation, etc).
20050831	PPC instruction updates. (Flag fixes, etc.)
20050901	Various minor PPC and ARM instruction emulation updates.
		Minor OpenFirmware emulation updates.
20050903	Adding support for adding arbitrary ARM coprocessors (with
		the i80321 I/O coprocessor as a first test).
		Various other ARM and PPC updates.
20050904	Adding some SHcompact disassembly routines.
20050907	(Re)adding a dummy HPPA CPU module, and a dummy i960 module.
20050908	Began hacking on some Apple Partition Table support.
20050909	Adding support for loading Mach-O (Darwin PPC) binaries.
20050910	Fixing an ARM bug (Carry flag was incorrectly updated for some
		data processing instructions); OpenBSD/cats and NetBSD/
		netwinder get quite a bit further now.
		Applying a patch to dev_wdc, and a one-liner to dev_pcic, to
		make them work better when emulating new versions of OpenBSD.
		(Thanks to Alexander Yurchenko for the patches.)
		Also doing some other minor updates to dev_wdc. (Some cleanup,
		and finally converting to devinit, etc.)
20050912	IRIX doesn't have u_int64_t by default (noticed by Andreas
		<avr@gnulinux.nl>); configure updated to reflect this.
		Working on ARM register bank switching, CPSR vs SPSR issues,
		and beginning the work on interrupt/exception support.
20050913	Various minor ARM updates (speeding up load/store multiple,
		and fixing a ROR bug in R(); NetBSD/cats now boots as far as
		OpenBSD/cats).
20050917	Adding a dummy Atmel AVR (8-bit) cpu family skeleton.
20050918	Various minor updates.
20050919	Symbols are now loaded from Mach-O executables.
		Continuing the work on adding ARM exception support.
20050920	More work on ARM stuff: OpenBSD/cats and NetBSD/cats reach
		userland! :-)
20050921	Some more progress on ARM interrupt specifics.
20050923	Fixing linesize for VR4121 (patch by Yurchenko). Also fixing
		linesizes/cachesizes for some other VR4xxx.
		Adding a dummy Acer Labs M1543 PCI-ISA bridge (for CATS) and a
		dummy Symphony Labs 83C553 bridge (for Netwinder), usable by 
		dev_footbridge.
20050924	Some PPC progress.
20050925	More PPC progress.
20050926	PPC progress (fixing some bugs etc); Darwin's kernel gets
		slightly further than before.
20050928	Various updates: footbridge/ISA/pciide stuff, and finally
		fixing the VGA text scroll-by-changing-the-base-offset bug.
20050930	Adding a dummy S3 ViRGE pci card for CATS emulation, which
		both NetBSD and OpenBSD detects as VGA.
		Continuing on Footbridge (timers, ISA interrupt stuff).
20051001	Continuing... there are still bugs, probably interrupt-
		related.
20051002	More work on the Footbridge (interrupt stuff).
20051003	Various minor updates. (Trying to find the bug(s).)
20051004	Continuing on the ARM stuff.
20051005	More ARM-related fixes.
20051007	FINALLY! Found and fixed 2 ARM bugs: 1 memory related, and the
		other was because of an error in the ARM manual (load multiple
		with the S-bit set should _NOT_ load usermode registers, as the
		manual says, but it should load saved registers, which may or
		may not happen to be usermode registers).
		NetBSD/cats and OpenBSD/cats seem to install fine now :-)
		except for a minor bug at the end of the OpenBSD/cats install.
		Updating the documentation, preparing for the next release.
20051008	Continuing with release testing and cleanup.

1 dpavlin 14 /*
2     * Copyright (C) 2003-2005 Anders Gavare. All rights reserved.
3     *
4     * Redistribution and use in source and binary forms, with or without
5     * modification, are permitted provided that the following conditions are met:
6     *
7     * 1. Redistributions of source code must retain the above copyright
8     * notice, this list of conditions and the following disclaimer.
9     * 2. Redistributions in binary form must reproduce the above copyright
10     * notice, this list of conditions and the following disclaimer in the
11     * documentation and/or other materials provided with the distribution.
12     * 3. The name of the author may not be used to endorse or promote products
13     * derived from this software without specific prior written permission.
14     *
15     * THIS SOFTWARE IS PROVIDED BY THE AUTHOR AND CONTRIBUTORS ``AS IS'' AND
16     * ANY EXPRESS OR IMPLIED WARRANTIES, INCLUDING, BUT NOT LIMITED TO, THE
17     * IMPLIED WARRANTIES OF MERCHANTABILITY AND FITNESS FOR A PARTICULAR PURPOSE
18     * ARE DISCLAIMED. IN NO EVENT SHALL THE AUTHOR OR CONTRIBUTORS BE LIABLE
19     * FOR ANY DIRECT, INDIRECT, INCIDENTAL, SPECIAL, EXEMPLARY, OR CONSEQUENTIAL
20     * DAMAGES (INCLUDING, BUT NOT LIMITED TO, PROCUREMENT OF SUBSTITUTE GOODS
21     * OR SERVICES; LOSS OF USE, DATA, OR PROFITS; OR BUSINESS INTERRUPTION)
22     * HOWEVER CAUSED AND ON ANY THEORY OF LIABILITY, WHETHER IN CONTRACT, STRICT
23     * LIABILITY, OR TORT (INCLUDING NEGLIGENCE OR OTHERWISE) ARISING IN ANY WAY
24     * OUT OF THE USE OF THIS SOFTWARE, EVEN IF ADVISED OF THE POSSIBILITY OF
25     * SUCH DAMAGE.
26     *
27     *
28     * $Id: arcbios.c,v 1.1 2005/08/29 14:46:34 debug Exp $
29     *
30     * ARCBIOS emulation.
31     */
32    
33     #include <stdio.h>
34     #include <stdlib.h>
35     #include <string.h>
36     #include <time.h>
37     #include <unistd.h>
38     #include <sys/time.h>
39     #include <sys/types.h>
40     #include <sys/resource.h>
41    
42     #include "arcbios.h"
43     #include "arcbios_other.h"
44     #include "console.h"
45     #include "cpu.h"
46     #include "cpu_mips.h"
47     #include "diskimage.h"
48     #include "machine.h"
49     #include "memory.h"
50     #include "misc.h"
51    
52    
53     extern int quiet_mode;
54    
55    
56     /*
57     * arcbios_add_string_to_component():
58     */
59     void arcbios_add_string_to_component(struct machine *machine,
60     char *string, uint64_t component)
61     {
62     if (machine->md.arc.n_string_to_components >= MAX_STRING_TO_COMPONENT) {
63     printf("Too many string-to-component mappings.\n");
64     exit(1);
65     }
66    
67     machine->md.arc.string_to_component[machine->
68     md.arc.n_string_to_components] = strdup(string);
69     if (machine->md.arc.string_to_component[machine->
70     md.arc.n_string_to_components] == NULL) {
71     fprintf(stderr, "out of memory in "
72     "arcbios_add_string_to_component()\n");
73     exit(1);
74     }
75     debug("adding ARC component mapping: 0x%08x = %s\n",
76     (int)component, string);
77    
78     machine->md.arc.string_to_component_value[
79     machine->md.arc.n_string_to_components] = component;
80    
81     machine->md.arc.n_string_to_components ++;
82     }
83    
84    
85     /*
86     * arcbios_get_dsp_stat():
87     *
88     * Fills in an arcbios_dsp_stat struct with valid data.
89     */
90     static void arcbios_get_dsp_stat(struct cpu *cpu,
91     struct arcbios_dsp_stat *dspstat)
92     {
93     memset(dspstat, 0, sizeof(struct arcbios_dsp_stat));
94    
95     store_16bit_word_in_host(cpu, (unsigned char *)&dspstat->
96     CursorXPosition, cpu->machine->md.arc.console_curx + 1);
97     store_16bit_word_in_host(cpu, (unsigned char *)&dspstat->
98     CursorYPosition, cpu->machine->md.arc.console_cury + 1);
99     store_16bit_word_in_host(cpu, (unsigned char *)&dspstat->
100     CursorMaxXPosition, ARC_CONSOLE_MAX_X);
101     store_16bit_word_in_host(cpu, (unsigned char *)&dspstat->
102     CursorMaxYPosition, ARC_CONSOLE_MAX_Y);
103     dspstat->ForegroundColor = cpu->machine->md.arc.console_curcolor;
104     dspstat->HighIntensity = cpu->machine->md.arc.console_curcolor ^ 0x08;
105     }
106    
107    
108     /*
109     * arcbios_putcell():
110     */
111     static void arcbios_putcell(struct cpu *cpu, int ch, int x, int y)
112     {
113     unsigned char buf[2];
114     buf[0] = ch;
115     buf[1] = cpu->machine->md.arc.console_curcolor;
116     if (cpu->machine->md.arc.console_reverse)
117     buf[1] = ((buf[1] & 0x70) >> 4) | ((buf[1] & 7) << 4)
118     | (buf[1] & 0x88);
119     cpu->memory_rw(cpu, cpu->mem, cpu->machine->md.arc.console_vram +
120     2*(x + cpu->machine->md.arc.console_maxx * y),
121     &buf[0], sizeof(buf), MEM_WRITE,
122     CACHE_NONE | PHYSICAL);
123     }
124    
125    
126     /*
127     * handle_esc_seq():
128     *
129     * Used by arcbios_putchar().
130     */
131     static void handle_esc_seq(struct cpu *cpu)
132     {
133     int i, len = strlen(cpu->machine->md.arc.escape_sequence);
134     int row, col, color, code, start, stop;
135     char *p;
136    
137     if (cpu->machine->md.arc.escape_sequence[0] != '[')
138     return;
139    
140     code = cpu->machine->md.arc.escape_sequence[len-1];
141     cpu->machine->md.arc.escape_sequence[len-1] = '\0';
142    
143     switch (code) {
144     case 'm':
145     color = atoi(cpu->machine->md.arc.escape_sequence + 1);
146     switch (color) {
147     case 0: /* Default. */
148     cpu->machine->md.arc.console_curcolor = 0x1f;
149     cpu->machine->md.arc.console_reverse = 0; break;
150     case 1: /* "Bold". */
151     cpu->machine->md.arc.console_curcolor |= 0x08; break;
152     case 7: /* "Reverse". */
153     cpu->machine->md.arc.console_reverse = 1; break;
154     case 30: /* Black foreground. */
155     cpu->machine->md.arc.console_curcolor &= 0xf0;
156     cpu->machine->md.arc.console_curcolor |= 0x00; break;
157     case 31: /* Red foreground. */
158     cpu->machine->md.arc.console_curcolor &= 0xf0;
159     cpu->machine->md.arc.console_curcolor |= 0x04; break;
160     case 32: /* Green foreground. */
161     cpu->machine->md.arc.console_curcolor &= 0xf0;
162     cpu->machine->md.arc.console_curcolor |= 0x02; break;
163     case 33: /* Yellow foreground. */
164     cpu->machine->md.arc.console_curcolor &= 0xf0;
165     cpu->machine->md.arc.console_curcolor |= 0x06; break;
166     case 34: /* Blue foreground. */
167     cpu->machine->md.arc.console_curcolor &= 0xf0;
168     cpu->machine->md.arc.console_curcolor |= 0x01; break;
169     case 35: /* Red-blue foreground. */
170     cpu->machine->md.arc.console_curcolor &= 0xf0;
171     cpu->machine->md.arc.console_curcolor |= 0x05; break;
172     case 36: /* Green-blue foreground. */
173     cpu->machine->md.arc.console_curcolor &= 0xf0;
174     cpu->machine->md.arc.console_curcolor |= 0x03; break;
175     case 37: /* White foreground. */
176     cpu->machine->md.arc.console_curcolor &= 0xf0;
177     cpu->machine->md.arc.console_curcolor |= 0x07; break;
178     case 40: /* Black background. */
179     cpu->machine->md.arc.console_curcolor &= 0x0f;
180     cpu->machine->md.arc.console_curcolor |= 0x00; break;
181     case 41: /* Red background. */
182     cpu->machine->md.arc.console_curcolor &= 0x0f;
183     cpu->machine->md.arc.console_curcolor |= 0x40; break;
184     case 42: /* Green background. */
185     cpu->machine->md.arc.console_curcolor &= 0x0f;
186     cpu->machine->md.arc.console_curcolor |= 0x20; break;
187     case 43: /* Yellow background. */
188     cpu->machine->md.arc.console_curcolor &= 0x0f;
189     cpu->machine->md.arc.console_curcolor |= 0x60; break;
190     case 44: /* Blue background. */
191     cpu->machine->md.arc.console_curcolor &= 0x0f;
192     cpu->machine->md.arc.console_curcolor |= 0x10; break;
193     case 45: /* Red-blue background. */
194     cpu->machine->md.arc.console_curcolor &= 0x0f;
195     cpu->machine->md.arc.console_curcolor |= 0x50; break;
196     case 46: /* Green-blue background. */
197     cpu->machine->md.arc.console_curcolor &= 0x0f;
198     cpu->machine->md.arc.console_curcolor |= 0x30; break;
199     case 47: /* White background. */
200     cpu->machine->md.arc.console_curcolor &= 0x0f;
201     cpu->machine->md.arc.console_curcolor |= 0x70; break;
202     default:fatal("{ handle_esc_seq: color %i }\n", color);
203     }
204     return;
205     case 'H':
206     p = strchr(cpu->machine->md.arc.escape_sequence, ';');
207     if (p == NULL)
208     return; /* TODO */
209     row = atoi(cpu->machine->md.arc.escape_sequence + 1);
210     col = atoi(p + 1);
211     if (col < 1)
212     col = 1;
213     if (row < 1)
214     row = 1;
215     cpu->machine->md.arc.console_curx = col - 1;
216     cpu->machine->md.arc.console_cury = row - 1;
217     return;
218     case 'J':
219     /*
220     * J = clear screen below cursor, and the rest of the
221     * current line,
222     * 2J = clear whole screen.
223     */
224     i = atoi(cpu->machine->md.arc.escape_sequence + 1);
225     if (i != 0 && i != 2)
226     fatal("{ handle_esc_seq(): %iJ }\n", i);
227     if (i == 0)
228     for (col = cpu->machine->md.arc.console_curx;
229     col < cpu->machine->md.arc.console_maxx; col++)
230     arcbios_putcell(cpu, ' ', col,
231     cpu->machine->md.arc.console_cury);
232     for (col = 0; col < cpu->machine->md.arc.console_maxx; col++)
233     for (row = i? 0 : cpu->machine->md.arc.console_cury+1;
234     row < cpu->machine->md.arc.console_maxy; row++)
235     arcbios_putcell(cpu, ' ', col, row);
236     return;
237     case 'K':
238     col = atoi(cpu->machine->md.arc.escape_sequence + 1);
239     /* 2 = clear line to the right. 1 = to the left (?) */
240     start = 0; stop = cpu->machine->md.arc.console_curx;
241     if (col == 2) {
242     start = cpu->machine->md.arc.console_curx;
243     stop = cpu->machine->md.arc.console_maxx - 1;
244     }
245     for (i=start; i<=stop; i++)
246     arcbios_putcell(cpu, ' ', i,
247     cpu->machine->md.arc.console_cury);
248    
249     return;
250     }
251    
252     fatal("{ handle_esc_seq(): unimplemented escape sequence: ");
253     for (i=0; i<len; i++) {
254     int x = cpu->machine->md.arc.escape_sequence[i];
255     if (i == len-1)
256     x = code;
257    
258     if (x >= ' ' && x < 127)
259     fatal("%c", x);
260     else
261     fatal("[0x%02x]", x);
262     }
263     fatal(" }\n");
264     }
265    
266    
267     /*
268     * scroll_if_necessary():
269     */
270     static void scroll_if_necessary(struct cpu *cpu)
271     {
272     /* Scroll? */
273     if (cpu->machine->md.arc.console_cury >=
274     cpu->machine->md.arc.console_maxy) {
275     unsigned char buf[2];
276     int x, y;
277     for (y=0; y<cpu->machine->md.arc.console_maxy-1; y++)
278     for (x=0; x<cpu->machine->md.arc.console_maxx;
279     x++) {
280     cpu->memory_rw(cpu, cpu->mem,
281     cpu->machine->md.arc.console_vram +
282     2*(x + cpu->machine->md.arc.
283     console_maxx * (y+1)),
284     &buf[0], sizeof(buf), MEM_READ,
285     CACHE_NONE | PHYSICAL);
286     cpu->memory_rw(cpu, cpu->mem,
287     cpu->machine->md.arc.console_vram +
288     2*(x + cpu->machine->md.arc.
289     console_maxx * y),
290     &buf[0], sizeof(buf), MEM_WRITE,
291     CACHE_NONE | PHYSICAL);
292     }
293    
294     cpu->machine->md.arc.console_cury =
295     cpu->machine->md.arc.console_maxy - 1;
296    
297     for (x=0; x<cpu->machine->md.arc.console_maxx; x++)
298     arcbios_putcell(cpu, ' ', x,
299     cpu->machine->md.arc.console_cury);
300     }
301     }
302    
303    
304     /*
305     * arcbios_putchar():
306     *
307     * If we're using X11 with VGA-style console, then output to that console.
308     * Otherwise, use console_putchar().
309     */
310     static void arcbios_putchar(struct cpu *cpu, int ch)
311     {
312     int addr;
313     unsigned char byte;
314    
315     if (!cpu->machine->md.arc.vgaconsole) {
316     /* Text console output: */
317    
318     /* Hack for Windows NT, which uses 0x9b instead of ESC + [ */
319     if (ch == 0x9b) {
320     console_putchar(cpu->machine->main_console_handle, 27);
321     ch = '[';
322     }
323     console_putchar(cpu->machine->main_console_handle, ch);
324     return;
325     }
326    
327     if (cpu->machine->md.arc.in_escape_sequence) {
328     int len = strlen(cpu->machine->md.arc.escape_sequence);
329     cpu->machine->md.arc.escape_sequence[len] = ch;
330     len++;
331     if (len >= ARC_MAX_ESC)
332     len = ARC_MAX_ESC;
333     cpu->machine->md.arc.escape_sequence[len] = '\0';
334     if ((ch >= 'a' && ch <= 'z') ||
335     (ch >= 'A' && ch <= 'Z') || len >= ARC_MAX_ESC) {
336     handle_esc_seq(cpu);
337     cpu->machine->md.arc.in_escape_sequence = 0;
338     }
339     } else {
340     if (ch == 27) {
341     cpu->machine->md.arc.in_escape_sequence = 1;
342     cpu->machine->md.arc.escape_sequence[0] = '\0';
343     } else if (ch == 0x9b) {
344     cpu->machine->md.arc.in_escape_sequence = 1;
345     cpu->machine->md.arc.escape_sequence[0] = '[';
346     cpu->machine->md.arc.escape_sequence[1] = '\0';
347     } else if (ch == '\b') {
348     if (cpu->machine->md.arc.console_curx > 0)
349     cpu->machine->md.arc.console_curx --;
350     } else if (ch == '\r') {
351     cpu->machine->md.arc.console_curx = 0;
352     } else if (ch == '\n') {
353     cpu->machine->md.arc.console_cury ++;
354     } else if (ch == '\t') {
355     cpu->machine->md.arc.console_curx =
356     ((cpu->machine->md.arc.console_curx - 1)
357     | 7) + 1;
358     /* TODO: Print spaces? */
359     } else {
360     /* Put char: */
361     if (cpu->machine->md.arc.console_curx >=
362     cpu->machine->md.arc.console_maxx) {
363     cpu->machine->md.arc.console_curx = 0;
364     cpu->machine->md.arc.console_cury ++;
365     scroll_if_necessary(cpu);
366     }
367     arcbios_putcell(cpu, ch,
368     cpu->machine->md.arc.console_curx,
369     cpu->machine->md.arc.console_cury);
370     cpu->machine->md.arc.console_curx ++;
371     }
372     }
373    
374     scroll_if_necessary(cpu);
375    
376     /* Update cursor position: */
377     addr = (cpu->machine->md.arc.console_curx >=
378     cpu->machine->md.arc.console_maxx?
379     cpu->machine->md.arc.console_maxx - 1 :
380     cpu->machine->md.arc.console_curx) +
381     cpu->machine->md.arc.console_cury *
382     cpu->machine->md.arc.console_maxx;
383     byte = 0x0e;
384     cpu->memory_rw(cpu, cpu->mem, cpu->machine->md.arc.
385     console_ctrlregs + 0x14,
386     &byte, sizeof(byte), MEM_WRITE, CACHE_NONE | PHYSICAL);
387     byte = (addr >> 8) & 255;
388     cpu->memory_rw(cpu, cpu->mem, cpu->machine->md.arc.
389     console_ctrlregs + 0x15,
390     &byte, sizeof(byte), MEM_WRITE, CACHE_NONE | PHYSICAL);
391     byte = 0x0f;
392     cpu->memory_rw(cpu, cpu->mem, cpu->machine->md.arc.
393     console_ctrlregs + 0x14,
394     &byte, sizeof(byte), MEM_WRITE, CACHE_NONE | PHYSICAL);
395     byte = addr & 255;
396     cpu->memory_rw(cpu, cpu->mem, cpu->machine->md.arc.
397     console_ctrlregs + 0x15,
398     &byte, sizeof(byte), MEM_WRITE, CACHE_NONE | PHYSICAL);
399     }
400    
401    
402     /*
403     * arcbios_putstring():
404     */
405     static void arcbios_putstring(struct cpu *cpu, char *s)
406     {
407     while (*s) {
408     if (*s == '\n')
409     arcbios_putchar(cpu, '\r');
410     arcbios_putchar(cpu, *s++);
411     }
412     }
413    
414    
415     /*
416     * arcbios_register_scsicontroller():
417     */
418     void arcbios_register_scsicontroller(struct machine *machine,
419     uint64_t scsicontroller_component)
420     {
421     machine->md.arc.scsicontroller = scsicontroller_component;
422     }
423    
424    
425     /*
426     * arcbios_get_scsicontroller():
427     */
428     uint64_t arcbios_get_scsicontroller(struct machine *machine)
429     {
430     return machine->md.arc.scsicontroller;
431     }
432    
433    
434     /*
435     * arcbios_add_memory_descriptor():
436     *
437     * NOTE: arctype is the ARC type, not the SGI type. This function takes
438     * care of converting, when necessary.
439     */
440     void arcbios_add_memory_descriptor(struct cpu *cpu,
441     uint64_t base, uint64_t len, int arctype)
442     {
443     uint64_t memdesc_addr;
444     int s;
445     struct arcbios_mem arcbios_mem;
446     struct arcbios_mem64 arcbios_mem64;
447    
448     base /= 4096;
449     len /= 4096;
450    
451     /*
452     * TODO: Huh? Why isn't it necessary to convert from arc to sgi types?
453     *
454     * TODO 2: It seems that it _is_ neccessary, but NetBSD's arcdiag
455     * doesn't handle the sgi case separately.
456     */
457     #if 1
458     if (cpu->machine->machine_type == MACHINE_SGI) {
459     /* arctype is SGI style */
460     /* printf("%i => ", arctype); */
461     switch (arctype) {
462     case 0: arctype = 0; break;
463     case 1: arctype = 1; break;
464     case 2: arctype = 3; break;
465     case 3: arctype = 4; break;
466     case 4: arctype = 5; break;
467     case 5: arctype = 6; break;
468     case 6: arctype = 7; break;
469     case 7: arctype = 2; break;
470     }
471     /* printf("%i\n", arctype); */
472     }
473     #endif
474     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     int i;
847    
848     if (machine->md.arc.n_configuration_data >= MAX_CONFIG_DATA) {
849     printf("fatal error: you need to increase "
850     "MAX_CONFIG_DATA\n");
851     exit(1);
852     }
853    
854     for (i=0; i<config_len; i++) {
855     unsigned char ch = p[i];
856     cpu->memory_rw(cpu, cpu->mem,
857     machine->md.arc.configuration_data_next_addr + i,
858     &ch, 1, MEM_WRITE, CACHE_NONE);
859     }
860    
861     machine->md.arc.configuration_data_len[
862     machine->md.arc.n_configuration_data] = config_len;
863     machine->md.arc.configuration_data_configdata[
864     machine->md.arc.n_configuration_data] =
865     machine->md.arc.configuration_data_next_addr;
866     machine->md.arc.configuration_data_next_addr += config_len;
867     machine->md.arc.configuration_data_component[
868     machine->md.arc.n_configuration_data] =
869     machine->md.arc.next_component_address +
870     (cpu->machine->md.arc.arc_64bit? 0x18 : 0x0c);
871    
872     /* printf("& ADDING %i: configdata=0x%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     for (i=0; i<sizeof(buf); i++) {
1387     cpu->memory_rw(cpu, cpu->mem,
1388     cpu->cd.mips.gpr[MIPS_GPR_A0] + i,
1389     &buf[i], 1, MEM_READ, CACHE_NONE);
1390     if (buf[i] == '\0')
1391     i = sizeof(buf);
1392     }
1393     buf[sizeof(buf) - 1] = '\0';
1394    
1395     /* "scsi(0)disk(0)rdisk(0)partition(0)" and such. */
1396     /* printf("GetComponent(\"%s\")\n", buf); */
1397    
1398     /* Default to NULL return value. */
1399     cpu->cd.mips.gpr[MIPS_GPR_V0] = 0;
1400    
1401     /* Scan the string to component table: */
1402     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     for (i=0; i<cpu->cd.mips.gpr[MIPS_GPR_A2]; i++) {
1555     int x;
1556     unsigned char ch;
1557    
1558     /* Read from STDIN is blocking (at least
1559     that seems to be how NetBSD's arcdiag
1560     wants it) */
1561     x = console_readchar(
1562     machine->main_console_handle);
1563     if (x < 0)
1564     return 0;
1565    
1566     /*
1567     * ESC + '[' should be transformed into 0x9b:
1568     *
1569     * NOTE/TODO: This makes the behaviour of just
1570     * pressing ESC a bit harder to define.
1571     */
1572     if (x == 27) {
1573     x = console_readchar(cpu->
1574     machine->main_console_handle);
1575     if (x == '[' || x == 'O')
1576     x = 0x9b;
1577     }
1578    
1579     ch = x;
1580     nread ++;
1581     cpu->memory_rw(cpu, cpu->mem,
1582     cpu->cd.mips.gpr[MIPS_GPR_A1] + i,
1583     &ch, 1, MEM_WRITE, CACHE_NONE);
1584    
1585     /* NOTE: Only one char, from STDIN: */
1586     i = cpu->cd.mips.gpr[MIPS_GPR_A2]; /* :-) */
1587     }
1588     store_32bit_word(cpu, cpu->cd.mips.gpr[MIPS_GPR_A3],
1589     nread);
1590     /* TODO: not EAGAIN? */
1591     cpu->cd.mips.gpr[MIPS_GPR_V0] =
1592     nread? ARCBIOS_ESUCCESS: ARCBIOS_EAGAIN;
1593     } else {
1594     int handle = cpu->cd.mips.gpr[MIPS_GPR_A0];
1595     int disk_type;
1596     int disk_id = arcbios_handle_to_disk_id_and_type(
1597     machine, handle, &disk_type);
1598     uint64_t partition_offset = 0;
1599     int res;
1600     uint64_t size; /* dummy */
1601     unsigned char *tmp_buf;
1602    
1603     arcbios_handle_to_start_and_size(machine, handle,
1604     &partition_offset, &size);
1605    
1606     debug("[ ARCBIOS Read(%i,0x%08x,0x%08x,0x%08x) ]\n",
1607     (int)cpu->cd.mips.gpr[MIPS_GPR_A0],
1608     (int)cpu->cd.mips.gpr[MIPS_GPR_A1],
1609     (int)cpu->cd.mips.gpr[MIPS_GPR_A2],
1610     (int)cpu->cd.mips.gpr[MIPS_GPR_A3]);
1611    
1612     tmp_buf = malloc(cpu->cd.mips.gpr[MIPS_GPR_A2]);
1613     if (tmp_buf == NULL) {
1614     fprintf(stderr, "[ *** Out of memory in "
1615     "arcbios.c, allocating %i bytes ]\n",
1616     (int)cpu->cd.mips.gpr[MIPS_GPR_A2]);
1617     break;
1618     }
1619    
1620     res = diskimage_access(machine, disk_id, disk_type,
1621     0, partition_offset + machine->md.arc.
1622     current_seek_offset[handle], tmp_buf,
1623     cpu->cd.mips.gpr[MIPS_GPR_A2]);
1624    
1625     /* If the transfer was successful, transfer the
1626     data to emulated memory: */
1627     if (res) {
1628     uint64_t dst = cpu->cd.mips.gpr[MIPS_GPR_A1];
1629     store_buf(cpu, dst, (char *)tmp_buf,
1630     cpu->cd.mips.gpr[MIPS_GPR_A2]);
1631     store_32bit_word(cpu,
1632     cpu->cd.mips.gpr[MIPS_GPR_A3],
1633     cpu->cd.mips.gpr[MIPS_GPR_A2]);
1634     machine->md.arc.current_seek_offset[handle] +=
1635     cpu->cd.mips.gpr[MIPS_GPR_A2];
1636     cpu->cd.mips.gpr[MIPS_GPR_V0] = 0;
1637     } else
1638     cpu->cd.mips.gpr[MIPS_GPR_V0] = ARCBIOS_EIO;
1639     free(tmp_buf);
1640     }
1641     break;
1642     case 0x68: /* GetReadStatus(handle) */
1643     /*
1644     * According to arcbios_tty_getchar() in NetBSD's
1645     * dev/arcbios/arcbios_tty.c, GetReadStatus should
1646     * return 0 if there is something available.
1647     *
1648     * TODO: Error codes are things like ARCBIOS_EAGAIN.
1649     */
1650     if (cpu->cd.mips.gpr[MIPS_GPR_A0] == ARCBIOS_STDIN) {
1651     cpu->cd.mips.gpr[MIPS_GPR_V0] = console_charavail(
1652     machine->main_console_handle)? 0 : 1;
1653     } else {
1654     fatal("[ ARCBIOS GetReadStatus(%i) from "
1655     "something other than STDIN: TODO ]\n",
1656     (int)cpu->cd.mips.gpr[MIPS_GPR_A0]);
1657     /* TODO */
1658     cpu->cd.mips.gpr[MIPS_GPR_V0] = 1;
1659     }
1660     break;
1661     case 0x6c: /* Write(handle, buf, len, &returnlen) */
1662     if (cpu->cd.mips.gpr[MIPS_GPR_A0] != ARCBIOS_STDOUT) {
1663     /*
1664     * TODO: this is just a test
1665     */
1666     int handle = cpu->cd.mips.gpr[MIPS_GPR_A0];
1667     int disk_type;
1668     int disk_id = arcbios_handle_to_disk_id_and_type(
1669     machine, handle, &disk_type);
1670     uint64_t partition_offset = 0;
1671     int res, i;
1672     uint64_t size; /* dummy */
1673     unsigned char *tmp_buf;
1674    
1675     arcbios_handle_to_start_and_size(machine,
1676     handle, &partition_offset, &size);
1677    
1678     debug("[ ARCBIOS Write(%i,0x%08llx,%i,0x%08llx) ]\n",
1679     (int)cpu->cd.mips.gpr[MIPS_GPR_A0],
1680     (long long)cpu->cd.mips.gpr[MIPS_GPR_A1],
1681     (int)cpu->cd.mips.gpr[MIPS_GPR_A2],
1682     (long long)cpu->cd.mips.gpr[MIPS_GPR_A3]);
1683    
1684     tmp_buf = malloc(cpu->cd.mips.gpr[MIPS_GPR_A2]);
1685     if (tmp_buf == NULL) {
1686     fprintf(stderr, "[ *** Out of memory in"
1687     " arcbios.c, allocating %i bytes ]\n",
1688     (int)cpu->cd.mips.gpr[MIPS_GPR_A2]);
1689     break;
1690     }
1691    
1692     for (i=0; i<cpu->cd.mips.gpr[MIPS_GPR_A2]; i++)
1693     cpu->memory_rw(cpu, cpu->mem,
1694     cpu->cd.mips.gpr[MIPS_GPR_A1] + i,
1695     &tmp_buf[i], sizeof(char), MEM_READ,
1696     CACHE_NONE);
1697    
1698     res = diskimage_access(machine, disk_id, disk_type,
1699     1, partition_offset + machine->md.arc.
1700     current_seek_offset[handle], tmp_buf,
1701     cpu->cd.mips.gpr[MIPS_GPR_A2]);
1702    
1703     if (res) {
1704     store_32bit_word(cpu,
1705     cpu->cd.mips.gpr[MIPS_GPR_A3],
1706     cpu->cd.mips.gpr[MIPS_GPR_A2]);
1707     machine->md.arc.current_seek_offset[handle] +=
1708     cpu->cd.mips.gpr[MIPS_GPR_A2];
1709     cpu->cd.mips.gpr[MIPS_GPR_V0] = 0;
1710     } else
1711     cpu->cd.mips.gpr[MIPS_GPR_V0] = ARCBIOS_EIO;
1712     free(tmp_buf);
1713     } else {
1714     for (i=0; i<cpu->cd.mips.gpr[MIPS_GPR_A2]; i++) {
1715     unsigned char ch = '\0';
1716     cpu->memory_rw(cpu, cpu->mem,
1717     cpu->cd.mips.gpr[MIPS_GPR_A1] + i,
1718     &ch, sizeof(ch), MEM_READ, CACHE_NONE);
1719    
1720     arcbios_putchar(cpu, ch);
1721     }
1722     }
1723     store_32bit_word(cpu, cpu->cd.mips.gpr[MIPS_GPR_A3],
1724     cpu->cd.mips.gpr[MIPS_GPR_A2]);
1725     cpu->cd.mips.gpr[MIPS_GPR_V0] = 0; /* Success. */
1726     break;
1727     case 0x70: /* Seek(uint32_t handle, int64_t *ofs,
1728     uint32_t whence): uint32_t */
1729     debug("[ ARCBIOS Seek(%i,0x%08llx,%i): ",
1730     (int)cpu->cd.mips.gpr[MIPS_GPR_A0],
1731     (long long)cpu->cd.mips.gpr[MIPS_GPR_A1],
1732     (int)cpu->cd.mips.gpr[MIPS_GPR_A2]);
1733    
1734     if (cpu->cd.mips.gpr[MIPS_GPR_A2] != 0) {
1735     fatal("[ ARCBIOS Seek(%i,0x%08llx,%i): "
1736     "UNIMPLEMENTED whence=%i ]\n",
1737     (int)cpu->cd.mips.gpr[MIPS_GPR_A0],
1738     (long long)cpu->cd.mips.gpr[MIPS_GPR_A1],
1739     (int)cpu->cd.mips.gpr[MIPS_GPR_A2],
1740     (int)cpu->cd.mips.gpr[MIPS_GPR_A2]);
1741     }
1742    
1743     {
1744     unsigned char buf[8];
1745     uint64_t ofs;
1746     cpu->memory_rw(cpu, cpu->mem,
1747     cpu->cd.mips.gpr[MIPS_GPR_A1], &buf[0],
1748     sizeof(buf), MEM_READ, CACHE_NONE);
1749     if (cpu->byte_order == EMUL_BIG_ENDIAN) {
1750     unsigned char tmp;
1751     tmp = buf[0]; buf[0] = buf[7]; buf[7] = tmp;
1752     tmp = buf[1]; buf[1] = buf[6]; buf[6] = tmp;
1753     tmp = buf[2]; buf[2] = buf[5]; buf[5] = tmp;
1754     tmp = buf[3]; buf[3] = buf[4]; buf[4] = tmp;
1755     }
1756     ofs = buf[0] + (buf[1] << 8) + (buf[2] << 16) +
1757     (buf[3] << 24) + ((uint64_t)buf[4] << 32) +
1758     ((uint64_t)buf[5] << 40) + ((uint64_t)buf[6] << 48)
1759     + ((uint64_t)buf[7] << 56);
1760     machine->md.arc.current_seek_offset[
1761     cpu->cd.mips.gpr[MIPS_GPR_A0]] = ofs;
1762     debug("%016llx ]\n", (long long)ofs);
1763     }
1764    
1765     cpu->cd.mips.gpr[MIPS_GPR_V0] = 0; /* Success. */
1766    
1767     break;
1768     case 0x78: /* GetEnvironmentVariable(char *) */
1769     /* Find the environment variable given by a0: */
1770     for (i=0; i<sizeof(buf); i++)
1771     cpu->memory_rw(cpu, cpu->mem,
1772     cpu->cd.mips.gpr[MIPS_GPR_A0] + i,
1773     &buf[i], sizeof(char), MEM_READ, CACHE_NONE);
1774     buf[sizeof(buf)-1] = '\0';
1775     debug("[ ARCBIOS GetEnvironmentVariable(\"%s\") ]\n", buf);
1776     for (i=0; i<0x1000; i++) {
1777     /* Matching string at offset i? */
1778     int nmatches = 0;
1779     for (j=0; j<strlen((char *)buf); j++) {
1780     cpu->memory_rw(cpu, cpu->mem,
1781     (uint64_t)(ARC_ENV_STRINGS + i + j),
1782     &ch2, sizeof(char), MEM_READ, CACHE_NONE);
1783     if (ch2 == buf[j])
1784     nmatches++;
1785     }
1786     cpu->memory_rw(cpu, cpu->mem,
1787     (uint64_t)(ARC_ENV_STRINGS + i +
1788     strlen((char *)buf)), &ch2, sizeof(char),
1789     MEM_READ, CACHE_NONE);
1790     if (nmatches == strlen((char *)buf) && ch2 == '=') {
1791     cpu->cd.mips.gpr[MIPS_GPR_V0] =
1792     ARC_ENV_STRINGS + i +
1793     strlen((char *)buf) + 1;
1794     return 1;
1795     }
1796     }
1797     /* Return NULL if string wasn't found. */
1798     cpu->cd.mips.gpr[MIPS_GPR_V0] = 0;
1799     break;
1800     case 0x7c: /* SetEnvironmentVariable(char *, char *) */
1801     debug("[ ARCBIOS SetEnvironmentVariable(\"");
1802     dump_mem_string(cpu, cpu->cd.mips.gpr[MIPS_GPR_A0]);
1803     debug("\",\"");
1804     dump_mem_string(cpu, cpu->cd.mips.gpr[MIPS_GPR_A1]);
1805     debug("\") ]\n");
1806     /* TODO: This is a dummy. */
1807     cpu->cd.mips.gpr[MIPS_GPR_V0] = ARCBIOS_ESUCCESS;
1808     break;
1809     case 0x80: /* GetFileInformation() */
1810     debug("[ ARCBIOS GetFileInformation(%i,0x%x): ",
1811     (int)cpu->cd.mips.gpr[MIPS_GPR_A0],
1812     (int)cpu->cd.mips.gpr[MIPS_GPR_A1]);
1813    
1814     if (cpu->cd.mips.gpr[MIPS_GPR_A0] >= ARC_MAX_HANDLES) {
1815     debug("invalid file handle ]\n");
1816     cpu->cd.mips.gpr[MIPS_GPR_V0] = ARCBIOS_EINVAL;
1817     } else if (!machine->md.arc.file_handle_in_use[cpu->cd.
1818     mips.gpr[MIPS_GPR_A0]]) {
1819     debug("file handle not in use! ]\n");
1820     cpu->cd.mips.gpr[MIPS_GPR_V0] = ARCBIOS_EBADF;
1821     } else {
1822     debug("'%s' ]\n", machine->md.arc.file_handle_string[
1823     cpu->cd.mips.gpr[MIPS_GPR_A0]]);
1824     cpu->cd.mips.gpr[MIPS_GPR_V0] =
1825     arcbios_getfileinformation(cpu);
1826     }
1827     break;
1828     case 0x88: /* FlushAllCaches() */
1829     debug("[ ARCBIOS FlushAllCaches(): TODO ]\n");
1830     cpu->cd.mips.gpr[MIPS_GPR_V0] = 0;
1831     break;
1832     case 0x90: /* void *GetDisplayStatus(handle) */
1833     debug("[ ARCBIOS GetDisplayStatus(%i) ]\n",
1834     (int)cpu->cd.mips.gpr[MIPS_GPR_A0]);
1835     /* TODO: handle different values of 'handle'? */
1836     cpu->cd.mips.gpr[MIPS_GPR_V0] = ARC_DSPSTAT_ADDR;
1837     break;
1838     case 0x100:
1839     /*
1840     * Undocumented, used by IRIX.
1841     */
1842     debug("[ ARCBIOS: IRIX 0x100 (?) ]\n");
1843     /* TODO */
1844     cpu->cd.mips.gpr[MIPS_GPR_V0] = 0;
1845     break;
1846     case 0x888:
1847     /*
1848     * Magical crash if there is no exception handling code.
1849     */
1850     fatal("EXCEPTION, but no exception handler installed yet.\n");
1851     quiet_mode = 0;
1852     cpu_register_dump(machine, cpu, 1, 0x1);
1853     cpu->running = 0;
1854     cpu->dead = 1;
1855     break;
1856     default:
1857     quiet_mode = 0;
1858     cpu_register_dump(machine, cpu, 1, 0x1);
1859     debug("a0 points to: ");
1860     dump_mem_string(cpu, cpu->cd.mips.gpr[MIPS_GPR_A0]);
1861     debug("\n");
1862     fatal("ARCBIOS: unimplemented vector 0x%x\n", vector);
1863     cpu->running = 0;
1864     cpu->dead = 1;
1865     }
1866    
1867     return 1;
1868     }
1869    
1870    
1871     /*
1872     * arcbios_set_default_exception_handler():
1873     */
1874     void arcbios_set_default_exception_handler(struct cpu *cpu)
1875     {
1876     /*
1877     * The default exception handlers simply jump to 0xbfc88888,
1878     * which is then taken care of in arcbios_emul() above.
1879     *
1880     * 3c1abfc8 lui k0,0xbfc8
1881     * 375a8888 ori k0,k0,0x8888
1882     * 03400008 jr k0
1883     * 00000000 nop
1884     */
1885     store_32bit_word(cpu, 0xffffffff80000000ULL, 0x3c1abfc8);
1886     store_32bit_word(cpu, 0xffffffff80000004ULL, 0x375a8888);
1887     store_32bit_word(cpu, 0xffffffff80000008ULL, 0x03400008);
1888     store_32bit_word(cpu, 0xffffffff8000000cULL, 0x00000000);
1889    
1890     store_32bit_word(cpu, 0xffffffff80000080ULL, 0x3c1abfc8);
1891     store_32bit_word(cpu, 0xffffffff80000084ULL, 0x375a8888);
1892     store_32bit_word(cpu, 0xffffffff80000088ULL, 0x03400008);
1893     store_32bit_word(cpu, 0xffffffff8000008cULL, 0x00000000);
1894    
1895     store_32bit_word(cpu, 0xffffffff80000180ULL, 0x3c1abfc8);
1896     store_32bit_word(cpu, 0xffffffff80000184ULL, 0x375a8888);
1897     store_32bit_word(cpu, 0xffffffff80000188ULL, 0x03400008);
1898     store_32bit_word(cpu, 0xffffffff8000018cULL, 0x00000000);
1899     }
1900    
1901    
1902     /*
1903     * arcbios_add_other_components():
1904     *
1905     * TODO: How should this be synched with the hardware devices
1906     * added in machine.c?
1907     */
1908     static void arcbios_add_other_components(struct machine *machine,
1909     uint64_t system)
1910     {
1911     struct cpu *cpu = machine->cpus[0];
1912    
1913     if (machine->machine_type == MACHINE_ARC &&
1914     ( machine->machine_subtype == MACHINE_ARC_NEC_RD94 ||
1915     machine->machine_subtype == MACHINE_ARC_NEC_R94 ||
1916     machine->machine_subtype == MACHINE_ARC_NEC_R96 )) {
1917     uint64_t jazzbus, eisa, other;
1918    
1919     jazzbus = arcbios_addchild_manual(cpu,
1920     COMPONENT_CLASS_AdapterClass,
1921     COMPONENT_TYPE_MultiFunctionAdapter,
1922     0, 1, 2, 0, 0xffffffff, "Jazz-Internal Bus",
1923     system, NULL, 0);
1924    
1925     switch (machine->machine_subtype) {
1926     case MACHINE_ARC_NEC_RD94:
1927     case MACHINE_ARC_NEC_R94:
1928     if (machine->use_x11)
1929     arcbios_addchild_manual(cpu,
1930     COMPONENT_CLASS_ControllerClass,
1931     COMPONENT_TYPE_DisplayController,
1932     0, 1, 2, 0, 0x0, "10110004",
1933     system, NULL, 0);
1934     break;
1935     case MACHINE_ARC_NEC_R96:
1936     if (machine->use_x11) {
1937     uint64_t x;
1938     x = arcbios_addchild_manual(cpu,
1939     COMPONENT_CLASS_ControllerClass,
1940     COMPONENT_TYPE_DisplayController,
1941     COMPONENT_FLAG_ConsoleOut |
1942     COMPONENT_FLAG_Output,
1943     1, 2, 0, 0x0, "necvdfrb",
1944     jazzbus, NULL, 0);
1945     arcbios_addchild_manual(cpu,
1946     COMPONENT_CLASS_PeripheralClass,
1947     COMPONENT_TYPE_MonitorPeripheral,
1948     COMPONENT_FLAG_ConsoleOut |
1949     COMPONENT_FLAG_Output,
1950     1, 2, 0, 0xffffffff, "640x480",
1951     x, NULL, 0);
1952     }
1953    
1954     /* TODO: R[D]94 too? */
1955     eisa = arcbios_addchild_manual(cpu,
1956     COMPONENT_CLASS_AdapterClass,
1957     COMPONENT_TYPE_EISAAdapter,
1958     0, 1, 2, 0, 0xffffffff, "EISA",
1959     system, NULL, 0);
1960    
1961     other = arcbios_addchild_manual(cpu,
1962     COMPONENT_CLASS_ControllerClass,
1963     COMPONENT_TYPE_OtherController,
1964     0, 1, 2, 0, 0xffffffff, "NEC1C01",
1965     eisa, NULL, 0);
1966     break;
1967     }
1968     }
1969    
1970     if (machine->machine_type == MACHINE_ARC &&
1971     (machine->machine_subtype == MACHINE_ARC_JAZZ_PICA
1972     || machine->machine_subtype == MACHINE_ARC_JAZZ_MAGNUM)) {
1973     uint64_t jazzbus, ali_s3, vxl;
1974     uint64_t diskcontroller, floppy, kbdctl, kbd;
1975     uint64_t ptrctl, ptr, paral, audio;
1976     uint64_t eisa, scsi;
1977     /* uint64_t serial1, serial2; */
1978    
1979     jazzbus = arcbios_addchild_manual(cpu,
1980     COMPONENT_CLASS_AdapterClass,
1981     COMPONENT_TYPE_MultiFunctionAdapter,
1982     0, 1, 2, 0, 0xffffffff, "Jazz-Internal Bus",
1983     system, NULL, 0);
1984    
1985     /*
1986     * DisplayController, needed by NetBSD:
1987     * TODO: NetBSD still doesn't use it :(
1988     */
1989     switch (machine->machine_subtype) {
1990     case MACHINE_ARC_JAZZ_PICA:
1991     /* Default TLB entries on PICA-61: */
1992    
1993     /* 7: 256K, asid: 0x0, v: 0xe1000000,
1994     p0: 0xfff00000(2.VG), p1: 0x0(0..G) */
1995     mips_coproc_tlb_set_entry(cpu, 7, 262144,
1996     0xffffffffe1000000ULL,
1997     0x0fff00000ULL, 0, 1, 0, 0, 0, 1, 0, 2, 0);
1998    
1999     /* 8: 64K, asid: 0x0, v: 0xe0000000,
2000     p0: 0x80000000(2DVG), p1: 0x0(0..G) */
2001     mips_coproc_tlb_set_entry(cpu, 8, 65536,
2002     0xffffffffe0000000ULL,
2003     0x080000000ULL, 0, 1, 0, 1, 0, 1, 0, 2, 0);
2004    
2005     /* 9: 64K, asid: 0x0, v: 0xe00e0000,
2006     p0: 0x800e0000(2DVG), p1: 0x800f0000(2DVG) */
2007     mips_coproc_tlb_set_entry(cpu, 9, 65536,
2008     (uint64_t)0xffffffffe00e0000ULL,
2009     (uint64_t)0x0800e0000ULL,
2010     (uint64_t)0x0800f0000ULL, 1, 1, 1, 1, 1, 0, 2, 2);
2011    
2012     /* 10: 4K, asid: 0x0, v: 0xe0100000,
2013     p0: 0xf0000000(2DVG), p1: 0x0(0..G) */
2014     mips_coproc_tlb_set_entry(cpu, 10, 4096,
2015     (uint64_t)0xffffffffe0100000ULL,
2016     (uint64_t)0x0f0000000ULL, 0,1, 0, 1, 0, 1, 0, 2, 0);
2017    
2018     /* 11: 1M, asid: 0x0, v: 0xe0200000,
2019     p0: 0x60000000(2DVG), p1: 0x60100000(2DVG) */
2020     mips_coproc_tlb_set_entry(cpu, 11, 1048576,
2021     0xffffffffe0200000ULL,
2022     0x060000000ULL, 0x060100000ULL,1,1,1,1,1, 0, 2, 2);
2023    
2024     /* 12: 1M, asid: 0x0, v: 0xe0400000,
2025     p0: 0x60200000(2DVG), p1: 0x60300000(2DVG) */
2026     mips_coproc_tlb_set_entry(cpu, 12, 1048576,
2027     0xffffffffe0400000ULL, 0x060200000ULL,
2028     0x060300000ULL, 1, 1, 1, 1, 1, 0, 2, 2);
2029    
2030     /* 13: 4M, asid: 0x0, v: 0xe0800000,
2031     p0: 0x40000000(2DVG), p1: 0x40400000(2DVG) */
2032     mips_coproc_tlb_set_entry(cpu, 13, 1048576*4,
2033     0xffffffffe0800000ULL, 0x040000000ULL,
2034     0x040400000ULL, 1, 1, 1, 1, 1, 0, 2, 2);
2035    
2036     /* 14: 16M, asid: 0x0, v: 0xe2000000,
2037     p0: 0x90000000(2DVG), p1: 0x91000000(2DVG) */
2038     mips_coproc_tlb_set_entry(cpu, 14, 1048576*16,
2039     0xffffffffe2000000ULL, 0x090000000ULL,
2040     0x091000000ULL, 1, 1, 1, 1, 1, 0, 2, 2);
2041    
2042     if (machine->use_x11) {
2043     ali_s3 = arcbios_addchild_manual(cpu,
2044     COMPONENT_CLASS_ControllerClass,
2045     COMPONENT_TYPE_DisplayController,
2046     COMPONENT_FLAG_ConsoleOut |
2047     COMPONENT_FLAG_Output,
2048     1, 2, 0, 0xffffffff, "ALI_S3",
2049     jazzbus, NULL, 0);
2050    
2051     arcbios_addchild_manual(cpu,
2052     COMPONENT_CLASS_PeripheralClass,
2053     COMPONENT_TYPE_MonitorPeripheral,
2054     COMPONENT_FLAG_ConsoleOut |
2055     COMPONENT_FLAG_Output,
2056     1, 2, 0, 0xffffffff, "1024x768",
2057     ali_s3, NULL, 0);
2058     }
2059     break;
2060     case MACHINE_ARC_JAZZ_MAGNUM:
2061     if (machine->use_x11) {
2062     vxl = arcbios_addchild_manual(cpu,
2063     COMPONENT_CLASS_ControllerClass,
2064     COMPONENT_TYPE_DisplayController,
2065     COMPONENT_FLAG_ConsoleOut |
2066     COMPONENT_FLAG_Output,
2067     1, 2, 0, 0xffffffff, "VXL",
2068     jazzbus, NULL, 0);
2069    
2070     arcbios_addchild_manual(cpu,
2071     COMPONENT_CLASS_PeripheralClass,
2072     COMPONENT_TYPE_MonitorPeripheral,
2073     COMPONENT_FLAG_ConsoleOut |
2074     COMPONENT_FLAG_Output,
2075     1, 2, 0, 0xffffffff, "1024x768",
2076     vxl, NULL, 0);
2077     }
2078     break;
2079     }
2080    
2081     diskcontroller = arcbios_addchild_manual(cpu,
2082     COMPONENT_CLASS_ControllerClass,
2083     COMPONENT_TYPE_DiskController,
2084     COMPONENT_FLAG_Input | COMPONENT_FLAG_Output,
2085     1, 2, 0, 0xffffffff, "I82077", jazzbus, NULL, 0);
2086    
2087     floppy = arcbios_addchild_manual(cpu,
2088     COMPONENT_CLASS_PeripheralClass,
2089     COMPONENT_TYPE_FloppyDiskPeripheral,
2090     COMPONENT_FLAG_Removable |
2091     COMPONENT_FLAG_Input | COMPONENT_FLAG_Output,
2092     1, 2, 0, 0xffffffff, NULL, diskcontroller, NULL, 0);
2093    
2094     kbdctl = arcbios_addchild_manual(cpu,
2095     COMPONENT_CLASS_ControllerClass,
2096     COMPONENT_TYPE_KeyboardController,
2097     COMPONENT_FLAG_ConsoleIn | COMPONENT_FLAG_Input,
2098     1, 2, 0, 0xffffffff, "I8742", jazzbus, NULL, 0);
2099    
2100     kbd = arcbios_addchild_manual(cpu,
2101     COMPONENT_CLASS_PeripheralClass,
2102     COMPONENT_TYPE_KeyboardPeripheral,
2103     COMPONENT_FLAG_ConsoleIn | COMPONENT_FLAG_Input,
2104     1, 2, 0, 0xffffffff, "PCAT_ENHANCED", kbdctl, NULL, 0);
2105    
2106     ptrctl = arcbios_addchild_manual(cpu,
2107     COMPONENT_CLASS_ControllerClass,
2108     COMPONENT_TYPE_PointerController, COMPONENT_FLAG_Input,
2109     1, 2, 0, 0xffffffff, "I8742", jazzbus, NULL, 0);
2110    
2111     ptr = arcbios_addchild_manual(cpu,
2112     COMPONENT_CLASS_PeripheralClass,
2113     COMPONENT_TYPE_PointerPeripheral, COMPONENT_FLAG_Input,
2114     1, 2, 0, 0xffffffff, "PS2 MOUSE", ptrctl, NULL, 0);
2115    
2116     /* These cause Windows NT to bug out. */
2117     #if 0
2118     serial1 = arcbios_addchild_manual(cpu,
2119     COMPONENT_CLASS_ControllerClass,
2120     COMPONENT_TYPE_SerialController,
2121     COMPONENT_FLAG_Input | COMPONENT_FLAG_Output,
2122     1, 2, 0, 0xffffffff, "COM1", jazzbus, NULL, 0);
2123    
2124     serial2 = arcbios_addchild_manual(cpu,
2125     COMPONENT_CLASS_ControllerClass,
2126     COMPONENT_TYPE_SerialController,
2127     COMPONENT_FLAG_Input | COMPONENT_FLAG_Output,
2128     1, 2, 0, 0xffffffff, "COM1", jazzbus, NULL, 0);
2129     #endif
2130    
2131     paral = arcbios_addchild_manual(cpu,
2132     COMPONENT_CLASS_ControllerClass,
2133     COMPONENT_TYPE_ParallelController,
2134     COMPONENT_FLAG_Input | COMPONENT_FLAG_Output,
2135     1, 2, 0, 0xffffffff, "LPT1", jazzbus, NULL, 0);
2136    
2137     audio = arcbios_addchild_manual(cpu,
2138     COMPONENT_CLASS_ControllerClass,
2139     COMPONENT_TYPE_AudioController,
2140     COMPONENT_FLAG_Input | COMPONENT_FLAG_Output,
2141     1, 2, 0, 0xffffffff, "MAGNUM", jazzbus, NULL, 0);
2142    
2143     eisa = arcbios_addchild_manual(cpu,
2144     COMPONENT_CLASS_AdapterClass, COMPONENT_TYPE_EISAAdapter,
2145     0, 1, 2, 0, 0xffffffff, "EISA", system, NULL, 0);
2146    
2147     {
2148     unsigned char config[78];
2149     memset(config, 0, sizeof(config));
2150    
2151     /* config data version: 1, revision: 2, count: 4 */
2152     config[0] = 0x01; config[1] = 0x00;
2153     config[2] = 0x02; config[3] = 0x00;
2154     config[4] = 0x04; config[5] = 0x00; config[6] = 0x00; config[7] = 0x00;
2155    
2156     /*
2157     type: Interrupt
2158     share_disposition: DeviceExclusive, flags: LevelSensitive
2159     level: 4, vector: 22, reserved1: 0
2160     */
2161     config[8] = arc_CmResourceTypeInterrupt;
2162     config[9] = arc_CmResourceShareDeviceExclusive;
2163     config[10] = arc_CmResourceInterruptLevelSensitive;
2164     config[12] = 4;
2165     config[16] = 22;
2166     config[20] = 0;
2167    
2168     /*
2169     type: Memory
2170     share_disposition: DeviceExclusive, flags: ReadWrite
2171     start: 0x 0 80002000, length: 0x1000
2172     */
2173     config[24] = arc_CmResourceTypeMemory;
2174     config[25] = arc_CmResourceShareDeviceExclusive;
2175     config[26] = arc_CmResourceMemoryReadWrite;
2176     config[28] = 0x00; config[29] = 0x20; config[30] = 0x00; config[31] = 0x80;
2177     config[32] = 0x00; config[33] = 0x00; config[34] = 0x00; config[35] = 0x00;
2178     config[36] = 0x00; config[37] = 0x10; config[38] = 0x00; config[39] = 0x00;
2179    
2180     /*
2181     type: DMA
2182     share_disposition: DeviceExclusive, flags: 0x0
2183     channel: 0, port: 0, reserved1: 0
2184     */
2185     config[40] = arc_CmResourceTypeDMA;
2186     config[41] = arc_CmResourceShareDeviceExclusive;
2187     /* 42..43 = flags, 44,45,46,47 = channel, 48,49,50,51 = port, 52,53,54,55
2188     = reserved */
2189    
2190     /* type: DeviceSpecific
2191     share_disposition: DeviceExclusive, flags: 0x0
2192     datasize: 6, reserved1: 0, reserved2: 0
2193     data: [0x1:0x0:0x2:0x0:0x7:0x30]
2194     */
2195     config[56] = arc_CmResourceTypeDeviceSpecific;
2196     config[57] = arc_CmResourceShareDeviceExclusive;
2197     /* 58,59 = flags 60,61,62,63 = data size, 64..71 = reserved */
2198     config[60] = 6;
2199     /* 72..77 = the data */
2200     config[72] = 0x01; config[73] = 0x00; config[74] = 0x02;
2201     config[75] = 0x00; config[76] = 0x07; config[77] = 0x30;
2202     scsi = arcbios_addchild_manual(cpu,
2203     COMPONENT_CLASS_AdapterClass,
2204     COMPONENT_TYPE_SCSIAdapter,
2205     0, 1, 2, 0, 0xffffffff, "ESP216",
2206     system, config, sizeof(config));
2207    
2208     arcbios_register_scsicontroller(machine, scsi);
2209     }
2210     }
2211     }
2212    
2213    
2214     /*
2215     * arcbios_console_init():
2216     *
2217     * Called from machine.c whenever an ARC-based machine is running with
2218     * a graphical VGA-style framebuffer, which can be used as console.
2219     */
2220     void arcbios_console_init(struct machine *machine,
2221     uint64_t vram, uint64_t ctrlregs)
2222     {
2223     machine->md.arc.vgaconsole = 1;
2224    
2225     machine->md.arc.console_vram = vram;
2226     machine->md.arc.console_ctrlregs = ctrlregs;
2227     machine->md.arc.console_maxx = ARC_CONSOLE_MAX_X;
2228     machine->md.arc.console_maxy = ARC_CONSOLE_MAX_Y;
2229     machine->md.arc.in_escape_sequence = 0;
2230     machine->md.arc.escape_sequence[0] = '\0';
2231     }
2232    
2233    
2234     /*
2235     * arcbios_init():
2236     *
2237     * Should be called before any other arcbios function is used. An exception
2238     * is arcbios_console_init(), which may be called before this function.
2239     */
2240     void arcbios_init(struct machine *machine, int is64bit,
2241     uint64_t sgi_ram_offset)
2242     {
2243     int i, alloclen = 20;
2244     char *name;
2245     uint64_t arc_reserved, mem_base, mem_count;
2246     struct cpu *cpu = machine->cpus[0];
2247     struct arcbios_sysid arcbios_sysid;
2248     struct arcbios_dsp_stat arcbios_dsp_stat;
2249     uint64_t system = 0;
2250     struct arcbios_spb arcbios_spb;
2251     struct arcbios_spb_64 arcbios_spb_64;
2252    
2253     machine->md.arc.arc_64bit = is64bit;
2254     machine->md.arc.wordlen = is64bit? sizeof(uint64_t) : sizeof(uint32_t);
2255    
2256     machine->md.arc.next_component_address = FIRST_ARC_COMPONENT;
2257     machine->md.arc.configuration_data_next_addr = ARC_CONFIG_DATA_ADDR;
2258    
2259     if (machine->physical_ram_in_mb < 16)
2260     fprintf(stderr, "WARNING! The ARC platform specification "
2261     "doesn't allow less than 16 MB of RAM. Continuing "
2262     "anyway.\n");
2263    
2264     /* File handles 0, 1, and 2 are stdin, stdout, and stderr. */
2265     for (i=0; i<ARC_MAX_HANDLES; i++) {
2266     machine->md.arc.file_handle_in_use[i] = i<3? 1 : 0;
2267     machine->md.arc.file_handle_string[i] = i>=3? NULL :
2268     (i==0? "(stdin)" : (i==1? "(stdout)" : "(stderr)"));
2269     machine->md.arc.current_seek_offset[i] = 0;
2270     }
2271    
2272     if (!machine->use_x11)
2273     machine->md.arc.vgaconsole = 0;
2274    
2275     if (machine->md.arc.vgaconsole) {
2276     char tmpstr[100];
2277     int x, y;
2278    
2279     machine->md.arc.console_curcolor = 0x1f;
2280     for (y=0; y<machine->md.arc.console_maxy; y++)
2281     for (x=0; x<machine->md.arc.console_maxx; x++)
2282     arcbios_putcell(cpu, ' ', x, y);
2283    
2284     machine->md.arc.console_curx = 0;
2285     machine->md.arc.console_cury = 0;
2286    
2287     arcbios_putstring(cpu, "GXemul");
2288     #ifdef VERSION
2289     arcbios_putstring(cpu, " "VERSION);
2290     #endif
2291     arcbios_putstring(cpu, " ARCBIOS emulation\n");
2292    
2293     snprintf(tmpstr, sizeof(tmpstr), "%i cpu%s (%s), %i MB "
2294     "memory\n\n", machine->ncpus, machine->ncpus > 1? "s" : "",
2295     cpu->cd.mips.cpu_type.name,
2296     machine->physical_ram_in_mb);
2297     arcbios_putstring(cpu, tmpstr);
2298     }
2299    
2300     arcbios_set_default_exception_handler(cpu);
2301    
2302     memset(&arcbios_sysid, 0, sizeof(arcbios_sysid));
2303     if (machine->machine_type == MACHINE_SGI) {
2304     /* Vendor ID, max 8 chars: */
2305     strncpy(arcbios_sysid.VendorId, "SGI", 3);
2306     switch (machine->machine_subtype) {
2307     case 22:
2308     strncpy(arcbios_sysid.ProductId,
2309     "87654321", 8); /* some kind of ID? */
2310     break;
2311     case 32:
2312     strncpy(arcbios_sysid.ProductId, "8", 1);
2313     /* 6 or 8 (?) */
2314     break;
2315     default:
2316     snprintf(arcbios_sysid.ProductId, 8, "IP%i",
2317     machine->machine_subtype);
2318     }
2319     } else {
2320     switch (machine->machine_subtype) {
2321     case MACHINE_ARC_NEC_RD94:
2322     strncpy(arcbios_sysid.VendorId, "NEC W&S", 8);
2323     strncpy(arcbios_sysid.ProductId, "RD94", 4);
2324     break;
2325     case MACHINE_ARC_NEC_R94:
2326     strncpy(arcbios_sysid.VendorId, "NEC W&S", 8);
2327     strncpy(arcbios_sysid.ProductId, "ijkl", 4);
2328     break;
2329     case MACHINE_ARC_NEC_R96:
2330     strncpy(arcbios_sysid.VendorId, "MIPS DUO", 8);
2331     strncpy(arcbios_sysid.ProductId, "blahblah", 8);
2332     break;
2333     case MACHINE_ARC_NEC_R98:
2334     strncpy(arcbios_sysid.VendorId, "NEC W&S", 8);
2335     strncpy(arcbios_sysid.ProductId, "R98", 4);
2336     break;
2337     case MACHINE_ARC_JAZZ_PICA:
2338     strncpy(arcbios_sysid.VendorId, "MIPS MAG", 8);
2339     strncpy(arcbios_sysid.ProductId, "ijkl", 4);
2340     break;
2341     case MACHINE_ARC_JAZZ_MAGNUM:
2342     strncpy(arcbios_sysid.VendorId, "MIPS MAG", 8);
2343     strncpy(arcbios_sysid.ProductId, "ijkl", 4);
2344     break;
2345     case MACHINE_ARC_JAZZ_M700:
2346     strncpy(arcbios_sysid.VendorId, "OLI00000", 8);
2347     strncpy(arcbios_sysid.ProductId, "ijkl", 4);
2348     break;
2349     case MACHINE_ARC_DESKTECH_TYNE:
2350     strncpy(arcbios_sysid.VendorId, "DESKTECH", 8);
2351     strncpy(arcbios_sysid.ProductId, "ijkl", 4);
2352     break;
2353     default:
2354     fatal("error in machine.c sysid\n");
2355     exit(1);
2356     }
2357     }
2358    
2359     store_buf(cpu, SGI_SYSID_ADDR, (char *)&arcbios_sysid,
2360     sizeof(arcbios_sysid));
2361    
2362     arcbios_get_dsp_stat(cpu, &arcbios_dsp_stat);
2363     store_buf(cpu, ARC_DSPSTAT_ADDR, (char *)&arcbios_dsp_stat,
2364     sizeof(arcbios_dsp_stat));
2365    
2366     /*
2367     * The first 12 MBs of RAM are simply reserved... this simplifies
2368     * things a lot. If there's more than 512MB of RAM, it has to be
2369     * split in two, according to the ARC spec. This code creates a
2370     * number of chunks of at most 512MB each.
2371     *
2372     * NOTE: The region of physical address space between 0x10000000 and
2373     * 0x1fffffff (256 - 512 MB) is usually occupied by memory mapped
2374     * devices, so that portion is "lost".
2375     */
2376     machine->md.arc.memdescriptor_base = ARC_MEMDESC_ADDR;
2377    
2378     arc_reserved = 0x2000;
2379     if (machine->machine_type == MACHINE_SGI)
2380     arc_reserved = 0x4000;
2381    
2382     arcbios_add_memory_descriptor(cpu, 0, arc_reserved,
2383     ARCBIOS_MEM_FirmwarePermanent);
2384     arcbios_add_memory_descriptor(cpu, sgi_ram_offset + arc_reserved,
2385     0x60000-arc_reserved, ARCBIOS_MEM_FirmwareTemporary);
2386    
2387     mem_base = 12;
2388     mem_base += sgi_ram_offset / 1048576;
2389    
2390     while (mem_base < machine->physical_ram_in_mb+sgi_ram_offset/1048576) {
2391     mem_count = machine->physical_ram_in_mb+sgi_ram_offset/1048576
2392     - mem_base;
2393    
2394     /* Skip the 256-512MB region (for devices) */
2395     if (mem_base < 256 && mem_base + mem_count > 256) {
2396     mem_count = 256-mem_base;
2397     }
2398    
2399     /* At most 512MB per descriptor (at least the first 512MB
2400     must be separated this way, according to the ARC spec) */
2401     if (mem_count > 512)
2402     mem_count = 512;
2403    
2404     arcbios_add_memory_descriptor(cpu, mem_base * 1048576,
2405     mem_count * 1048576, ARCBIOS_MEM_FreeMemory);
2406    
2407     mem_base += mem_count;
2408    
2409     /* Skip the devices: */
2410     if (mem_base == 256)
2411     mem_base = 512;
2412     }
2413    
2414     /*
2415     * Components: (this is an example of what a system could look like)
2416     *
2417     * [System]
2418     * [CPU] (one for each cpu)
2419     * [FPU] (one for each cpu)
2420     * [CPU Caches]
2421     * [Memory]
2422     * [Ethernet]
2423     * [Serial]
2424     * [SCSI]
2425     * [Disk]
2426     *
2427     * Here's a good list of what hardware is in different IP-models:
2428     * http://www.linux-mips.org/archives/linux-mips/2001-03/msg00101.html
2429     */
2430    
2431     if (machine->machine_name == NULL)
2432     fatal("ERROR: machine_name == NULL\n");
2433    
2434     /* Add the root node: */
2435     switch (machine->machine_type) {
2436     case MACHINE_SGI:
2437     name = malloc(alloclen);
2438     if (name == NULL) {
2439     fprintf(stderr, "out of memory\n");
2440     exit(1);
2441     }
2442     snprintf(name, alloclen, "SGI-IP%i",
2443     machine->machine_subtype);
2444    
2445     /* A very special case for IP24 (which identifies itself
2446     as an IP22): */
2447     if (machine->machine_subtype == 24)
2448     snprintf(name, alloclen, "SGI-IP22");
2449     break;
2450     case MACHINE_ARC:
2451     /* ARC: */
2452     switch (machine->machine_subtype) {
2453     case MACHINE_ARC_NEC_RD94:
2454     name = "NEC-RD94";
2455     break;
2456     case MACHINE_ARC_NEC_R94:
2457     name = "NEC-R94";
2458     break;
2459     case MACHINE_ARC_NEC_R96:
2460     name = "NEC-R96";
2461     break;
2462     case MACHINE_ARC_NEC_R98:
2463     name = "NEC-R98";
2464     break;
2465     case MACHINE_ARC_JAZZ_PICA:
2466     name = "PICA-61";
2467     break;
2468     case MACHINE_ARC_JAZZ_MAGNUM:
2469     case MACHINE_ARC_JAZZ_M700:
2470     name = "Microsoft-Jazz";
2471     break;
2472     case MACHINE_ARC_DESKTECH_TYNE:
2473     name = "DESKTECH-TYNE";
2474     break;
2475     default:
2476     fatal("Unimplemented ARC machine type %i\n",
2477     machine->machine_subtype);
2478     exit(1);
2479     }
2480     break;
2481     default:
2482     fatal("ERROR: non-SGI and non-ARC?\n");
2483     exit(1);
2484     }
2485    
2486     system = arcbios_addchild_manual(cpu, COMPONENT_CLASS_SystemClass,
2487     COMPONENT_TYPE_ARC, 0,1,2,0, 0xffffffff, name, 0/*ROOT*/, NULL, 0);
2488     debug("ARC system @ 0x%llx (\"%s\")\n", (long long)system, name);
2489    
2490    
2491     /*
2492     * Add tree nodes for CPUs and their caches:
2493     */
2494    
2495     for (i=0; i<machine->ncpus; i++) {
2496     uint64_t cpuaddr, fpu=0, picache, pdcache, sdcache=0;
2497     int cache_size, cache_line_size;
2498     unsigned int jj;
2499     char arc_cpu_name[100];
2500     char arc_fpc_name[105];
2501    
2502     snprintf(arc_cpu_name, sizeof(arc_cpu_name),
2503     "MIPS-%s", machine->cpu_name);
2504    
2505     if (machine->machine_type == MACHINE_ARC &&
2506     machine->machine_subtype == MACHINE_ARC_NEC_R96)
2507     snprintf(arc_cpu_name, sizeof(arc_cpu_name),
2508     "MIPS-%s - Pr 4/5.0, Fp 5/0", machine->cpu_name);
2509    
2510     arc_cpu_name[sizeof(arc_cpu_name)-1] = 0;
2511     for (jj=0; jj<strlen(arc_cpu_name); jj++)
2512     if (arc_cpu_name[jj] >= 'a' && arc_cpu_name[jj] <= 'z')
2513     arc_cpu_name[jj] += ('A' - 'a');
2514    
2515     strlcpy(arc_fpc_name, arc_cpu_name, sizeof(arc_fpc_name));
2516     strlcat(arc_fpc_name, "FPC", sizeof(arc_fpc_name));
2517    
2518     cpuaddr = arcbios_addchild_manual(cpu,
2519     COMPONENT_CLASS_ProcessorClass, COMPONENT_TYPE_CPU,
2520     0, 1, 2, i, 0xffffffff, arc_cpu_name, system, NULL, 0);
2521    
2522     /*
2523     * TODO: This was in the ARC specs, but it isn't really used
2524     * by ARC implementations? At least SGI-IP32 uses it.
2525     */
2526     if (machine->machine_type == MACHINE_SGI)
2527     fpu = arcbios_addchild_manual(cpu,
2528     COMPONENT_CLASS_ProcessorClass, COMPONENT_TYPE_FPU,
2529     0, 1, 2, 0, 0xffffffff, arc_fpc_name, cpuaddr,
2530     NULL, 0);
2531    
2532     cache_size = DEFAULT_PCACHE_SIZE - 12;
2533     if (machine->cache_picache)
2534     cache_size = machine->cache_picache - 12;
2535     if (cache_size < 0)
2536     cache_size = 0;
2537    
2538     cache_line_size = DEFAULT_PCACHE_LINESIZE;
2539     if (machine->cache_picache_linesize)
2540     cache_line_size = machine->cache_picache_linesize;
2541     if (cache_line_size < 0)
2542     cache_line_size = 0;
2543    
2544     picache = arcbios_addchild_manual(cpu,
2545     COMPONENT_CLASS_CacheClass, COMPONENT_TYPE_PrimaryICache,
2546     0, 1, 2,
2547     /*
2548     * Key bits: 0xXXYYZZZZ
2549     * XX is refill-size.
2550     * Cache line size is 1 << YY,
2551     * Cache size is 4KB << ZZZZ.
2552     */
2553     0x01000000 + (cache_line_size << 16) + cache_size,
2554     /* 32 bytes per line, default = 32 KB total */
2555     0xffffffff, NULL, cpuaddr, NULL, 0);
2556    
2557     cache_size = DEFAULT_PCACHE_SIZE - 12;
2558     if (machine->cache_pdcache)
2559     cache_size = machine->cache_pdcache - 12;
2560     if (cache_size < 0)
2561     cache_size = 0;
2562    
2563     cache_line_size = DEFAULT_PCACHE_LINESIZE;
2564     if (machine->cache_pdcache_linesize)
2565     cache_line_size = machine->cache_pdcache_linesize;
2566     if (cache_line_size < 0)
2567     cache_line_size = 0;
2568    
2569     pdcache = arcbios_addchild_manual(cpu,
2570     COMPONENT_CLASS_CacheClass,
2571     COMPONENT_TYPE_PrimaryDCache, 0, 1, 2,
2572     /*
2573     * Key bits: 0xYYZZZZ
2574     * Cache line size is 1 << YY,
2575     * Cache size is 4KB << ZZZZ.
2576     */
2577     0x01000000 + (cache_line_size << 16) + cache_size,
2578     /* 32 bytes per line, default = 32 KB total */
2579     0xffffffff, NULL, cpuaddr, NULL, 0);
2580    
2581     if (machine->cache_secondary >= 12) {
2582     cache_size = machine->cache_secondary - 12;
2583    
2584     cache_line_size = 6; /* 64 bytes default */
2585     if (machine->cache_secondary_linesize)
2586     cache_line_size = machine->
2587     cache_secondary_linesize;
2588     if (cache_line_size < 0)
2589     cache_line_size = 0;
2590    
2591     sdcache = arcbios_addchild_manual(cpu,
2592     COMPONENT_CLASS_CacheClass,
2593     COMPONENT_TYPE_SecondaryDCache, 0, 1, 2,
2594     /*
2595     * Key bits: 0xYYZZZZ
2596     * Cache line size is 1 << YY,
2597     * Cache size is 4KB << ZZZZ.
2598     */
2599     0x01000000 + (cache_line_size << 16) + cache_size,
2600     /* 64 bytes per line, default = 1 MB total */
2601     0xffffffff, NULL, cpuaddr, NULL, 0);
2602     }
2603    
2604     debug("ARC cpu%i @ 0x%llx", i, (long long)cpuaddr);
2605    
2606     if (fpu != 0)
2607     debug(" (fpu @ 0x%llx)\n", (long long)fpu);
2608     else
2609     debug("\n");
2610    
2611     debug(" picache @ 0x%llx, pdcache @ 0x%llx\n",
2612     (long long)picache, (long long)pdcache);
2613    
2614     if (machine->cache_secondary >= 12)
2615     debug(" sdcache @ 0x%llx\n",
2616     (long long)sdcache);
2617    
2618     if (machine->machine_type == MACHINE_SGI) {
2619     /* TODO: Memory amount (and base address?)! */
2620     uint64_t memory = arcbios_addchild_manual(cpu,
2621     COMPONENT_CLASS_MemoryClass,
2622     COMPONENT_TYPE_MemoryUnit, 0, 1, 2, 0,
2623     0xffffffff, "memory", cpuaddr, NULL, 0);
2624     debug("ARC memory @ 0x%llx\n", (long long)memory);
2625     }
2626     }
2627    
2628    
2629     /*
2630     * Add other components:
2631     *
2632     * TODO: How should this be synched with the hardware devices
2633     * added in machine.c?
2634     */
2635    
2636     arcbios_add_other_components(machine, system);
2637    
2638    
2639     /*
2640     * Defalt TLB entry for 64-bit SGI machines:
2641     */
2642     if (machine->machine_type == MACHINE_SGI &&
2643     machine->machine_subtype != 12 /* TODO: ugly */ ) {
2644     /* TODO: On which models is this required? */
2645     mips_coproc_tlb_set_entry(cpu, 0, 1048576*16,
2646     0xc000000000000000ULL, 0, 1048576*16, 1,1,1,1,1, 0, 2, 2);
2647     }
2648    
2649    
2650     /*
2651     * Set up Firmware Vectors:
2652     */
2653     add_symbol_name(&machine->symbol_context,
2654     ARC_FIRMWARE_ENTRIES, 0x10000, "[ARCBIOS entry]", 0, 1);
2655    
2656     for (i=0; i<100; i++) {
2657     if (is64bit) {
2658     store_64bit_word(cpu, ARC_FIRMWARE_VECTORS + i*8,
2659     ARC_FIRMWARE_ENTRIES + i*8);
2660     store_64bit_word(cpu, ARC_PRIVATE_VECTORS + i*8,
2661     ARC_PRIVATE_ENTRIES + i*8);
2662     } else {
2663     store_32bit_word(cpu, ARC_FIRMWARE_VECTORS + i*4,
2664     ARC_FIRMWARE_ENTRIES + i*4);
2665     store_32bit_word(cpu, ARC_PRIVATE_VECTORS + i*4,
2666     ARC_PRIVATE_ENTRIES + i*4);
2667     }
2668     }
2669    
2670    
2671     /*
2672     * Set up the ARC SPD:
2673     */
2674     if (is64bit) {
2675     /* ARCS64 SPD (TODO: This is just a guess) */
2676     memset(&arcbios_spb_64, 0, sizeof(arcbios_spb_64));
2677     store_64bit_word_in_host(cpu, (unsigned char *)
2678     &arcbios_spb_64.SPBSignature, ARCBIOS_SPB_SIGNATURE);
2679     store_16bit_word_in_host(cpu, (unsigned char *)
2680     &arcbios_spb_64.Version, 64);
2681     store_16bit_word_in_host(cpu, (unsigned char *)
2682     &arcbios_spb_64.Revision, 0);
2683     store_64bit_word_in_host(cpu, (unsigned char *)
2684     &arcbios_spb_64.FirmwareVector, ARC_FIRMWARE_VECTORS);
2685     store_buf(cpu, SGI_SPB_ADDR, (char *)&arcbios_spb_64,
2686     sizeof(arcbios_spb_64));
2687     } else {
2688     /* ARCBIOS SPB: (For ARC and 32-bit SGI modes) */
2689     memset(&arcbios_spb, 0, sizeof(arcbios_spb));
2690     store_32bit_word_in_host(cpu, (unsigned char *)
2691     &arcbios_spb.SPBSignature, ARCBIOS_SPB_SIGNATURE);
2692     store_32bit_word_in_host(cpu, (unsigned char *)
2693     &arcbios_spb.SPBLength, sizeof(arcbios_spb));
2694     store_16bit_word_in_host(cpu, (unsigned char *)
2695     &arcbios_spb.Version, 1);
2696     store_16bit_word_in_host(cpu, (unsigned char *)
2697     &arcbios_spb.Revision, machine->machine_type ==
2698     MACHINE_SGI? 10 : 2);
2699     store_32bit_word_in_host(cpu, (unsigned char *)
2700     &arcbios_spb.FirmwareVector, ARC_FIRMWARE_VECTORS);
2701     store_32bit_word_in_host(cpu, (unsigned char *)
2702     &arcbios_spb.FirmwareVectorLength, 100 * 4); /* ? */
2703     store_32bit_word_in_host(cpu, (unsigned char *)
2704     &arcbios_spb.PrivateVector, ARC_PRIVATE_VECTORS);
2705     store_32bit_word_in_host(cpu, (unsigned char *)
2706     &arcbios_spb.PrivateVectorLength, 100 * 4); /* ? */
2707     store_buf(cpu, SGI_SPB_ADDR, (char *)&arcbios_spb,
2708     sizeof(arcbios_spb));
2709     }
2710     }
2711    

  ViewVC Help
Powered by ViewVC 1.1.26