/[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 4 - (hide annotations)
Mon Oct 8 16:18:00 2007 UTC (16 years, 6 months ago) by dpavlin
File MIME type: text/plain
File size: 13888 byte(s)
++ trunk/HISTORY	(local)
$Id: HISTORY,v 1.707 2005/04/27 16:37:33 debug Exp $
20050408	Some minor updates to the wdc. Linux now doesn't complain
		anymore if a disk is non-present.
20050409	Various minor fixes (a bintrans bug, and some other things).
		The wdc seems to work with Playstation2 emulation, but there
		is a _long_ annoying delay when disks are detected.
		Fixing a really important bintrans bug (when devices and RAM
		are mixed within 4KB pages), which was triggered with
		NetBSD/playstation2 kernels.
20050410	Adding a dummy dev_ps2_ether (just so that NetBSD doesn't
		complain as much during bootup).
		Symbols starting with '$' are now ignored.
		Renaming dev_ps2_ohci.c to dev_ohci.c, etc.
20050411	Moving the bintrans-cache-isolation check from cpu_mips.c to
		cpu_mips_coproc.c. (I thought this would give a speedup, but
		it's not noticable.)
		Better playstation2 sbus interrupt code.
		Skip ahead many ticks if the count register is read manually.
		(This increases the speed of delay-loops that simply read
		the count register.)
20050412	Updates to the playstation2 timer/interrupt code.
		Some other minor updates.
20050413	NetBSD/cobalt runs from a disk image :-) including userland;
		updating the documentation on how to install NetBSD/cobalt
		using NetBSD/pmax (!).
		Some minor bintrans updates (no real speed improvement) and
		other minor updates (playstation2 now uses the -o options).
20050414	Adding a dummy x86 (and AMD64) mode.
20050415	Adding some (32-bit and 16-bit) x86 instructions.
		Adding some initial support for non-SCSI, non-IDE floppy
		images. (The x86 mode can boot from these, more or less.)
		Moving the devices/ and include/ directories to src/devices/
		and src/include/, respectively.
20050416	Continuing on the x86 stuff. (Adding pc_bios.c and some simple
		support for software interrupts in 16-bit mode.)
20050417	Ripping out most of the x86 instruction decoding stuff, trying
		to rewrite it in a cleaner way.
		Disabling some of the least working CPU families in the
		configure script (sparc, x86, alpha, hppa), so that they are
		not enabled by default.
20050418	Trying to fix the bug which caused problems when turning on
		and off bintrans interactively, by flushing the bintrans cache
		whenever bintrans is manually (re)enabled.
20050419	Adding the 'lswi' ppc instruction.
		Minor updates to the x86 instruction decoding.
20050420	Renaming x86 register name indices from R_xx to X86_R_xx (this
		makes building on Tru64 nicer).
20050422	Adding a check for duplicate MIPS TLB entries on tlbwr/tlbwi.
20050427	Adding screenshots to guestoses.html.
		Some minor fixes and testing for the next release.

==============  RELEASE 0.3.2  ==============


1 dpavlin 4 /*
2     * Copyright (C) 2004-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     * $Id: dev_jazz.c,v 1.18 2005/04/04 21:50:04 debug Exp $
29     *
30     * Microsoft Jazz-related stuff (Acer PICA-61, etc).
31     */
32    
33     #include <stdio.h>
34     #include <stdlib.h>
35     #include <string.h>
36    
37     #include "cpu.h"
38     #include "device.h"
39     #include "devices.h"
40     #include "machine.h"
41     #include "memory.h"
42     #include "misc.h"
43    
44     #include "jazz_r4030_dma.h"
45     #include "pica.h"
46    
47    
48     #define DEV_JAZZ_TICKSHIFT 14
49    
50     #define PICA_TIMER_IRQ 15
51    
52    
53     /*
54     * dev_jazz_dma_controller():
55     */
56     size_t dev_jazz_dma_controller(void *dma_controller_data,
57     unsigned char *data, size_t len, int writeflag)
58     {
59     struct jazz_data *d = (struct jazz_data *) dma_controller_data;
60     struct cpu *cpu = d->cpu;
61     int i, enab_writeflag;
62     int res, ncpy;
63     uint32_t dma_addr;
64     unsigned char tr[sizeof(uint32_t)];
65     uint32_t phys_addr;
66    
67     #if 0
68     fatal("[ dev_jazz_dma_controller(): writeflag=%i, len=%i, data =",
69     writeflag, (int)len);
70     for (i=0; i<len; i++)
71     fatal(" %02x", data[i]);
72     fatal(" mode=%08x enable=%08x count=%08x addr=%08x",
73     d->dma0_mode, d->dma0_enable, d->dma0_count, d->dma0_addr);
74     fatal(" table=%08x",
75     d->dma_translation_table_base);
76     fatal(" ]\n");
77     #endif
78    
79     if (!(d->dma0_enable & R4030_DMA_ENAB_RUN)) {
80     fatal("[ dev_jazz_dma_controller(): dma not enabled? ]\n");
81     /* return 0; */
82     }
83    
84     /* R4030 "write" means write to the device, writeflag as the
85     argument to this function means write to memory. */
86     enab_writeflag = (d->dma0_enable & R4030_DMA_ENAB_WRITE)? 0 : 1;
87     if (enab_writeflag != writeflag) {
88     fatal("[ dev_jazz_dma_controller(): wrong direction? ]\n");
89     return 0;
90     }
91    
92     dma_addr = d->dma0_addr;
93     i = 0;
94     while (dma_addr < d->dma0_addr + d->dma0_count && i < len) {
95    
96     res = cpu->memory_rw(cpu, cpu->mem,
97     d->dma_translation_table_base + (dma_addr >> 12) * 8,
98     tr, sizeof(tr), 0, PHYSICAL | NO_EXCEPTIONS);
99    
100     if (cpu->byte_order==EMUL_BIG_ENDIAN)
101     phys_addr = (tr[0] << 24) + (tr[1] << 16) +
102     (tr[2] << 8) + tr[3];
103     else
104     phys_addr = (tr[3] << 24) + (tr[2] << 16) +
105     (tr[1] << 8) + tr[0];
106     phys_addr &= ~0xfff; /* just in case */
107     phys_addr += (dma_addr & 0xfff);
108    
109     /* fatal(" !!! dma_addr = %08x, phys_addr = %08x\n",
110     (int)dma_addr, (int)phys_addr); */
111    
112     /* Speed up the copying by copying 16 or 256 bytes: */
113     ncpy = 1;
114     if ((phys_addr & 15) == 0 && i + 15 <= len)
115     ncpy = 15;
116     if ((phys_addr & 255) == 0 && i + 255 <= len)
117     ncpy = 255;
118    
119     res = cpu->memory_rw(cpu, cpu->mem, phys_addr,
120     &data[i], ncpy, writeflag, PHYSICAL | NO_EXCEPTIONS);
121    
122     dma_addr += ncpy;
123     i += ncpy;
124     }
125    
126     /* TODO: Is this correct? */
127     d->dma0_count = 0;
128    
129     return len;
130     }
131    
132    
133     /*
134     * dev_jazz_tick():
135     */
136     void dev_jazz_tick(struct cpu *cpu, void *extra)
137     {
138     struct jazz_data *d = extra;
139    
140     /* Used by NetBSD/arc and OpenBSD/arc: */
141     if (d->interval_start > 0 && d->interval > 0
142     && (d->int_enable_mask & 2) /* Hm? */ ) {
143     d->interval -= 2;
144     if (d->interval <= 0) {
145     debug("[ jazz: interval timer interrupt ]\n");
146     cpu_interrupt(cpu, 8 + PICA_TIMER_IRQ);
147     }
148     }
149    
150     /* Linux? */
151     if (d->jazz_timer_value != 0) {
152     d->jazz_timer_current -= 5;
153     if (d->jazz_timer_current < 1) {
154     d->jazz_timer_current = d->jazz_timer_value;
155     cpu_interrupt(cpu, 6);
156     }
157     }
158     }
159    
160    
161     /*
162     * dev_jazz_access():
163     */
164     int dev_jazz_access(struct cpu *cpu, struct memory *mem,
165     uint64_t relative_addr, unsigned char *data, size_t len,
166     int writeflag, void *extra)
167     {
168     struct jazz_data *d = (struct jazz_data *) extra;
169     uint64_t idata = 0, odata = 0;
170     int regnr;
171    
172     idata = memory_readmax64(cpu, data, len);
173     regnr = relative_addr / sizeof(uint32_t);
174    
175     switch (relative_addr) {
176     case R4030_SYS_CONFIG:
177     if (writeflag == MEM_WRITE) {
178     fatal("[ jazz: unimplemented write to R4030_SYS_CONFIG"
179     ", data=0x%08x ]\n", (int)idata);
180     } else {
181     /* Reading the config register should give
182     0x0104 or 0x0410. Why? TODO */
183     odata = 0x104;
184     }
185     break;
186     case R4030_SYS_TL_BASE:
187     if (writeflag == MEM_WRITE) {
188     d->dma_translation_table_base = idata;
189     } else {
190     odata = d->dma_translation_table_base;
191     }
192     break;
193     case R4030_SYS_TL_LIMIT:
194     if (writeflag == MEM_WRITE) {
195     d->dma_translation_table_limit = idata;
196     } else {
197     odata = d->dma_translation_table_limit;
198     }
199     break;
200     case R4030_SYS_TL_IVALID:
201     /* TODO: Does invalidation actually need to be implemented? */
202     break;
203     case R4030_SYS_DMA0_REGS:
204     if (writeflag == MEM_WRITE) {
205     d->dma0_mode = idata;
206     } else {
207     odata = d->dma0_mode;
208     }
209     break;
210     case R4030_SYS_DMA0_REGS + 0x8:
211     if (writeflag == MEM_WRITE) {
212     d->dma0_enable = idata;
213     } else {
214     odata = d->dma0_enable;
215     }
216     break;
217     case R4030_SYS_DMA0_REGS + 0x10:
218     if (writeflag == MEM_WRITE) {
219     d->dma0_count = idata;
220     } else {
221     odata = d->dma0_count;
222     }
223     break;
224     case R4030_SYS_DMA0_REGS + 0x18:
225     if (writeflag == MEM_WRITE) {
226     d->dma0_addr = idata;
227     } else {
228     odata = d->dma0_addr;
229     }
230     break;
231     case R4030_SYS_DMA1_REGS:
232     if (writeflag == MEM_WRITE) {
233     d->dma1_mode = idata;
234     } else {
235     odata = d->dma1_mode;
236     }
237     break;
238     case R4030_SYS_ISA_VECTOR:
239     /* ? */
240     printf("R4030_SYS_ISA_VECTOR: w=%i\n", writeflag);
241     {
242     uint32_t x = d->isa_int_asserted
243     & d->isa_int_enable_mask;
244     odata = 0;
245     while (odata < 16) {
246     if (x & (1 << odata))
247     break;
248     odata ++;
249     }
250     if (odata >= 16)
251     odata = 0;
252     }
253     break;
254     case R4030_SYS_IT_VALUE: /* Interval timer reload value */
255     if (writeflag == MEM_WRITE) {
256     d->interval_start = idata;
257     d->interval = d->interval_start;
258     } else
259     odata = d->interval_start;
260     break;
261     case R4030_SYS_IT_STAT:
262     /* Accessing this word seems to acknowledge interrupts? */
263     cpu_interrupt_ack(cpu, 8 + PICA_TIMER_IRQ);
264     if (writeflag == MEM_WRITE)
265     d->interval = idata;
266     else
267     odata = d->interval;
268     d->interval = d->interval_start;
269     break;
270     case R4030_SYS_EXT_IMASK:
271     if (writeflag == MEM_WRITE) {
272     d->int_enable_mask = idata;
273     /* Do a "nonsense" interrupt recalibration: */
274     cpu_interrupt_ack(cpu, 8);
275     } else
276     odata = d->int_enable_mask;
277     break;
278     default:
279     if (writeflag == MEM_WRITE) {
280     fatal("[ jazz: unimplemented write to address 0x%x"
281     ", data=0x%02x ]\n", (int)relative_addr,
282     (int)idata);
283     } else {
284     fatal("[ jazz: unimplemented read from address 0x%x"
285     " ]\n", (int)relative_addr);
286     }
287     }
288    
289     if (writeflag == MEM_READ)
290     memory_writemax64(cpu, data, len, odata);
291    
292     return 1;
293     }
294    
295    
296     /*
297     * dev_jazz_led_access():
298     */
299     int dev_jazz_led_access(struct cpu *cpu, struct memory *mem,
300     uint64_t relative_addr, unsigned char *data, size_t len,
301     int writeflag, void *extra)
302     {
303     struct jazz_data *d = (struct jazz_data *) extra;
304     uint64_t idata = 0, odata = 0;
305     int regnr;
306    
307     idata = memory_readmax64(cpu, data, len);
308     regnr = relative_addr / sizeof(uint32_t);
309    
310     switch (relative_addr) {
311     case 0:
312     if (writeflag == MEM_WRITE) {
313     d->led = idata;
314     debug("[ jazz_led: write to LED: 0x%02x ]\n",
315     (int)idata);
316     } else {
317     odata = d->led;
318     }
319     break;
320     default:
321     if (writeflag == MEM_WRITE) {
322     fatal("[ jazz_led: unimplemented write to address 0x%x"
323     ", data=0x%02x ]\n", (int)relative_addr,
324     (int)idata);
325     } else {
326     fatal("[ jazz_led: unimplemented read from address 0x%x"
327     " ]\n", (int)relative_addr);
328     }
329     }
330    
331     if (writeflag == MEM_READ)
332     memory_writemax64(cpu, data, len, odata);
333    
334     return 1;
335     }
336    
337    
338     /*
339     * dev_jazz_access_a0():
340     *
341     * ISA interrupt stuff, high 8 interrupts.
342     */
343     int dev_jazz_access_a0(struct cpu *cpu, struct memory *mem,
344     uint64_t relative_addr, unsigned char *data, size_t len,
345     int writeflag, void *extra)
346     {
347     struct jazz_data *d = (struct jazz_data *) extra;
348     uint64_t idata = 0, odata = 0;
349    
350     idata = memory_readmax64(cpu, data, len);
351     odata = 0;
352    
353     switch (relative_addr) {
354     case 0:
355     if (writeflag == MEM_WRITE) {
356     /* TODO: only if idata == 0x20? */
357     d->isa_int_asserted &= 0xff;
358     cpu_interrupt_ack(cpu, 8 + 0);
359     }
360     break;
361     case 1:
362     if (writeflag == MEM_WRITE) {
363     idata = ((idata ^ 0xff) & 0xff) << 8;
364     d->isa_int_enable_mask =
365     (d->isa_int_enable_mask & 0xff) | idata;
366     debug("[ jazz_isa_a0: setting isa_int_enable_mask "
367     "to 0x%04x ]\n", (int)d->isa_int_enable_mask);
368     /* Recompute interrupt stuff: */
369     cpu_interrupt_ack(cpu, 8 + 0);
370     } else
371     odata = d->isa_int_enable_mask;
372     break;
373     default:
374     if (writeflag == MEM_WRITE) {
375     fatal("[ jazz_isa_a0: unimplemented write to "
376     "address 0x%x, data=0x%02x ]\n",
377     (int)relative_addr, (int)idata);
378     } else {
379     fatal("[ jazz_isa_a0: unimplemented read from "
380     "address 0x%x ]\n", (int)relative_addr);
381     }
382     }
383    
384     if (writeflag == MEM_READ)
385     memory_writemax64(cpu, data, len, odata);
386    
387     return 1;
388     }
389    
390    
391     /*
392     * dev_jazz_access_20():
393     *
394     * ISA interrupt stuff, low 8 interrupts.
395     */
396     int dev_jazz_access_20(struct cpu *cpu, struct memory *mem,
397     uint64_t relative_addr, unsigned char *data, size_t len,
398     int writeflag, void *extra)
399     {
400     struct jazz_data *d = (struct jazz_data *) extra;
401     uint64_t idata = 0, odata = 0;
402    
403     idata = memory_readmax64(cpu, data, len);
404     odata = 0;
405    
406     switch (relative_addr) {
407     case 0:
408     if (writeflag == MEM_WRITE) {
409     /* TODO: only if idata == 0x20? */
410     d->isa_int_asserted &= 0xff00;
411     cpu_interrupt_ack(cpu, 8 + 0);
412     }
413     break;
414     case 1:
415     if (writeflag == MEM_WRITE) {
416     idata = (idata ^ 0xff) & 0xff;
417     d->isa_int_enable_mask =
418     (d->isa_int_enable_mask & 0xff00) | idata;
419     debug("[ jazz_isa_20: setting isa_int_enable_mask "
420     "to 0x%04x ]\n", (int)d->isa_int_enable_mask);
421     /* Recompute interrupt stuff: */
422     cpu_interrupt_ack(cpu, 8 + 0);
423     } else
424     odata = d->isa_int_enable_mask;
425     break;
426     default:
427     if (writeflag == MEM_WRITE) {
428     fatal("[ jazz_isa_20: unimplemented write to "
429     "address 0x%x, data=0x%02x ]\n",
430     (int)relative_addr, (int)idata);
431     } else {
432     fatal("[ jazz_isa_20: unimplemented read from "
433     "address 0x%x ]\n", (int)relative_addr);
434     }
435     }
436    
437     if (writeflag == MEM_READ)
438     memory_writemax64(cpu, data, len, odata);
439    
440     return 1;
441     }
442    
443    
444     /*
445     * dev_jazz_access_jazzio():
446     *
447     * See jazzio_intr() in NetBSD's
448     * /usr/src/sys/arch/arc/jazz/jazzio.c for more info.
449     */
450     int dev_jazz_access_jazzio(struct cpu *cpu, struct memory *mem,
451     uint64_t relative_addr, unsigned char *data, size_t len,
452     int writeflag, void *extra)
453     {
454     struct jazz_data *d = (struct jazz_data *) extra;
455     uint64_t idata = 0, odata = 0;
456     int i, v;
457    
458     idata = memory_readmax64(cpu, data, len);
459    
460     switch (relative_addr) {
461     case 0:
462     v = 0;
463     for (i=0; i<15; i++) {
464     if (d->int_asserted & (1<<i)) {
465     v = i+1;
466     break;
467     }
468     }
469     odata = v << 2;
470     break;
471     case 2:
472     /* TODO: Should this be here?! */
473    
474     if (writeflag == MEM_WRITE)
475     d->jazz_timer_value = idata;
476     else
477     odata = d->jazz_timer_value;
478     break;
479     default:
480     if (writeflag == MEM_WRITE) {
481     fatal("[ jazzio: unimplemented write to address 0x%x"
482     ", data=0x%02x ]\n", (int)relative_addr,
483     (int)idata);
484     } else {
485     fatal("[ jazzio: unimplemented read from address 0x%x"
486     " ]\n", (int)relative_addr);
487     }
488     }
489    
490     /* This is needed by Windows NT during startup: */
491     cpu_interrupt_ack(cpu, 3);
492    
493     if (writeflag == MEM_READ)
494     memory_writemax64(cpu, data, len, odata);
495    
496     return 1;
497     }
498    
499    
500     /*
501     * devinit_jazz():
502     */
503     int devinit_jazz(struct devinit *devinit)
504     {
505     struct jazz_data *d = malloc(sizeof(struct jazz_data));
506     if (d == NULL) {
507     fprintf(stderr, "out of memory\n");
508     exit(1);
509     }
510     memset(d, 0, sizeof(struct jazz_data));
511    
512     d->cpu = devinit->machine->cpus[0]; /* TODO */
513    
514     d->isa_int_enable_mask = 0xffff;
515    
516     memory_device_register(devinit->machine->memory, "jazz",
517     devinit->addr, DEV_JAZZ_LENGTH,
518     dev_jazz_access, (void *)d, MEM_DEFAULT, NULL);
519    
520     /* At least for Magnum and Pica-61: */
521     memory_device_register(devinit->machine->memory, "jazz_led",
522     0x08000f000ULL, 4, dev_jazz_led_access, (void *)d,
523     MEM_DEFAULT, NULL);
524    
525     memory_device_register(devinit->machine->memory, "jazz_isa_20",
526     0x90000020ULL, 2, dev_jazz_access_20, (void *)d, MEM_DEFAULT, NULL);
527    
528     memory_device_register(devinit->machine->memory, "jazz_isa_a0",
529     0x900000a0ULL, 2, dev_jazz_access_a0, (void *)d, MEM_DEFAULT, NULL);
530    
531     memory_device_register(devinit->machine->memory, "pica_jazzio",
532     0xf0000000ULL, 4, dev_jazz_access_jazzio, (void *)d,
533     MEM_DEFAULT, NULL);
534    
535     machine_add_tickfunction(devinit->machine, dev_jazz_tick,
536     d, DEV_JAZZ_TICKSHIFT);
537    
538     devinit->return_ptr = d;
539    
540     return 1;
541     }
542    

  ViewVC Help
Powered by ViewVC 1.1.26