/[gxemul]/upstream/0.3.3.2/src/dec_prom.c
This is repository of my old source code which isn't updated any more. Go to git.rot13.org for current projects!
ViewVC logotype

Contents of /upstream/0.3.3.2/src/dec_prom.c

Parent Directory Parent Directory | Revision Log Revision Log


Revision 9 - (show annotations)
Mon Oct 8 16:18:22 2007 UTC (16 years, 6 months ago) by dpavlin
File MIME type: text/plain
File size: 19383 byte(s)
0.3.3.2
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: dec_prom.c,v 1.58 2005/05/15 01:55:49 debug Exp $
29 *
30 * DECstation PROM emulation.
31 */
32
33 #include <stdio.h>
34 #include <stdlib.h>
35 #include <string.h>
36 #include <sys/types.h>
37 #include <sys/time.h>
38 #include <sys/resource.h>
39
40 #include "console.h"
41 #include "cpu.h"
42 #include "cpu_mips.h"
43 #include "diskimage.h"
44 #include "machine.h"
45 #include "memory.h"
46 #include "misc.h"
47
48 #include "dec_prom.h"
49 #include "dec_5100.h"
50 #include "dec_kn01.h"
51 #include "dec_kn02.h"
52 #include "dec_kn03.h"
53
54
55 extern int quiet_mode;
56
57
58 /*
59 * mem_readchar():
60 *
61 * Reads a byte from emulated RAM, using a MIPS register as a base address.
62 * (Helper function.)
63 */
64 static unsigned char mem_readchar(struct cpu *cpu, int regbase, int offset)
65 {
66 unsigned char ch;
67 cpu->memory_rw(cpu, cpu->mem, cpu->cd.mips.gpr[regbase] + offset,
68 &ch, sizeof(ch), MEM_READ, CACHE_DATA | NO_EXCEPTIONS);
69 return ch;
70 }
71
72
73 /*
74 * dec_jumptable_func():
75 *
76 * The jumptable is located at the beginning of the PROM, at 0xbfc00000 + i*8,
77 * where i is the decimal function number. Many of these can be converted to
78 * an identical callback function.
79 *
80 * Return value is non-zero if the vector number was converted into a callback
81 * function number, otherwise 0.
82 *
83 * Vector (dec) Function
84 * 0x0 0 reset()
85 * 0x10 2 restart()
86 * 0x18 3 reinit()
87 * 0x30 6 open()
88 * 0x38 7 read()
89 * 0x58 11 lseek()
90 * 0x68 13 putchar()
91 * 0x88 17 printf()
92 * 0x108 33 getenv2()
93 */
94 int dec_jumptable_func(struct cpu *cpu, int vector)
95 {
96 int i;
97 static int file_opened = 0;
98 static int current_file_offset = 0;
99
100 switch (vector) {
101 case 0x0: /* reset() */
102 /* TODO */
103 cpu->machine->exit_without_entering_debugger = 1;
104 cpu->running = 0;
105 cpu->dead = 1;
106 break;
107 case 0x10: /* restart() */
108 /* TODO */
109 cpu->machine->exit_without_entering_debugger = 1;
110 cpu->running = 0;
111 cpu->dead = 1;
112 break;
113 case 0x18: /* reinit() */
114 /* TODO */
115 cpu->machine->exit_without_entering_debugger = 1;
116 cpu->cd.mips.gpr[MIPS_GPR_V0] = 0;
117 break;
118 case 0x30: /* open() */
119 /*
120 * TODO: This is just a hack to allow Sprite/pmax' bootblock
121 * code to load /vmsprite. The filename argument (in A0)
122 * is ignored, and a file handle value of 1 is returned.
123 */
124 if (file_opened) {
125 fatal("\ndec_jumptable_func(): opening more than one "
126 "file isn't supported yet.\n");
127 cpu->running = 0;
128 cpu->dead = 1;
129 }
130 file_opened = 1;
131 cpu->cd.mips.gpr[MIPS_GPR_V0] = 1;
132 break;
133 case 0x38: /* read(handle, ptr, length) */
134 cpu->cd.mips.gpr[MIPS_GPR_V0] = -1;
135 if ((int32_t)cpu->cd.mips.gpr[MIPS_GPR_A2] > 0) {
136 int disk_id = diskimage_bootdev(cpu->machine, NULL);
137 int res;
138 unsigned char *tmp_buf;
139
140 tmp_buf = malloc(cpu->cd.mips.gpr[MIPS_GPR_A2]);
141 if (tmp_buf == NULL) {
142 fprintf(stderr, "[ *** Out of memory in "
143 "dec_prom.c, allocating %i bytes ]\n",
144 (int)cpu->cd.mips.gpr[MIPS_GPR_A2]);
145 break;
146 }
147
148 res = diskimage_access(cpu->machine, disk_id,
149 DISKIMAGE_SCSI, 0, current_file_offset, tmp_buf,
150 cpu->cd.mips.gpr[MIPS_GPR_A2]);
151
152 /* If the transfer was successful, transfer the data
153 to emulated memory: */
154 if (res) {
155 uint64_t dst = cpu->cd.mips.gpr[MIPS_GPR_A1];
156 store_buf(cpu, dst, (char *)tmp_buf,
157 cpu->cd.mips.gpr[MIPS_GPR_A2]);
158 cpu->cd.mips.gpr[MIPS_GPR_V0] =
159 cpu->cd.mips.gpr[MIPS_GPR_A2];
160 current_file_offset +=
161 cpu->cd.mips.gpr[MIPS_GPR_A2];
162 }
163
164 free(tmp_buf);
165 }
166 break;
167 case 0x58: /* lseek(handle, offset[, whence]) */
168 /* TODO */
169 if (cpu->cd.mips.gpr[MIPS_GPR_A2] == 0)
170 current_file_offset = cpu->cd.mips.gpr[MIPS_GPR_A1];
171 else
172 fatal("WARNING! Unimplemented whence in "
173 "dec_jumptable_func()\n");
174 cpu->cd.mips.gpr[MIPS_GPR_V0] = 0;
175 break;
176 case 0x68: /* putchar() */
177 console_putchar(cpu->machine->main_console_handle,
178 cpu->cd.mips.gpr[MIPS_GPR_A0]);
179 break;
180 case 0x88: /* printf() */
181 return 0x30;
182 case 0x108: /* getenv2() */
183 return 0x64;
184 default:
185 cpu_register_dump(cpu->machine, cpu, 1, 0x1);
186 printf("a0 points to: ");
187 for (i=0; i<40; i++) {
188 unsigned char ch = '\0';
189 cpu->memory_rw(cpu, cpu->mem,
190 cpu->cd.mips.gpr[MIPS_GPR_A0] + i, &ch,
191 sizeof(ch), MEM_READ, CACHE_DATA | NO_EXCEPTIONS);
192 if (ch >= ' ' && ch < 126)
193 printf("%c", ch);
194 else
195 printf("[%02x]", ch);
196 }
197 printf("\n");
198 fatal("PROM emulation: unimplemented JUMP TABLE vector "
199 "0x%x (decimal function %i)\n", vector, vector/8);
200 cpu->running = 0;
201 cpu->dead = 1;
202 }
203
204 return 0;
205 }
206
207
208 /*
209 * decstation_prom_emul():
210 *
211 * DECstation PROM emulation.
212 *
213 * Callback functions:
214 * 0x0c strcmp()
215 * 0x14 strlen()
216 * 0x24 getchar()
217 * 0x28 gets()
218 * 0x2c puts()
219 * 0x30 printf()
220 * 0x38 iopoll()
221 * 0x54 bootinit()
222 * 0x58 bootread()
223 * 0x64 getenv()
224 * 0x6c slot_address()
225 * 0x70 wbflush()
226 * 0x7c clear_cache()
227 * 0x80 getsysid()
228 * 0x84 getbitmap()
229 * 0x88 disableintr()
230 * 0x8c enableintr()
231 * 0x9c halt()
232 * 0xa4 gettcinfo()
233 * 0xa8 execute_cmd()
234 * 0xac rex()
235 */
236 int decstation_prom_emul(struct cpu *cpu)
237 {
238 int i, j, ch, argreg, argdata;
239 int vector = cpu->pc & 0xfff;
240 int callback = (cpu->pc & 0xf000)? 1 : 0;
241 unsigned char buf[100];
242 unsigned char ch1, ch2, ch3;
243 uint64_t tmpaddr, slot_base = 0x10000000, slot_size = 0;
244
245 if (!callback) {
246 vector = dec_jumptable_func(cpu, vector);
247 if (vector == 0)
248 return 1;
249 } else {
250 /* Vector number is n*4, PC points to n*8. */
251 vector /= 2;
252 }
253
254 switch (vector) {
255 case 0x0c: /* strcmp(): */
256 i = j = 0;
257 do {
258 ch1 = mem_readchar(cpu, MIPS_GPR_A0, i++);
259 ch2 = mem_readchar(cpu, MIPS_GPR_A1, j++);
260 } while (ch1 == ch2 && ch1 != '\0');
261
262 /* If ch1=='\0', then strings are equal. */
263 if (ch1 == '\0')
264 cpu->cd.mips.gpr[MIPS_GPR_V0] = 0;
265 if ((signed char)ch1 > (signed char)ch2)
266 cpu->cd.mips.gpr[MIPS_GPR_V0] = 1;
267 if ((signed char)ch1 < (signed char)ch2)
268 cpu->cd.mips.gpr[MIPS_GPR_V0] = -1;
269 break;
270 case 0x14: /* strlen(): */
271 i = 0;
272 do {
273 ch2 = mem_readchar(cpu, MIPS_GPR_A0, i++);
274 } while (ch2 != 0);
275 cpu->cd.mips.gpr[MIPS_GPR_V0] = i - 1;
276 break;
277 case 0x24: /* getchar() */
278 /* debug("[ DEC PROM getchar() ]\n"); */
279 cpu->cd.mips.gpr[MIPS_GPR_V0] = console_readchar(
280 cpu->machine->main_console_handle);
281 break;
282 case 0x28: /* gets() */
283 /* debug("[ DEC PROM gets() ]\n"); */
284 tmpaddr = cpu->cd.mips.gpr[MIPS_GPR_A0];
285 i = 0;
286
287 /* TODO: Make this not hang (block) the entire emulator */
288
289 do {
290 while ((ch = console_readchar(
291 cpu->machine->main_console_handle)) < 1)
292 ;
293 if (ch == '\r')
294 ch = '\n';
295 ch2 = ch;
296
297 if (ch == '\b') {
298 if (i > 0) {
299 console_putchar(cpu->machine->
300 main_console_handle, ch2);
301 console_putchar(cpu->machine->
302 main_console_handle, ' ');
303 console_putchar(cpu->machine->
304 main_console_handle, ch2);
305 }
306 } else
307 console_putchar(cpu->machine->
308 main_console_handle, ch2);
309
310 fflush(stdout);
311
312 if (ch == '\n') {
313 /* It seems that trailing newlines
314 are not included in the buffer. */
315 } else if (ch != '\b') {
316 cpu->memory_rw(cpu, cpu->mem,
317 cpu->cd.mips.gpr[MIPS_GPR_A0] + i,
318 &ch2, sizeof(ch2), MEM_WRITE,
319 CACHE_DATA | NO_EXCEPTIONS);
320 i++;
321 } else {
322 if (i > 0)
323 i--;
324 }
325 } while (ch2 != '\n');
326
327 /* Trailing nul-byte: */
328 ch2 = '\0';
329 cpu->memory_rw(cpu, cpu->mem, cpu->cd.mips.gpr[MIPS_GPR_A0] +
330 i, &ch2, sizeof(ch2), MEM_WRITE,
331 CACHE_DATA | NO_EXCEPTIONS);
332
333 /* Return the input argument: */
334 cpu->cd.mips.gpr[MIPS_GPR_V0] = cpu->cd.mips.gpr[MIPS_GPR_A0];
335 break;
336 case 0x2c: /* puts() */
337 i = 0;
338 while ((ch = mem_readchar(cpu, MIPS_GPR_A0, i++)) != '\0')
339 console_putchar(cpu->machine->main_console_handle, ch);
340 console_putchar(cpu->machine->main_console_handle, '\n');
341 cpu->cd.mips.gpr[MIPS_GPR_V0] = 0;
342 break;
343 case 0x30: /* printf() */
344 if (cpu->machine->register_dump ||
345 cpu->machine->instruction_trace)
346 debug("PROM printf(0x%08lx): \n",
347 (long)cpu->cd.mips.gpr[MIPS_GPR_A0]);
348
349 i = 0; ch = -1; argreg = MIPS_GPR_A1;
350 while (ch != '\0') {
351 char printfbuf[8000];
352 int x;
353
354 printfbuf[0] = printfbuf[sizeof(printfbuf)-1] = '\0';
355
356 ch = mem_readchar(cpu, MIPS_GPR_A0, i++);
357 switch (ch) {
358 case '%':
359 ch = '0';
360 while (ch >= '0' && ch <= '9')
361 ch = mem_readchar(cpu,
362 MIPS_GPR_A0, i++);
363
364 switch (ch) {
365 case '%':
366 strcpy(printfbuf, "%%");
367 break;
368 case 'c':
369 case 'd':
370 case 's':
371 case 'x':
372 /* Get argument: */
373 if (argreg > MIPS_GPR_A3) {
374 #if 1
375 /* Linux booters seem to go
376 over the edge sometimes: */
377 ch = '\0';
378 strcpy(printfbuf, "[...]\n");
379 #else
380 printf("[ decstation_prom_emul"
381 "(): too many arguments ]");
382 /* This reuses the last arg,
383 which is utterly incorrect.
384 (TODO) */
385 argreg = MIPS_GPR_A3;
386 #endif
387 }
388
389 ch2 = argdata =
390 cpu->cd.mips.gpr[argreg];
391
392 switch (ch) {
393 case 'c':
394 sprintf(printfbuf, "%c", ch2);
395 break;
396 case 'd':
397 sprintf(printfbuf, "%d",
398 argdata);
399 break;
400 case 'x':
401 sprintf(printfbuf, "%x",
402 argdata);
403 break;
404 case 's':
405 /* Print a "%s" string. */
406 j = 0; ch3 = '\n';
407 while (ch2) {
408 ch2 = mem_readchar(cpu,
409 argreg, j++);
410 if (ch2) {
411 snprintf(
412 printfbuf +
413 strlen(
414 printfbuf),
415 sizeof(
416 printfbuf)-
417 1-strlen(
418 printfbuf),
419 "%c", ch2);
420 ch3 = ch2;
421 }
422 }
423 break;
424 }
425 argreg ++;
426 break;
427 default:
428 printf("[ unknown printf format char"
429 " '%c' ]", ch);
430 }
431 break;
432 case '\0':
433 break;
434 default:
435 sprintf(printfbuf, "%c", ch);
436 }
437
438 printfbuf[sizeof(printfbuf)-1] = '\0';
439
440 for (x=0; x<strlen(printfbuf); x++)
441 console_putchar(cpu->machine->
442 main_console_handle, printfbuf[x]);
443 }
444 if (cpu->machine->register_dump ||
445 cpu->machine->instruction_trace)
446 debug("\n");
447 fflush(stdout);
448 cpu->cd.mips.gpr[MIPS_GPR_V0] = 0;
449 break;
450 case 0x54: /* bootinit() */
451 /* debug("[ DEC PROM bootinit(0x%08x): TODO ]\n",
452 (int)cpu->cd.mips.gpr[MIPS_GPR_A0]); */
453 cpu->cd.mips.gpr[MIPS_GPR_V0] = 0;
454 break;
455 case 0x58: /* bootread(int b, void *buffer, int n) */
456 /*
457 * Read data from the boot device.
458 * b is a sector number (512 bytes per sector),
459 * buffer is the destination address, and n
460 * is the number of _bytes_ to read.
461 *
462 * TODO: Return value? NetBSD thinks that 0 is ok.
463 */
464 debug("[ DEC PROM bootread(0x%x, 0x%08x, 0x%x) ]\n",
465 (int)cpu->cd.mips.gpr[MIPS_GPR_A0],
466 (int)cpu->cd.mips.gpr[MIPS_GPR_A1],
467 (int)cpu->cd.mips.gpr[MIPS_GPR_A2]);
468
469 cpu->cd.mips.gpr[MIPS_GPR_V0] = 0;
470
471 if ((int32_t)cpu->cd.mips.gpr[MIPS_GPR_A2] > 0) {
472 int disk_id = diskimage_bootdev(cpu->machine, NULL);
473 int res;
474 unsigned char *tmp_buf;
475
476 tmp_buf = malloc(cpu->cd.mips.gpr[MIPS_GPR_A2]);
477 if (tmp_buf == NULL) {
478 fprintf(stderr, "[ *** Out of memory in "
479 "dec_prom.c, allocating %i bytes ]\n",
480 (int)cpu->cd.mips.gpr[MIPS_GPR_A2]);
481 break;
482 }
483
484 res = diskimage_access(cpu->machine, disk_id,
485 DISKIMAGE_SCSI, 0,
486 cpu->cd.mips.gpr[MIPS_GPR_A0] * 512, tmp_buf,
487 cpu->cd.mips.gpr[MIPS_GPR_A2]);
488
489 /* If the transfer was successful, transfer the data
490 to emulated memory: */
491 if (res) {
492 uint64_t dst = cpu->cd.mips.gpr[MIPS_GPR_A1];
493 if (dst < 0x80000000ULL)
494 dst |= 0x80000000;
495
496 store_buf(cpu, dst, (char *)tmp_buf,
497 cpu->cd.mips.gpr[MIPS_GPR_A2]);
498 cpu->cd.mips.gpr[MIPS_GPR_V0] =
499 cpu->cd.mips.gpr[MIPS_GPR_A2];
500 }
501
502 free(tmp_buf);
503 }
504 break;
505 case 0x64: /* getenv() */
506 /* Find the environment variable given by a0: */
507 for (i=0; i<sizeof(buf); i++)
508 cpu->memory_rw(cpu, cpu->mem,
509 cpu->cd.mips.gpr[MIPS_GPR_A0] + i, &buf[i],
510 sizeof(char), MEM_READ, CACHE_DATA | NO_EXCEPTIONS);
511 buf[sizeof(buf)-1] = '\0';
512 debug("[ DEC PROM getenv(\"%s\") ]\n", buf);
513 for (i=0; i<0x1000; i++) {
514 /* Matching string at offset i? */
515 int nmatches = 0;
516 for (j=0; j<strlen((char *)buf); j++) {
517 cpu->memory_rw(cpu, cpu->mem, (uint64_t)
518 (DEC_PROM_STRINGS + i + j), &ch2,
519 sizeof(char), MEM_READ, CACHE_DATA |
520 NO_EXCEPTIONS);
521 if (ch2 == buf[j])
522 nmatches++;
523 }
524 cpu->memory_rw(cpu, cpu->mem,
525 (uint64_t)(DEC_PROM_STRINGS
526 + i + strlen((char *)buf)), &ch2, sizeof(char),
527 MEM_READ, CACHE_DATA | NO_EXCEPTIONS);
528 if (nmatches == strlen((char *)buf) && ch2 == '=') {
529 cpu->cd.mips.gpr[MIPS_GPR_V0] =
530 DEC_PROM_STRINGS + i +
531 strlen((char *)buf) + 1;
532 return 1;
533 }
534 }
535 /* Return NULL if string wasn't found. */
536 fatal("[ DEC PROM getenv(\"%s\"): WARNING: Not in "
537 "environment! ]\n", buf);
538 cpu->cd.mips.gpr[MIPS_GPR_V0] = 0;
539 break;
540 case 0x6c: /* ulong slot_address(int sn) */
541 debug("[ DEC PROM slot_address(%i) ]\n",
542 (int)cpu->cd.mips.gpr[MIPS_GPR_A0]);
543 /* TODO: This is too hardcoded. */
544 /* TODO 2: Should these be physical or virtual addresses? */
545 switch (cpu->machine->machine_subtype) {
546 case MACHINE_DEC_3MAX_5000:
547 slot_base = KN02_PHYS_TC_0_START;/* 0x1e000000 */
548 slot_size = 4*1048576; /* 4 MB */
549 break;
550 case MACHINE_DEC_3MIN_5000:
551 slot_base = 0x10000000;
552 slot_size = 0x4000000; /* 64 MB */
553 break;
554 case MACHINE_DEC_3MAXPLUS_5000:
555 slot_base = 0x1e000000;
556 slot_size = 0x800000; /* 8 MB */
557 break;
558 case MACHINE_DEC_MAXINE_5000:
559 slot_base = 0x10000000;
560 slot_size = 0x4000000; /* 64 MB */
561 break;
562 default:
563 fatal("warning: DEC PROM slot_address() "
564 "unimplemented for this machine type\n");
565 }
566 cpu->cd.mips.gpr[MIPS_GPR_V0] = (int64_t)(int32_t)
567 (0x80000000 + slot_base + slot_size *
568 cpu->cd.mips.gpr[MIPS_GPR_A0]);
569 break;
570 case 0x70: /* wbflush() */
571 debug("[ DEC PROM wbflush(): TODO ]\n");
572 cpu->cd.mips.gpr[MIPS_GPR_V0] = 0;
573 break;
574 case 0x7c: /* clear_cache(addr, len) */
575 debug("[ DEC PROM clear_cache(0x%x,%i) ]\n",
576 (uint32_t)cpu->cd.mips.gpr[MIPS_GPR_A0],
577 (int)cpu->cd.mips.gpr[MIPS_GPR_A1]);
578 /* TODO */
579 cpu->cd.mips.gpr[MIPS_GPR_V0] = 0; /* ? */
580 break;
581 case 0x80: /* getsysid() */
582 /* debug("[ DEC PROM getsysid() ]\n"); */
583 /* TODO: why did I add the 0x82 stuff??? */
584 cpu->cd.mips.gpr[MIPS_GPR_V0] = ((uint32_t)0x82 << 24)
585 + (cpu->machine->machine_subtype << 16) + (0x3 << 8);
586 cpu->cd.mips.gpr[MIPS_GPR_V0] =
587 (int64_t)(int32_t)cpu->cd.mips.gpr[MIPS_GPR_V0];
588 break;
589 case 0x84: /* getbitmap() */
590 debug("[ DEC PROM getbitmap(0x%08x) ]\n",
591 (int)cpu->cd.mips.gpr[MIPS_GPR_A0]);
592 store_buf(cpu, cpu->cd.mips.gpr[MIPS_GPR_A0],
593 (char *)&memmap, sizeof(memmap));
594 cpu->cd.mips.gpr[MIPS_GPR_V0] = sizeof((memmap.bitmap));
595 break;
596 case 0x88: /* disableintr() */
597 debug("[ DEC PROM disableintr(): TODO ]\n");
598 cpu->cd.mips.gpr[MIPS_GPR_V0] = 0;
599 break;
600 case 0x8c: /* enableintr() */
601 debug("[ DEC PROM enableintr(): TODO ]\n");
602 cpu->cd.mips.gpr[MIPS_GPR_V0] = 0;
603 break;
604 case 0x9c: /* halt() */
605 debug("[ DEC PROM halt() ]\n");
606 cpu->machine->exit_without_entering_debugger = 1;
607 cpu->running = 0;
608 cpu->dead = 1;
609 break;
610 case 0xa4: /* gettcinfo() */
611 /*
612 * These are just bogus values... TODO
613 *
614 * 0: revision
615 * 4: clock period in nano seconds
616 * 8: slot size in megabytes TODO: not same for all models!
617 * 12: I/O timeout in cycles
618 * 16: DMA address range in megabytes
619 * 20: maximum DMA burst length
620 * 24: turbochannel parity (yes = 1)
621 * 28: reserved
622 */
623 store_32bit_word(cpu, DEC_PROM_TCINFO + 0, 0);
624 store_32bit_word(cpu, DEC_PROM_TCINFO + 4, 50);
625 store_32bit_word(cpu, DEC_PROM_TCINFO + 8, 4);
626 store_32bit_word(cpu, DEC_PROM_TCINFO + 12, 10);
627 store_32bit_word(cpu, DEC_PROM_TCINFO + 16, 1);
628 store_32bit_word(cpu, DEC_PROM_TCINFO + 20, 100);
629 store_32bit_word(cpu, DEC_PROM_TCINFO + 24, 0);
630 store_32bit_word(cpu, DEC_PROM_TCINFO + 28, 0);
631 cpu->cd.mips.gpr[MIPS_GPR_V0] = DEC_PROM_TCINFO;
632 break;
633 case 0xa8: /* int execute_cmd(char *) */
634 i = 0;
635 while ((ch = mem_readchar(cpu, MIPS_GPR_A0, i++)) != '\0')
636 console_putchar(cpu->machine->main_console_handle, ch);
637 console_putchar(cpu->machine->main_console_handle, '\n');
638 cpu->cd.mips.gpr[MIPS_GPR_V0] = 0;
639 break;
640 case 0xac: /* rex() */
641 debug("[ DEC PROM rex('%c') ]\n",
642 (int)cpu->cd.mips.gpr[MIPS_GPR_A0]);
643 switch (cpu->cd.mips.gpr[MIPS_GPR_A0]) {
644 case 'h':
645 debug("DEC PROM: rex('h') ==> halt\n");
646 cpu->machine->exit_without_entering_debugger = 1;
647 cpu->running = 0;
648 cpu->dead = 1;
649 break;
650 case 'b':
651 debug("DEC PROM: rex('b') ==> reboot: TODO "
652 "(halting CPU instead)\n");
653 cpu->machine->exit_without_entering_debugger = 1;
654 cpu->running = 0;
655 cpu->dead = 1;
656 break;
657 default:
658 fatal("DEC prom emulation: unknown rex() a0=0x%llx ("
659 "'%c')\n", (long long)cpu->cd.mips.gpr[MIPS_GPR_A0],
660 (char)cpu->cd.mips.gpr[MIPS_GPR_A0]);
661 cpu->running = 0;
662 cpu->dead = 1;
663 }
664 break;
665 default:
666 cpu_register_dump(cpu->machine, cpu, 1, 0x1);
667 printf("a0 points to: ");
668 for (i=0; i<40; i++) {
669 unsigned char ch = '\0';
670 cpu->memory_rw(cpu, cpu->mem,
671 cpu->cd.mips.gpr[MIPS_GPR_A0] + i, &ch,
672 sizeof(ch), MEM_READ, CACHE_DATA | NO_EXCEPTIONS);
673 if (ch >= ' ' && ch < 126)
674 printf("%c", ch);
675 else
676 printf("[%02x]", ch);
677 }
678 printf("\n");
679 fatal("PROM emulation: unimplemented callback vector 0x%x\n",
680 vector);
681 cpu->running = 0;
682 cpu->dead = 1;
683 }
684
685 return 1;
686 }
687

  ViewVC Help
Powered by ViewVC 1.1.26