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

Contents of /trunk/src/promemul/dec_prom.c

Parent Directory Parent Directory | Revision Log Revision Log


Revision 30 - (show annotations)
Mon Oct 8 16:20:40 2007 UTC (16 years, 6 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 /*
2 * Copyright (C) 2003-2006 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.10 2006/07/26 23:21:48 debug Exp $
29 *
30 * DECstation PROM emulation.
31 *
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 */
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 {
69 unsigned char ch;
70 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 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 (int32_t)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 }
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 cpu->memory_rw(cpu, cpu->mem, (int32_t)
316 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 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
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 size_t x;
352
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 for (i=0; i<(int)sizeof(buf); i++)
511 cpu->memory_rw(cpu, cpu->mem, (int32_t)
512 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 for (j=0; j<(int32_t)strlen((char *)buf); j++) {
520 cpu->memory_rw(cpu, cpu->mem, (int32_t)
521 (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 cpu->memory_rw(cpu, cpu->mem, (int32_t)(DEC_PROM_STRINGS
528 + i + strlen((char *)buf)), &ch2, sizeof(char),
529 MEM_READ, CACHE_DATA | NO_EXCEPTIONS);
530 if (nmatches == (int)strlen((char *)buf) && ch2=='=') {
531 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 (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 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 switch ((int32_t)cpu->cd.mips.gpr[MIPS_GPR_A0]) {
647 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 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 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 cpu->memory_rw(cpu, cpu->mem, (int32_t)
672 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