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

Annotation of /upstream/0.4.0/src/promemul/dec_prom.c

Parent Directory Parent Directory | Revision Log Revision Log


Revision 25 - (hide annotations)
Mon Oct 8 16:20:03 2007 UTC (16 years, 8 months ago) by dpavlin
File MIME type: text/plain
File size: 19833 byte(s)
0.4.0
1 dpavlin 14 /*
2 dpavlin 22 * Copyright (C) 2003-2006 Anders Gavare. All rights reserved.
3 dpavlin 14 *
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 dpavlin 24 * $Id: dec_prom.c,v 1.9 2006/06/23 11:47:05 debug Exp $
29 dpavlin 14 *
30     * DECstation PROM emulation.
31 dpavlin 24 *
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 dpavlin 14 */
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 dpavlin 24 {
69 dpavlin 14 unsigned char ch;
70 dpavlin 24 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 dpavlin 14 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 dpavlin 24 (int32_t)cpu->cd.mips.gpr[MIPS_GPR_A0] + i, &ch,
194 dpavlin 14 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 dpavlin 24 cpu->memory_rw(cpu, cpu->mem, (int32_t)
320 dpavlin 14 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 dpavlin 24 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 dpavlin 14
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 dpavlin 22 size_t x;
356 dpavlin 14
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 dpavlin 22 for (i=0; i<(int)sizeof(buf); i++)
515 dpavlin 24 cpu->memory_rw(cpu, cpu->mem, (int32_t)
516 dpavlin 14 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 dpavlin 22 for (j=0; j<(int32_t)strlen((char *)buf); j++) {
524 dpavlin 24 cpu->memory_rw(cpu, cpu->mem, (int32_t)
525 dpavlin 14 (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 dpavlin 24 cpu->memory_rw(cpu, cpu->mem, (int32_t)(DEC_PROM_STRINGS
532 dpavlin 14 + i + strlen((char *)buf)), &ch2, sizeof(char),
533     MEM_READ, CACHE_DATA | NO_EXCEPTIONS);
534 dpavlin 22 if (nmatches == (int)strlen((char *)buf) && ch2=='=') {
535 dpavlin 14 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 dpavlin 24 (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 dpavlin 14 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 dpavlin 24 switch ((int32_t)cpu->cd.mips.gpr[MIPS_GPR_A0]) {
652 dpavlin 14 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 dpavlin 24 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 dpavlin 14 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 dpavlin 24 cpu->memory_rw(cpu, cpu->mem, (int32_t)
680 dpavlin 14 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