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

Parent Directory Parent Directory | Revision Log Revision Log


Revision 42 - (hide annotations)
Mon Oct 8 16:22:32 2007 UTC (16 years, 6 months ago) by dpavlin
File MIME type: text/plain
File size: 18183 byte(s)
++ trunk/HISTORY	(local)
$Id: HISTORY,v 1.1613 2007/06/15 20:11:26 debug Exp $
20070501	Continuing a little on m88k disassembly (control registers,
		more instructions).
		Adding a dummy mvme88k machine mode.
20070502	Re-adding MIPS load/store alignment exceptions.
20070503	Implementing more of the M88K disassembly code.
20070504	Adding disassembly of some more M88K load/store instructions.
		Implementing some relatively simple M88K instructions (br.n,
		xor[.u] imm, and[.u] imm).
20070505	Implementing M88K three-register and, or, xor, and jmp[.n],
		bsr[.n] including function call trace stuff.
		Applying a patch from Bruce M. Simpson which implements the
		SYSCON_BOARD_CPU_CLOCK_FREQ_ID object of the syscon call in
		the yamon PROM emulation.
20070506	Implementing M88K bb0[.n] and bb1[.n], and skeletons for
		ldcr and stcr (although no control regs are implemented yet).
20070509	Found and fixed the bug which caused Linux for QEMU_MIPS to
		stop working in 0.4.5.1: It was a faulty change to the MIPS
		'sc' and 'scd' instructions I made while going through gcc -W
		warnings on 20070428.
20070510	Updating the Linux/QEMU_MIPS section in guestoses.html to
		use mips-test-0.2.tar.gz instead of 0.1.
		A big thank you to Miod Vallat for sending me M88K manuals.
		Implementing more M88K instructions (addu, subu, div[u], mulu,
		ext[u], clr, set, cmp).
20070511	Fixing bugs in the M88K "and" and "and.u" instructions (found
		by comparing against the manual).
		Implementing more M88K instructions (mask[.u], mak, bcnd (auto-
		generated)) and some more control register details.
		Cleanup: Removing the experimental AVR emulation mode and
		corresponding devices; AVR emulation wasn't really meaningful.
		Implementing autogeneration of most M88K loads/stores. The
		rectangle drawing demo (with -O0) for M88K runs :-)
		Beginning on M88K exception handling.
		More M88K instructions: tb0, tb1, rte, sub, jsr[.n].
		Adding some skeleton MVME PROM ("BUG") emulation.
20070512	Fixing a bug in the M88K cmp instruction.
		Adding the M88K lda (scaled register) instruction.
		Fixing bugs in 64-bit (32-bit pairs) M88K loads/stores.
		Removing the unused tick_hz stuff from the machine struct.
		Implementing the M88K xmem instruction. OpenBSD/mvme88k gets
		far enough to display the Copyright banner :-)
		Implementing subu.co (guess), addu.co, addu.ci, ff0, and ff1.
		Adding a dev_mvme187, for MVME187-specific devices/registers.
		OpenBSD/mvme88k prints more boot messages. :)
20070515	Continuing on MVME187 emulation (adding more devices, beginning
		on the CMMUs, etc).
		Adding the M88K and.c, xor.c, and or.c instructions, and making
		sure that mul, div, etc cause exceptions if executed when SFD1
		is disabled.
20070517	Continuing on M88K and MVME187 emulation in general; moving
		the CMMU registers to the CPU struct, separating dev_pcc2 from
		dev_mvme187, and beginning on memory_m88k.c (BATC and PATC).
		Fixing a bug in 64-bit (32-bit pairs) M88K fast stores.
		Implementing the clock part of dev_mk48txx.
		Implementing the M88K fstcr and xcr instructions.
		Implementing m88k_cpu_tlbdump().
		Beginning on the implementation of a separate address space
		for M88K .usr loads/stores.
20070520	Removing the non-working (skeleton) Sandpoint, SonyNEWS, SHARK
		Dnard, and Zaurus machine modes.
		Experimenting with dyntrans to_be_translated read-ahead. It
		seems to give a very small performance increase for MIPS
		emulation, but a large performance degradation for SuperH. Hm.
20070522	Disabling correct SuperH ITLB emulation; it does not seem to be
		necessary in order to let SH4 guest OSes run, and it slows down
		userspace code.
		Implementing "samepage" branches for SuperH emulation, and some
		other minor speed hacks.
20070525	Continuing on M88K memory-related stuff: exceptions, memory
		transaction register contents, etc.
		Implementing the M88K subu.ci instruction.
		Removing the non-working (skeleton) Iyonix machine mode.
		OpenBSD/mvme88k reaches userland :-), starts executing
		/sbin/init's instructions, and issues a few syscalls, before
		crashing.
20070526	Fixing bugs in dev_mk48txx, so that OpenBSD/mvme88k detects
		the correct time-of-day.
		Implementing a generic IRQ controller for the test machines
		(dev_irqc), similar to a proposed patch from Petr Stepan.
		Experimenting some more with translation read-ahead.
		Adding an "expect" script for automated OpenBSD/landisk
		install regression/performance tests.
20070527	Adding a dummy mmEye (SH3) machine mode skeleton.
		FINALLY found the strange M88K bug I have been hunting: I had
		not emulated the SNIP value for exceptions occurring in
		branch delay slots correctly.
		Implementing correct exceptions for 64-bit M88K loads/stores.
		Address to symbol lookups are now disabled when M88K is
		running in usermode (because usermode addresses don't have
		anything to do with supervisor addresses).
20070531	Removing the mmEye machine mode skeleton.
20070604	Some minor code cleanup.
20070605	Moving src/useremul.c into a subdir (src/useremul/), and
		cleaning up some more legacy constructs.
		Adding -Wstrict-aliasing and -fstrict-aliasing detection to
		the configure script.
20070606	Adding a check for broken GCC on Solaris to the configure
		script. (GCC 3.4.3 on Solaris cannot handle static variables
		which are initialized to 0 or NULL. :-/)
		Removing the old (non-working) ARC emulation modes: NEC RD94,
		R94, R96, and R98, and the last traces of Olivetti M700 and
		Deskstation Tyne.
		Removing the non-working skeleton WDSC device (dev_wdsc).
20070607	Thinking about how to use the host's cc + ld at runtime to
		generate native code. (See experiments/native_cc_ld_test.i
		for an example.)
20070608	Adding a program counter sampling timer, which could be useful
		for native code generation experiments.
		The KN02_CSR_NRMMOD bit in the DECstation 5000/200 (KN02) CSR
		should always be set, to allow a 5000/200 PROM to boot.
20070609	Moving out breakpoint details from the machine struct into
		a helper struct, and removing the limit on max nr of
		breakpoints.
20070610	Moving out tick functions into a helper struct as well (which
		also gets rid of the max limit).
20070612	FINALLY figured out why Debian/DECstation stopped working when
		translation read-ahead was enabled: in src/memory_rw.c, the
		call to invalidate_code_translation was made also if the
		memory access was an instruction load (if the page was mapped
		as writable); it shouldn't be called in that case.
20070613	Implementing some more MIPS32/64 revision 2 instructions: di,
		ei, ext, dext, dextm, dextu, and ins.
20070614	Implementing an instruction combination for the NetBSD/arm
		idle loop (making the host not use any cpu if NetBSD/arm
		inside the emulator is not using any cpu).
		Increasing the nr of ARM VPH entries from 128 to 384.
20070615	Removing the ENABLE_arch stuff from the configure script, so
		that all included architectures are included in both release
		and development builds.
		Moving memory related helper functions from misc.c to memory.c.
		Adding preliminary instructions for netbooting NetBSD/pmppc to
		guestoses.html; it doesn't work yet, there are weird timeouts.
		Beginning a total rewrite of the userland emulation modes
		(removing all emulation modes, beginning from scratch with
		NetBSD/MIPS and FreeBSD/Alpha only).
20070616	After fixing a bug in the DEC21143 NIC (the TDSTAT_OWN bit was
		only cleared for the last segment when transmitting, not all
		segments), NetBSD/pmppc boots with root-on-nfs without the
		timeouts. Updating guestoses.html.
		Removing the skeleton PSP (Playstation Portable) mode.
		Moving X11-related stuff in the machine struct into a helper
		struct.
		Cleanup of out-of-memory checks, to use a new CHECK_ALLOCATION
		macro (which prints a meaningful error message).
		Adding a COMMENT to each machine and device (for automagic
		.index comment generation).
		Doing regression testing for the next release.

==============  RELEASE 0.4.6  ==============


1 dpavlin 4 /*
2 dpavlin 34 * Copyright (C) 2004-2007 Anders Gavare. All rights reserved.
3 dpavlin 4 *
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 42 * $Id: dev_jazz.c,v 1.29 2007/06/15 19:11:15 debug Exp $
29 dpavlin 4 *
30 dpavlin 42 * COMMENT: Microsoft Jazz-related stuff (Acer PICA-61, etc)
31 dpavlin 22 *
32     * TODO/NOTE: This is mostly a quick hack, it doesn't really implement
33     * much of the Jazz architecture. Also, the a0/20 isa-like stuff is
34     * not supposed to be here.
35 dpavlin 34 *
36     * TODO: Figure out how the int enable mask works; it seems to be shifted
37     * 10 bits (?) according to NetBSD/arc sources.
38     *
39     * TODO: Don't hardcode the timer to 100 Hz.
40     *
41     * JAZZ interrupts 0..14 are connected to MIPS irq 3,
42     * JAZZ interrupt 15 (the timer) is connected to MIPS irq 6,
43     * and ISA interrupts 0..15 are connected to MIPS irq 4.
44 dpavlin 4 */
45    
46     #include <stdio.h>
47     #include <stdlib.h>
48     #include <string.h>
49    
50     #include "cpu.h"
51     #include "device.h"
52     #include "devices.h"
53 dpavlin 34 #include "interrupt.h"
54 dpavlin 4 #include "machine.h"
55     #include "memory.h"
56     #include "misc.h"
57 dpavlin 34 #include "timer.h"
58 dpavlin 4
59     #include "jazz_r4030_dma.h"
60     #include "pica.h"
61    
62    
63 dpavlin 34 #define DEV_JAZZ_LENGTH 0x280
64 dpavlin 4 #define DEV_JAZZ_TICKSHIFT 14
65     #define PICA_TIMER_IRQ 15
66    
67 dpavlin 34 struct jazz_data {
68     struct interrupt mips_irq_3;
69     struct interrupt mips_irq_4;
70     struct interrupt mips_irq_6;
71 dpavlin 4
72 dpavlin 34 struct cpu *cpu;
73    
74     /* Jazz stuff: */
75     uint32_t int_enable_mask; /* TODO! */
76     uint32_t int_asserted;
77    
78     /* ISA stuff: */
79     uint32_t isa_int_enable_mask;
80     uint32_t isa_int_asserted;
81    
82     int interval;
83     int interval_start;
84    
85     struct timer *timer;
86     int pending_timer_interrupts;
87     int jazz_timer_value;
88     int jazz_timer_current;
89     struct interrupt jazz_timer_irq;
90    
91     uint64_t dma_translation_table_base;
92     uint64_t dma_translation_table_limit;
93    
94     uint32_t dma0_mode;
95     uint32_t dma0_enable;
96     uint32_t dma0_count;
97     uint32_t dma0_addr;
98    
99     uint32_t dma1_mode;
100     /* same for dma1,2,3 actually (TODO) */
101    
102     int led;
103     };
104    
105    
106     void reassert_isa_interrupts(struct jazz_data *d)
107     {
108     if (d->isa_int_asserted & d->isa_int_enable_mask)
109     INTERRUPT_ASSERT(d->mips_irq_4);
110     else
111     INTERRUPT_DEASSERT(d->mips_irq_4);
112     }
113    
114    
115     void jazz_interrupt_assert(struct interrupt *interrupt)
116     {
117     struct jazz_data *d = interrupt->extra;
118     d->int_asserted |= (1 << interrupt->line);
119    
120     if (d->int_asserted & 0x7fff)
121     INTERRUPT_ASSERT(d->mips_irq_3);
122     if (d->int_asserted & 0x8000)
123     INTERRUPT_ASSERT(d->mips_irq_6);
124     }
125     void jazz_interrupt_deassert(struct interrupt *interrupt)
126     {
127     struct jazz_data *d = interrupt->extra;
128     d->int_asserted &= ~(1 << interrupt->line);
129    
130     if (!(d->int_asserted & 0x7fff))
131     INTERRUPT_DEASSERT(d->mips_irq_3);
132     if (!(d->int_asserted & 0x8000))
133     INTERRUPT_DEASSERT(d->mips_irq_6);
134     }
135     void jazz_isa_interrupt_assert(struct interrupt *interrupt)
136     {
137     struct jazz_data *d = interrupt->extra;
138     d->isa_int_asserted |= (1 << interrupt->line);
139     reassert_isa_interrupts(d);
140     }
141     void jazz_isa_interrupt_deassert(struct interrupt *interrupt)
142     {
143     struct jazz_data *d = interrupt->extra;
144     d->isa_int_asserted &= ~(1 << interrupt->line);
145     reassert_isa_interrupts(d);
146     }
147    
148    
149 dpavlin 4 /*
150     * dev_jazz_dma_controller():
151     */
152     size_t dev_jazz_dma_controller(void *dma_controller_data,
153     unsigned char *data, size_t len, int writeflag)
154     {
155     struct jazz_data *d = (struct jazz_data *) dma_controller_data;
156     struct cpu *cpu = d->cpu;
157     int i, enab_writeflag;
158     int res, ncpy;
159     uint32_t dma_addr;
160     unsigned char tr[sizeof(uint32_t)];
161     uint32_t phys_addr;
162    
163     #if 0
164     fatal("[ dev_jazz_dma_controller(): writeflag=%i, len=%i, data =",
165     writeflag, (int)len);
166     for (i=0; i<len; i++)
167     fatal(" %02x", data[i]);
168     fatal(" mode=%08x enable=%08x count=%08x addr=%08x",
169     d->dma0_mode, d->dma0_enable, d->dma0_count, d->dma0_addr);
170     fatal(" table=%08x",
171     d->dma_translation_table_base);
172     fatal(" ]\n");
173     #endif
174    
175     if (!(d->dma0_enable & R4030_DMA_ENAB_RUN)) {
176     fatal("[ dev_jazz_dma_controller(): dma not enabled? ]\n");
177     /* return 0; */
178     }
179    
180     /* R4030 "write" means write to the device, writeflag as the
181     argument to this function means write to memory. */
182     enab_writeflag = (d->dma0_enable & R4030_DMA_ENAB_WRITE)? 0 : 1;
183     if (enab_writeflag != writeflag) {
184     fatal("[ dev_jazz_dma_controller(): wrong direction? ]\n");
185     return 0;
186     }
187    
188     dma_addr = d->dma0_addr;
189     i = 0;
190 dpavlin 22 while (dma_addr < d->dma0_addr + d->dma0_count && i < (int32_t)len) {
191 dpavlin 4
192     res = cpu->memory_rw(cpu, cpu->mem,
193     d->dma_translation_table_base + (dma_addr >> 12) * 8,
194     tr, sizeof(tr), 0, PHYSICAL | NO_EXCEPTIONS);
195    
196     if (cpu->byte_order==EMUL_BIG_ENDIAN)
197     phys_addr = (tr[0] << 24) + (tr[1] << 16) +
198     (tr[2] << 8) + tr[3];
199     else
200     phys_addr = (tr[3] << 24) + (tr[2] << 16) +
201     (tr[1] << 8) + tr[0];
202     phys_addr &= ~0xfff; /* just in case */
203     phys_addr += (dma_addr & 0xfff);
204    
205     /* fatal(" !!! dma_addr = %08x, phys_addr = %08x\n",
206     (int)dma_addr, (int)phys_addr); */
207    
208     /* Speed up the copying by copying 16 or 256 bytes: */
209     ncpy = 1;
210 dpavlin 22 if ((phys_addr & 15) == 0 && i + 15 <= (int32_t)len)
211 dpavlin 4 ncpy = 15;
212 dpavlin 22 if ((phys_addr & 255) == 0 && i + 255 <= (int32_t)len)
213 dpavlin 4 ncpy = 255;
214    
215     res = cpu->memory_rw(cpu, cpu->mem, phys_addr,
216     &data[i], ncpy, writeflag, PHYSICAL | NO_EXCEPTIONS);
217    
218     dma_addr += ncpy;
219     i += ncpy;
220     }
221    
222     /* TODO: Is this correct? */
223     d->dma0_count = 0;
224    
225     return len;
226     }
227    
228    
229 dpavlin 34 static void timer_tick(struct timer *t, void *extra)
230 dpavlin 4 {
231     struct jazz_data *d = extra;
232 dpavlin 34 d->pending_timer_interrupts ++;
233     }
234 dpavlin 4
235 dpavlin 34
236     DEVICE_TICK(jazz)
237     {
238     struct jazz_data *d = extra;
239    
240 dpavlin 4 /* Used by NetBSD/arc and OpenBSD/arc: */
241     if (d->interval_start > 0 && d->interval > 0
242     && (d->int_enable_mask & 2) /* Hm? */ ) {
243     d->interval -= 2;
244     if (d->interval <= 0) {
245 dpavlin 34 /* debug("[ jazz: interval timer interrupt ]\n");
246     INTERRUPT_ASSERT(d->jazz_timer_irq); */
247 dpavlin 4 }
248 dpavlin 34
249     /* New timer system: */
250     if (d->pending_timer_interrupts > 0)
251     INTERRUPT_ASSERT(d->jazz_timer_irq);
252 dpavlin 4 }
253    
254     /* Linux? */
255     if (d->jazz_timer_value != 0) {
256     d->jazz_timer_current -= 5;
257     if (d->jazz_timer_current < 1) {
258     d->jazz_timer_current = d->jazz_timer_value;
259 dpavlin 34 /* INTERRUPT_ASSERT(d->mips_irq_6); */
260 dpavlin 4 }
261 dpavlin 34
262     /* New timer system: */
263     if (d->pending_timer_interrupts > 0)
264     INTERRUPT_ASSERT(d->mips_irq_6);
265 dpavlin 4 }
266     }
267    
268    
269 dpavlin 22 DEVICE_ACCESS(jazz)
270 dpavlin 4 {
271 dpavlin 42 struct jazz_data *d = extra;
272 dpavlin 4 uint64_t idata = 0, odata = 0;
273     int regnr;
274    
275 dpavlin 18 if (writeflag == MEM_WRITE)
276     idata = memory_readmax64(cpu, data, len);
277    
278 dpavlin 4 regnr = relative_addr / sizeof(uint32_t);
279    
280     switch (relative_addr) {
281     case R4030_SYS_CONFIG:
282     if (writeflag == MEM_WRITE) {
283     fatal("[ jazz: unimplemented write to R4030_SYS_CONFIG"
284     ", data=0x%08x ]\n", (int)idata);
285     } else {
286     /* Reading the config register should give
287     0x0104 or 0x0410. Why? TODO */
288     odata = 0x104;
289     }
290     break;
291     case R4030_SYS_TL_BASE:
292     if (writeflag == MEM_WRITE) {
293     d->dma_translation_table_base = idata;
294     } else {
295     odata = d->dma_translation_table_base;
296     }
297     break;
298     case R4030_SYS_TL_LIMIT:
299     if (writeflag == MEM_WRITE) {
300     d->dma_translation_table_limit = idata;
301     } else {
302     odata = d->dma_translation_table_limit;
303     }
304     break;
305     case R4030_SYS_TL_IVALID:
306     /* TODO: Does invalidation actually need to be implemented? */
307     break;
308     case R4030_SYS_DMA0_REGS:
309     if (writeflag == MEM_WRITE) {
310     d->dma0_mode = idata;
311     } else {
312     odata = d->dma0_mode;
313     }
314     break;
315     case R4030_SYS_DMA0_REGS + 0x8:
316     if (writeflag == MEM_WRITE) {
317     d->dma0_enable = idata;
318     } else {
319     odata = d->dma0_enable;
320     }
321     break;
322     case R4030_SYS_DMA0_REGS + 0x10:
323     if (writeflag == MEM_WRITE) {
324     d->dma0_count = idata;
325     } else {
326     odata = d->dma0_count;
327     }
328     break;
329     case R4030_SYS_DMA0_REGS + 0x18:
330     if (writeflag == MEM_WRITE) {
331     d->dma0_addr = idata;
332     } else {
333     odata = d->dma0_addr;
334     }
335     break;
336     case R4030_SYS_DMA1_REGS:
337     if (writeflag == MEM_WRITE) {
338     d->dma1_mode = idata;
339     } else {
340     odata = d->dma1_mode;
341     }
342     break;
343     case R4030_SYS_ISA_VECTOR:
344     /* ? */
345     printf("R4030_SYS_ISA_VECTOR: w=%i\n", writeflag);
346     {
347     uint32_t x = d->isa_int_asserted
348     & d->isa_int_enable_mask;
349     odata = 0;
350     while (odata < 16) {
351     if (x & (1 << odata))
352     break;
353     odata ++;
354     }
355     if (odata >= 16)
356     odata = 0;
357     }
358     break;
359     case R4030_SYS_IT_VALUE: /* Interval timer reload value */
360     if (writeflag == MEM_WRITE) {
361     d->interval_start = idata;
362     d->interval = d->interval_start;
363     } else
364     odata = d->interval_start;
365     break;
366     case R4030_SYS_IT_STAT:
367     /* Accessing this word seems to acknowledge interrupts? */
368 dpavlin 34 INTERRUPT_DEASSERT(d->jazz_timer_irq);
369     if (d->pending_timer_interrupts > 0)
370     d->pending_timer_interrupts --;
371    
372 dpavlin 4 if (writeflag == MEM_WRITE)
373     d->interval = idata;
374     else
375     odata = d->interval;
376     d->interval = d->interval_start;
377     break;
378     case R4030_SYS_EXT_IMASK:
379     if (writeflag == MEM_WRITE) {
380 dpavlin 34 int old_assert_3 = (0x7fff &
381     d->int_asserted & d->int_enable_mask);
382     int old_assert_6 = (0x8000 &
383     d->int_asserted & d->int_enable_mask);
384     int new_assert_3, new_assert_6;
385    
386 dpavlin 4 d->int_enable_mask = idata;
387 dpavlin 34
388     new_assert_3 =
389     d->int_asserted & d->int_enable_mask & 0x7fff;
390     new_assert_6 =
391     d->int_asserted & d->int_enable_mask & 0x8000;
392    
393     if (old_assert_3 && !new_assert_3)
394     INTERRUPT_DEASSERT(d->mips_irq_3);
395     else if (!old_assert_3 && new_assert_3)
396     INTERRUPT_ASSERT(d->mips_irq_3);
397    
398     if (old_assert_6 && !new_assert_6)
399     INTERRUPT_DEASSERT(d->mips_irq_6);
400     else if (!old_assert_6 && new_assert_6)
401     INTERRUPT_ASSERT(d->mips_irq_6);
402 dpavlin 4 } else
403     odata = d->int_enable_mask;
404     break;
405     default:
406     if (writeflag == MEM_WRITE) {
407     fatal("[ jazz: unimplemented write to address 0x%x"
408     ", data=0x%02x ]\n", (int)relative_addr,
409     (int)idata);
410     } else {
411     fatal("[ jazz: unimplemented read from address 0x%x"
412     " ]\n", (int)relative_addr);
413     }
414     }
415    
416     if (writeflag == MEM_READ)
417     memory_writemax64(cpu, data, len, odata);
418    
419     return 1;
420     }
421    
422    
423 dpavlin 22 DEVICE_ACCESS(jazz_led)
424 dpavlin 4 {
425 dpavlin 42 struct jazz_data *d = extra;
426 dpavlin 4 uint64_t idata = 0, odata = 0;
427     int regnr;
428    
429 dpavlin 18 if (writeflag == MEM_WRITE)
430     idata = memory_readmax64(cpu, data, len);
431    
432 dpavlin 4 regnr = relative_addr / sizeof(uint32_t);
433    
434     switch (relative_addr) {
435     case 0:
436     if (writeflag == MEM_WRITE) {
437     d->led = idata;
438     debug("[ jazz_led: write to LED: 0x%02x ]\n",
439     (int)idata);
440     } else {
441     odata = d->led;
442     }
443     break;
444     default:
445     if (writeflag == MEM_WRITE) {
446     fatal("[ jazz_led: unimplemented write to address 0x%x"
447     ", data=0x%02x ]\n", (int)relative_addr,
448     (int)idata);
449     } else {
450     fatal("[ jazz_led: unimplemented read from address 0x%x"
451     " ]\n", (int)relative_addr);
452     }
453     }
454    
455     if (writeflag == MEM_READ)
456     memory_writemax64(cpu, data, len, odata);
457    
458     return 1;
459     }
460    
461    
462     /*
463 dpavlin 22 * dev_jazz_a0_access():
464 dpavlin 4 *
465     * ISA interrupt stuff, high 8 interrupts.
466 dpavlin 22 *
467     * TODO: use isa8 stuff instead!
468 dpavlin 4 */
469 dpavlin 22 DEVICE_ACCESS(jazz_a0)
470 dpavlin 4 {
471 dpavlin 42 struct jazz_data *d = extra;
472 dpavlin 4 uint64_t idata = 0, odata = 0;
473    
474 dpavlin 18 if (writeflag == MEM_WRITE)
475     idata = memory_readmax64(cpu, data, len);
476 dpavlin 4
477     switch (relative_addr) {
478     case 0:
479     if (writeflag == MEM_WRITE) {
480     /* TODO: only if idata == 0x20? */
481     d->isa_int_asserted &= 0xff;
482 dpavlin 34
483     reassert_isa_interrupts(d);
484 dpavlin 4 }
485     break;
486     case 1:
487     if (writeflag == MEM_WRITE) {
488     idata = ((idata ^ 0xff) & 0xff) << 8;
489     d->isa_int_enable_mask =
490     (d->isa_int_enable_mask & 0xff) | idata;
491     debug("[ jazz_isa_a0: setting isa_int_enable_mask "
492     "to 0x%04x ]\n", (int)d->isa_int_enable_mask);
493 dpavlin 34
494     reassert_isa_interrupts(d);
495 dpavlin 4 } else
496     odata = d->isa_int_enable_mask;
497     break;
498     default:
499     if (writeflag == MEM_WRITE) {
500     fatal("[ jazz_isa_a0: unimplemented write to "
501     "address 0x%x, data=0x%02x ]\n",
502     (int)relative_addr, (int)idata);
503     } else {
504     fatal("[ jazz_isa_a0: unimplemented read from "
505     "address 0x%x ]\n", (int)relative_addr);
506     }
507     }
508    
509     if (writeflag == MEM_READ)
510     memory_writemax64(cpu, data, len, odata);
511    
512     return 1;
513     }
514    
515    
516     /*
517 dpavlin 22 * dev_jazz_20_access():
518 dpavlin 4 *
519     * ISA interrupt stuff, low 8 interrupts.
520     */
521 dpavlin 22 DEVICE_ACCESS(jazz_20)
522 dpavlin 4 {
523 dpavlin 42 struct jazz_data *d = extra;
524 dpavlin 4 uint64_t idata = 0, odata = 0;
525    
526 dpavlin 18 if (writeflag == MEM_WRITE)
527     idata = memory_readmax64(cpu, data, len);
528 dpavlin 4
529     switch (relative_addr) {
530     case 0:
531     if (writeflag == MEM_WRITE) {
532     /* TODO: only if idata == 0x20? */
533     d->isa_int_asserted &= 0xff00;
534 dpavlin 34 reassert_isa_interrupts(d);
535 dpavlin 4 }
536     break;
537     case 1:
538     if (writeflag == MEM_WRITE) {
539     idata = (idata ^ 0xff) & 0xff;
540     d->isa_int_enable_mask =
541     (d->isa_int_enable_mask & 0xff00) | idata;
542     debug("[ jazz_isa_20: setting isa_int_enable_mask "
543     "to 0x%04x ]\n", (int)d->isa_int_enable_mask);
544 dpavlin 34
545     reassert_isa_interrupts(d);
546 dpavlin 4 } else
547     odata = d->isa_int_enable_mask;
548     break;
549     default:
550     if (writeflag == MEM_WRITE) {
551     fatal("[ jazz_isa_20: unimplemented write to "
552     "address 0x%x, data=0x%02x ]\n",
553     (int)relative_addr, (int)idata);
554     } else {
555     fatal("[ jazz_isa_20: unimplemented read from "
556     "address 0x%x ]\n", (int)relative_addr);
557     }
558     }
559    
560     if (writeflag == MEM_READ)
561     memory_writemax64(cpu, data, len, odata);
562    
563     return 1;
564     }
565    
566    
567     /*
568 dpavlin 22 * dev_jazz_jazzio_access():
569 dpavlin 4 *
570     * See jazzio_intr() in NetBSD's
571     * /usr/src/sys/arch/arc/jazz/jazzio.c for more info.
572     */
573 dpavlin 22 DEVICE_ACCESS(jazz_jazzio)
574 dpavlin 4 {
575 dpavlin 42 struct jazz_data *d = extra;
576 dpavlin 4 uint64_t idata = 0, odata = 0;
577     int i, v;
578    
579 dpavlin 18 if (writeflag == MEM_WRITE)
580     idata = memory_readmax64(cpu, data, len);
581 dpavlin 4
582     switch (relative_addr) {
583     case 0:
584     v = 0;
585     for (i=0; i<15; i++) {
586     if (d->int_asserted & (1<<i)) {
587     v = i+1;
588     break;
589     }
590     }
591     odata = v << 2;
592     break;
593     case 2:
594     /* TODO: Should this be here?! */
595    
596     if (writeflag == MEM_WRITE)
597     d->jazz_timer_value = idata;
598     else
599     odata = d->jazz_timer_value;
600     break;
601     default:
602     if (writeflag == MEM_WRITE) {
603     fatal("[ jazzio: unimplemented write to address 0x%x"
604     ", data=0x%02x ]\n", (int)relative_addr,
605     (int)idata);
606     } else {
607     fatal("[ jazzio: unimplemented read from address 0x%x"
608     " ]\n", (int)relative_addr);
609     }
610     }
611    
612     /* This is needed by Windows NT during startup: */
613 dpavlin 34 INTERRUPT_DEASSERT(d->mips_irq_3);
614 dpavlin 4
615     if (writeflag == MEM_READ)
616     memory_writemax64(cpu, data, len, odata);
617    
618     return 1;
619     }
620    
621    
622 dpavlin 22 DEVINIT(jazz)
623 dpavlin 4 {
624 dpavlin 42 struct jazz_data *d;
625 dpavlin 34 char tmpstr[300];
626     int i;
627 dpavlin 42
628     CHECK_ALLOCATION(d = malloc(sizeof(struct jazz_data)));
629 dpavlin 4 memset(d, 0, sizeof(struct jazz_data));
630    
631     d->cpu = devinit->machine->cpus[0]; /* TODO */
632    
633     d->isa_int_enable_mask = 0xffff;
634    
635 dpavlin 34 /*
636     * Register 16 native JAZZ irqs, and 16 ISA irqs:
637     *
638     * emul[x].machine[y].cpu[z].jazz.%i (native)
639     * emul[x].machine[y].cpu[z].jazz.isa.%i (ISA)
640     */
641     for (i=0; i<16; i++) {
642     struct interrupt template;
643     char n[300];
644     snprintf(n, sizeof(n), "%s.jazz.%i",
645     devinit->interrupt_path, i);
646     memset(&template, 0, sizeof(template));
647     template.line = i;
648     template.name = n;
649     template.extra = d;
650     template.interrupt_assert = jazz_interrupt_assert;
651     template.interrupt_deassert = jazz_interrupt_deassert;
652     interrupt_handler_register(&template);
653     }
654     for (i=0; i<16; i++) {
655     struct interrupt template;
656     char n[300];
657     snprintf(n, sizeof(n), "%s.jazz.isa.%i",
658     devinit->interrupt_path, i);
659     memset(&template, 0, sizeof(template));
660     template.line = i;
661     template.name = n;
662     template.extra = d;
663     template.interrupt_assert = jazz_isa_interrupt_assert;
664     template.interrupt_deassert = jazz_isa_interrupt_deassert;
665     interrupt_handler_register(&template);
666     }
667    
668     /* Connect to MIPS CPU interrupt lines: */
669     snprintf(tmpstr, sizeof(tmpstr), "%s.3", devinit->interrupt_path);
670     INTERRUPT_CONNECT(tmpstr, d->mips_irq_3);
671     snprintf(tmpstr, sizeof(tmpstr), "%s.4", devinit->interrupt_path);
672     INTERRUPT_CONNECT(tmpstr, d->mips_irq_4);
673     snprintf(tmpstr, sizeof(tmpstr), "%s.6", devinit->interrupt_path);
674     INTERRUPT_CONNECT(tmpstr, d->mips_irq_6);
675    
676     /* Connect to JAZZ timer interrupt: */
677     snprintf(tmpstr, sizeof(tmpstr), "%s.jazz.%i",
678     devinit->interrupt_path, PICA_TIMER_IRQ);
679     INTERRUPT_CONNECT(tmpstr, d->jazz_timer_irq);
680    
681 dpavlin 4 memory_device_register(devinit->machine->memory, "jazz",
682     devinit->addr, DEV_JAZZ_LENGTH,
683 dpavlin 20 dev_jazz_access, (void *)d, DM_DEFAULT, NULL);
684 dpavlin 4
685     /* At least for Magnum and Pica-61: */
686     memory_device_register(devinit->machine->memory, "jazz_led",
687     0x08000f000ULL, 4, dev_jazz_led_access, (void *)d,
688 dpavlin 20 DM_DEFAULT, NULL);
689 dpavlin 4
690     memory_device_register(devinit->machine->memory, "jazz_isa_20",
691 dpavlin 22 0x90000020ULL, 2, dev_jazz_20_access, (void *)d, DM_DEFAULT, NULL);
692 dpavlin 4
693     memory_device_register(devinit->machine->memory, "jazz_isa_a0",
694 dpavlin 22 0x900000a0ULL, 2, dev_jazz_a0_access, (void *)d, DM_DEFAULT, NULL);
695 dpavlin 4
696     memory_device_register(devinit->machine->memory, "pica_jazzio",
697 dpavlin 22 0xf0000000ULL, 4, dev_jazz_jazzio_access, (void *)d,
698 dpavlin 20 DM_DEFAULT, NULL);
699 dpavlin 4
700 dpavlin 34 /* Add a timer, hardcoded to 100 Hz. TODO: Don't hardcode! */
701     d->timer = timer_add(100.0, timer_tick, d);
702 dpavlin 4 machine_add_tickfunction(devinit->machine, dev_jazz_tick,
703 dpavlin 42 d, DEV_JAZZ_TICKSHIFT);
704 dpavlin 4
705     devinit->return_ptr = d;
706    
707     return 1;
708     }
709    

  ViewVC Help
Powered by ViewVC 1.1.26