/[gxemul]/trunk/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

Annotation of /trunk/src/dec_prom.c

Parent Directory Parent Directory | Revision Log Revision Log


Revision 10 - (hide annotations)
Mon Oct 8 16:18:27 2007 UTC (16 years, 6 months ago) by dpavlin
File MIME type: text/plain
File size: 19543 byte(s)
++ trunk/HISTORY	(local)
$Id: HISTORY,v 1.815 2005/06/27 23:04:35 debug Exp $
20050617	Experimenting some more with netbooting OpenBSD/sgi. Adding
		a hack which allows emulated ethernet networks to be
		distributed across multiple emulator processes.
20050618	Minor updates (documentation, dummy YAMON emulation, etc).
20050620	strcpy/strcat -> strlcpy/strlcat updates.
		Some more progress on evbmips (Malta).
20050621	Adding a section to doc/configfiles.html about ethernet
		emulation across multiple hosts.
		Beginning the work on the ARM translation engine (using the
		dynamic-but-not-binary translation method).
		Fixing a bintrans bug: 0x9fc00000 should always be treated as
		PROM area, just as 0xbfc00000 is.
		Minor progress on Malta emulation (the PCI-ISA bus).
20050622	NetBSD/evbmips can now be installed (using another emulated
		machine) and run (including userland and so on). :-)
		Spliting up the bintrans haddr_entry field into two (one for
		read, one for write). Probably not much of a speed increase,
		though.
		Updating some NetBSD 2.0 -> 2.0.2 in the documentation.
20050623	Minor updates (documentation, the TODO file, etc).
		gzipped kernels are now always automagically gunzipped when
		loaded.
20050624	Adding a dummy Playstation Portable (PSP) mode, just barely
		enough to run Hello World (in weird colors :-).
		Removing the -b command line option; old bintrans is enabled
		by default instead. It makes more sense.
		Trying to finally fix the non-working performance measurement
		thing (instr/second etc).
20050625	Continuing on the essential basics for ARM emulation. Two
		instructions seem to work, a branch and a simple "mov". (The
		mov arguments are not correct yet.) Performance is definitely
		reasonable.
		Various other minor updates.
		Adding the ARM "bl" instruction.
		Adding support for combining multiple ARM instructions into one
		function call. ("mov" + "mov" is the only one implemented so
		far, but it seems to work.)
		Cleaning up some IP32 interrupt things (crime/mace); disabling
		the PS/2 keyboard controller on IP32, so that NetBSD/sgimips
		boots into userland again.
20050626	Finally! NetBSD/sgimips netboots. Adding instructions to
		doc/guestoses.html on how to set up an nfs server etc.
		Various other minor fixes.
		Playstation Portable ".pbp" files can now be used directly.
		(The ELF part of the .pbp is extracted transparently.)
		Converting some sprintf -> snprintf.
		Adding some more instructions to the ARM disassembler.
20050627	More ARM updates. Adding some simple ldr(b), str(b),
		cmps, and conditional branch instructions, enough to run
		a simple Hello World program.
		All ARM instructions are now inlined/generated for all possible
		condition codes.
		Adding add and sub, and more load/store instructions.
		Removing dummy files: cpu_alpha.c, cpu_hppa.c, and cpu_sparc.c.
		Some minor documentation updates; preparing for a 0.3.4
		release. Updating some URLs.

==============  RELEASE 0.3.4  ==============


1 dpavlin 2 /*
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 dpavlin 10 * $Id: dec_prom.c,v 1.60 2005/06/26 11:36:28 debug Exp $
29 dpavlin 2 *
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 dpavlin 6 int disk_id = diskimage_bootdev(cpu->machine, NULL);
137 dpavlin 2 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 dpavlin 6 res = diskimage_access(cpu->machine, disk_id,
149     DISKIMAGE_SCSI, 0, current_file_offset, tmp_buf,
150 dpavlin 2 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 dpavlin 10 strlcpy(printfbuf, "%%",
367     sizeof(printfbuf));
368 dpavlin 2 break;
369     case 'c':
370     case 'd':
371     case 's':
372     case 'x':
373     /* Get argument: */
374     if (argreg > MIPS_GPR_A3) {
375     #if 1
376     /* Linux booters seem to go
377     over the edge sometimes: */
378     ch = '\0';
379 dpavlin 10 strlcpy(printfbuf, "[...]\n",
380     sizeof(printfbuf));
381 dpavlin 2 #else
382     printf("[ decstation_prom_emul"
383     "(): too many arguments ]");
384     /* This reuses the last arg,
385     which is utterly incorrect.
386     (TODO) */
387     argreg = MIPS_GPR_A3;
388     #endif
389     }
390    
391     ch2 = argdata =
392     cpu->cd.mips.gpr[argreg];
393    
394     switch (ch) {
395     case 'c':
396 dpavlin 10 snprintf(printfbuf, sizeof(
397     printfbuf), "%c", ch2);
398 dpavlin 2 break;
399     case 'd':
400 dpavlin 10 snprintf(printfbuf, sizeof(
401     printfbuf), "%d", argdata);
402 dpavlin 2 break;
403     case 'x':
404 dpavlin 10 snprintf(printfbuf, sizeof(
405     printfbuf), "%x", argdata);
406 dpavlin 2 break;
407     case 's':
408     /* Print a "%s" string. */
409     j = 0; ch3 = '\n';
410     while (ch2) {
411     ch2 = mem_readchar(cpu,
412     argreg, j++);
413     if (ch2) {
414     snprintf(
415     printfbuf +
416     strlen(
417     printfbuf),
418     sizeof(
419     printfbuf)-
420     1-strlen(
421     printfbuf),
422     "%c", ch2);
423     ch3 = ch2;
424     }
425     }
426     break;
427     }
428     argreg ++;
429     break;
430     default:
431     printf("[ unknown printf format char"
432     " '%c' ]", ch);
433     }
434     break;
435     case '\0':
436     break;
437     default:
438 dpavlin 10 snprintf(printfbuf, sizeof(printfbuf),
439     "%c", ch);
440 dpavlin 2 }
441    
442     printfbuf[sizeof(printfbuf)-1] = '\0';
443    
444     for (x=0; x<strlen(printfbuf); x++)
445     console_putchar(cpu->machine->
446     main_console_handle, printfbuf[x]);
447     }
448     if (cpu->machine->register_dump ||
449     cpu->machine->instruction_trace)
450     debug("\n");
451     fflush(stdout);
452     cpu->cd.mips.gpr[MIPS_GPR_V0] = 0;
453     break;
454     case 0x54: /* bootinit() */
455     /* debug("[ DEC PROM bootinit(0x%08x): TODO ]\n",
456     (int)cpu->cd.mips.gpr[MIPS_GPR_A0]); */
457     cpu->cd.mips.gpr[MIPS_GPR_V0] = 0;
458     break;
459     case 0x58: /* bootread(int b, void *buffer, int n) */
460     /*
461     * Read data from the boot device.
462     * b is a sector number (512 bytes per sector),
463     * buffer is the destination address, and n
464     * is the number of _bytes_ to read.
465     *
466     * TODO: Return value? NetBSD thinks that 0 is ok.
467     */
468     debug("[ DEC PROM bootread(0x%x, 0x%08x, 0x%x) ]\n",
469     (int)cpu->cd.mips.gpr[MIPS_GPR_A0],
470     (int)cpu->cd.mips.gpr[MIPS_GPR_A1],
471     (int)cpu->cd.mips.gpr[MIPS_GPR_A2]);
472    
473     cpu->cd.mips.gpr[MIPS_GPR_V0] = 0;
474    
475     if ((int32_t)cpu->cd.mips.gpr[MIPS_GPR_A2] > 0) {
476 dpavlin 6 int disk_id = diskimage_bootdev(cpu->machine, NULL);
477 dpavlin 2 int res;
478     unsigned char *tmp_buf;
479    
480     tmp_buf = malloc(cpu->cd.mips.gpr[MIPS_GPR_A2]);
481     if (tmp_buf == NULL) {
482     fprintf(stderr, "[ *** Out of memory in "
483     "dec_prom.c, allocating %i bytes ]\n",
484     (int)cpu->cd.mips.gpr[MIPS_GPR_A2]);
485     break;
486     }
487    
488 dpavlin 6 res = diskimage_access(cpu->machine, disk_id,
489     DISKIMAGE_SCSI, 0,
490 dpavlin 2 cpu->cd.mips.gpr[MIPS_GPR_A0] * 512, tmp_buf,
491     cpu->cd.mips.gpr[MIPS_GPR_A2]);
492    
493     /* If the transfer was successful, transfer the data
494     to emulated memory: */
495     if (res) {
496     uint64_t dst = cpu->cd.mips.gpr[MIPS_GPR_A1];
497     if (dst < 0x80000000ULL)
498     dst |= 0x80000000;
499    
500     store_buf(cpu, dst, (char *)tmp_buf,
501     cpu->cd.mips.gpr[MIPS_GPR_A2]);
502     cpu->cd.mips.gpr[MIPS_GPR_V0] =
503     cpu->cd.mips.gpr[MIPS_GPR_A2];
504     }
505    
506     free(tmp_buf);
507     }
508     break;
509     case 0x64: /* getenv() */
510     /* Find the environment variable given by a0: */
511     for (i=0; i<sizeof(buf); i++)
512     cpu->memory_rw(cpu, cpu->mem,
513     cpu->cd.mips.gpr[MIPS_GPR_A0] + i, &buf[i],
514     sizeof(char), MEM_READ, CACHE_DATA | NO_EXCEPTIONS);
515     buf[sizeof(buf)-1] = '\0';
516     debug("[ DEC PROM getenv(\"%s\") ]\n", buf);
517     for (i=0; i<0x1000; i++) {
518     /* Matching string at offset i? */
519     int nmatches = 0;
520     for (j=0; j<strlen((char *)buf); j++) {
521     cpu->memory_rw(cpu, cpu->mem, (uint64_t)
522     (DEC_PROM_STRINGS + i + j), &ch2,
523     sizeof(char), MEM_READ, CACHE_DATA |
524     NO_EXCEPTIONS);
525     if (ch2 == buf[j])
526     nmatches++;
527     }
528     cpu->memory_rw(cpu, cpu->mem,
529     (uint64_t)(DEC_PROM_STRINGS
530     + i + strlen((char *)buf)), &ch2, sizeof(char),
531     MEM_READ, CACHE_DATA | NO_EXCEPTIONS);
532     if (nmatches == strlen((char *)buf) && ch2 == '=') {
533     cpu->cd.mips.gpr[MIPS_GPR_V0] =
534     DEC_PROM_STRINGS + i +
535     strlen((char *)buf) + 1;
536     return 1;
537     }
538     }
539     /* Return NULL if string wasn't found. */
540     fatal("[ DEC PROM getenv(\"%s\"): WARNING: Not in "
541     "environment! ]\n", buf);
542     cpu->cd.mips.gpr[MIPS_GPR_V0] = 0;
543     break;
544     case 0x6c: /* ulong slot_address(int sn) */
545     debug("[ DEC PROM slot_address(%i) ]\n",
546     (int)cpu->cd.mips.gpr[MIPS_GPR_A0]);
547     /* TODO: This is too hardcoded. */
548     /* TODO 2: Should these be physical or virtual addresses? */
549     switch (cpu->machine->machine_subtype) {
550     case MACHINE_DEC_3MAX_5000:
551     slot_base = KN02_PHYS_TC_0_START;/* 0x1e000000 */
552     slot_size = 4*1048576; /* 4 MB */
553     break;
554     case MACHINE_DEC_3MIN_5000:
555     slot_base = 0x10000000;
556     slot_size = 0x4000000; /* 64 MB */
557     break;
558     case MACHINE_DEC_3MAXPLUS_5000:
559     slot_base = 0x1e000000;
560     slot_size = 0x800000; /* 8 MB */
561     break;
562     case MACHINE_DEC_MAXINE_5000:
563     slot_base = 0x10000000;
564     slot_size = 0x4000000; /* 64 MB */
565     break;
566     default:
567     fatal("warning: DEC PROM slot_address() "
568     "unimplemented for this machine type\n");
569     }
570     cpu->cd.mips.gpr[MIPS_GPR_V0] = (int64_t)(int32_t)
571     (0x80000000 + slot_base + slot_size *
572     cpu->cd.mips.gpr[MIPS_GPR_A0]);
573     break;
574     case 0x70: /* wbflush() */
575     debug("[ DEC PROM wbflush(): TODO ]\n");
576     cpu->cd.mips.gpr[MIPS_GPR_V0] = 0;
577     break;
578     case 0x7c: /* clear_cache(addr, len) */
579     debug("[ DEC PROM clear_cache(0x%x,%i) ]\n",
580     (uint32_t)cpu->cd.mips.gpr[MIPS_GPR_A0],
581     (int)cpu->cd.mips.gpr[MIPS_GPR_A1]);
582     /* TODO */
583     cpu->cd.mips.gpr[MIPS_GPR_V0] = 0; /* ? */
584     break;
585     case 0x80: /* getsysid() */
586     /* debug("[ DEC PROM getsysid() ]\n"); */
587     /* TODO: why did I add the 0x82 stuff??? */
588     cpu->cd.mips.gpr[MIPS_GPR_V0] = ((uint32_t)0x82 << 24)
589     + (cpu->machine->machine_subtype << 16) + (0x3 << 8);
590     cpu->cd.mips.gpr[MIPS_GPR_V0] =
591     (int64_t)(int32_t)cpu->cd.mips.gpr[MIPS_GPR_V0];
592     break;
593     case 0x84: /* getbitmap() */
594     debug("[ DEC PROM getbitmap(0x%08x) ]\n",
595     (int)cpu->cd.mips.gpr[MIPS_GPR_A0]);
596     store_buf(cpu, cpu->cd.mips.gpr[MIPS_GPR_A0],
597     (char *)&memmap, sizeof(memmap));
598     cpu->cd.mips.gpr[MIPS_GPR_V0] = sizeof((memmap.bitmap));
599     break;
600     case 0x88: /* disableintr() */
601     debug("[ DEC PROM disableintr(): TODO ]\n");
602     cpu->cd.mips.gpr[MIPS_GPR_V0] = 0;
603     break;
604     case 0x8c: /* enableintr() */
605     debug("[ DEC PROM enableintr(): TODO ]\n");
606     cpu->cd.mips.gpr[MIPS_GPR_V0] = 0;
607     break;
608     case 0x9c: /* halt() */
609     debug("[ DEC PROM halt() ]\n");
610     cpu->machine->exit_without_entering_debugger = 1;
611     cpu->running = 0;
612     cpu->dead = 1;
613     break;
614     case 0xa4: /* gettcinfo() */
615     /*
616     * These are just bogus values... TODO
617     *
618     * 0: revision
619     * 4: clock period in nano seconds
620     * 8: slot size in megabytes TODO: not same for all models!
621     * 12: I/O timeout in cycles
622     * 16: DMA address range in megabytes
623     * 20: maximum DMA burst length
624     * 24: turbochannel parity (yes = 1)
625     * 28: reserved
626     */
627     store_32bit_word(cpu, DEC_PROM_TCINFO + 0, 0);
628     store_32bit_word(cpu, DEC_PROM_TCINFO + 4, 50);
629     store_32bit_word(cpu, DEC_PROM_TCINFO + 8, 4);
630     store_32bit_word(cpu, DEC_PROM_TCINFO + 12, 10);
631     store_32bit_word(cpu, DEC_PROM_TCINFO + 16, 1);
632     store_32bit_word(cpu, DEC_PROM_TCINFO + 20, 100);
633     store_32bit_word(cpu, DEC_PROM_TCINFO + 24, 0);
634     store_32bit_word(cpu, DEC_PROM_TCINFO + 28, 0);
635     cpu->cd.mips.gpr[MIPS_GPR_V0] = DEC_PROM_TCINFO;
636     break;
637     case 0xa8: /* int execute_cmd(char *) */
638     i = 0;
639     while ((ch = mem_readchar(cpu, MIPS_GPR_A0, i++)) != '\0')
640     console_putchar(cpu->machine->main_console_handle, ch);
641     console_putchar(cpu->machine->main_console_handle, '\n');
642     cpu->cd.mips.gpr[MIPS_GPR_V0] = 0;
643     break;
644     case 0xac: /* rex() */
645     debug("[ DEC PROM rex('%c') ]\n",
646     (int)cpu->cd.mips.gpr[MIPS_GPR_A0]);
647     switch (cpu->cd.mips.gpr[MIPS_GPR_A0]) {
648     case 'h':
649     debug("DEC PROM: rex('h') ==> halt\n");
650     cpu->machine->exit_without_entering_debugger = 1;
651     cpu->running = 0;
652     cpu->dead = 1;
653     break;
654     case 'b':
655     debug("DEC PROM: rex('b') ==> reboot: TODO "
656     "(halting CPU instead)\n");
657     cpu->machine->exit_without_entering_debugger = 1;
658     cpu->running = 0;
659     cpu->dead = 1;
660     break;
661     default:
662     fatal("DEC prom emulation: unknown rex() a0=0x%llx ("
663     "'%c')\n", (long long)cpu->cd.mips.gpr[MIPS_GPR_A0],
664     (char)cpu->cd.mips.gpr[MIPS_GPR_A0]);
665     cpu->running = 0;
666     cpu->dead = 1;
667     }
668     break;
669     default:
670     cpu_register_dump(cpu->machine, cpu, 1, 0x1);
671     printf("a0 points to: ");
672     for (i=0; i<40; i++) {
673     unsigned char ch = '\0';
674     cpu->memory_rw(cpu, cpu->mem,
675     cpu->cd.mips.gpr[MIPS_GPR_A0] + i, &ch,
676     sizeof(ch), MEM_READ, CACHE_DATA | NO_EXCEPTIONS);
677     if (ch >= ' ' && ch < 126)
678     printf("%c", ch);
679     else
680     printf("[%02x]", ch);
681     }
682     printf("\n");
683     fatal("PROM emulation: unimplemented callback vector 0x%x\n",
684     vector);
685     cpu->running = 0;
686     cpu->dead = 1;
687     }
688    
689     return 1;
690     }
691    

  ViewVC Help
Powered by ViewVC 1.1.26