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

Parent Directory Parent Directory | Revision Log Revision Log


Revision 18 - (hide annotations)
Mon Oct 8 16:19:11 2007 UTC (16 years, 6 months ago) by dpavlin
File MIME type: text/plain
File size: 12503 byte(s)
++ trunk/HISTORY	(local)
$Id: HISTORY,v 1.1004 2005/10/27 14:01:10 debug Exp $
20051011        Passing -A as the default boot arg for CATS (works fine with
                OpenBSD/cats).
20051012	Fixing the VGA cursor offset bug, and speeding up framebuffer
		redraws if character cells contain the same thing as during
		the last redraw.
20051013	Adding a slow strd ARM instruction hack.
20051017	Minor updates: Adding a dummy i80321 Verde controller (for
		XScale emulation), fixing the disassembly of the ARM "ldrd"
		instruction, adding "support" for less-than-4KB pages for ARM
		(by not adding them to translation tables).
20051020	Continuing on some HPCarm stuff. A NetBSD/hpcarm kernel prints
		some boot messages on an emulated Jornada 720.
		Making dev_ram work better with dyntrans (speeds up some things
		quite a bit).
20051021	Automatically generating some of the most common ARM load/store
		multiple instructions.
20051022	Better statistics gathering for the ARM load/store multiple.
		Various other dyntrans and device updates.
20051023	Various minor updates.
20051024	Continuing; minor device and dyntrans fine-tuning. Adding the
		first "reasonable" instruction combination hacks for ARM (the
		cores of NetBSD/cats' memset and memcpy).
20051025	Fixing a dyntrans-related bug in dev_vga. Also changing the
		dyntrans low/high access notification to only be updated on
		writes, not reads. Hopefully it will be enough. (dev_vga in
		charcell mode now seems to work correctly with both reads and
		writes.)
		Experimenting with gathering dyntrans statistics (which parts
		of emulated RAM that are actually executed), and adding
		instruction combination hacks for cache cleaning and a part of
		NetBSD's scanc() function.
20051026	Adding a bitmap for ARM emulation which indicates if a page is
		(specifically) user accessible; loads and stores with the t-
		flag set can now use the translation arrays, which results in
		a measurable speedup.
20051027	Dyntrans updates; adding an extra bitmap array for 32-bit
		emulation modes, speeding up the check whether a physical page
		has any code translations or not (O(n) -> O(1)). Doing a
		similar reduction of O(n) to O(1) by avoiding the scan through
		the translation entries on a translation update (32-bit mode
		only).
		Various other minor hacks.
20051029	Quick release, without any testing at all.

==============  RELEASE 0.3.6.2  ==============


1 dpavlin 4 /*
2     * Copyright (C) 2003-2005 Anders Gavare. All rights reserved.
3     *
4     * Redistribution and use in source and binary forms, with or without
5     * modification, are permitted provided that the following conditions are met:
6     *
7     * 1. Redistributions of source code must retain the above copyright
8     * notice, this list of conditions and the following disclaimer.
9     * 2. Redistributions in binary form must reproduce the above copyright
10     * notice, this list of conditions and the following disclaimer in the
11     * documentation and/or other materials provided with the distribution.
12     * 3. The name of the author may not be used to endorse or promote products
13     * derived from this software without specific prior written permission.
14     *
15     * THIS SOFTWARE IS PROVIDED BY THE AUTHOR AND CONTRIBUTORS ``AS IS'' AND
16     * ANY EXPRESS OR IMPLIED WARRANTIES, INCLUDING, BUT NOT LIMITED TO, THE
17     * IMPLIED WARRANTIES OF MERCHANTABILITY AND FITNESS FOR A PARTICULAR PURPOSE
18     * ARE DISCLAIMED. IN NO EVENT SHALL THE AUTHOR OR CONTRIBUTORS BE LIABLE
19     * FOR ANY DIRECT, INDIRECT, INCIDENTAL, SPECIAL, EXEMPLARY, OR CONSEQUENTIAL
20     * DAMAGES (INCLUDING, BUT NOT LIMITED TO, PROCUREMENT OF SUBSTITUTE GOODS
21     * OR SERVICES; LOSS OF USE, DATA, OR PROFITS; OR BUSINESS INTERRUPTION)
22     * HOWEVER CAUSED AND ON ANY THEORY OF LIABILITY, WHETHER IN CONTRACT, STRICT
23     * LIABILITY, OR TORT (INCLUDING NEGLIGENCE OR OTHERWISE) ARISING IN ANY WAY
24     * OUT OF THE USE OF THIS SOFTWARE, EVEN IF ADVISED OF THE POSSIBILITY OF
25     * SUCH DAMAGE.
26     *
27     *
28 dpavlin 18 * $Id: dev_dec5800.c,v 1.16 2005/10/26 14:37:03 debug Exp $
29 dpavlin 4 *
30     * Emulation of devices found in a DECsystem 58x0, where x is the number
31     * of CPUs in the system. (The CPU board is called KN5800 by Ultrix.)
32     *
33     * o) timers and misc stuff
34     * o) BI (Backplane Interconnect)
35     * o) CCA (Console Communication Area)
36     * o) XMI (Extended Memory Interconnect)
37     *
38     * TODO: This hardware is not very easy to find docs about.
39     * Perhaps VAX 6000/300 docs?
40     */
41    
42     #include <stdio.h>
43     #include <stdlib.h>
44     #include <string.h>
45    
46     #include "console.h"
47     #include "cpu.h"
48     #include "devices.h"
49     #include "machine.h"
50     #include "memory.h"
51     #include "misc.h"
52    
53    
54     /*
55     * dev_dec5800_tick():
56     */
57     void dev_dec5800_tick(struct cpu *cpu, void *extra)
58     {
59     struct dec5800_data *d = extra;
60    
61     /* Timer interrupts? */
62     if (d->csr & 0x8000) {
63     debug("[ dec5800: timer interrupt! ]\n");
64    
65     /* Set timer interrupt pending bit: */
66     d->csr |= 0x20000000;
67    
68     cpu_interrupt(cpu, 3);
69     }
70     }
71    
72    
73     /*
74     * dev_dec5800_vectors_access():
75     */
76     int dev_dec5800_vectors_access(struct cpu *cpu, struct memory *mem,
77     uint64_t relative_addr, unsigned char *data, size_t len,
78     int writeflag, void *extra)
79     {
80     uint64_t idata = 0, odata = 0;
81     struct dec5800_data *d = extra;
82    
83 dpavlin 18 if (writeflag == MEM_WRITE)
84     idata = memory_readmax64(cpu, data, len);
85 dpavlin 4
86     if (writeflag == MEM_READ) {
87     /* TODO */
88     /* 0xfc = transmit interrupt, 0xf8 = receive interrupt,
89     0x80 = IPI */
90     odata = d->vector_0x50;
91     /* odata = 0xfc; */
92     debug("[ dec5800_vectors: read from 0x%02x: 0x%02x ]\n",
93     (int)relative_addr, (int)odata);
94     } else {
95     d->vector_0x50 = idata;
96     debug("[ dec5800_vectors: write to 0x%02x: 0x%02x ]\n",
97     (int)relative_addr, (int)idata);
98     }
99    
100     if (writeflag == MEM_READ)
101     memory_writemax64(cpu, data, len, odata);
102    
103     return 1;
104     }
105    
106    
107     /*
108     * dev_dec5800_access():
109     */
110     int dev_dec5800_access(struct cpu *cpu, struct memory *mem,
111     uint64_t relative_addr, unsigned char *data, size_t len,
112     int writeflag, void *extra)
113     {
114     uint64_t idata = 0, odata = 0;
115     struct dec5800_data *d = extra;
116    
117 dpavlin 18 if (writeflag == MEM_WRITE)
118     idata = memory_readmax64(cpu, data, len);
119 dpavlin 4
120     /* Lowest 4 bits of csr contain cpu id: */
121     d->csr = (d->csr & ~0xf) | (cpu->cpu_id & 0xf);
122    
123     switch (relative_addr) {
124     case 0x0000: /* csr */
125     if (writeflag == MEM_READ) {
126     odata = d->csr;
127     odata ^= random() & 0x10000;
128     debug("[ dec5800: read from csr: 0x%08x ]\n",
129     (int)odata);
130     } else {
131     d->csr = idata;
132    
133     /* Ack. timer interrupts: */
134     d->csr &= ~0x20000000;
135     cpu_interrupt_ack(cpu, 3);
136    
137     debug("[ dec5800: write to csr: 0x%08x ]\n",
138     (int)idata);
139     }
140     break;
141     default:
142     if (writeflag==MEM_READ) {
143     debug("[ dec5800: read from 0x%08lx ]\n",
144     (long)relative_addr);
145     } else {
146     debug("[ dec5800: write to 0x%08lx: 0x%08x ]\n",
147     (long)relative_addr, (int)idata);
148     }
149     }
150    
151     if (writeflag == MEM_READ)
152     memory_writemax64(cpu, data, len, odata);
153    
154     return 1;
155     }
156    
157    
158     /*
159     * dev_dec5800_init():
160     */
161     struct dec5800_data *dev_dec5800_init(struct machine *machine,
162     struct memory *mem, uint64_t baseaddr)
163     {
164     struct dec5800_data *d;
165    
166     d = malloc(sizeof(struct dec5800_data));
167     if (d == NULL) {
168     fprintf(stderr, "out of memory\n");
169     exit(1);
170     }
171     memset(d, 0, sizeof(struct dec5800_data));
172    
173     memory_device_register(mem, "dec5800", baseaddr,
174     DEV_DEC5800_LENGTH, dev_dec5800_access, d, MEM_DEFAULT, NULL);
175     memory_device_register(mem, "dec5800_vectors",
176     baseaddr + 0x30000000, 0x100, dev_dec5800_vectors_access,
177     d, MEM_DEFAULT, NULL);
178     machine_add_tickfunction(machine, dev_dec5800_tick, d, 14);
179    
180     return d;
181     }
182    
183    
184     /*****************************************************************************/
185    
186    
187     #include "bireg.h"
188    
189     struct decbi_data {
190     int csr[NNODEBI];
191     };
192    
193    
194     /*
195     * dev_decbi_access():
196     */
197     int dev_decbi_access(struct cpu *cpu, struct memory *mem,
198     uint64_t relative_addr, unsigned char *data, size_t len,
199     int writeflag, void *extra)
200     {
201     uint64_t idata = 0, odata = 0;
202     int node_nr;
203     struct decbi_data *d = extra;
204    
205 dpavlin 18 if (writeflag == MEM_WRITE)
206     idata = memory_readmax64(cpu, data, len);
207 dpavlin 4
208     relative_addr += BI_NODESIZE; /* HACK */
209    
210     node_nr = relative_addr / BI_NODESIZE;
211     relative_addr &= (BI_NODESIZE - 1);
212    
213     /* TODO: This "1" here is the max node number in actual use. */
214     if (node_nr > 1 || node_nr >= NNODEBI)
215     return 0;
216    
217     switch (relative_addr) {
218     case BIREG_DTYPE:
219     if (writeflag==MEM_READ) {
220     /*
221     * This is a list of the devices in our BI slots:
222     */
223     switch (node_nr) {
224     case 1: odata = BIDT_KDB50; break; /* Disk */
225     /* case 2: odata = BIDT_DEBNA; break; */
226     /* BIDT_DEBNA = Ethernet */
227     /* case 3: odata = BIDT_MS820; break; */
228     /* BIDT_MS820 = Memory */
229     default:
230     /* No device. */
231     odata = 0;
232     }
233    
234     debug("[ decbi: (node %i) read from BIREG_DTYPE:"
235     " 0x%x ]\n", node_nr, (int)odata);
236     } else {
237     debug("[ decbi: (node %i) attempt to write to "
238     "BIREG_DTYPE: 0x%08x ]\n", node_nr, (int)idata);
239     }
240     break;
241     case BIREG_VAXBICSR:
242     if (writeflag==MEM_READ) {
243     odata = (d->csr[node_nr] & ~BICSR_NODEMASK) | node_nr;
244     debug("[ decbi: (node %i) read from BIREG_"
245     "VAXBICSR: 0x%x ]\n", node_nr, (int)odata);
246     } else {
247     d->csr[node_nr] = idata;
248     debug("[ decbi: (node %i) attempt to write to "
249     "BIREG_VAXBICSR: 0x%08x ]\n", node_nr, (int)idata);
250     }
251     break;
252     case 0xf4:
253     if (writeflag==MEM_READ) {
254     odata = 0xffff; /* ? */
255     debug("[ decbi: (node %i) read from 0xf4: "
256     "0x%x ]\n", node_nr, (int)odata);
257     } else {
258     debug("[ decbi: (node %i) attempt to write "
259     "to 0xf4: 0x%08x ]\n", node_nr, (int)idata);
260     }
261     break;
262     default:
263     if (writeflag==MEM_READ) {
264     debug("[ decbi: (node %i) read from unimplemented "
265     "0x%08lx ]\n", node_nr, (long)relative_addr,
266     (int)odata);
267     } else {
268     debug("[ decbi: (node %i) write to unimplemented "
269     "0x%08lx: 0x%08x ]\n", node_nr,
270     (long)relative_addr, (int)idata);
271     }
272     }
273    
274     if (writeflag == MEM_READ)
275     memory_writemax64(cpu, data, len, odata);
276    
277     return 1;
278     }
279    
280    
281     /*
282     * dev_decbi_init():
283     */
284     void dev_decbi_init(struct memory *mem, uint64_t baseaddr)
285     {
286     struct decbi_data *d;
287    
288     d = malloc(sizeof(struct decbi_data));
289     if (d == NULL) {
290     fprintf(stderr, "out of memory\n");
291     exit(1);
292     }
293     memset(d, 0, sizeof(struct decbi_data));
294    
295     memory_device_register(mem, "decbi", baseaddr + 0x2000,
296     DEV_DECBI_LENGTH - 0x2000, dev_decbi_access, d, MEM_DEFAULT, NULL);
297     }
298    
299    
300     /*****************************************************************************/
301    
302    
303     /*
304     * CCA, "Console Communication Area" for a DEC 5800 SMP system.
305     */
306    
307     struct deccca_data {
308     int dummy;
309     };
310    
311    
312     /*
313     * dev_deccca_access():
314     */
315     int dev_deccca_access(struct cpu *cpu, struct memory *mem,
316     uint64_t relative_addr, unsigned char *data, size_t len,
317     int writeflag, void *extra)
318     {
319     uint64_t idata = 0, odata = 0;
320     /* struct deccca_data *d = extra; */
321    
322 dpavlin 18 if (writeflag == MEM_WRITE)
323     idata = memory_readmax64(cpu, data, len);
324 dpavlin 4
325     switch (relative_addr) {
326     case 6:
327     case 7:
328     /* CCA "ID" bytes? These must be here, or Ultrix complains. */
329     if (writeflag == MEM_READ)
330     odata = 67;
331     break;
332     case 8:
333     if (writeflag == MEM_READ)
334     odata = cpu->machine->ncpus;
335     break;
336     case 20:
337     if (writeflag == MEM_READ)
338     odata = (1 << cpu->machine->ncpus) - 1;
339     /* one bit for each cpu */
340     break;
341     case 28:
342     if (writeflag == MEM_READ)
343     odata = (1 << cpu->machine->ncpus) - 1;
344     /* one bit for each enabled(?) cpu */
345     break;
346     default:
347     if (writeflag==MEM_READ) {
348     debug("[ deccca: read from 0x%08lx ]\n",
349     (long)relative_addr);
350     } else {
351     debug("[ deccca: write to 0x%08lx: 0x%08x ]\n",
352     (long)relative_addr, (int)idata);
353     }
354     }
355    
356     if (writeflag == MEM_READ)
357     memory_writemax64(cpu, data, len, odata);
358    
359     return 1;
360     }
361    
362    
363     /*
364     * dev_deccca_init():
365     */
366     void dev_deccca_init(struct memory *mem, uint64_t baseaddr)
367     {
368     struct deccca_data *d;
369    
370     d = malloc(sizeof(struct deccca_data));
371     if (d == NULL) {
372     fprintf(stderr, "out of memory\n");
373     exit(1);
374     }
375     memset(d, 0, sizeof(struct deccca_data));
376    
377     memory_device_register(mem, "deccca", baseaddr, DEV_DECCCA_LENGTH,
378     dev_deccca_access, d, MEM_DEFAULT, NULL);
379     }
380    
381    
382     /*****************************************************************************/
383    
384    
385     /*
386     * DEC 5800 XMI (this has to do with SMP...)
387     */
388    
389     #include "xmireg.h"
390    
391     struct decxmi_data {
392     uint32_t reg_0xc[NNODEXMI];
393     };
394    
395    
396     /*
397     * dev_decxmi_access():
398     */
399     int dev_decxmi_access(struct cpu *cpu, struct memory *mem,
400     uint64_t relative_addr, unsigned char *data, size_t len,
401     int writeflag, void *extra)
402     {
403     uint64_t idata = 0, odata = 0;
404     int node_nr;
405     struct decxmi_data *d = extra;
406    
407 dpavlin 18 if (writeflag == MEM_WRITE)
408     idata = memory_readmax64(cpu, data, len);
409 dpavlin 4
410     node_nr = relative_addr / XMI_NODESIZE;
411     relative_addr &= (XMI_NODESIZE - 1);
412    
413     if (node_nr >= cpu->machine->ncpus + 1 || node_nr >= NNODEXMI)
414     return 0;
415    
416     switch (relative_addr) {
417     case XMI_TYPE:
418     if (writeflag == MEM_READ) {
419     /*
420     * The first node is an XMI->BI adapter node, and then
421     * there are n CPU nodes.
422     */
423     odata = XMIDT_ISIS;
424     if (node_nr == 0)
425     odata = XMIDT_DWMBA;
426    
427     debug("[ decxmi: (node %i) read from XMI_TYPE: "
428     "0x%08x ]\n", node_nr, (int)odata);
429     } else
430     debug("[ decxmi: (node %i) write to XMI_TYPE: "
431     "0x%08x ]\n", node_nr, (int)idata);
432     break;
433     case XMI_BUSERR:
434     if (writeflag == MEM_READ) {
435     odata = 0;
436     debug("[ decxmi: (node %i) read from XMI_BUSERR: "
437     "0x%08x ]\n", node_nr, (int)odata);
438     } else
439     debug("[ decxmi: (node %i) write to XMI_BUSERR: "
440     "0x%08x ]\n", node_nr, (int)idata);
441     break;
442     case XMI_FAIL:
443     if (writeflag == MEM_READ) {
444     odata = 0;
445     debug("[ decxmi: (node %i) read from XMI_FAIL: "
446     "0x%08x ]\n", node_nr, (int)odata);
447     } else
448     debug("[ decxmi: (node %i) write to XMI_FAIL: "
449     "0x%08x ]\n", node_nr, (int)idata);
450     break;
451     case 0xc:
452     if (writeflag == MEM_READ) {
453     odata = d->reg_0xc[node_nr];
454     debug("[ decxmi: (node %i) read from REG 0xC: "
455     "0x%08x ]\n", node_nr, (int)odata);
456     } else {
457     d->reg_0xc[node_nr] = idata;
458     debug("[ decxmi: (node %i) write to REG 0xC: "
459     "0x%08x ]\n", node_nr, (int)idata);
460     }
461     break;
462     default:
463     if (writeflag==MEM_READ) {
464     debug("[ decxmi: (node %i) read from unimplemented "
465     "0x%08lx ]\n", node_nr, (long)relative_addr,
466     (int)odata);
467     } else {
468     debug("[ decxmi: (node %i) write to unimplemented "
469     "0x%08lx: 0x%08x ]\n", node_nr,
470     (long)relative_addr, (int)idata);
471     }
472     }
473    
474     if (writeflag == MEM_READ)
475     memory_writemax64(cpu, data, len, odata);
476    
477     return 1;
478     }
479    
480    
481     /*
482     * dev_decxmi_init():
483     */
484     void dev_decxmi_init(struct memory *mem, uint64_t baseaddr)
485     {
486     struct decxmi_data *d;
487    
488     d = malloc(sizeof(struct decxmi_data));
489     if (d == NULL) {
490     fprintf(stderr, "out of memory\n");
491     exit(1);
492     }
493     memset(d, 0, sizeof(struct decxmi_data));
494    
495     memory_device_register(mem, "decxmi", baseaddr, DEV_DECXMI_LENGTH,
496     dev_decxmi_access, d, MEM_DEFAULT, NULL);
497     }
498    

  ViewVC Help
Powered by ViewVC 1.1.26