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

Parent Directory Parent Directory | Revision Log Revision Log


Revision 14 - (hide annotations)
Mon Oct 8 16:18:51 2007 UTC (16 years, 7 months ago) by dpavlin
File MIME type: text/plain
File size: 19542 byte(s)
++ trunk/HISTORY	(local)
$Id: HISTORY,v 1.982 2005/10/07 22:45:32 debug Exp $
20050816	Some success in decoding the way the SGI O2 PROM draws graphics
		during bootup; lines/rectangles and bitmaps work, enough to
		show the bootlogo etc. :-)
		Adding more PPC instructions, and (dummy) BAT registers.
20050817	Updating the pckbc to support scancode type 3 keyboards
		(required in order to interact with the SGI O2 PROM).
		Adding more PPC instructions.
20050818	Adding more ARM instructions; general register forms.
		Importing armreg.h from NetBSD (ARM cpu ids). Adding a (dummy)
		CATS machine mode (using SA110 as the default CPU).
		Continuing on general dyntrans related stuff.
20050819	Register forms for ARM load/stores. Gaah! The Compaq C Compiler
		bug is triggered for ARM loads as well, not just PPC :-(
		Adding full support for ARM PC-relative load/stores, and load/
		stores where the PC register is the destination register.
		Adding support for ARM a.out binaries.
20050820	Continuing to add more ARM instructions, and correcting some
		bugs. Continuing on CATS emulation.
		More work on the PPC stuff.
20050821	Minor PPC and ARM updates. Adding more machine types.
20050822	All ARM "data processing instructions" are now generated
		automatically.
20050824	Beginning the work on the ARM system control coprocessor.
		Adding support for ARM halfword load/stores, and signed loads.
20050825	Fixing an important bug related to the ARM condition codes.
		OpenBSD/zaurus and NetBSD/netwinder now print some boot
		messages. :)
		Adding a dummy SH (Hitachi SuperH) cpu family.
		Beginning to add some ARM virtual address translation.
		MIPS bugfixes: unaligned PC now cause an ADEL exception (at
		least for non-bintrans execution), and ADEL/ADES (not
		TLBL/TLBS) are used if userland tries to access kernel space.
		(Thanks to Joshua Wise for making me aware of these bugs.)
20050827	More work on the ARM emulation, and various other updates.
20050828	More ARM updates.
		Finally taking the time to work on translation invalidation
		(i.e. invalidating translated code mappings when memory is
		written to). Hopefully this doesn't break anything.
20050829	Moving CPU related files from src/ to a new subdir, src/cpus/.
		Moving PROM emulation stuff from src/ to src/promemul/.
		Better debug instruction trace for ARM loads and stores.
20050830	Various ARM updates (correcting CMP flag calculation, etc).
20050831	PPC instruction updates. (Flag fixes, etc.)
20050901	Various minor PPC and ARM instruction emulation updates.
		Minor OpenFirmware emulation updates.
20050903	Adding support for adding arbitrary ARM coprocessors (with
		the i80321 I/O coprocessor as a first test).
		Various other ARM and PPC updates.
20050904	Adding some SHcompact disassembly routines.
20050907	(Re)adding a dummy HPPA CPU module, and a dummy i960 module.
20050908	Began hacking on some Apple Partition Table support.
20050909	Adding support for loading Mach-O (Darwin PPC) binaries.
20050910	Fixing an ARM bug (Carry flag was incorrectly updated for some
		data processing instructions); OpenBSD/cats and NetBSD/
		netwinder get quite a bit further now.
		Applying a patch to dev_wdc, and a one-liner to dev_pcic, to
		make them work better when emulating new versions of OpenBSD.
		(Thanks to Alexander Yurchenko for the patches.)
		Also doing some other minor updates to dev_wdc. (Some cleanup,
		and finally converting to devinit, etc.)
20050912	IRIX doesn't have u_int64_t by default (noticed by Andreas
		<avr@gnulinux.nl>); configure updated to reflect this.
		Working on ARM register bank switching, CPSR vs SPSR issues,
		and beginning the work on interrupt/exception support.
20050913	Various minor ARM updates (speeding up load/store multiple,
		and fixing a ROR bug in R(); NetBSD/cats now boots as far as
		OpenBSD/cats).
20050917	Adding a dummy Atmel AVR (8-bit) cpu family skeleton.
20050918	Various minor updates.
20050919	Symbols are now loaded from Mach-O executables.
		Continuing the work on adding ARM exception support.
20050920	More work on ARM stuff: OpenBSD/cats and NetBSD/cats reach
		userland! :-)
20050921	Some more progress on ARM interrupt specifics.
20050923	Fixing linesize for VR4121 (patch by Yurchenko). Also fixing
		linesizes/cachesizes for some other VR4xxx.
		Adding a dummy Acer Labs M1543 PCI-ISA bridge (for CATS) and a
		dummy Symphony Labs 83C553 bridge (for Netwinder), usable by 
		dev_footbridge.
20050924	Some PPC progress.
20050925	More PPC progress.
20050926	PPC progress (fixing some bugs etc); Darwin's kernel gets
		slightly further than before.
20050928	Various updates: footbridge/ISA/pciide stuff, and finally
		fixing the VGA text scroll-by-changing-the-base-offset bug.
20050930	Adding a dummy S3 ViRGE pci card for CATS emulation, which
		both NetBSD and OpenBSD detects as VGA.
		Continuing on Footbridge (timers, ISA interrupt stuff).
20051001	Continuing... there are still bugs, probably interrupt-
		related.
20051002	More work on the Footbridge (interrupt stuff).
20051003	Various minor updates. (Trying to find the bug(s).)
20051004	Continuing on the ARM stuff.
20051005	More ARM-related fixes.
20051007	FINALLY! Found and fixed 2 ARM bugs: 1 memory related, and the
		other was because of an error in the ARM manual (load multiple
		with the S-bit set should _NOT_ load usermode registers, as the
		manual says, but it should load saved registers, which may or
		may not happen to be usermode registers).
		NetBSD/cats and OpenBSD/cats seem to install fine now :-)
		except for a minor bug at the end of the OpenBSD/cats install.
		Updating the documentation, preparing for the next release.
20051008	Continuing with release testing and cleanup.

1 dpavlin 14 /*
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.1 2005/08/29 14:46:34 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     strlcpy(printfbuf, "%%",
367     sizeof(printfbuf));
368     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     strlcpy(printfbuf, "[...]\n",
380     sizeof(printfbuf));
381     #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     snprintf(printfbuf, sizeof(
397     printfbuf), "%c", ch2);
398     break;
399     case 'd':
400     snprintf(printfbuf, sizeof(
401     printfbuf), "%d", argdata);
402     break;
403     case 'x':
404     snprintf(printfbuf, sizeof(
405     printfbuf), "%x", argdata);
406     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     snprintf(printfbuf, sizeof(printfbuf),
439     "%c", ch);
440     }
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     int disk_id = diskimage_bootdev(cpu->machine, NULL);
477     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     res = diskimage_access(cpu->machine, disk_id,
489     DISKIMAGE_SCSI, 0,
490     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