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 |
|
|
|