/[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 20 - (hide annotations)
Mon Oct 8 16:19:23 2007 UTC (16 years, 6 months ago) by dpavlin
File MIME type: text/plain
File size: 12498 byte(s)
++ trunk/HISTORY	(local)
$Id: HISTORY,v 1.1055 2005/11/25 22:48:36 debug Exp $
20051031	Adding disassembly support for more ARM instructions (clz,
		smul* etc), and adding a hack to support "new tiny" pages
		for StrongARM.
20051101	Minor documentation updates (NetBSD 2.0.2 -> 2.1, and OpenBSD
		3.7 -> 3.8, and lots of testing).
		Changing from 1-sector PIO mode 0 transfers to 128-sector PIO
		mode 3 (in dev_wdc).
		Various minor ARM dyntrans updates (pc-relative loads from
		within the same page as the instruction are now treated as
		constant "mov").
20051102	Re-enabling instruction combinations (they were accidentally
		disabled).
		Dyntrans TLB entries are now overwritten using a round-robin
		scheme instead of randomly. This increases performance.
		Fixing a typo in file.c (thanks to Chuan-Hua Chang for
		noticing it).
		Experimenting with adding ATAPI support to dev_wdc (to make
		emulated *BSD detect cdroms as cdroms, not harddisks).
20051104	Various minor updates.
20051105	Continuing on the ATAPI emulation. Seems to work well enough
		for a NetBSD/cats installation, but not OpenBSD/cats.
		Various other updates.
20051106	Modifying the -Y command line option to allow scaleup with
		certain graphic controllers (only dev_vga so far), not just
		scaledown.
		Some minor dyntrans cleanups.
20051107	Beginning a cleanup up the PCI subsystem (removing the
		read_register hack, etc).
20051108	Continuing the cleanup; splitting up some pci devices into a
		normal autodev device and some separate pci glue code.
20051109	Continuing on the PCI bus stuff; all old pci_*.c have been
		incorporated into normal devices and/or rewritten as glue code
		only, adding a dummy Intel 82371AB PIIX4 for Malta (not really
		tested yet).
		Minor pckbc fix so that Linux doesn't complain.
		Working on the DEC 21143 NIC (ethernet mac rom stuff mostly).
		Various other minor fixes.
20051110	Some more ARM dyntrans fine-tuning (e.g. some instruction
		combinations (cmps followed by conditional branch within the
		same page) and special cases for DPIs with regform when the
		shifter isn't used).
20051111	ARM dyntrans updates: O(n)->O(1) for just-mark-as-non-
		writable in the generic pc_to_pointers function, and some other
		minor hacks.
		Merging Cobalt and evbmips (Malta) ISA interrupt handling,
		and some minor fixes to allow Linux to accept harddisk irqs.
20051112	Minor device updates (pckbc, dec21143, lpt, ...), most
		importantly fixing the ALI M1543/M5229 so that harddisk irqs
		work with Linux/CATS.
20051113	Some more generalizations of the PCI subsystem.
		Finally took the time to add a hack for SCSI CDROM TOCs; this
		enables OpenBSD to use partition 'a' (as needed by the OpenBSD
		installer), and Windows NT's installer to get a bit further.
		Also fixing dev_wdc to allow Linux to detect ATAPI CDROMs.
		Continuing on the DEC 21143.
20051114	Minor ARM dyntrans tweaks; ARM cmps+branch optimization when
		comparing with 0, and generalizing the xchg instr. comb.
		Adding disassembly of ARM mrrc/mcrr and q{,d}{add,sub}.
20051115	Continuing on various PPC things (BATs, other address trans-
		lation things, various loads/stores, BeBox emulation, etc.).
		Beginning to work on PPC interrupt/exception support.
20051116	Factoring out some code which initializes legacy ISA devices
		from those machines that use them (bus_isa).
		Continuing on PPC interrupt/exception support.
20051117	Minor Malta fixes: RTC year offset = 80, disabling a speed hack
		which caused NetBSD to detect a too fast cpu, and adding a new
		hack to make Linux detect a faster cpu.
		Continuing on the Artesyn PM/PPC emulation mode.
		Adding an Algor emulation skeleton (P4032 and P5064);
		implementing some of the basics.
		Continuing on PPC emulation in general; usage of unimplemented
		SPRs is now easier to track, continuing on memory/exception
		related issues, etc.
20051118	More work on PPC emulation (tgpr0..3, exception handling,
		memory stuff, syscalls, etc.).
20051119	Changing the ARM dyntrans code to mostly use cpu->pc, and not
		necessarily use arm reg 15. Seems to work.
		Various PPC updates; continuing on the PReP emulation mode.
20051120	Adding a workaround/hack to dev_mc146818 to allow NetBSD/prep
		to detect the clock.
20051121	More cleanup of the PCI bus (memory and I/O bases, etc).
		Continuing on various PPC things (decrementer and timebase,
		WDCs on obio (on PReP) use irq 13, not 14/15).
20051122	Continuing on the CPC700 controller (interrupts etc) for PMPPC,
		and on PPC stuff in general.
		Finally! After some bug fixes to the virtual to physical addr
		translation, NetBSD/{prep,pmppc} 2.1 reach userland and are
		stable enough to be interacted with.
		More PCI updates; reverse-endian device access for PowerPC etc.
20051123	Generalizing the IEEE floating point subsystem (moving it out
		from src/cpus/cpu_mips_coproc.c into a new src/float_emul.c).
		Input via slave xterms was sometimes not really working; fixing
		this for ns16550, and a warning message is now displayed if
		multiple non-xterm consoles are active.
		Adding some PPC floating point support, etc.
		Various interrupt related updates (dev_wdc, _ns16550, _8259,
		and the isa32 common code in machine.c).
		NetBSD/prep can now be installed! :-) (Well, with some manual
		commands necessary before running sysinst.) Updating the
		documentation and various other things to reflect this.
20051124	Various minor documentation updates.
		Continuing the work on the DEC 21143 NIC.
20051125	LOTS of work on the 21143. Both OpenBSD and NetBSD work fine
		with it now, except that OpenBSD sometimes gives a time-out
		warning.
		Minor documentation updates.

==============  RELEASE 0.3.7  ==============


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 20 * $Id: dev_dec5800.c,v 1.17 2005/11/13 00:14:08 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 dpavlin 20 DEV_DEC5800_LENGTH, dev_dec5800_access, d, DM_DEFAULT, NULL);
175 dpavlin 4 memory_device_register(mem, "dec5800_vectors",
176     baseaddr + 0x30000000, 0x100, dev_dec5800_vectors_access,
177 dpavlin 20 d, DM_DEFAULT, NULL);
178 dpavlin 4 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 dpavlin 20 DEV_DECBI_LENGTH - 0x2000, dev_decbi_access, d, DM_DEFAULT, NULL);
297 dpavlin 4 }
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 dpavlin 20 dev_deccca_access, d, DM_DEFAULT, NULL);
379 dpavlin 4 }
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 dpavlin 20 dev_decxmi_access, d, DM_DEFAULT, NULL);
497 dpavlin 4 }
498    

  ViewVC Help
Powered by ViewVC 1.1.26