/[gxemul]/upstream/0.4.0/src/promemul/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.4.0/src/promemul/dec_prom.c

Parent Directory Parent Directory | Revision Log Revision Log


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

  ViewVC Help
Powered by ViewVC 1.1.26