/[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 30 - (hide annotations)
Mon Oct 8 16:20:40 2007 UTC (16 years, 7 months ago) by dpavlin
File MIME type: text/plain
File size: 19677 byte(s)
++ trunk/HISTORY	(local)
$Id: HISTORY,v 1.1325 2006/08/15 15:38:37 debug Exp $
20060723	More Transputer instructions (pfix, nfix, opr, mint, ldl, ldlp,
		eqc, rev, ajw, stl, stlf, sthf, sub, ldnl, ldnlp, ldpi, move,
		wcnt, add, bcnt).
		Adding more SPARC instructions (andcc, addcc, bl, rdpr).
		Progress on the igsfb framebuffer used by NetBSD/netwinder.
		Enabling 8-bit fills in dev_fb.
		NetBSD/netwinder 3.0.1 can now run from a disk image :-)
20060724	Cleanup/performance fix for 64-bit virtual translation table
		updates (by removing the "timestamp" stuff). A full NetBSD/pmax
		3.0.1 install for R4400 has dropped from 667 seconds to 584 :)
		Fixing the igsfb "almost vga" color (it is 24-bit, not 18-bit).
		Adding some MIPS instruction combinations (3*lw, and 3*addu).
		The 8048 keyboard now turns off interrupt enable between the
		KBR_ACK and the KBR_RSTDONE, to work better with Linux 2.6.
		Not causing PPC DEC interrupts if PPC_NO_DEC is set for a
		specific CPU; NetBSD/bebox gets slightly further than before.
		Adding some more SPARC instructions: branches, udiv.
20060725	Refreshing dev_pckbc.c a little.
		Cleanups for the SH emulation mode, and adding the first
		"compact" (16-bit) instructions: various simple movs, nop,
		shll, stc, or, ldc.
20060726	Adding dummy "pcn" (AMD PCnet NIC) PCI glue.
20060727	Various cleanups; removing stuff from cpu.h, such as
		running_translated (not really meaningful anymore), and
		page flags (breaking into the debugger clears all translations
		anyway).
		Minor MIPS instruction combination updates.
20060807	Expanding the 3*sw and 3*lw MIPS instruction combinations to
		work with 2* and 4* too, resulting in a minor performance gain.
		Implementing a usleep hack for the RM52xx/MIPS32/MIPS64 "wait"
		instruction (when emulating 1 cpu).
20060808	Experimenting with some more MIPS instruction combinations.
		Implementing support for showing a (hardcoded 12x22) text
		cursor in igsfb.
20060809	Simplifying the NetBSD/evbmips (Malta) install instructions
		somewhat (by using a NetBSD/pmax ramdisk install kernel).
20060812	Experimenting more with the MIPS 'wait' instruction.
		PCI configuration register writes can now be handled, which
		allow PCI IDE controllers to work with NetBSD/Malta 3.0.1 and
		NetBSD/cobalt 3.0.1. (Previously only NetBSD 2.1 worked.)
20060813	Updating dev_gt.c based on numbers from Alec Voropay, to enable
		Linux 2.6 to use PCI on Malta.
		Continuing on Algor interrupt stuff.
20060814	Adding support for routing ISA interrupts to two different
		interrupts, making it possible to run NetBSD/algor :-)
20060814-15	Testing for the release.

==============  RELEASE 0.4.2  ==============


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 30 * $Id: dec_prom.c,v 1.10 2006/07/26 23:21:48 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     break;
109     case 0x10: /* restart() */
110     /* TODO */
111     cpu->machine->exit_without_entering_debugger = 1;
112     cpu->running = 0;
113     break;
114     case 0x18: /* reinit() */
115     /* TODO */
116     cpu->machine->exit_without_entering_debugger = 1;
117     cpu->cd.mips.gpr[MIPS_GPR_V0] = 0;
118     break;
119     case 0x30: /* open() */
120     /*
121     * TODO: This is just a hack to allow Sprite/pmax' bootblock
122     * code to load /vmsprite. The filename argument (in A0)
123     * is ignored, and a file handle value of 1 is returned.
124     */
125     if (file_opened) {
126     fatal("\ndec_jumptable_func(): opening more than one "
127     "file isn't supported yet.\n");
128     cpu->running = 0;
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 dpavlin 24 (int32_t)cpu->cd.mips.gpr[MIPS_GPR_A0] + i, &ch,
191 dpavlin 14 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     }
202    
203     return 0;
204     }
205    
206    
207     /*
208     * decstation_prom_emul():
209     *
210     * DECstation PROM emulation.
211     *
212     * Callback functions:
213     * 0x0c strcmp()
214     * 0x14 strlen()
215     * 0x24 getchar()
216     * 0x28 gets()
217     * 0x2c puts()
218     * 0x30 printf()
219     * 0x38 iopoll()
220     * 0x54 bootinit()
221     * 0x58 bootread()
222     * 0x64 getenv()
223     * 0x6c slot_address()
224     * 0x70 wbflush()
225     * 0x7c clear_cache()
226     * 0x80 getsysid()
227     * 0x84 getbitmap()
228     * 0x88 disableintr()
229     * 0x8c enableintr()
230     * 0x9c halt()
231     * 0xa4 gettcinfo()
232     * 0xa8 execute_cmd()
233     * 0xac rex()
234     */
235     int decstation_prom_emul(struct cpu *cpu)
236     {
237     int i, j, ch, argreg, argdata;
238     int vector = cpu->pc & 0xfff;
239     int callback = (cpu->pc & 0xf000)? 1 : 0;
240     unsigned char buf[100];
241     unsigned char ch1, ch2, ch3;
242     uint64_t tmpaddr, slot_base = 0x10000000, slot_size = 0;
243    
244     if (!callback) {
245     vector = dec_jumptable_func(cpu, vector);
246     if (vector == 0)
247     return 1;
248     } else {
249     /* Vector number is n*4, PC points to n*8. */
250     vector /= 2;
251     }
252    
253     switch (vector) {
254     case 0x0c: /* strcmp(): */
255     i = j = 0;
256     do {
257     ch1 = mem_readchar(cpu, MIPS_GPR_A0, i++);
258     ch2 = mem_readchar(cpu, MIPS_GPR_A1, j++);
259     } while (ch1 == ch2 && ch1 != '\0');
260    
261     /* If ch1=='\0', then strings are equal. */
262     if (ch1 == '\0')
263     cpu->cd.mips.gpr[MIPS_GPR_V0] = 0;
264     if ((signed char)ch1 > (signed char)ch2)
265     cpu->cd.mips.gpr[MIPS_GPR_V0] = 1;
266     if ((signed char)ch1 < (signed char)ch2)
267     cpu->cd.mips.gpr[MIPS_GPR_V0] = -1;
268     break;
269     case 0x14: /* strlen(): */
270     i = 0;
271     do {
272     ch2 = mem_readchar(cpu, MIPS_GPR_A0, i++);
273     } while (ch2 != 0);
274     cpu->cd.mips.gpr[MIPS_GPR_V0] = i - 1;
275     break;
276     case 0x24: /* getchar() */
277     /* debug("[ DEC PROM getchar() ]\n"); */
278     cpu->cd.mips.gpr[MIPS_GPR_V0] = console_readchar(
279     cpu->machine->main_console_handle);
280     break;
281     case 0x28: /* gets() */
282     /* debug("[ DEC PROM gets() ]\n"); */
283     tmpaddr = cpu->cd.mips.gpr[MIPS_GPR_A0];
284     i = 0;
285    
286     /* TODO: Make this not hang (block) the entire emulator */
287    
288     do {
289     while ((ch = console_readchar(
290     cpu->machine->main_console_handle)) < 1)
291     ;
292     if (ch == '\r')
293     ch = '\n';
294     ch2 = ch;
295    
296     if (ch == '\b') {
297     if (i > 0) {
298     console_putchar(cpu->machine->
299     main_console_handle, ch2);
300     console_putchar(cpu->machine->
301     main_console_handle, ' ');
302     console_putchar(cpu->machine->
303     main_console_handle, ch2);
304     }
305     } else
306     console_putchar(cpu->machine->
307     main_console_handle, ch2);
308    
309     fflush(stdout);
310    
311     if (ch == '\n') {
312     /* It seems that trailing newlines
313     are not included in the buffer. */
314     } else if (ch != '\b') {
315 dpavlin 24 cpu->memory_rw(cpu, cpu->mem, (int32_t)
316 dpavlin 14 cpu->cd.mips.gpr[MIPS_GPR_A0] + i,
317     &ch2, sizeof(ch2), MEM_WRITE,
318     CACHE_DATA | NO_EXCEPTIONS);
319     i++;
320     } else {
321     if (i > 0)
322     i--;
323     }
324     } while (ch2 != '\n');
325    
326     /* Trailing nul-byte: */
327     ch2 = '\0';
328 dpavlin 24 cpu->memory_rw(cpu, cpu->mem, (int32_t)
329     cpu->cd.mips.gpr[MIPS_GPR_A0] + i, &ch2, sizeof(ch2),
330     MEM_WRITE, CACHE_DATA | NO_EXCEPTIONS);
331 dpavlin 14
332     /* Return the input argument: */
333     cpu->cd.mips.gpr[MIPS_GPR_V0] = cpu->cd.mips.gpr[MIPS_GPR_A0];
334     break;
335     case 0x2c: /* puts() */
336     i = 0;
337     while ((ch = mem_readchar(cpu, MIPS_GPR_A0, i++)) != '\0')
338     console_putchar(cpu->machine->main_console_handle, ch);
339     console_putchar(cpu->machine->main_console_handle, '\n');
340     cpu->cd.mips.gpr[MIPS_GPR_V0] = 0;
341     break;
342     case 0x30: /* printf() */
343     if (cpu->machine->register_dump ||
344     cpu->machine->instruction_trace)
345     debug("PROM printf(0x%08lx): \n",
346     (long)cpu->cd.mips.gpr[MIPS_GPR_A0]);
347    
348     i = 0; ch = -1; argreg = MIPS_GPR_A1;
349     while (ch != '\0') {
350     char printfbuf[8000];
351 dpavlin 22 size_t x;
352 dpavlin 14
353     printfbuf[0] = printfbuf[sizeof(printfbuf)-1] = '\0';
354    
355     ch = mem_readchar(cpu, MIPS_GPR_A0, i++);
356     switch (ch) {
357     case '%':
358     ch = '0';
359     while (ch >= '0' && ch <= '9')
360     ch = mem_readchar(cpu,
361     MIPS_GPR_A0, i++);
362    
363     switch (ch) {
364     case '%':
365     strlcpy(printfbuf, "%%",
366     sizeof(printfbuf));
367     break;
368     case 'c':
369     case 'd':
370     case 's':
371     case 'x':
372     /* Get argument: */
373     if (argreg > MIPS_GPR_A3) {
374     #if 1
375     /* Linux booters seem to go
376     over the edge sometimes: */
377     ch = '\0';
378     strlcpy(printfbuf, "[...]\n",
379     sizeof(printfbuf));
380     #else
381     printf("[ decstation_prom_emul"
382     "(): too many arguments ]");
383     /* This reuses the last arg,
384     which is utterly incorrect.
385     (TODO) */
386     argreg = MIPS_GPR_A3;
387     #endif
388     }
389    
390     ch2 = argdata =
391     cpu->cd.mips.gpr[argreg];
392    
393     switch (ch) {
394     case 'c':
395     snprintf(printfbuf, sizeof(
396     printfbuf), "%c", ch2);
397     break;
398     case 'd':
399     snprintf(printfbuf, sizeof(
400     printfbuf), "%d", argdata);
401     break;
402     case 'x':
403     snprintf(printfbuf, sizeof(
404     printfbuf), "%x", argdata);
405     break;
406     case 's':
407     /* Print a "%s" string. */
408     j = 0; ch3 = '\n';
409     while (ch2) {
410     ch2 = mem_readchar(cpu,
411     argreg, j++);
412     if (ch2) {
413     snprintf(
414     printfbuf +
415     strlen(
416     printfbuf),
417     sizeof(
418     printfbuf)-
419     1-strlen(
420     printfbuf),
421     "%c", ch2);
422     ch3 = ch2;
423     }
424     }
425     break;
426     }
427     argreg ++;
428     break;
429     default:
430     printf("[ unknown printf format char"
431     " '%c' ]", ch);
432     }
433     break;
434     case '\0':
435     break;
436     default:
437     snprintf(printfbuf, sizeof(printfbuf),
438     "%c", ch);
439     }
440    
441     printfbuf[sizeof(printfbuf)-1] = '\0';
442    
443     for (x=0; x<strlen(printfbuf); x++)
444     console_putchar(cpu->machine->
445     main_console_handle, printfbuf[x]);
446     }
447     if (cpu->machine->register_dump ||
448     cpu->machine->instruction_trace)
449     debug("\n");
450     fflush(stdout);
451     cpu->cd.mips.gpr[MIPS_GPR_V0] = 0;
452     break;
453     case 0x54: /* bootinit() */
454     /* debug("[ DEC PROM bootinit(0x%08x): TODO ]\n",
455     (int)cpu->cd.mips.gpr[MIPS_GPR_A0]); */
456     cpu->cd.mips.gpr[MIPS_GPR_V0] = 0;
457     break;
458     case 0x58: /* bootread(int b, void *buffer, int n) */
459     /*
460     * Read data from the boot device.
461     * b is a sector number (512 bytes per sector),
462     * buffer is the destination address, and n
463     * is the number of _bytes_ to read.
464     *
465     * TODO: Return value? NetBSD thinks that 0 is ok.
466     */
467     debug("[ DEC PROM bootread(0x%x, 0x%08x, 0x%x) ]\n",
468     (int)cpu->cd.mips.gpr[MIPS_GPR_A0],
469     (int)cpu->cd.mips.gpr[MIPS_GPR_A1],
470     (int)cpu->cd.mips.gpr[MIPS_GPR_A2]);
471    
472     cpu->cd.mips.gpr[MIPS_GPR_V0] = 0;
473    
474     if ((int32_t)cpu->cd.mips.gpr[MIPS_GPR_A2] > 0) {
475     int disk_id = diskimage_bootdev(cpu->machine, NULL);
476     int res;
477     unsigned char *tmp_buf;
478    
479     tmp_buf = malloc(cpu->cd.mips.gpr[MIPS_GPR_A2]);
480     if (tmp_buf == NULL) {
481     fprintf(stderr, "[ *** Out of memory in "
482     "dec_prom.c, allocating %i bytes ]\n",
483     (int)cpu->cd.mips.gpr[MIPS_GPR_A2]);
484     break;
485     }
486    
487     res = diskimage_access(cpu->machine, disk_id,
488     DISKIMAGE_SCSI, 0,
489     cpu->cd.mips.gpr[MIPS_GPR_A0] * 512, tmp_buf,
490     cpu->cd.mips.gpr[MIPS_GPR_A2]);
491    
492     /* If the transfer was successful, transfer the data
493     to emulated memory: */
494     if (res) {
495     uint64_t dst = cpu->cd.mips.gpr[MIPS_GPR_A1];
496     if (dst < 0x80000000ULL)
497     dst |= 0x80000000;
498    
499     store_buf(cpu, dst, (char *)tmp_buf,
500     cpu->cd.mips.gpr[MIPS_GPR_A2]);
501     cpu->cd.mips.gpr[MIPS_GPR_V0] =
502     cpu->cd.mips.gpr[MIPS_GPR_A2];
503     }
504    
505     free(tmp_buf);
506     }
507     break;
508     case 0x64: /* getenv() */
509     /* Find the environment variable given by a0: */
510 dpavlin 22 for (i=0; i<(int)sizeof(buf); i++)
511 dpavlin 24 cpu->memory_rw(cpu, cpu->mem, (int32_t)
512 dpavlin 14 cpu->cd.mips.gpr[MIPS_GPR_A0] + i, &buf[i],
513     sizeof(char), MEM_READ, CACHE_DATA | NO_EXCEPTIONS);
514     buf[sizeof(buf)-1] = '\0';
515     debug("[ DEC PROM getenv(\"%s\") ]\n", buf);
516     for (i=0; i<0x1000; i++) {
517     /* Matching string at offset i? */
518     int nmatches = 0;
519 dpavlin 22 for (j=0; j<(int32_t)strlen((char *)buf); j++) {
520 dpavlin 24 cpu->memory_rw(cpu, cpu->mem, (int32_t)
521 dpavlin 14 (DEC_PROM_STRINGS + i + j), &ch2,
522     sizeof(char), MEM_READ, CACHE_DATA |
523     NO_EXCEPTIONS);
524     if (ch2 == buf[j])
525     nmatches++;
526     }
527 dpavlin 24 cpu->memory_rw(cpu, cpu->mem, (int32_t)(DEC_PROM_STRINGS
528 dpavlin 14 + i + strlen((char *)buf)), &ch2, sizeof(char),
529     MEM_READ, CACHE_DATA | NO_EXCEPTIONS);
530 dpavlin 22 if (nmatches == (int)strlen((char *)buf) && ch2=='=') {
531 dpavlin 14 cpu->cd.mips.gpr[MIPS_GPR_V0] =
532     DEC_PROM_STRINGS + i +
533     strlen((char *)buf) + 1;
534     return 1;
535     }
536     }
537     /* Return NULL if string wasn't found. */
538     fatal("[ DEC PROM getenv(\"%s\"): WARNING: Not in "
539     "environment! ]\n", buf);
540     cpu->cd.mips.gpr[MIPS_GPR_V0] = 0;
541     break;
542     case 0x6c: /* ulong slot_address(int sn) */
543     debug("[ DEC PROM slot_address(%i) ]\n",
544     (int)cpu->cd.mips.gpr[MIPS_GPR_A0]);
545     /* TODO: This is too hardcoded. */
546     /* TODO 2: Should these be physical or virtual addresses? */
547     switch (cpu->machine->machine_subtype) {
548     case MACHINE_DEC_3MAX_5000:
549     slot_base = KN02_PHYS_TC_0_START;/* 0x1e000000 */
550     slot_size = 4*1048576; /* 4 MB */
551     break;
552     case MACHINE_DEC_3MIN_5000:
553     slot_base = 0x10000000;
554     slot_size = 0x4000000; /* 64 MB */
555     break;
556     case MACHINE_DEC_3MAXPLUS_5000:
557     slot_base = 0x1e000000;
558     slot_size = 0x800000; /* 8 MB */
559     break;
560     case MACHINE_DEC_MAXINE_5000:
561     slot_base = 0x10000000;
562     slot_size = 0x4000000; /* 64 MB */
563     break;
564     default:
565     fatal("warning: DEC PROM slot_address() "
566     "unimplemented for this machine type\n");
567     }
568     cpu->cd.mips.gpr[MIPS_GPR_V0] = (int64_t)(int32_t)
569     (0x80000000 + slot_base + slot_size *
570     cpu->cd.mips.gpr[MIPS_GPR_A0]);
571     break;
572     case 0x70: /* wbflush() */
573     debug("[ DEC PROM wbflush(): TODO ]\n");
574     cpu->cd.mips.gpr[MIPS_GPR_V0] = 0;
575     break;
576     case 0x7c: /* clear_cache(addr, len) */
577     debug("[ DEC PROM clear_cache(0x%x,%i) ]\n",
578     (uint32_t)cpu->cd.mips.gpr[MIPS_GPR_A0],
579     (int)cpu->cd.mips.gpr[MIPS_GPR_A1]);
580     /* TODO */
581     cpu->cd.mips.gpr[MIPS_GPR_V0] = 0; /* ? */
582     break;
583     case 0x80: /* getsysid() */
584     /* debug("[ DEC PROM getsysid() ]\n"); */
585     /* TODO: why did I add the 0x82 stuff??? */
586     cpu->cd.mips.gpr[MIPS_GPR_V0] = ((uint32_t)0x82 << 24)
587     + (cpu->machine->machine_subtype << 16) + (0x3 << 8);
588     cpu->cd.mips.gpr[MIPS_GPR_V0] =
589     (int64_t)(int32_t)cpu->cd.mips.gpr[MIPS_GPR_V0];
590     break;
591     case 0x84: /* getbitmap() */
592     debug("[ DEC PROM getbitmap(0x%08x) ]\n",
593     (int)cpu->cd.mips.gpr[MIPS_GPR_A0]);
594     store_buf(cpu, cpu->cd.mips.gpr[MIPS_GPR_A0],
595 dpavlin 24 (char *)cpu->machine->md.pmax.memmap,
596     sizeof(struct dec_memmap));
597     cpu->cd.mips.gpr[MIPS_GPR_V0] =
598     sizeof(cpu->machine->md.pmax.memmap->bitmap);
599 dpavlin 14 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     break;
613     case 0xa4: /* gettcinfo() */
614     /*
615     * These are just bogus values... TODO
616     *
617     * 0: revision
618     * 4: clock period in nano seconds
619     * 8: slot size in megabytes TODO: not same for all models!
620     * 12: I/O timeout in cycles
621     * 16: DMA address range in megabytes
622     * 20: maximum DMA burst length
623     * 24: turbochannel parity (yes = 1)
624     * 28: reserved
625     */
626     store_32bit_word(cpu, DEC_PROM_TCINFO + 0, 0);
627     store_32bit_word(cpu, DEC_PROM_TCINFO + 4, 50);
628     store_32bit_word(cpu, DEC_PROM_TCINFO + 8, 4);
629     store_32bit_word(cpu, DEC_PROM_TCINFO + 12, 10);
630     store_32bit_word(cpu, DEC_PROM_TCINFO + 16, 1);
631     store_32bit_word(cpu, DEC_PROM_TCINFO + 20, 100);
632     store_32bit_word(cpu, DEC_PROM_TCINFO + 24, 0);
633     store_32bit_word(cpu, DEC_PROM_TCINFO + 28, 0);
634     cpu->cd.mips.gpr[MIPS_GPR_V0] = DEC_PROM_TCINFO;
635     break;
636     case 0xa8: /* int execute_cmd(char *) */
637     i = 0;
638     while ((ch = mem_readchar(cpu, MIPS_GPR_A0, i++)) != '\0')
639     console_putchar(cpu->machine->main_console_handle, ch);
640     console_putchar(cpu->machine->main_console_handle, '\n');
641     cpu->cd.mips.gpr[MIPS_GPR_V0] = 0;
642     break;
643     case 0xac: /* rex() */
644     debug("[ DEC PROM rex('%c') ]\n",
645     (int)cpu->cd.mips.gpr[MIPS_GPR_A0]);
646 dpavlin 24 switch ((int32_t)cpu->cd.mips.gpr[MIPS_GPR_A0]) {
647 dpavlin 14 case 'h':
648     debug("DEC PROM: rex('h') ==> halt\n");
649     cpu->machine->exit_without_entering_debugger = 1;
650     cpu->running = 0;
651     break;
652     case 'b':
653     debug("DEC PROM: rex('b') ==> reboot: TODO "
654     "(halting CPU instead)\n");
655     cpu->machine->exit_without_entering_debugger = 1;
656     cpu->running = 0;
657     break;
658     default:
659 dpavlin 24 fatal("DEC prom emulation: unknown rex() a0=0x%"PRIx64
660     " ('%c')\n",
661     (int64_t) cpu->cd.mips.gpr[MIPS_GPR_A0],
662     (char) cpu->cd.mips.gpr[MIPS_GPR_A0]);
663 dpavlin 14 cpu->running = 0;
664     }
665     break;
666     default:
667     cpu_register_dump(cpu->machine, cpu, 1, 0x1);
668     printf("a0 points to: ");
669     for (i=0; i<40; i++) {
670     unsigned char ch = '\0';
671 dpavlin 24 cpu->memory_rw(cpu, cpu->mem, (int32_t)
672 dpavlin 14 cpu->cd.mips.gpr[MIPS_GPR_A0] + i, &ch,
673     sizeof(ch), MEM_READ, CACHE_DATA | NO_EXCEPTIONS);
674     if (ch >= ' ' && ch < 126)
675     printf("%c", ch);
676     else
677     printf("[%02x]", ch);
678     }
679     printf("\n");
680     fatal("PROM emulation: unimplemented callback vector 0x%x\n",
681     vector);
682     cpu->running = 0;
683     }
684    
685     return 1;
686     }
687    

  ViewVC Help
Powered by ViewVC 1.1.26