/[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 22 - (hide annotations)
Mon Oct 8 16:19:37 2007 UTC (16 years, 7 months ago) by dpavlin
File MIME type: text/plain
File size: 19562 byte(s)
++ trunk/HISTORY	(local)
$Id: HISTORY,v 1.1121 2006/02/18 21:03:08 debug Exp $
20051126	Cobalt and PReP now work with the 21143 NIC.
		Continuing on Alpha dyntrans things.
		Fixing some more left-shift-by-24 to unsigned.
20051127	Working on OpenFirmware emulation; major cleanup/redesign.
		Progress on MacPPC emulation: NetBSD detects two CPUs (when
		running with -n 2), framebuffer output (for text) works.
		Adding quick-hack Bandit PCI controller and "gc" interrupt
		controller for MacPPC.
20051128	Changing from a Bandit to a Uni-North controller for macppc.
		Continuing on OpenFirmware and MacPPC emulation in general
		(obio controller, and wdc attached to the obio seems to work).
20051129	More work on MacPPC emulation (adding a dummy ADB controller).
		Continuing the PCI bus cleanup (endianness and tag composition)
		and rewriting all PCI controllers' access functions.
20051130	Various minor PPC dyntrans optimizations.
		Manually inlining some parts of the framebuffer redraw routine.
		Slowly beginning the conversion of the old MIPS emulation into
		dyntrans (but this will take quite some time to get right).
		Generalizing quick_pc_to_pointers.
20051201	Documentation update (David Muse has made available a kernel
		which simplifies Debian/DECstation installation).
		Continuing on the ADB bus controller.
20051202	Beginning a rewrite of the Zilog serial controller (dev_zs).
20051203	Continuing on the zs rewrite (now called dev_z8530); conversion
		to devinit style.
		Reworking some of the input-only vs output-only vs input-output
		details of src/console.c, better warning messages, and adding
		a debug dump.
		Removing the concept of "device state"; it wasn't really used.
		Changing some debug output (-vv should now be used to show all
		details about devices and busses; not shown during normal
		startup anymore).
		Beginning on some SPARC instruction disassembly support.
20051204	Minor PPC updates (WALNUT skeleton stuff).
		Continuing on the MIPS dyntrans rewrite.
		More progress on the ADB controller (a keyboard is "detected"
		by NetBSD and OpenBSD).
		Downgrading OpenBSD/arc as a guest OS from "working" to
		"almost working" in the documentation.
		Progress on Algor emulation ("v3" PCI controller).
20051205	Minor updates.
20051207	Sorting devices according to address; this reduces complexity
		of device lookups from O(n) to O(log n) in memory_rw (but no
		real performance increase (yet) in experiments).
20051210	Beginning the work on native dyntrans backends (by making a
		simple skeleton; so far only for Alpha hosts).
20051211	Some very minor SPARC updates.
20051215	Fixing a bug in the MIPS mul (note: not mult) instruction,
		so it also works with non-64-bit emulation. (Thanks to Alec
		Voropay for noticing the problem.)
20051216	More work on the fake/empty/simple/skeleton/whatever backend;
		performance doesn't increase, so this isn't really worth it,
		but it was probably worth it to prepare for a real backend
		later.
20051219	More instr call statistics gathering and analysis stuff.
20051220	Another fix for MIPS 'mul'. Also converting mul and {d,}cl{o,z}
		to dyntrans.
		memory_ppc.c syntax error fix (noticed by Peter Valchev).
		Beginning to move out machines from src/machine.c into
		individual files in src/machines (in a way similar to the
		autodev system for devices).
20051222	Updating the documentation regarding NetBSD/pmax 3.0.
20051223	- " - NetBSD/cats 3.0.
20051225	- " - NetBSD/hpcmips 3.0.
20051226	Continuing on the machine registry redesign.
		Adding support for ARM rrx (33-bit rotate).
		Fixing some signed/unsigned issues (exposed by gcc -W).
20051227	Fixing the bug which prevented a NetBSD/prep 3.0 install kernel
		from starting (triggered when an mtmsr was the last instruction
		on a page). Unfortunately not enough to get the kernel to run
		as well as the 2.1 kernels did.
20051230	Some dyntrans refactoring.
20051231	Continuing on the machine registry redesign.
20060101-10	Continuing... moving more machines. Moving MD interrupt stuff
		from machine.c into a new src/machines/interrupts.c.
20060114	Adding various mvmeppc machine skeletons.
20060115	Continuing on mvme* stuff. NetBSD/mvmeppc prints boot messages
		(for MVME1600) and reaches the root device prompt, but no
		specific hardware devices are emulated yet.
20060116	Minor updates to the mvme1600 emulation mode; the Eagle PCI bus
		seems to work without much modification, and a 21143 can be
		detected, interrupts might work (but untested so far).
		Adding a fake MK48Txx (mkclock) device, for NetBSD/mvmeppc.
20060121	Adding an aux control register for ARM. (A BIG thank you to
		Olivier Houchard for tracking down this bug.)
20060122	Adding more ARM instructions (smulXY), and dev_iq80321_7seg.
20060124	Adding disassembly of more ARM instructions (mia*, mra/mar),
		and some semi-bogus XScale and i80321 registers.
20060201-02	Various minor updates. Moving the last machines out of
		machine.c.
20060204	Adding a -c command line option, for running debugger commands
		before the simulation starts, but after all files have been
		loaded.
		Minor iq80321-related updates.
20060209	Minor hacks (DEVINIT macro, etc).
		Preparing for the generalization of the 64-bit dyntrans address
		translation subsystem.
20060216	Adding ARM ldrd (double-register load).
20060217	Continuing on various ARM-related stuff.
20060218	More progress on the ATA/wdc emulation for NetBSD/iq80321.
		NetBSD/evbarm can now be installed :-)  Updating the docs, etc.
		Continuing on Algor emulation.

==============  RELEASE 0.3.8  ==============


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 22 * $Id: dec_prom.c,v 1.4 2006/02/16 05:57:10 debug Exp $
29 dpavlin 14 *
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 dpavlin 22 size_t x;
353 dpavlin 14
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 dpavlin 22 for (i=0; i<(int)sizeof(buf); i++)
512 dpavlin 14 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 dpavlin 22 for (j=0; j<(int32_t)strlen((char *)buf); j++) {
521 dpavlin 14 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 dpavlin 22 if (nmatches == (int)strlen((char *)buf) && ch2=='=') {
533 dpavlin 14 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