1 |
/* |
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.96 2005/03/20 11:11:39 debug Exp $ |
29 |
* |
30 |
* ARCBIOS emulation. |
31 |
* |
32 |
* This whole file is a mess. |
33 |
* |
34 |
* TODO: Fix. |
35 |
* |
36 |
* TODO: FACTOR OUT COMMON PARTS OF THE 64-bit and 32-bit stuff!! |
37 |
*/ |
38 |
|
39 |
#include <stdio.h> |
40 |
#include <stdlib.h> |
41 |
#include <string.h> |
42 |
#include <time.h> |
43 |
#include <unistd.h> |
44 |
#include <sys/time.h> |
45 |
#include <sys/types.h> |
46 |
#include <sys/resource.h> |
47 |
|
48 |
#include "arcbios.h" |
49 |
#include "console.h" |
50 |
#include "cpu.h" |
51 |
#include "cpu_mips.h" |
52 |
#include "diskimage.h" |
53 |
#include "machine.h" |
54 |
#include "memory.h" |
55 |
#include "misc.h" |
56 |
|
57 |
|
58 |
extern int quiet_mode; |
59 |
|
60 |
|
61 |
/* |
62 |
* TODO: all this should be _per machine_! |
63 |
*/ |
64 |
|
65 |
/* Configuration data: */ |
66 |
#define MAX_CONFIG_DATA 50 |
67 |
static int n_configuration_data = 0; |
68 |
static uint64_t configuration_data_next_addr = ARC_CONFIG_DATA_ADDR; |
69 |
static uint64_t configuration_data_component[MAX_CONFIG_DATA]; |
70 |
static int configuration_data_len[MAX_CONFIG_DATA]; |
71 |
static uint64_t configuration_data_configdata[MAX_CONFIG_DATA]; |
72 |
|
73 |
static int arc_64bit = 0; /* For some SGI modes */ |
74 |
static int arc_wordlen = sizeof(uint32_t); |
75 |
|
76 |
static uint64_t scsicontroller = 0; |
77 |
|
78 |
static int arc_n_memdescriptors = 0; |
79 |
static uint64_t arcbios_memdescriptor_base = ARC_MEMDESC_ADDR; |
80 |
|
81 |
static uint64_t arcbios_next_component_address = FIRST_ARC_COMPONENT; |
82 |
static int n_arc_components = 0; |
83 |
|
84 |
static uint64_t arcbios_console_vram = 0; |
85 |
static uint64_t arcbios_console_ctrlregs = 0; |
86 |
#define MAX_ESC 16 |
87 |
static char arcbios_escape_sequence[MAX_ESC+1]; |
88 |
static int arcbios_in_escape_sequence; |
89 |
static int arcbios_console_maxx, arcbios_console_maxy; |
90 |
int arcbios_console_curx = 0, arcbios_console_cury = 0; |
91 |
static int arcbios_console_reverse = 0; |
92 |
int arcbios_console_curcolor = 0x1f; |
93 |
|
94 |
/* Open file handles: */ |
95 |
#define MAX_OPEN_STRINGLEN 200 |
96 |
#define MAX_HANDLES 10 |
97 |
static int file_handle_in_use[MAX_HANDLES]; |
98 |
static unsigned char *file_handle_string[MAX_HANDLES]; |
99 |
static uint64_t arcbios_current_seek_offset[MAX_HANDLES]; |
100 |
|
101 |
#define MAX_STRING_TO_COMPONENT 20 |
102 |
static char *arcbios_string_to_component[MAX_STRING_TO_COMPONENT]; |
103 |
static uint64_t arcbios_string_to_component_value[MAX_STRING_TO_COMPONENT]; |
104 |
static int arcbios_n_string_to_components = 0; |
105 |
|
106 |
|
107 |
/* |
108 |
* arcbios_add_string_to_component(): |
109 |
*/ |
110 |
void arcbios_add_string_to_component(char *string, uint64_t component) |
111 |
{ |
112 |
if (arcbios_n_string_to_components >= MAX_STRING_TO_COMPONENT) { |
113 |
printf("Too many string-to-component mappings.\n"); |
114 |
exit(1); |
115 |
} |
116 |
|
117 |
arcbios_string_to_component[arcbios_n_string_to_components] = |
118 |
strdup(string); |
119 |
if (arcbios_string_to_component[arcbios_n_string_to_components] == |
120 |
NULL) { |
121 |
fprintf(stderr, "out of memory in " |
122 |
"arcbios_add_string_to_component()\n"); |
123 |
exit(1); |
124 |
} |
125 |
debug("adding ARC component mapping: 0x%08x = %s\n", |
126 |
(int)component, string); |
127 |
|
128 |
arcbios_string_to_component_value[arcbios_n_string_to_components] = |
129 |
component; |
130 |
arcbios_n_string_to_components ++; |
131 |
} |
132 |
|
133 |
|
134 |
/* |
135 |
* arcbios_get_dsp_stat(): |
136 |
* |
137 |
* Fills in an arcbios_dsp_stat struct with valid data. |
138 |
*/ |
139 |
void arcbios_get_dsp_stat(struct cpu *cpu, struct arcbios_dsp_stat *dspstat) |
140 |
{ |
141 |
memset(dspstat, 0, sizeof(struct arcbios_dsp_stat)); |
142 |
|
143 |
store_16bit_word_in_host(cpu, (unsigned char *)&dspstat-> |
144 |
CursorXPosition, arcbios_console_curx + 1); |
145 |
store_16bit_word_in_host(cpu, (unsigned char *)&dspstat-> |
146 |
CursorYPosition, arcbios_console_cury + 1); |
147 |
store_16bit_word_in_host(cpu, (unsigned char *)&dspstat-> |
148 |
CursorMaxXPosition, ARC_CONSOLE_MAX_X); |
149 |
store_16bit_word_in_host(cpu, (unsigned char *)&dspstat-> |
150 |
CursorMaxYPosition, ARC_CONSOLE_MAX_Y); |
151 |
dspstat->ForegroundColor = arcbios_console_curcolor; |
152 |
dspstat->HighIntensity = arcbios_console_curcolor ^ 0x08; |
153 |
} |
154 |
|
155 |
|
156 |
/* |
157 |
* arcbios_putcell(): |
158 |
*/ |
159 |
static void arcbios_putcell(struct cpu *cpu, int ch, int x, int y) |
160 |
{ |
161 |
unsigned char buf[2]; |
162 |
buf[0] = ch; |
163 |
buf[1] = arcbios_console_curcolor; |
164 |
if (arcbios_console_reverse) |
165 |
buf[1] = ((buf[1] & 0x70) >> 4) | ((buf[1] & 7) << 4) |
166 |
| (buf[1] & 0x88); |
167 |
cpu->memory_rw(cpu, cpu->mem, arcbios_console_vram + |
168 |
2*(x + arcbios_console_maxx * y), |
169 |
&buf[0], sizeof(buf), MEM_WRITE, |
170 |
CACHE_NONE | PHYSICAL); |
171 |
} |
172 |
|
173 |
|
174 |
/* |
175 |
* arcbios_console_init(): |
176 |
* |
177 |
* Called from machine.c whenever an ARC-based machine is running with |
178 |
* a graphical VGA-style framebuffer, which can be used as console. |
179 |
*/ |
180 |
void arcbios_console_init(struct cpu *cpu, |
181 |
uint64_t vram, uint64_t ctrlregs, int maxx, int maxy) |
182 |
{ |
183 |
int x, y; |
184 |
|
185 |
arcbios_console_vram = vram; |
186 |
arcbios_console_ctrlregs = ctrlregs; |
187 |
arcbios_console_maxx = maxx; |
188 |
arcbios_console_maxy = maxy; |
189 |
arcbios_in_escape_sequence = 0; |
190 |
arcbios_escape_sequence[0] = '\0'; |
191 |
arcbios_console_curcolor = 0x1f; |
192 |
|
193 |
for (y=1; y<arcbios_console_maxy; y++) |
194 |
for (x=0; x<arcbios_console_maxx; x++) |
195 |
arcbios_putcell(cpu, ' ', x, y); |
196 |
|
197 |
arcbios_console_curx = 0; |
198 |
arcbios_console_cury = 1; |
199 |
} |
200 |
|
201 |
|
202 |
/* |
203 |
* handle_esc_seq(): |
204 |
* |
205 |
* Used by arcbios_putchar(). |
206 |
*/ |
207 |
static void handle_esc_seq(struct cpu *cpu) |
208 |
{ |
209 |
int i, len = strlen(arcbios_escape_sequence); |
210 |
int row, col, color, code, start, stop; |
211 |
char *p; |
212 |
|
213 |
if (arcbios_escape_sequence[0] != '[') |
214 |
return; |
215 |
|
216 |
code = arcbios_escape_sequence[len-1]; |
217 |
arcbios_escape_sequence[len-1] = '\0'; |
218 |
|
219 |
switch (code) { |
220 |
case 'm': |
221 |
color = atoi(arcbios_escape_sequence + 1); |
222 |
switch (color) { |
223 |
case 0: /* Default. */ |
224 |
arcbios_console_curcolor = 0x1f; |
225 |
arcbios_console_reverse = 0; break; |
226 |
case 1: /* "Bold". */ |
227 |
arcbios_console_curcolor |= 0x08; break; |
228 |
case 7: /* "Reverse". */ |
229 |
arcbios_console_reverse = 1; break; |
230 |
case 30: /* Black foreground. */ |
231 |
arcbios_console_curcolor &= 0xf0; |
232 |
arcbios_console_curcolor |= 0x00; break; |
233 |
case 31: /* Red foreground. */ |
234 |
arcbios_console_curcolor &= 0xf0; |
235 |
arcbios_console_curcolor |= 0x04; break; |
236 |
case 32: /* Green foreground. */ |
237 |
arcbios_console_curcolor &= 0xf0; |
238 |
arcbios_console_curcolor |= 0x02; break; |
239 |
case 33: /* Yellow foreground. */ |
240 |
arcbios_console_curcolor &= 0xf0; |
241 |
arcbios_console_curcolor |= 0x06; break; |
242 |
case 34: /* Blue foreground. */ |
243 |
arcbios_console_curcolor &= 0xf0; |
244 |
arcbios_console_curcolor |= 0x01; break; |
245 |
case 35: /* Red-blue foreground. */ |
246 |
arcbios_console_curcolor &= 0xf0; |
247 |
arcbios_console_curcolor |= 0x05; break; |
248 |
case 36: /* Green-blue foreground. */ |
249 |
arcbios_console_curcolor &= 0xf0; |
250 |
arcbios_console_curcolor |= 0x03; break; |
251 |
case 37: /* White foreground. */ |
252 |
arcbios_console_curcolor &= 0xf0; |
253 |
arcbios_console_curcolor |= 0x07; break; |
254 |
case 40: /* Black background. */ |
255 |
arcbios_console_curcolor &= 0x0f; |
256 |
arcbios_console_curcolor |= 0x00; break; |
257 |
case 41: /* Red background. */ |
258 |
arcbios_console_curcolor &= 0x0f; |
259 |
arcbios_console_curcolor |= 0x40; break; |
260 |
case 42: /* Green background. */ |
261 |
arcbios_console_curcolor &= 0x0f; |
262 |
arcbios_console_curcolor |= 0x20; break; |
263 |
case 43: /* Yellow background. */ |
264 |
arcbios_console_curcolor &= 0x0f; |
265 |
arcbios_console_curcolor |= 0x60; break; |
266 |
case 44: /* Blue background. */ |
267 |
arcbios_console_curcolor &= 0x0f; |
268 |
arcbios_console_curcolor |= 0x10; break; |
269 |
case 45: /* Red-blue background. */ |
270 |
arcbios_console_curcolor &= 0x0f; |
271 |
arcbios_console_curcolor |= 0x50; break; |
272 |
case 46: /* Green-blue background. */ |
273 |
arcbios_console_curcolor &= 0x0f; |
274 |
arcbios_console_curcolor |= 0x30; break; |
275 |
case 47: /* White background. */ |
276 |
arcbios_console_curcolor &= 0x0f; |
277 |
arcbios_console_curcolor |= 0x70; break; |
278 |
default:fatal("{ handle_esc_seq: color %i }\n", color); |
279 |
} |
280 |
return; |
281 |
case 'H': |
282 |
p = strchr(arcbios_escape_sequence, ';'); |
283 |
if (p == NULL) |
284 |
return; /* TODO */ |
285 |
row = atoi(arcbios_escape_sequence + 1); |
286 |
col = atoi(p + 1); |
287 |
if (col < 1) |
288 |
col = 1; |
289 |
if (row < 1) |
290 |
row = 1; |
291 |
arcbios_console_curx = col - 1; |
292 |
arcbios_console_cury = row - 1; |
293 |
return; |
294 |
case 'J': |
295 |
/* |
296 |
* J = clear screen below cursor, and the rest of the |
297 |
* current line, |
298 |
* 2J = clear whole screen. |
299 |
*/ |
300 |
i = atoi(arcbios_escape_sequence + 1); |
301 |
if (i != 0 && i != 2) |
302 |
fatal("{ handle_esc_seq(): %iJ }\n", i); |
303 |
if (i == 0) |
304 |
for (col = arcbios_console_curx; |
305 |
col < arcbios_console_maxx; col++) |
306 |
arcbios_putcell(cpu, ' ', col, |
307 |
arcbios_console_cury); |
308 |
for (col = 0; col < arcbios_console_maxx; col++) |
309 |
for (row = i? 0 : arcbios_console_cury+1; |
310 |
row < arcbios_console_maxy; row++) |
311 |
arcbios_putcell(cpu, ' ', col, row); |
312 |
return; |
313 |
case 'K': |
314 |
col = atoi(arcbios_escape_sequence + 1); |
315 |
/* 2 = clear line to the right. 1 = to the left (?) */ |
316 |
start = 0; stop = arcbios_console_curx; |
317 |
if (col == 2) { |
318 |
start = arcbios_console_curx; |
319 |
stop = arcbios_console_maxx-1; |
320 |
} |
321 |
for (i=start; i<=stop; i++) |
322 |
arcbios_putcell(cpu, ' ', i, arcbios_console_cury); |
323 |
|
324 |
return; |
325 |
} |
326 |
|
327 |
fatal("{ handle_esc_seq(): unimplemented escape sequence: "); |
328 |
for (i=0; i<len; i++) { |
329 |
int x = arcbios_escape_sequence[i]; |
330 |
if (i == len-1) |
331 |
x = code; |
332 |
|
333 |
if (x >= ' ' && x < 127) |
334 |
fatal("%c", x); |
335 |
else |
336 |
fatal("[0x%02x]", x); |
337 |
} |
338 |
fatal(" }\n"); |
339 |
} |
340 |
|
341 |
|
342 |
/* |
343 |
* scroll_if_necessary(): |
344 |
*/ |
345 |
static void scroll_if_necessary(struct cpu *cpu) |
346 |
{ |
347 |
/* Scroll? */ |
348 |
if (arcbios_console_cury >= arcbios_console_maxy) { |
349 |
unsigned char buf[2]; |
350 |
int x, y; |
351 |
for (y=0; y<arcbios_console_maxy-1; y++) |
352 |
for (x=0; x<arcbios_console_maxx; x++) { |
353 |
cpu->memory_rw(cpu, cpu->mem, |
354 |
arcbios_console_vram + |
355 |
2*(x + arcbios_console_maxx * (y+1)), |
356 |
&buf[0], sizeof(buf), MEM_READ, |
357 |
CACHE_NONE | PHYSICAL); |
358 |
cpu->memory_rw(cpu, cpu->mem, |
359 |
arcbios_console_vram + |
360 |
2*(x + arcbios_console_maxx * y), |
361 |
&buf[0], sizeof(buf), MEM_WRITE, |
362 |
CACHE_NONE | PHYSICAL); |
363 |
} |
364 |
|
365 |
arcbios_console_cury = arcbios_console_maxy - 1; |
366 |
|
367 |
for (x=0; x<arcbios_console_maxx; x++) |
368 |
arcbios_putcell(cpu, ' ', x, arcbios_console_cury); |
369 |
} |
370 |
} |
371 |
|
372 |
|
373 |
/* |
374 |
* arcbios_putchar(): |
375 |
* |
376 |
* If we're using X11 with VGA-style console, then output to that console. |
377 |
* Otherwise, use console_putchar(). |
378 |
*/ |
379 |
static void arcbios_putchar(struct cpu *cpu, int ch) |
380 |
{ |
381 |
int addr; |
382 |
unsigned char byte; |
383 |
|
384 |
if (!cpu->machine->use_x11) { |
385 |
/* Text console output: */ |
386 |
|
387 |
/* Hack for Windows NT, which uses 0x9b instead of ESC + [ */ |
388 |
if (ch == 0x9b) { |
389 |
console_putchar(cpu->machine->main_console_handle, 27); |
390 |
ch = '['; |
391 |
} |
392 |
console_putchar(cpu->machine->main_console_handle, ch); |
393 |
return; |
394 |
} |
395 |
|
396 |
if (arcbios_in_escape_sequence) { |
397 |
int len = strlen(arcbios_escape_sequence); |
398 |
arcbios_escape_sequence[len] = ch; |
399 |
len++; |
400 |
if (len >= MAX_ESC) |
401 |
len = MAX_ESC; |
402 |
arcbios_escape_sequence[len] = '\0'; |
403 |
if ((ch >= 'a' && ch <= 'z') || |
404 |
(ch >= 'A' && ch <= 'Z') || len >= MAX_ESC) { |
405 |
handle_esc_seq(cpu); |
406 |
arcbios_in_escape_sequence = 0; |
407 |
} |
408 |
} else { |
409 |
if (ch == 27) { |
410 |
arcbios_in_escape_sequence = 1; |
411 |
arcbios_escape_sequence[0] = '\0'; |
412 |
} else if (ch == 0x9b) { |
413 |
arcbios_in_escape_sequence = 1; |
414 |
arcbios_escape_sequence[0] = '['; |
415 |
arcbios_escape_sequence[1] = '\0'; |
416 |
} else if (ch == '\b') { |
417 |
if (arcbios_console_curx > 0) |
418 |
arcbios_console_curx --; |
419 |
} else if (ch == '\r') { |
420 |
arcbios_console_curx = 0; |
421 |
} else if (ch == '\n') { |
422 |
arcbios_console_cury ++; |
423 |
} else if (ch == '\t') { |
424 |
arcbios_console_curx = |
425 |
((arcbios_console_curx - 1) | 7) + 1; |
426 |
/* TODO: Print spaces? */ |
427 |
} else { |
428 |
/* Put char: */ |
429 |
if (arcbios_console_curx >= arcbios_console_maxx) { |
430 |
arcbios_console_curx = 0; |
431 |
arcbios_console_cury ++; |
432 |
scroll_if_necessary(cpu); |
433 |
} |
434 |
arcbios_putcell(cpu, ch, arcbios_console_curx, |
435 |
arcbios_console_cury); |
436 |
arcbios_console_curx ++; |
437 |
} |
438 |
} |
439 |
|
440 |
scroll_if_necessary(cpu); |
441 |
|
442 |
/* Update cursor position: */ |
443 |
addr = (arcbios_console_curx >= arcbios_console_maxx? |
444 |
arcbios_console_maxx-1 : arcbios_console_curx) + |
445 |
arcbios_console_cury * arcbios_console_maxx; |
446 |
byte = 0x0e; |
447 |
cpu->memory_rw(cpu, cpu->mem, arcbios_console_ctrlregs + 0x14, |
448 |
&byte, sizeof(byte), MEM_WRITE, CACHE_NONE | PHYSICAL); |
449 |
byte = (addr >> 8) & 255; |
450 |
cpu->memory_rw(cpu, cpu->mem, arcbios_console_ctrlregs + 0x15, |
451 |
&byte, sizeof(byte), MEM_WRITE, CACHE_NONE | PHYSICAL); |
452 |
byte = 0x0f; |
453 |
cpu->memory_rw(cpu, cpu->mem, arcbios_console_ctrlregs + 0x14, |
454 |
&byte, sizeof(byte), MEM_WRITE, CACHE_NONE | PHYSICAL); |
455 |
byte = addr & 255; |
456 |
cpu->memory_rw(cpu, cpu->mem, arcbios_console_ctrlregs + 0x15, |
457 |
&byte, sizeof(byte), MEM_WRITE, CACHE_NONE | PHYSICAL); |
458 |
} |
459 |
|
460 |
|
461 |
/* |
462 |
* arcbios_register_scsicontroller(): |
463 |
*/ |
464 |
void arcbios_register_scsicontroller(uint64_t scsicontroller_component) |
465 |
{ |
466 |
scsicontroller = scsicontroller_component; |
467 |
} |
468 |
|
469 |
|
470 |
/* |
471 |
* arcbios_get_scsicontroller(): |
472 |
*/ |
473 |
uint64_t arcbios_get_scsicontroller(void) |
474 |
{ |
475 |
return scsicontroller; |
476 |
} |
477 |
|
478 |
|
479 |
/* |
480 |
* arcbios_add_memory_descriptor(): |
481 |
* |
482 |
* NOTE: arctype is the ARC type, not the SGI type. This function takes |
483 |
* care of converting, when necessary. |
484 |
*/ |
485 |
void arcbios_add_memory_descriptor(struct cpu *cpu, |
486 |
uint64_t base, uint64_t len, int arctype) |
487 |
{ |
488 |
uint64_t memdesc_addr; |
489 |
int s; |
490 |
struct arcbios_mem arcbios_mem; |
491 |
struct arcbios_mem64 arcbios_mem64; |
492 |
|
493 |
base /= 4096; |
494 |
len /= 4096; |
495 |
|
496 |
/* |
497 |
* TODO: Huh? Why isn't it necessary to convert from arc to sgi types? |
498 |
* |
499 |
* TODO 2: It seems that it _is_ neccessary, but NetBSD's arcdiag |
500 |
* doesn't handle the sgi case separately. |
501 |
*/ |
502 |
#if 1 |
503 |
if (cpu->machine->machine_type == MACHINE_SGI) { |
504 |
/* arctype is SGI style */ |
505 |
/* printf("%i => ", arctype); */ |
506 |
switch (arctype) { |
507 |
case 0: arctype = 0; break; |
508 |
case 1: arctype = 1; break; |
509 |
case 2: arctype = 3; break; |
510 |
case 3: arctype = 4; break; |
511 |
case 4: arctype = 5; break; |
512 |
case 5: arctype = 6; break; |
513 |
case 6: arctype = 7; break; |
514 |
case 7: arctype = 2; break; |
515 |
} |
516 |
/* printf("%i\n", arctype); */ |
517 |
} |
518 |
#endif |
519 |
if (arc_64bit) |
520 |
s = sizeof(arcbios_mem64); |
521 |
else |
522 |
s = sizeof(arcbios_mem); |
523 |
|
524 |
memdesc_addr = arcbios_memdescriptor_base + |
525 |
arc_n_memdescriptors * s; |
526 |
|
527 |
if (arc_64bit) { |
528 |
memset(&arcbios_mem64, 0, s); |
529 |
store_32bit_word_in_host(cpu, |
530 |
(unsigned char *)&arcbios_mem64.Type, arctype); |
531 |
store_64bit_word_in_host(cpu, |
532 |
(unsigned char *)&arcbios_mem64.BasePage, base); |
533 |
store_64bit_word_in_host(cpu, |
534 |
(unsigned char *)&arcbios_mem64.PageCount, len); |
535 |
store_buf(cpu, memdesc_addr, (char *)&arcbios_mem64, s); |
536 |
} else { |
537 |
memset(&arcbios_mem, 0, s); |
538 |
store_32bit_word_in_host(cpu, |
539 |
(unsigned char *)&arcbios_mem.Type, arctype); |
540 |
store_32bit_word_in_host(cpu, |
541 |
(unsigned char *)&arcbios_mem.BasePage, base); |
542 |
store_32bit_word_in_host(cpu, |
543 |
(unsigned char *)&arcbios_mem.PageCount, len); |
544 |
store_buf(cpu, memdesc_addr, (char *)&arcbios_mem, s); |
545 |
} |
546 |
|
547 |
arc_n_memdescriptors ++; |
548 |
} |
549 |
|
550 |
|
551 |
/* |
552 |
* arcbios_addchild(): |
553 |
* |
554 |
* host_tmp_component is a temporary component, with data formated for |
555 |
* the host system. It needs to be translated/copied into emulated RAM. |
556 |
* |
557 |
* Return value is the virtual (emulated) address of the added component. |
558 |
* |
559 |
* TODO: This function doesn't care about memory management, but simply |
560 |
* stores the new child after the last stored child. |
561 |
* TODO: This stuff is really ugly. |
562 |
*/ |
563 |
static uint64_t arcbios_addchild(struct cpu *cpu, |
564 |
struct arcbios_component *host_tmp_component, |
565 |
char *identifier, uint32_t parent) |
566 |
{ |
567 |
uint64_t a = arcbios_next_component_address; |
568 |
uint32_t peer=0; |
569 |
uint32_t child=0; |
570 |
int n_left; |
571 |
uint64_t peeraddr = FIRST_ARC_COMPONENT; |
572 |
|
573 |
/* |
574 |
* This component has no children yet, but it may have peers (that is, |
575 |
* other components that share this component's parent) so we have to |
576 |
* set the peer value correctly. |
577 |
* |
578 |
* Also, if this is the first child of some parent, the parent's child |
579 |
* pointer should be set to point to this component. (But only if it |
580 |
* is the first.) |
581 |
* |
582 |
* This is really ugly: scan through all components, starting from |
583 |
* FIRST_ARC_COMPONENT, to find a component with the same parent as |
584 |
* this component will have. If such a component is found, and its |
585 |
* 'peer' value is NULL, then set it to this component's address (a). |
586 |
* |
587 |
* TODO: make this nicer |
588 |
*/ |
589 |
|
590 |
n_left = n_arc_components; |
591 |
while (n_left > 0) { |
592 |
/* Load parent, child, and peer values: */ |
593 |
uint32_t eparent, echild, epeer, tmp; |
594 |
unsigned char buf[4]; |
595 |
|
596 |
/* debug("[ addchild: peeraddr = 0x%08x ]\n", |
597 |
(int)peeraddr); */ |
598 |
|
599 |
cpu->memory_rw(cpu, cpu->mem, |
600 |
peeraddr + 0 * arc_wordlen, &buf[0], sizeof(eparent), |
601 |
MEM_READ, CACHE_NONE); |
602 |
if (cpu->byte_order == EMUL_BIG_ENDIAN) { |
603 |
unsigned char tmp; |
604 |
tmp = buf[0]; buf[0] = buf[3]; buf[3] = tmp; |
605 |
tmp = buf[1]; buf[1] = buf[2]; buf[2] = tmp; |
606 |
} |
607 |
epeer = buf[0] + (buf[1]<<8) + (buf[2]<<16) + (buf[3]<<24); |
608 |
|
609 |
cpu->memory_rw(cpu, cpu->mem, peeraddr + 1 * arc_wordlen, |
610 |
&buf[0], sizeof(eparent), MEM_READ, CACHE_NONE); |
611 |
if (cpu->byte_order == EMUL_BIG_ENDIAN) { |
612 |
unsigned char tmp; tmp = buf[0]; |
613 |
buf[0] = buf[3]; buf[3] = tmp; |
614 |
tmp = buf[1]; buf[1] = buf[2]; buf[2] = tmp; |
615 |
} |
616 |
echild = buf[0] + (buf[1]<<8) + (buf[2]<<16) + (buf[3]<<24); |
617 |
|
618 |
cpu->memory_rw(cpu, cpu->mem, peeraddr + 2 * arc_wordlen, |
619 |
&buf[0], sizeof(eparent), MEM_READ, CACHE_NONE); |
620 |
if (cpu->byte_order == EMUL_BIG_ENDIAN) { |
621 |
unsigned char tmp; tmp = buf[0]; |
622 |
buf[0] = buf[3]; buf[3] = tmp; |
623 |
tmp = buf[1]; buf[1] = buf[2]; buf[2] = tmp; |
624 |
} |
625 |
eparent = buf[0] + (buf[1]<<8) + (buf[2]<<16) + (buf[3]<<24); |
626 |
|
627 |
/* debug(" epeer=%x echild=%x eparent=%x\n", |
628 |
(int)epeer,(int)echild,(int)eparent); */ |
629 |
|
630 |
if ((uint32_t)eparent == (uint32_t)parent && |
631 |
(uint32_t)epeer == 0) { |
632 |
epeer = a; |
633 |
store_32bit_word(cpu, peeraddr + 0x00, epeer); |
634 |
/* debug("[ addchild: adding 0x%08x as peer " |
635 |
"to 0x%08x ]\n", (int)a, (int)peeraddr); */ |
636 |
} |
637 |
if ((uint32_t)peeraddr == (uint32_t)parent && |
638 |
(uint32_t)echild == 0) { |
639 |
echild = a; |
640 |
store_32bit_word(cpu, peeraddr + 0x04, echild); |
641 |
/* debug("[ addchild: adding 0x%08x as " |
642 |
"child to 0x%08x ]\n", (int)a, (int)peeraddr); */ |
643 |
} |
644 |
|
645 |
/* Go to the next component: */ |
646 |
cpu->memory_rw(cpu, cpu->mem, peeraddr + 0x28, &buf[0], |
647 |
sizeof(eparent), MEM_READ, CACHE_NONE); |
648 |
if (cpu->byte_order == EMUL_BIG_ENDIAN) { |
649 |
unsigned char tmp; tmp = buf[0]; |
650 |
buf[0] = buf[3]; buf[3] = tmp; |
651 |
tmp = buf[1]; buf[1] = buf[2]; buf[2] = tmp; |
652 |
} |
653 |
tmp = buf[0] + (buf[1]<<8) + (buf[2]<<16) + (buf[3]<<24); |
654 |
peeraddr += 0x30; |
655 |
peeraddr += tmp + 1; |
656 |
peeraddr = ((peeraddr - 1) | 3) + 1; |
657 |
|
658 |
n_left --; |
659 |
} |
660 |
|
661 |
store_32bit_word(cpu, a + 0x00, peer); |
662 |
store_32bit_word(cpu, a + 0x04, child); |
663 |
store_32bit_word(cpu, a + 0x08, parent); |
664 |
store_32bit_word(cpu, a+ 0x0c, host_tmp_component->Class); |
665 |
store_32bit_word(cpu, a+ 0x10, host_tmp_component->Type); |
666 |
store_32bit_word(cpu, a+ 0x14, host_tmp_component->Flags + |
667 |
65536 * host_tmp_component->Version); |
668 |
store_32bit_word(cpu, a+ 0x18, host_tmp_component->Revision); |
669 |
store_32bit_word(cpu, a+ 0x1c, host_tmp_component->Key); |
670 |
store_32bit_word(cpu, a+ 0x20, host_tmp_component->AffinityMask); |
671 |
store_32bit_word(cpu, a+ 0x24, host_tmp_component-> |
672 |
ConfigurationDataSize); |
673 |
store_32bit_word(cpu, a+ 0x28, host_tmp_component->IdentifierLength); |
674 |
store_32bit_word(cpu, a+ 0x2c, host_tmp_component->Identifier); |
675 |
|
676 |
arcbios_next_component_address += 0x30; |
677 |
|
678 |
if (host_tmp_component->IdentifierLength != 0) { |
679 |
store_32bit_word(cpu, a + 0x2c, a + 0x30); |
680 |
store_string(cpu, a + 0x30, identifier); |
681 |
if (identifier != NULL) |
682 |
arcbios_next_component_address += |
683 |
strlen(identifier) + 1; |
684 |
} |
685 |
|
686 |
arcbios_next_component_address ++; |
687 |
|
688 |
/* Round up to next 0x4 bytes: */ |
689 |
arcbios_next_component_address = |
690 |
((arcbios_next_component_address - 1) | 3) + 1; |
691 |
|
692 |
n_arc_components ++; |
693 |
|
694 |
return a; |
695 |
} |
696 |
|
697 |
|
698 |
/* |
699 |
* arcbios_addchild64(): |
700 |
* |
701 |
* host_tmp_component is a temporary component, with data formated for |
702 |
* the host system. It needs to be translated/copied into emulated RAM. |
703 |
* |
704 |
* Return value is the virtual (emulated) address of the added component. |
705 |
* |
706 |
* TODO: This function doesn't care about memory management, but simply |
707 |
* stores the new child after the last stored child. |
708 |
* TODO: This stuff is really ugly. |
709 |
*/ |
710 |
static uint64_t arcbios_addchild64(struct cpu *cpu, |
711 |
struct arcbios_component64 *host_tmp_component, |
712 |
char *identifier, uint64_t parent) |
713 |
{ |
714 |
uint64_t a = arcbios_next_component_address; |
715 |
uint64_t peer=0; |
716 |
uint64_t child=0; |
717 |
int n_left; |
718 |
uint64_t peeraddr = FIRST_ARC_COMPONENT; |
719 |
|
720 |
/* |
721 |
* This component has no children yet, but it may have peers (that is, |
722 |
* other components that share this component's parent) so we have to |
723 |
* set the peer value correctly. |
724 |
* |
725 |
* Also, if this is the first child of some parent, the parent's child |
726 |
* pointer should be set to point to this component. (But only if it |
727 |
* is the first.) |
728 |
* |
729 |
* This is really ugly: scan through all components, starting from |
730 |
* FIRST_ARC_COMPONENT, to find a component with the same parent as |
731 |
* this component will have. If such a component is found, and its |
732 |
* 'peer' value is NULL, then set it to this component's address (a). |
733 |
* |
734 |
* TODO: make this nicer |
735 |
*/ |
736 |
|
737 |
n_left = n_arc_components; |
738 |
while (n_left > 0) { |
739 |
/* Load parent, child, and peer values: */ |
740 |
uint64_t eparent, echild, epeer, tmp; |
741 |
unsigned char buf[8]; |
742 |
|
743 |
/* debug("[ addchild: peeraddr = 0x%016llx ]\n", |
744 |
(long long)peeraddr); */ |
745 |
|
746 |
cpu->memory_rw(cpu, cpu->mem, |
747 |
peeraddr + 0 * arc_wordlen, &buf[0], sizeof(eparent), |
748 |
MEM_READ, CACHE_NONE); |
749 |
if (cpu->byte_order == EMUL_BIG_ENDIAN) { |
750 |
unsigned char tmp; |
751 |
tmp = buf[0]; buf[0] = buf[7]; buf[7] = tmp; |
752 |
tmp = buf[1]; buf[1] = buf[6]; buf[6] = tmp; |
753 |
tmp = buf[2]; buf[2] = buf[5]; buf[5] = tmp; |
754 |
tmp = buf[3]; buf[3] = buf[4]; buf[4] = tmp; |
755 |
} |
756 |
epeer = buf[0] + (buf[1]<<8) + (buf[2]<<16) + (buf[3]<<24) |
757 |
+ ((uint64_t)buf[4] << 32) + ((uint64_t)buf[5] << 40) |
758 |
+ ((uint64_t)buf[6] << 48) + ((uint64_t)buf[7] << 56); |
759 |
|
760 |
cpu->memory_rw(cpu, cpu->mem, peeraddr + 1 * arc_wordlen, |
761 |
&buf[0], sizeof(eparent), MEM_READ, CACHE_NONE); |
762 |
if (cpu->byte_order == EMUL_BIG_ENDIAN) { |
763 |
unsigned char tmp; |
764 |
tmp = buf[0]; buf[0] = buf[7]; buf[7] = tmp; |
765 |
tmp = buf[1]; buf[1] = buf[6]; buf[6] = tmp; |
766 |
tmp = buf[2]; buf[2] = buf[5]; buf[5] = tmp; |
767 |
tmp = buf[3]; buf[3] = buf[4]; buf[4] = tmp; |
768 |
} |
769 |
echild = buf[0] + (buf[1]<<8) + (buf[2]<<16) + (buf[3]<<24) |
770 |
+ ((uint64_t)buf[4] << 32) + ((uint64_t)buf[5] << 40) |
771 |
+ ((uint64_t)buf[6] << 48) + ((uint64_t)buf[7] << 56); |
772 |
|
773 |
cpu->memory_rw(cpu, cpu->mem, peeraddr + 2 * arc_wordlen, |
774 |
&buf[0], sizeof(eparent), MEM_READ, CACHE_NONE); |
775 |
if (cpu->byte_order == EMUL_BIG_ENDIAN) { |
776 |
unsigned char tmp; |
777 |
tmp = buf[0]; buf[0] = buf[7]; buf[7] = tmp; |
778 |
tmp = buf[1]; buf[1] = buf[6]; buf[6] = tmp; |
779 |
tmp = buf[2]; buf[2] = buf[5]; buf[5] = tmp; |
780 |
tmp = buf[3]; buf[3] = buf[4]; buf[4] = tmp; |
781 |
} |
782 |
eparent = buf[0] + (buf[1]<<8) + (buf[2]<<16) + (buf[3]<<24) |
783 |
+ ((uint64_t)buf[4] << 32) + ((uint64_t)buf[5] << 40) |
784 |
+ ((uint64_t)buf[6] << 48) + ((uint64_t)buf[7] << 56); |
785 |
|
786 |
/* debug(" epeer=%llx echild=%llx eparent=%llx\n", |
787 |
(long long)epeer, (long long)echild, |
788 |
(long long)eparent); */ |
789 |
|
790 |
if (eparent == parent && epeer == 0) { |
791 |
epeer = a; |
792 |
store_64bit_word(cpu, peeraddr + 0 * arc_wordlen, |
793 |
epeer); |
794 |
/* debug("[ addchild: adding 0x%016llx as peer " |
795 |
"to 0x%016llx ]\n", (long long)a, |
796 |
(long long)peeraddr); */ |
797 |
} |
798 |
if (peeraddr == parent && echild == 0) { |
799 |
echild = a; |
800 |
store_64bit_word(cpu, peeraddr + 1 * arc_wordlen, |
801 |
echild); |
802 |
/* debug("[ addchild: adding 0x%016llx as child " |
803 |
"to 0x%016llx ]\n", (long long)a, |
804 |
(long long)peeraddr); */ |
805 |
} |
806 |
|
807 |
/* Go to the next component: */ |
808 |
cpu->memory_rw(cpu, cpu->mem, peeraddr + 0x34, |
809 |
&buf[0], sizeof(uint32_t), MEM_READ, CACHE_NONE); |
810 |
if (cpu->byte_order == EMUL_BIG_ENDIAN) { |
811 |
unsigned char tmp; |
812 |
tmp = buf[0]; buf[0] = buf[3]; buf[3] = tmp; |
813 |
tmp = buf[1]; buf[1] = buf[2]; buf[2] = tmp; |
814 |
} |
815 |
tmp = buf[0] + (buf[1]<<8) + (buf[2]<<16) + (buf[3]<<24); |
816 |
|
817 |
tmp &= 0xfffff; |
818 |
|
819 |
peeraddr += 0x50; |
820 |
peeraddr += tmp + 1; |
821 |
peeraddr = ((peeraddr - 1) | 3) + 1; |
822 |
|
823 |
n_left --; |
824 |
} |
825 |
|
826 |
store_64bit_word(cpu, a + 0x00, peer); |
827 |
store_64bit_word(cpu, a + 0x08, child); |
828 |
store_64bit_word(cpu, a + 0x10, parent); |
829 |
store_32bit_word(cpu, a+ 0x18, host_tmp_component->Class); |
830 |
store_32bit_word(cpu, a+ 0x1c, host_tmp_component->Type); |
831 |
store_32bit_word(cpu, a+ 0x20, host_tmp_component->Flags); |
832 |
store_32bit_word(cpu, a+ 0x24, host_tmp_component->Version + |
833 |
((uint64_t)host_tmp_component->Revision << 16)); |
834 |
store_32bit_word(cpu, a+ 0x28, host_tmp_component->Key); |
835 |
store_64bit_word(cpu, a+ 0x30, host_tmp_component->AffinityMask); |
836 |
store_64bit_word(cpu, a+ 0x38, host_tmp_component-> |
837 |
ConfigurationDataSize); |
838 |
store_64bit_word(cpu, a+ 0x40, host_tmp_component->IdentifierLength); |
839 |
store_64bit_word(cpu, a+ 0x48, host_tmp_component->Identifier); |
840 |
|
841 |
/* TODO: Find out how a REAL ARCS64 implementation does it. */ |
842 |
|
843 |
arcbios_next_component_address += 0x50; |
844 |
|
845 |
if (host_tmp_component->IdentifierLength != 0) { |
846 |
store_64bit_word(cpu, a + 0x48, a + 0x50); |
847 |
store_string(cpu, a + 0x50, identifier); |
848 |
if (identifier != NULL) |
849 |
arcbios_next_component_address += |
850 |
strlen(identifier) + 1; |
851 |
} |
852 |
|
853 |
arcbios_next_component_address ++; |
854 |
|
855 |
/* Round up to next 0x8 bytes: */ |
856 |
arcbios_next_component_address = |
857 |
((arcbios_next_component_address - 1) | 7) + 1; |
858 |
|
859 |
n_arc_components ++; |
860 |
return a; |
861 |
} |
862 |
|
863 |
|
864 |
/* |
865 |
* arcbios_addchild_manual(): |
866 |
* |
867 |
* Used internally to set up component structures. |
868 |
* Parent may only be NULL for the first (system) component. |
869 |
* |
870 |
* Return value is the virtual (emulated) address of the added component. |
871 |
*/ |
872 |
uint64_t arcbios_addchild_manual(struct cpu *cpu, |
873 |
uint64_t class, uint64_t type, uint64_t flags, |
874 |
uint64_t version, uint64_t revision, uint64_t key, |
875 |
uint64_t affinitymask, char *identifier, uint64_t parent, |
876 |
void *config_data, size_t config_len) |
877 |
{ |
878 |
/* This component is only for temporary use: */ |
879 |
struct arcbios_component component; |
880 |
struct arcbios_component64 component64; |
881 |
|
882 |
if (config_data != NULL) { |
883 |
unsigned char *p = config_data; |
884 |
int i; |
885 |
|
886 |
if (n_configuration_data >= MAX_CONFIG_DATA) { |
887 |
printf("fatal error: you need to increase " |
888 |
"MAX_CONFIG_DATA\n"); |
889 |
exit(1); |
890 |
} |
891 |
|
892 |
for (i=0; i<config_len; i++) { |
893 |
unsigned char ch = p[i]; |
894 |
cpu->memory_rw(cpu, cpu->mem, |
895 |
configuration_data_next_addr + i, |
896 |
&ch, 1, MEM_WRITE, CACHE_NONE); |
897 |
} |
898 |
|
899 |
configuration_data_len[n_configuration_data] = config_len; |
900 |
configuration_data_configdata[n_configuration_data] = |
901 |
configuration_data_next_addr; |
902 |
configuration_data_next_addr += config_len; |
903 |
configuration_data_component[n_configuration_data] = |
904 |
arcbios_next_component_address + (arc_64bit? 0x18 : 0x0c); |
905 |
|
906 |
/* printf("& ADDING %i: configdata=0x%016llx " |
907 |
"component=0x%016llx\n", n_configuration_data, |
908 |
(long long)configuration_data_configdata[ |
909 |
n_configuration_data], |
910 |
(long long)configuration_data_component[ |
911 |
n_configuration_data]); */ |
912 |
|
913 |
n_configuration_data ++; |
914 |
} |
915 |
|
916 |
if (!arc_64bit) { |
917 |
component.Class = class; |
918 |
component.Type = type; |
919 |
component.Flags = flags; |
920 |
component.Version = version; |
921 |
component.Revision = revision; |
922 |
component.Key = key; |
923 |
component.AffinityMask = affinitymask; |
924 |
component.ConfigurationDataSize = config_len; |
925 |
component.IdentifierLength = 0; |
926 |
component.Identifier = 0; |
927 |
if (identifier != NULL) { |
928 |
component.IdentifierLength = strlen(identifier) + 1; |
929 |
} |
930 |
return arcbios_addchild(cpu, &component, identifier, parent); |
931 |
} else { |
932 |
component64.Class = class; |
933 |
component64.Type = type; |
934 |
component64.Flags = flags; |
935 |
component64.Version = version; |
936 |
component64.Revision = revision; |
937 |
component64.Key = key; |
938 |
component64.AffinityMask = affinitymask; |
939 |
component64.ConfigurationDataSize = config_len; |
940 |
component64.IdentifierLength = 0; |
941 |
component64.Identifier = 0; |
942 |
if (identifier != NULL) { |
943 |
component64.IdentifierLength = strlen(identifier) + 1; |
944 |
} |
945 |
return arcbios_addchild64(cpu, &component64, identifier, |
946 |
parent); |
947 |
} |
948 |
} |
949 |
|
950 |
|
951 |
/* |
952 |
* arcbios_get_msdos_partition_size(): |
953 |
* |
954 |
* This function tries to parse MSDOS-style partition tables on a disk |
955 |
* image, and return the starting offset (counted in bytes), and the |
956 |
* size, of a specific partition. |
957 |
* |
958 |
* NOTE: partition_nr is 1-based! |
959 |
* |
960 |
* TODO: This is buggy, it doesn't really handle extended partitions. |
961 |
* |
962 |
* See http://www.nondot.org/sabre/os/files/Partitions/Partitions.html |
963 |
* for more info. |
964 |
*/ |
965 |
static void arcbios_get_msdos_partition_size(struct machine *machine, |
966 |
int scsi_id, int partition_nr, uint64_t *start, uint64_t *size) |
967 |
{ |
968 |
int res, i, partition_type, cur_partition = 0; |
969 |
unsigned char sector[512]; |
970 |
unsigned char buf[16]; |
971 |
uint64_t offset = 0, st; |
972 |
|
973 |
/* Partition 0 is the entire disk image: */ |
974 |
*start = 0; |
975 |
*size = diskimage_getsize(machine, scsi_id); |
976 |
if (partition_nr == 0) |
977 |
return; |
978 |
|
979 |
ugly_goto: |
980 |
*start = 0; *size = 0; |
981 |
|
982 |
/* printf("reading MSDOS partition from offset 0x%llx\n", |
983 |
(long long)offset); */ |
984 |
|
985 |
res = diskimage_access(machine, scsi_id, 0, offset, |
986 |
sector, sizeof(sector)); |
987 |
if (!res) { |
988 |
fatal("[ arcbios_get_msdos_partition_size(): couldn't " |
989 |
"read the disk image, id %i, offset 0x%llx ]\n", |
990 |
scsi_id, (long long)offset); |
991 |
return; |
992 |
} |
993 |
|
994 |
if (sector[510] != 0x55 || sector[511] != 0xaa) { |
995 |
fatal("[ arcbios_get_msdos_partition_size(): not an " |
996 |
"MSDOS partition table ]\n"); |
997 |
} |
998 |
|
999 |
#if 0 |
1000 |
/* Debug dump: */ |
1001 |
for (i=0; i<4; i++) { |
1002 |
int j; |
1003 |
printf(" partition %i: ", i+1); |
1004 |
for (j=0; j<16; j++) |
1005 |
printf(" %02x", sector[446 + i*16 + j]); |
1006 |
printf("\n"); |
1007 |
} |
1008 |
#endif |
1009 |
|
1010 |
for (i=0; i<4; i++) { |
1011 |
memmove(buf, sector + 446 + 16*i, 16); |
1012 |
|
1013 |
partition_type = buf[4]; |
1014 |
|
1015 |
if (partition_type == 0) |
1016 |
continue; |
1017 |
|
1018 |
st = (buf[8] + (buf[9] << 8) + (buf[10] << 16) + |
1019 |
(buf[11] << 24)) * 512; |
1020 |
|
1021 |
if (start != NULL) |
1022 |
*start = st; |
1023 |
if (size != NULL) |
1024 |
*size = (buf[12] + (buf[13] << 8) + (buf[14] << 16) + |
1025 |
(buf[15] << 24)) * 512; |
1026 |
|
1027 |
/* Extended DOS partition: */ |
1028 |
if (partition_type == 5) { |
1029 |
offset += st; |
1030 |
goto ugly_goto; |
1031 |
} |
1032 |
|
1033 |
/* Found the right partition? Then return. */ |
1034 |
cur_partition ++; |
1035 |
if (cur_partition == partition_nr) |
1036 |
return; |
1037 |
} |
1038 |
|
1039 |
fatal("[ partition(%i) NOT found ]\n", partition_nr); |
1040 |
} |
1041 |
|
1042 |
|
1043 |
/* |
1044 |
* arcbios_handle_to_scsi_id(): |
1045 |
*/ |
1046 |
static int arcbios_handle_to_scsi_id(int handle) |
1047 |
{ |
1048 |
int id, cdrom; |
1049 |
char *s; |
1050 |
|
1051 |
if (handle < 0 || handle >= MAX_HANDLES) |
1052 |
return -1; |
1053 |
|
1054 |
s = (char *)file_handle_string[handle]; |
1055 |
if (s == NULL) |
1056 |
return -1; |
1057 |
|
1058 |
/* |
1059 |
* s is something like "scsi(0)disk(0)rdisk(0)partition(0)". |
1060 |
* TODO: This is really ugly and hardcoded. |
1061 |
*/ |
1062 |
|
1063 |
if (strncmp(s, "scsi(", 5) != 0 || strlen(s) < 13) |
1064 |
return -1; |
1065 |
|
1066 |
cdrom = (s[7] == 'c'); |
1067 |
id = cdrom? atoi(s + 13) : atoi(s + 12); |
1068 |
|
1069 |
return id; |
1070 |
} |
1071 |
|
1072 |
|
1073 |
/* |
1074 |
* arcbios_handle_to_start_and_size(): |
1075 |
*/ |
1076 |
static void arcbios_handle_to_start_and_size(struct machine *machine, |
1077 |
int handle, uint64_t *start, uint64_t *size) |
1078 |
{ |
1079 |
char *s = (char *)file_handle_string[handle]; |
1080 |
char *s2; |
1081 |
int scsi_id = arcbios_handle_to_scsi_id(handle); |
1082 |
|
1083 |
if (scsi_id < 0) |
1084 |
return; |
1085 |
|
1086 |
/* This works for "partition(0)": */ |
1087 |
*start = 0; |
1088 |
*size = diskimage_getsize(machine, scsi_id); |
1089 |
|
1090 |
s2 = strstr(s, "partition("); |
1091 |
if (s2 != NULL) { |
1092 |
int partition_nr = atoi(s2 + 10); |
1093 |
/* printf("partition_nr = %i\n", partition_nr); */ |
1094 |
if (partition_nr != 0) |
1095 |
arcbios_get_msdos_partition_size(machine, |
1096 |
scsi_id, partition_nr, start, size); |
1097 |
} |
1098 |
} |
1099 |
|
1100 |
|
1101 |
/* |
1102 |
* arcbios_getfileinformation(): |
1103 |
* |
1104 |
* Fill in a GetFileInformation struct in emulated memory, |
1105 |
* for a specific file handle. (This is used to get the size |
1106 |
* and offsets of partitions on disk images.) |
1107 |
*/ |
1108 |
static int arcbios_getfileinformation(struct cpu *cpu) |
1109 |
{ |
1110 |
int handle = cpu->cd.mips.gpr[MIPS_GPR_A0]; |
1111 |
uint64_t addr = cpu->cd.mips.gpr[MIPS_GPR_A1]; |
1112 |
uint64_t start, size; |
1113 |
|
1114 |
arcbios_handle_to_start_and_size(cpu->machine, handle, &start, &size); |
1115 |
|
1116 |
store_64bit_word(cpu, addr + 0, 0); |
1117 |
store_64bit_word(cpu, addr + 8, size); |
1118 |
store_64bit_word(cpu, addr + 16, 0); |
1119 |
store_32bit_word(cpu, addr + 24, 1); |
1120 |
store_32bit_word(cpu, addr + 28, 0); |
1121 |
store_32bit_word(cpu, addr + 32, 0); |
1122 |
|
1123 |
/* printf("\n!!! size=0x%x start=0x%x\n", (int)size, (int)start); */ |
1124 |
|
1125 |
return ARCBIOS_ESUCCESS; |
1126 |
} |
1127 |
|
1128 |
|
1129 |
/* |
1130 |
* arcbios_private_emul(): |
1131 |
* |
1132 |
* TODO: This is probably SGI specific. (?) |
1133 |
* |
1134 |
* 0x04 get nvram table |
1135 |
*/ |
1136 |
void arcbios_private_emul(struct cpu *cpu) |
1137 |
{ |
1138 |
int vector = cpu->pc & 0xfff; |
1139 |
|
1140 |
switch (vector) { |
1141 |
case 0x04: |
1142 |
debug("[ ARCBIOS PRIVATE get nvram table(): TODO ]\n"); |
1143 |
cpu->cd.mips.gpr[MIPS_GPR_V0] = 0; |
1144 |
break; |
1145 |
default: |
1146 |
cpu_register_dump(cpu->machine, cpu, 1, 0x1); |
1147 |
debug("a0 points to: "); |
1148 |
dump_mem_string(cpu, cpu->cd.mips.gpr[MIPS_GPR_A0]); |
1149 |
debug("\n"); |
1150 |
fatal("ARCBIOS: unimplemented PRIVATE vector 0x%x\n", vector); |
1151 |
cpu->running = 0; |
1152 |
cpu->dead = 1; |
1153 |
} |
1154 |
} |
1155 |
|
1156 |
|
1157 |
/* |
1158 |
* arcbios_emul(): ARCBIOS emulation |
1159 |
* |
1160 |
* 0x0c Halt() |
1161 |
* 0x10 PowerDown() |
1162 |
* 0x14 Restart() |
1163 |
* 0x18 Reboot() |
1164 |
* 0x1c EnterInteractiveMode() |
1165 |
* 0x20 ReturnFromMain() |
1166 |
* 0x24 GetPeer(node) |
1167 |
* 0x28 GetChild(node) |
1168 |
* 0x2c GetParent(node) |
1169 |
* 0x30 GetConfigurationData(config_data, node) |
1170 |
* 0x3c GetComponent(name) |
1171 |
* 0x44 GetSystemId() |
1172 |
* 0x48 GetMemoryDescriptor(void *) |
1173 |
* 0x50 GetTime() |
1174 |
* 0x54 GetRelativeTime() |
1175 |
* 0x5c Open(path, mode, &fileid) |
1176 |
* 0x60 Close(handle) |
1177 |
* 0x64 Read(handle, &buf, len, &actuallen) |
1178 |
* 0x6c Write(handle, buf, len, &returnlen) |
1179 |
* 0x70 Seek(handle, &offset, len) |
1180 |
* 0x78 GetEnvironmentVariable(char *) |
1181 |
* 0x7c SetEnvironmentVariable(char *, char *) |
1182 |
* 0x80 GetFileInformation(handle, buf) |
1183 |
* 0x88 FlushAllCaches() |
1184 |
* 0x90 GetDisplayStatus(uint32_t handle) |
1185 |
* 0x100 undocumented IRIX (?) |
1186 |
*/ |
1187 |
int arcbios_emul(struct cpu *cpu) |
1188 |
{ |
1189 |
int vector = cpu->pc & 0xfff; |
1190 |
int i, j, handle; |
1191 |
unsigned char ch2; |
1192 |
unsigned char buf[40]; |
1193 |
|
1194 |
if (cpu->pc >= ARC_PRIVATE_ENTRIES && |
1195 |
cpu->pc < ARC_PRIVATE_ENTRIES + 100*sizeof(uint32_t)) { |
1196 |
arcbios_private_emul(cpu); |
1197 |
return 1; |
1198 |
} |
1199 |
|
1200 |
if (arc_64bit) |
1201 |
vector /= 2; |
1202 |
|
1203 |
/* Special case for reboot by jumping to 0xbfc00000: */ |
1204 |
if (vector == 0 && (cpu->pc & 0xffffffffULL) == 0xbfc00000ULL) |
1205 |
vector = 0x18; |
1206 |
|
1207 |
switch (vector) { |
1208 |
case 0x0c: /* Halt() */ |
1209 |
case 0x10: /* PowerDown() */ |
1210 |
case 0x14: /* Restart() */ |
1211 |
case 0x18: /* Reboot() */ |
1212 |
case 0x1c: /* EnterInteractiveMode() */ |
1213 |
case 0x20: /* ReturnFromMain() */ |
1214 |
debug("[ ARCBIOS Halt() or similar ]\n"); |
1215 |
/* Halt all CPUs. */ |
1216 |
for (i=0; i<cpu->machine->ncpus; i++) { |
1217 |
cpu->machine->cpus[i]->running = 0; |
1218 |
cpu->machine->cpus[i]->dead = 1; |
1219 |
} |
1220 |
cpu->machine->exit_without_entering_debugger = 1; |
1221 |
break; |
1222 |
case 0x24: /* GetPeer(node) */ |
1223 |
if (cpu->cd.mips.gpr[MIPS_GPR_A0] == 0) { |
1224 |
/* NULL ptr argument: return NULL. */ |
1225 |
cpu->cd.mips.gpr[MIPS_GPR_V0] = 0; |
1226 |
} else { |
1227 |
uint64_t peer; |
1228 |
cpu->memory_rw(cpu, cpu->mem, |
1229 |
cpu->cd.mips.gpr[MIPS_GPR_A0] - 3 * arc_wordlen, |
1230 |
&buf[0], arc_wordlen, MEM_READ, CACHE_NONE); |
1231 |
if (arc_64bit) { |
1232 |
if (cpu->byte_order == EMUL_BIG_ENDIAN) { |
1233 |
unsigned char tmp; tmp = buf[0]; |
1234 |
buf[0] = buf[7]; buf[7] = tmp; |
1235 |
tmp = buf[1]; buf[1] = buf[6]; |
1236 |
buf[6] = tmp; |
1237 |
tmp = buf[2]; buf[2] = buf[5]; |
1238 |
buf[5] = tmp; |
1239 |
tmp = buf[3]; buf[3] = buf[4]; |
1240 |
buf[4] = tmp; |
1241 |
} |
1242 |
peer = (uint64_t)buf[0] + ((uint64_t)buf[1]<<8) |
1243 |
+ ((uint64_t)buf[2]<<16) |
1244 |
+ ((uint64_t)buf[3]<<24) |
1245 |
+ ((uint64_t)buf[4]<<32) |
1246 |
+ ((uint64_t)buf[5]<<40) |
1247 |
+ ((uint64_t)buf[6]<<48) |
1248 |
+ ((uint64_t)buf[7]<<56); |
1249 |
} else { |
1250 |
if (cpu->byte_order == EMUL_BIG_ENDIAN) { |
1251 |
unsigned char tmp; tmp = buf[0]; |
1252 |
buf[0] = buf[3]; buf[3] = tmp; |
1253 |
tmp = buf[1]; buf[1] = buf[2]; |
1254 |
buf[2] = tmp; |
1255 |
} |
1256 |
peer = buf[0] + (buf[1]<<8) + (buf[2]<<16) |
1257 |
+ (buf[3]<<24); |
1258 |
} |
1259 |
|
1260 |
cpu->cd.mips.gpr[MIPS_GPR_V0] = peer? |
1261 |
(peer + 3 * arc_wordlen) : 0; |
1262 |
if (!arc_64bit) |
1263 |
cpu->cd.mips.gpr[MIPS_GPR_V0] = (int64_t) |
1264 |
(int32_t) cpu->cd.mips.gpr[MIPS_GPR_V0]; |
1265 |
} |
1266 |
debug("[ ARCBIOS GetPeer(node 0x%016llx): 0x%016llx ]\n", |
1267 |
(long long)cpu->cd.mips.gpr[MIPS_GPR_A0], |
1268 |
(long long)cpu->cd.mips.gpr[MIPS_GPR_V0]); |
1269 |
break; |
1270 |
case 0x28: /* GetChild(node) */ |
1271 |
/* 0 for the root, non-0 for children: */ |
1272 |
if (cpu->cd.mips.gpr[MIPS_GPR_A0] == 0) |
1273 |
cpu->cd.mips.gpr[MIPS_GPR_V0] = |
1274 |
FIRST_ARC_COMPONENT + arc_wordlen * 3; |
1275 |
else { |
1276 |
uint64_t child = 0; |
1277 |
cpu->memory_rw(cpu, cpu->mem, |
1278 |
cpu->cd.mips.gpr[MIPS_GPR_A0] - 2 * arc_wordlen, |
1279 |
&buf[0], arc_wordlen, MEM_READ, CACHE_NONE); |
1280 |
if (arc_64bit) { |
1281 |
if (cpu->byte_order == EMUL_BIG_ENDIAN) { |
1282 |
unsigned char tmp; tmp = buf[0]; |
1283 |
buf[0] = buf[7]; buf[7] = tmp; |
1284 |
tmp = buf[1]; buf[1] = buf[6]; |
1285 |
buf[6] = tmp; |
1286 |
tmp = buf[2]; buf[2] = buf[5]; |
1287 |
buf[5] = tmp; |
1288 |
tmp = buf[3]; buf[3] = buf[4]; |
1289 |
buf[4] = tmp; |
1290 |
} |
1291 |
child = (uint64_t)buf[0] + |
1292 |
((uint64_t)buf[1]<<8) + |
1293 |
((uint64_t)buf[2]<<16) + |
1294 |
((uint64_t)buf[3]<<24) + |
1295 |
((uint64_t)buf[4]<<32) + |
1296 |
((uint64_t)buf[5]<<40) + |
1297 |
((uint64_t)buf[6]<<48) + |
1298 |
((uint64_t)buf[7]<<56); |
1299 |
} else { |
1300 |
if (cpu->byte_order == EMUL_BIG_ENDIAN) { |
1301 |
unsigned char tmp; tmp = buf[0]; |
1302 |
buf[0] = buf[3]; buf[3] = tmp; |
1303 |
tmp = buf[1]; buf[1] = buf[2]; |
1304 |
buf[2] = tmp; |
1305 |
} |
1306 |
child = buf[0] + (buf[1]<<8) + (buf[2]<<16) + |
1307 |
(buf[3]<<24); |
1308 |
} |
1309 |
|
1310 |
cpu->cd.mips.gpr[MIPS_GPR_V0] = child? |
1311 |
(child + 3 * arc_wordlen) : 0; |
1312 |
if (!arc_64bit) |
1313 |
cpu->cd.mips.gpr[MIPS_GPR_V0] = (int64_t) |
1314 |
(int32_t)cpu->cd.mips.gpr[MIPS_GPR_V0]; |
1315 |
} |
1316 |
debug("[ ARCBIOS GetChild(node 0x%016llx): 0x%016llx ]\n", |
1317 |
(long long)cpu->cd.mips.gpr[MIPS_GPR_A0], |
1318 |
(long long)cpu->cd.mips.gpr[MIPS_GPR_V0]); |
1319 |
break; |
1320 |
case 0x2c: /* GetParent(node) */ |
1321 |
{ |
1322 |
uint64_t parent; |
1323 |
|
1324 |
cpu->memory_rw(cpu, cpu->mem, |
1325 |
cpu->cd.mips.gpr[MIPS_GPR_A0] - 1 * arc_wordlen, |
1326 |
&buf[0], arc_wordlen, MEM_READ, CACHE_NONE); |
1327 |
|
1328 |
if (arc_64bit) { |
1329 |
if (cpu->byte_order == EMUL_BIG_ENDIAN) { |
1330 |
unsigned char tmp; tmp = buf[0]; |
1331 |
buf[0] = buf[7]; buf[7] = tmp; |
1332 |
tmp = buf[1]; buf[1] = buf[6]; |
1333 |
buf[6] = tmp; |
1334 |
tmp = buf[2]; buf[2] = buf[5]; |
1335 |
buf[5] = tmp; |
1336 |
tmp = buf[3]; buf[3] = buf[4]; |
1337 |
buf[4] = tmp; |
1338 |
} |
1339 |
parent = (uint64_t)buf[0] + |
1340 |
((uint64_t)buf[1]<<8) + |
1341 |
((uint64_t)buf[2]<<16) + |
1342 |
((uint64_t)buf[3]<<24) + |
1343 |
((uint64_t)buf[4]<<32) + |
1344 |
((uint64_t)buf[5]<<40) + |
1345 |
((uint64_t)buf[6]<<48) + |
1346 |
((uint64_t)buf[7]<<56); |
1347 |
} else { |
1348 |
if (cpu->byte_order == EMUL_BIG_ENDIAN) { |
1349 |
unsigned char tmp; tmp = buf[0]; |
1350 |
buf[0] = buf[3]; buf[3] = tmp; |
1351 |
tmp = buf[1]; buf[1] = buf[2]; |
1352 |
buf[2] = tmp; |
1353 |
} |
1354 |
parent = buf[0] + (buf[1]<<8) + |
1355 |
(buf[2]<<16) + (buf[3]<<24); |
1356 |
} |
1357 |
|
1358 |
cpu->cd.mips.gpr[MIPS_GPR_V0] = parent? |
1359 |
(parent + 3 * arc_wordlen) : 0; |
1360 |
if (!arc_64bit) |
1361 |
cpu->cd.mips.gpr[MIPS_GPR_V0] = (int64_t) |
1362 |
(int32_t) cpu->cd.mips.gpr[MIPS_GPR_V0]; |
1363 |
} |
1364 |
debug("[ ARCBIOS GetParent(node 0x%016llx): 0x%016llx ]\n", |
1365 |
(long long)cpu->cd.mips.gpr[MIPS_GPR_A0], |
1366 |
(long long)cpu->cd.mips.gpr[MIPS_GPR_V0]); |
1367 |
break; |
1368 |
case 0x30: /* GetConfigurationData(void *configdata, void *node) */ |
1369 |
/* fatal("[ ARCBIOS GetConfigurationData(0x%016llx," |
1370 |
"0x%016llx) ]\n", (long long)cpu->cd.mips.gpr[MIPS_GPR_A0], |
1371 |
(long long)cpu->cd.mips.gpr[MIPS_GPR_A1]); */ |
1372 |
cpu->cd.mips.gpr[MIPS_GPR_V0] = ARCBIOS_EINVAL; |
1373 |
for (i=0; i<n_configuration_data; i++) { |
1374 |
/* fatal("configuration_data_component[%i] = " |
1375 |
"0x%016llx\n", i, |
1376 |
(long long)configuration_data_component[i]); */ |
1377 |
if (cpu->cd.mips.gpr[MIPS_GPR_A1] == |
1378 |
configuration_data_component[i]) { |
1379 |
cpu->cd.mips.gpr[MIPS_GPR_V0] = 0; |
1380 |
for (j=0; j<configuration_data_len[i]; j++) { |
1381 |
unsigned char ch; |
1382 |
cpu->memory_rw(cpu, cpu->mem, |
1383 |
configuration_data_configdata[i] + |
1384 |
j, &ch, 1, MEM_READ, CACHE_NONE); |
1385 |
cpu->memory_rw(cpu, cpu->mem, |
1386 |
cpu->cd.mips.gpr[MIPS_GPR_A0] + j, |
1387 |
&ch, 1, MEM_WRITE, CACHE_NONE); |
1388 |
} |
1389 |
break; |
1390 |
} |
1391 |
} |
1392 |
break; |
1393 |
case 0x3c: /* GetComponent(char *name) */ |
1394 |
debug("[ ARCBIOS GetComponent(\""); |
1395 |
dump_mem_string(cpu, cpu->cd.mips.gpr[MIPS_GPR_A0]); |
1396 |
debug("\") ]\n"); |
1397 |
|
1398 |
if (cpu->cd.mips.gpr[MIPS_GPR_A0] == 0) { |
1399 |
fatal("[ ARCBIOS GetComponent: NULL ptr ]\n"); |
1400 |
} else { |
1401 |
unsigned char buf[500]; |
1402 |
int match_index = -1; |
1403 |
int match_len = 0; |
1404 |
|
1405 |
memset(buf, 0, sizeof(buf)); |
1406 |
for (i=0; i<sizeof(buf); i++) { |
1407 |
cpu->memory_rw(cpu, cpu->mem, |
1408 |
cpu->cd.mips.gpr[MIPS_GPR_A0] + i, |
1409 |
&buf[i], 1, MEM_READ, CACHE_NONE); |
1410 |
if (buf[i] == '\0') |
1411 |
i = sizeof(buf); |
1412 |
} |
1413 |
buf[sizeof(buf) - 1] = '\0'; |
1414 |
|
1415 |
/* "scsi(0)disk(0)rdisk(0)partition(0)" and such. */ |
1416 |
/* printf("GetComponent(\"%s\")\n", buf); */ |
1417 |
|
1418 |
/* Default to NULL return value. */ |
1419 |
cpu->cd.mips.gpr[MIPS_GPR_V0] = 0; |
1420 |
|
1421 |
/* Scan the string to component table: */ |
1422 |
for (i=0; i<arcbios_n_string_to_components; i++) { |
1423 |
int m = 0; |
1424 |
while (buf[m] && arcbios_string_to_component |
1425 |
[i][m] && arcbios_string_to_component[i][m] |
1426 |
== buf[m]) |
1427 |
m++; |
1428 |
if (m > match_len) { |
1429 |
match_len = m; |
1430 |
match_index = i; |
1431 |
} |
1432 |
} |
1433 |
|
1434 |
if (match_index >= 0) { |
1435 |
/* printf("Longest match: '%s'\n", |
1436 |
arcbios_string_to_component[ |
1437 |
match_index]); */ |
1438 |
cpu->cd.mips.gpr[MIPS_GPR_V0] = |
1439 |
arcbios_string_to_component_value[ |
1440 |
match_index]; |
1441 |
} |
1442 |
} |
1443 |
break; |
1444 |
case 0x44: /* GetSystemId() */ |
1445 |
debug("[ ARCBIOS GetSystemId() ]\n"); |
1446 |
cpu->cd.mips.gpr[MIPS_GPR_V0] = SGI_SYSID_ADDR; |
1447 |
break; |
1448 |
case 0x48: /* void *GetMemoryDescriptor(void *ptr) */ |
1449 |
debug("[ ARCBIOS GetMemoryDescriptor(0x%08x) ]\n", |
1450 |
(int)cpu->cd.mips.gpr[MIPS_GPR_A0]); |
1451 |
|
1452 |
/* If a0=NULL, then return the first descriptor: */ |
1453 |
if ((uint32_t)cpu->cd.mips.gpr[MIPS_GPR_A0] == 0) |
1454 |
cpu->cd.mips.gpr[MIPS_GPR_V0] = |
1455 |
arcbios_memdescriptor_base; |
1456 |
else { |
1457 |
int s = arc_64bit? sizeof(struct arcbios_mem64) |
1458 |
: sizeof(struct arcbios_mem); |
1459 |
int nr = cpu->cd.mips.gpr[MIPS_GPR_A0] - |
1460 |
arcbios_memdescriptor_base; |
1461 |
nr /= s; |
1462 |
nr ++; |
1463 |
cpu->cd.mips.gpr[MIPS_GPR_V0] = |
1464 |
arcbios_memdescriptor_base + s * nr; |
1465 |
if (nr >= arc_n_memdescriptors) |
1466 |
cpu->cd.mips.gpr[MIPS_GPR_V0] = 0; |
1467 |
} |
1468 |
break; |
1469 |
case 0x50: /* GetTime() */ |
1470 |
debug("[ ARCBIOS GetTime() ]\n"); |
1471 |
cpu->cd.mips.gpr[MIPS_GPR_V0] = 0xffffffff80001000ULL; |
1472 |
/* TODO! */ |
1473 |
break; |
1474 |
case 0x54: /* GetRelativeTime() */ |
1475 |
debug("[ ARCBIOS GetRelativeTime() ]\n"); |
1476 |
cpu->cd.mips.gpr[MIPS_GPR_V0] = (int64_t)(int32_t)time(NULL); |
1477 |
break; |
1478 |
case 0x5c: /* Open(char *path, uint32_t mode, uint32_t *fileID) */ |
1479 |
debug("[ ARCBIOS Open(\""); |
1480 |
dump_mem_string(cpu, cpu->cd.mips.gpr[MIPS_GPR_A0]); |
1481 |
debug("\",0x%x,0x%x)", (int)cpu->cd.mips.gpr[MIPS_GPR_A0], |
1482 |
(int)cpu->cd.mips.gpr[MIPS_GPR_A1], |
1483 |
(int)cpu->cd.mips.gpr[MIPS_GPR_A2]); |
1484 |
|
1485 |
cpu->cd.mips.gpr[MIPS_GPR_V0] = ARCBIOS_ENOENT; |
1486 |
|
1487 |
handle = 3; |
1488 |
/* TODO: Starting at 0 would require some updates... */ |
1489 |
while (file_handle_in_use[handle]) { |
1490 |
handle ++; |
1491 |
if (handle >= MAX_HANDLES) { |
1492 |
cpu->cd.mips.gpr[MIPS_GPR_V0] = ARCBIOS_EMFILE; |
1493 |
break; |
1494 |
} |
1495 |
} |
1496 |
|
1497 |
if (handle >= MAX_HANDLES) { |
1498 |
fatal("[ ARCBIOS Open: out of file handles ]\n"); |
1499 |
} else if (cpu->cd.mips.gpr[MIPS_GPR_A0] == 0) { |
1500 |
fatal("[ ARCBIOS Open: NULL ptr ]\n"); |
1501 |
} else { |
1502 |
/* |
1503 |
* TODO: This is hardcoded to successfully open |
1504 |
* anything. It is used by the Windows NT SETUPLDR |
1505 |
* program to load stuff from the boot partition. |
1506 |
*/ |
1507 |
unsigned char *buf = malloc(MAX_OPEN_STRINGLEN); |
1508 |
if (buf == NULL) { |
1509 |
fprintf(stderr, "out of memory\n"); |
1510 |
exit(1); |
1511 |
} |
1512 |
memset(buf, 0, MAX_OPEN_STRINGLEN); |
1513 |
for (i=0; i<MAX_OPEN_STRINGLEN; i++) { |
1514 |
cpu->memory_rw(cpu, cpu->mem, |
1515 |
cpu->cd.mips.gpr[MIPS_GPR_A0] + i, |
1516 |
&buf[i], 1, MEM_READ, CACHE_NONE); |
1517 |
if (buf[i] == '\0') |
1518 |
i = MAX_OPEN_STRINGLEN; |
1519 |
} |
1520 |
buf[MAX_OPEN_STRINGLEN - 1] = '\0'; |
1521 |
file_handle_string[handle] = buf; |
1522 |
arcbios_current_seek_offset[handle] = 0; |
1523 |
cpu->cd.mips.gpr[MIPS_GPR_V0] = ARCBIOS_ESUCCESS; |
1524 |
} |
1525 |
|
1526 |
if (cpu->cd.mips.gpr[MIPS_GPR_V0] == ARCBIOS_ESUCCESS) { |
1527 |
debug(" = handle %i ]\n", (int)handle); |
1528 |
store_32bit_word(cpu, cpu->cd.mips.gpr[MIPS_GPR_A2], |
1529 |
handle); |
1530 |
file_handle_in_use[handle] = 1; |
1531 |
} else |
1532 |
debug(" = ERROR %i ]\n", |
1533 |
(int)cpu->cd.mips.gpr[MIPS_GPR_V0]); |
1534 |
break; |
1535 |
case 0x60: /* Close(uint32_t handle) */ |
1536 |
debug("[ ARCBIOS Close(%i) ]\n", |
1537 |
(int)cpu->cd.mips.gpr[MIPS_GPR_A0]); |
1538 |
if (!file_handle_in_use[cpu->cd.mips.gpr[MIPS_GPR_A0]]) { |
1539 |
fatal("ARCBIOS Close(%i): bad handle\n", |
1540 |
(int)cpu->cd.mips.gpr[MIPS_GPR_A0]); |
1541 |
cpu->cd.mips.gpr[MIPS_GPR_V0] = ARCBIOS_EBADF; |
1542 |
} else { |
1543 |
file_handle_in_use[cpu->cd.mips.gpr[MIPS_GPR_A0]] = 0; |
1544 |
if (file_handle_string[cpu->cd.mips.gpr[MIPS_GPR_A0]] |
1545 |
!= NULL) |
1546 |
free(file_handle_string[cpu->cd.mips.gpr[ |
1547 |
MIPS_GPR_A0]]); |
1548 |
file_handle_string[cpu->cd.mips.gpr[MIPS_GPR_A0]] = |
1549 |
NULL; |
1550 |
cpu->cd.mips.gpr[MIPS_GPR_V0] = ARCBIOS_ESUCCESS; |
1551 |
} |
1552 |
break; |
1553 |
case 0x64: /* Read(handle, void *buf, length, uint32_t *count) */ |
1554 |
if (cpu->cd.mips.gpr[MIPS_GPR_A0] == ARCBIOS_STDIN) { |
1555 |
int i, nread = 0; |
1556 |
/* |
1557 |
* Before going into the loop, make sure stdout |
1558 |
* is flushed. If we're using an X11 VGA console, |
1559 |
* then it needs to be flushed as well. |
1560 |
*/ |
1561 |
fflush(stdin); |
1562 |
fflush(stdout); |
1563 |
/* NOTE/TODO: This gives a tick to _everything_ */ |
1564 |
for (i=0; i<cpu->machine->n_tick_entries; i++) |
1565 |
cpu->machine->tick_func[i](cpu, |
1566 |
cpu->machine->tick_extra[i]); |
1567 |
|
1568 |
for (i=0; i<cpu->cd.mips.gpr[MIPS_GPR_A2]; i++) { |
1569 |
int x; |
1570 |
unsigned char ch; |
1571 |
|
1572 |
/* Read from STDIN is blocking (at least |
1573 |
that seems to be how NetBSD's arcdiag |
1574 |
wants it) */ |
1575 |
x = console_readchar(cpu->machine-> |
1576 |
main_console_handle); |
1577 |
if (x < 0) |
1578 |
return 0; |
1579 |
|
1580 |
/* |
1581 |
* ESC + '[' should be transformed into 0x9b: |
1582 |
* |
1583 |
* NOTE/TODO: This makes the behaviour of just |
1584 |
* pressing ESC a bit harder to define. |
1585 |
*/ |
1586 |
if (x == 27) { |
1587 |
x = console_readchar(cpu-> |
1588 |
machine->main_console_handle); |
1589 |
if (x == '[' || x == 'O') |
1590 |
x = 0x9b; |
1591 |
} |
1592 |
|
1593 |
ch = x; |
1594 |
nread ++; |
1595 |
cpu->memory_rw(cpu, cpu->mem, |
1596 |
cpu->cd.mips.gpr[MIPS_GPR_A1] + i, |
1597 |
&ch, 1, MEM_WRITE, CACHE_NONE); |
1598 |
|
1599 |
/* NOTE: Only one char, from STDIN: */ |
1600 |
i = cpu->cd.mips.gpr[MIPS_GPR_A2]; /* :-) */ |
1601 |
} |
1602 |
store_32bit_word(cpu, cpu->cd.mips.gpr[MIPS_GPR_A3], |
1603 |
nread); |
1604 |
/* TODO: not EAGAIN? */ |
1605 |
cpu->cd.mips.gpr[MIPS_GPR_V0] = |
1606 |
nread? ARCBIOS_ESUCCESS: ARCBIOS_EAGAIN; |
1607 |
} else { |
1608 |
int handle = cpu->cd.mips.gpr[MIPS_GPR_A0]; |
1609 |
int disk_id = arcbios_handle_to_scsi_id(handle); |
1610 |
uint64_t partition_offset = 0; |
1611 |
int res; |
1612 |
uint64_t size; /* dummy */ |
1613 |
unsigned char *tmp_buf; |
1614 |
|
1615 |
arcbios_handle_to_start_and_size(cpu->machine, |
1616 |
handle, &partition_offset, &size); |
1617 |
|
1618 |
debug("[ ARCBIOS Read(%i,0x%08x,0x%08x,0x%08x) ]\n", |
1619 |
(int)cpu->cd.mips.gpr[MIPS_GPR_A0], |
1620 |
(int)cpu->cd.mips.gpr[MIPS_GPR_A1], |
1621 |
(int)cpu->cd.mips.gpr[MIPS_GPR_A2], |
1622 |
(int)cpu->cd.mips.gpr[MIPS_GPR_A3]); |
1623 |
|
1624 |
tmp_buf = malloc(cpu->cd.mips.gpr[MIPS_GPR_A2]); |
1625 |
if (tmp_buf == NULL) { |
1626 |
fprintf(stderr, "[ *** Out of memory in " |
1627 |
"arcbios.c, allocating %i bytes ]\n", |
1628 |
(int)cpu->cd.mips.gpr[MIPS_GPR_A2]); |
1629 |
break; |
1630 |
} |
1631 |
|
1632 |
res = diskimage_access(cpu->machine, disk_id, 0, |
1633 |
partition_offset + arcbios_current_seek_offset[ |
1634 |
handle], tmp_buf, cpu->cd.mips.gpr[MIPS_GPR_A2]); |
1635 |
|
1636 |
/* If the transfer was successful, transfer the |
1637 |
data to emulated memory: */ |
1638 |
if (res) { |
1639 |
uint64_t dst = cpu->cd.mips.gpr[MIPS_GPR_A1]; |
1640 |
store_buf(cpu, dst, (char *)tmp_buf, |
1641 |
cpu->cd.mips.gpr[MIPS_GPR_A2]); |
1642 |
store_32bit_word(cpu, |
1643 |
cpu->cd.mips.gpr[MIPS_GPR_A3], |
1644 |
cpu->cd.mips.gpr[MIPS_GPR_A2]); |
1645 |
arcbios_current_seek_offset[handle] += |
1646 |
cpu->cd.mips.gpr[MIPS_GPR_A2]; |
1647 |
cpu->cd.mips.gpr[MIPS_GPR_V0] = 0; |
1648 |
} else |
1649 |
cpu->cd.mips.gpr[MIPS_GPR_V0] = ARCBIOS_EIO; |
1650 |
free(tmp_buf); |
1651 |
} |
1652 |
break; |
1653 |
case 0x68: /* GetReadStatus(handle) */ |
1654 |
/* |
1655 |
* According to arcbios_tty_getchar() in NetBSD's |
1656 |
* dev/arcbios/arcbios_tty.c, GetReadStatus should |
1657 |
* return 0 if there is something available. |
1658 |
* |
1659 |
* TODO: Error codes are things like ARCBIOS_EAGAIN. |
1660 |
*/ |
1661 |
if (cpu->cd.mips.gpr[MIPS_GPR_A0] == ARCBIOS_STDIN) { |
1662 |
cpu->cd.mips.gpr[MIPS_GPR_V0] = console_charavail( |
1663 |
cpu->machine->main_console_handle)? 0 : 1; |
1664 |
} else { |
1665 |
fatal("[ ARCBIOS GetReadStatus(%i) from " |
1666 |
"something other than STDIN: TODO ]\n", |
1667 |
(int)cpu->cd.mips.gpr[MIPS_GPR_A0]); |
1668 |
/* TODO */ |
1669 |
cpu->cd.mips.gpr[MIPS_GPR_V0] = 1; |
1670 |
} |
1671 |
break; |
1672 |
case 0x6c: /* Write(handle, buf, len, &returnlen) */ |
1673 |
if (cpu->cd.mips.gpr[MIPS_GPR_A0] != ARCBIOS_STDOUT) { |
1674 |
/* |
1675 |
* TODO: this is just a test |
1676 |
*/ |
1677 |
int handle = cpu->cd.mips.gpr[MIPS_GPR_A0]; |
1678 |
int disk_id = arcbios_handle_to_scsi_id(handle); |
1679 |
uint64_t partition_offset = 0; |
1680 |
int res, i; |
1681 |
uint64_t size; /* dummy */ |
1682 |
unsigned char *tmp_buf; |
1683 |
|
1684 |
arcbios_handle_to_start_and_size(cpu->machine, |
1685 |
handle, &partition_offset, &size); |
1686 |
|
1687 |
debug("[ ARCBIOS Write(%i,0x%08llx,%i,0x%08llx) ]\n", |
1688 |
(int)cpu->cd.mips.gpr[MIPS_GPR_A0], |
1689 |
(long long)cpu->cd.mips.gpr[MIPS_GPR_A1], |
1690 |
(int)cpu->cd.mips.gpr[MIPS_GPR_A2], |
1691 |
(long long)cpu->cd.mips.gpr[MIPS_GPR_A3]); |
1692 |
|
1693 |
tmp_buf = malloc(cpu->cd.mips.gpr[MIPS_GPR_A2]); |
1694 |
if (tmp_buf == NULL) { |
1695 |
fprintf(stderr, "[ *** Out of memory in" |
1696 |
" arcbios.c, allocating %i bytes ]\n", |
1697 |
(int)cpu->cd.mips.gpr[MIPS_GPR_A2]); |
1698 |
break; |
1699 |
} |
1700 |
|
1701 |
for (i=0; i<cpu->cd.mips.gpr[MIPS_GPR_A2]; i++) |
1702 |
cpu->memory_rw(cpu, cpu->mem, |
1703 |
cpu->cd.mips.gpr[MIPS_GPR_A1] + i, |
1704 |
&tmp_buf[i], sizeof(char), MEM_READ, |
1705 |
CACHE_NONE); |
1706 |
|
1707 |
res = diskimage_access(cpu->machine, disk_id, 1, |
1708 |
partition_offset + arcbios_current_seek_offset[ |
1709 |
handle], tmp_buf, cpu->cd.mips.gpr[MIPS_GPR_A2]); |
1710 |
|
1711 |
if (res) { |
1712 |
store_32bit_word(cpu, |
1713 |
cpu->cd.mips.gpr[MIPS_GPR_A3], |
1714 |
cpu->cd.mips.gpr[MIPS_GPR_A2]); |
1715 |
arcbios_current_seek_offset[handle] += |
1716 |
cpu->cd.mips.gpr[MIPS_GPR_A2]; |
1717 |
cpu->cd.mips.gpr[MIPS_GPR_V0] = 0; |
1718 |
} else |
1719 |
cpu->cd.mips.gpr[MIPS_GPR_V0] = ARCBIOS_EIO; |
1720 |
free(tmp_buf); |
1721 |
} else { |
1722 |
for (i=0; i<cpu->cd.mips.gpr[MIPS_GPR_A2]; i++) { |
1723 |
unsigned char ch = '\0'; |
1724 |
cpu->memory_rw(cpu, cpu->mem, |
1725 |
cpu->cd.mips.gpr[MIPS_GPR_A1] + i, |
1726 |
&ch, sizeof(ch), MEM_READ, CACHE_NONE); |
1727 |
|
1728 |
arcbios_putchar(cpu, ch); |
1729 |
} |
1730 |
} |
1731 |
store_32bit_word(cpu, cpu->cd.mips.gpr[MIPS_GPR_A3], |
1732 |
cpu->cd.mips.gpr[MIPS_GPR_A2]); |
1733 |
cpu->cd.mips.gpr[MIPS_GPR_V0] = 0; /* Success. */ |
1734 |
break; |
1735 |
case 0x70: /* Seek(uint32_t handle, int64_t *ofs, |
1736 |
uint32_t whence): uint32_t */ |
1737 |
debug("[ ARCBIOS Seek(%i,0x%08llx,%i): ", |
1738 |
(int)cpu->cd.mips.gpr[MIPS_GPR_A0], |
1739 |
(long long)cpu->cd.mips.gpr[MIPS_GPR_A1], |
1740 |
(int)cpu->cd.mips.gpr[MIPS_GPR_A2]); |
1741 |
|
1742 |
if (cpu->cd.mips.gpr[MIPS_GPR_A2] != 0) { |
1743 |
fatal("[ ARCBIOS Seek(%i,0x%08llx,%i): " |
1744 |
"UNIMPLEMENTED whence=%i ]\n", |
1745 |
(int)cpu->cd.mips.gpr[MIPS_GPR_A0], |
1746 |
(long long)cpu->cd.mips.gpr[MIPS_GPR_A1], |
1747 |
(int)cpu->cd.mips.gpr[MIPS_GPR_A2], |
1748 |
(int)cpu->cd.mips.gpr[MIPS_GPR_A2]); |
1749 |
} |
1750 |
|
1751 |
{ |
1752 |
unsigned char buf[8]; |
1753 |
uint64_t ofs; |
1754 |
cpu->memory_rw(cpu, cpu->mem, |
1755 |
cpu->cd.mips.gpr[MIPS_GPR_A1], &buf[0], |
1756 |
sizeof(buf), MEM_READ, CACHE_NONE); |
1757 |
if (cpu->byte_order == EMUL_BIG_ENDIAN) { |
1758 |
unsigned char tmp; |
1759 |
tmp = buf[0]; buf[0] = buf[7]; buf[7] = tmp; |
1760 |
tmp = buf[1]; buf[1] = buf[6]; buf[6] = tmp; |
1761 |
tmp = buf[2]; buf[2] = buf[5]; buf[5] = tmp; |
1762 |
tmp = buf[3]; buf[3] = buf[4]; buf[4] = tmp; |
1763 |
} |
1764 |
ofs = buf[0] + (buf[1] << 8) + (buf[2] << 16) + |
1765 |
(buf[3] << 24) + ((uint64_t)buf[4] << 32) + |
1766 |
((uint64_t)buf[5] << 40) + ((uint64_t)buf[6] << 48) |
1767 |
+ ((uint64_t)buf[7] << 56); |
1768 |
arcbios_current_seek_offset[ |
1769 |
cpu->cd.mips.gpr[MIPS_GPR_A0]] = ofs; |
1770 |
debug("%016llx ]\n", (long long)ofs); |
1771 |
} |
1772 |
|
1773 |
cpu->cd.mips.gpr[MIPS_GPR_V0] = 0; /* Success. */ |
1774 |
|
1775 |
break; |
1776 |
case 0x78: /* GetEnvironmentVariable(char *) */ |
1777 |
/* Find the environment variable given by a0: */ |
1778 |
for (i=0; i<sizeof(buf); i++) |
1779 |
cpu->memory_rw(cpu, cpu->mem, |
1780 |
cpu->cd.mips.gpr[MIPS_GPR_A0] + i, |
1781 |
&buf[i], sizeof(char), MEM_READ, CACHE_NONE); |
1782 |
buf[sizeof(buf)-1] = '\0'; |
1783 |
debug("[ ARCBIOS GetEnvironmentVariable(\"%s\") ]\n", buf); |
1784 |
for (i=0; i<0x1000; i++) { |
1785 |
/* Matching string at offset i? */ |
1786 |
int nmatches = 0; |
1787 |
for (j=0; j<strlen((char *)buf); j++) { |
1788 |
cpu->memory_rw(cpu, cpu->mem, |
1789 |
(uint64_t)(ARC_ENV_STRINGS + i + j), |
1790 |
&ch2, sizeof(char), MEM_READ, CACHE_NONE); |
1791 |
if (ch2 == buf[j]) |
1792 |
nmatches++; |
1793 |
} |
1794 |
cpu->memory_rw(cpu, cpu->mem, |
1795 |
(uint64_t)(ARC_ENV_STRINGS + i + |
1796 |
strlen((char *)buf)), &ch2, sizeof(char), |
1797 |
MEM_READ, CACHE_NONE); |
1798 |
if (nmatches == strlen((char *)buf) && ch2 == '=') { |
1799 |
cpu->cd.mips.gpr[MIPS_GPR_V0] = |
1800 |
ARC_ENV_STRINGS + i + |
1801 |
strlen((char *)buf) + 1; |
1802 |
return 1; |
1803 |
} |
1804 |
} |
1805 |
/* Return NULL if string wasn't found. */ |
1806 |
cpu->cd.mips.gpr[MIPS_GPR_V0] = 0; |
1807 |
break; |
1808 |
case 0x7c: /* SetEnvironmentVariable(char *, char *) */ |
1809 |
debug("[ ARCBIOS SetEnvironmentVariable(\""); |
1810 |
dump_mem_string(cpu, cpu->cd.mips.gpr[MIPS_GPR_A0]); |
1811 |
debug("\",\""); |
1812 |
dump_mem_string(cpu, cpu->cd.mips.gpr[MIPS_GPR_A1]); |
1813 |
debug("\") ]\n"); |
1814 |
/* TODO: This is a dummy. */ |
1815 |
cpu->cd.mips.gpr[MIPS_GPR_V0] = ARCBIOS_ESUCCESS; |
1816 |
break; |
1817 |
case 0x80: /* GetFileInformation() */ |
1818 |
debug("[ ARCBIOS GetFileInformation(%i,0x%x): ", |
1819 |
(int)cpu->cd.mips.gpr[MIPS_GPR_A0], |
1820 |
(int)cpu->cd.mips.gpr[MIPS_GPR_A1]); |
1821 |
|
1822 |
if (cpu->cd.mips.gpr[MIPS_GPR_A0] >= MAX_HANDLES) { |
1823 |
debug("invalid file handle ]\n"); |
1824 |
cpu->cd.mips.gpr[MIPS_GPR_V0] = ARCBIOS_EINVAL; |
1825 |
} else if (!file_handle_in_use[cpu->cd.mips.gpr[MIPS_GPR_A0]]) { |
1826 |
debug("file handle not in use! ]\n"); |
1827 |
cpu->cd.mips.gpr[MIPS_GPR_V0] = ARCBIOS_EBADF; |
1828 |
} else { |
1829 |
debug("'%s' ]\n", file_handle_string[ |
1830 |
cpu->cd.mips.gpr[MIPS_GPR_A0]]); |
1831 |
cpu->cd.mips.gpr[MIPS_GPR_V0] = |
1832 |
arcbios_getfileinformation(cpu); |
1833 |
} |
1834 |
break; |
1835 |
case 0x88: /* FlushAllCaches() */ |
1836 |
debug("[ ARCBIOS FlushAllCaches(): TODO ]\n"); |
1837 |
cpu->cd.mips.gpr[MIPS_GPR_V0] = 0; |
1838 |
break; |
1839 |
case 0x90: /* void *GetDisplayStatus(handle) */ |
1840 |
debug("[ ARCBIOS GetDisplayStatus(%i) ]\n", |
1841 |
(int)cpu->cd.mips.gpr[MIPS_GPR_A0]); |
1842 |
/* TODO: handle different values of 'handle'? */ |
1843 |
cpu->cd.mips.gpr[MIPS_GPR_V0] = ARC_DSPSTAT_ADDR; |
1844 |
break; |
1845 |
case 0x100: |
1846 |
/* |
1847 |
* Undocumented, used by IRIX. |
1848 |
*/ |
1849 |
debug("[ ARCBIOS: IRIX 0x100 (?) ]\n"); |
1850 |
/* TODO */ |
1851 |
cpu->cd.mips.gpr[MIPS_GPR_V0] = 0; |
1852 |
break; |
1853 |
case 0x888: |
1854 |
/* |
1855 |
* Magical crash if there is no exception handling code. |
1856 |
*/ |
1857 |
fatal("EXCEPTION, but no exception handler installed yet.\n"); |
1858 |
quiet_mode = 0; |
1859 |
cpu_register_dump(cpu->machine, cpu, 1, 0x1); |
1860 |
cpu->running = 0; |
1861 |
cpu->dead = 1; |
1862 |
break; |
1863 |
default: |
1864 |
quiet_mode = 0; |
1865 |
cpu_register_dump(cpu->machine, cpu, 1, 0x1); |
1866 |
debug("a0 points to: "); |
1867 |
dump_mem_string(cpu, cpu->cd.mips.gpr[MIPS_GPR_A0]); |
1868 |
debug("\n"); |
1869 |
fatal("ARCBIOS: unimplemented vector 0x%x\n", vector); |
1870 |
cpu->running = 0; |
1871 |
cpu->dead = 1; |
1872 |
} |
1873 |
|
1874 |
return 1; |
1875 |
} |
1876 |
|
1877 |
|
1878 |
/* |
1879 |
* arcbios_set_64bit_mode(): |
1880 |
* |
1881 |
* Should be used for some SGI modes. |
1882 |
*/ |
1883 |
void arcbios_set_64bit_mode(int enable) |
1884 |
{ |
1885 |
arc_64bit = enable; |
1886 |
arc_wordlen = arc_64bit? sizeof(uint64_t) : sizeof(uint32_t); |
1887 |
} |
1888 |
|
1889 |
|
1890 |
/* |
1891 |
* arcbios_set_default_exception_handler(): |
1892 |
*/ |
1893 |
void arcbios_set_default_exception_handler(struct cpu *cpu) |
1894 |
{ |
1895 |
/* |
1896 |
* The default exception handlers simply jump to 0xbfc88888, |
1897 |
* which is then taken care of in arcbios_emul() above. |
1898 |
* |
1899 |
* 3c1abfc8 lui k0,0xbfc8 |
1900 |
* 375a8888 ori k0,k0,0x8888 |
1901 |
* 03400008 jr k0 |
1902 |
* 00000000 nop |
1903 |
*/ |
1904 |
store_32bit_word(cpu, 0xffffffff80000000ULL, 0x3c1abfc8); |
1905 |
store_32bit_word(cpu, 0xffffffff80000004ULL, 0x375a8888); |
1906 |
store_32bit_word(cpu, 0xffffffff80000008ULL, 0x03400008); |
1907 |
store_32bit_word(cpu, 0xffffffff8000000cULL, 0x00000000); |
1908 |
|
1909 |
store_32bit_word(cpu, 0xffffffff80000080ULL, 0x3c1abfc8); |
1910 |
store_32bit_word(cpu, 0xffffffff80000084ULL, 0x375a8888); |
1911 |
store_32bit_word(cpu, 0xffffffff80000088ULL, 0x03400008); |
1912 |
store_32bit_word(cpu, 0xffffffff8000008cULL, 0x00000000); |
1913 |
|
1914 |
store_32bit_word(cpu, 0xffffffff80000180ULL, 0x3c1abfc8); |
1915 |
store_32bit_word(cpu, 0xffffffff80000184ULL, 0x375a8888); |
1916 |
store_32bit_word(cpu, 0xffffffff80000188ULL, 0x03400008); |
1917 |
store_32bit_word(cpu, 0xffffffff8000018cULL, 0x00000000); |
1918 |
} |
1919 |
|
1920 |
|
1921 |
/* |
1922 |
* arcbios_init(): |
1923 |
* |
1924 |
* Should be called before any other arcbios function is used. |
1925 |
*/ |
1926 |
void arcbios_init(void) |
1927 |
{ |
1928 |
int i; |
1929 |
|
1930 |
/* File handles 0, 1, and 2 are stdin, stdout, and stderr. */ |
1931 |
for (i=0; i<MAX_HANDLES; i++) { |
1932 |
file_handle_in_use[i] = i<3? 1 : 0; |
1933 |
file_handle_string[i] = NULL; |
1934 |
arcbios_current_seek_offset[i] = 0; |
1935 |
} |
1936 |
} |
1937 |
|