/[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 44 - (hide annotations)
Mon Oct 8 16:22:56 2007 UTC (16 years, 5 months ago) by dpavlin
File MIME type: text/plain
File size: 18167 byte(s)
++ trunk/HISTORY	(local)
$Id: HISTORY,v 1.1632 2007/09/11 21:46:35 debug Exp $
20070616	Implementing the MIPS32/64 revision 2 "ror" instruction.
20070617	Adding a struct for each physpage which keeps track of which
		ranges within that page (base offset, length) that are
		continuously translatable. When running with native code
		generation enabled (-b), a range is added after each read-
		ahead loop.
		Experimenting with using the physical program counter sample
		data (implemented 20070608) together with the "translatable
		range" information, to figure out which physical address ranges
		would be worth translating to native code (if the number of
		samples falling within a range is above a certain threshold).
20070618	Adding automagic building of .index comment files for
		src/file/, src/promemul/, src src/useremul/ as well.
		Adding a "has been translated" bit to the ranges, so that only
		not-yet-translated ranges will be sampled.
20070619	Moving src/cpu.c and src/memory_rw.c into src/cpus/,
		src/device.c into src/devices/, and src/machine.c into
		src/machines/.
		Creating a skeleton cc/ld native backend module; beginning on
		the function which will detect cc command line, etc.
20070620	Continuing on the native code generation infrastructure.
20070621	Moving src/x11.c and src/console.c into a new src/console/
		subdir (for everything that is console or framebuffer related).
		Moving src/symbol*.c into a new src/symbol/, which should
		contain anything that is symbol handling related.
20070624	Making the program counter sampling threshold a "settings
		variable" (sampling_threshold), i.e. it can now be changed
		during runtime.
		Switching the RELEASE notes format from plain text to HTML.
		If the TMPDIR environment variable is set, it is used instead
		of "/tmp" for temporary files.
		Continuing on the cc/ld backend: simple .c code is generated,
		the compiler and linker are called, etc.
		Adding detection of host architecture to the configure script
		(again), and adding icache invalidation support (only
		implemented for Alpha hosts so far).
20070625	Simplifying the program counter sampling mechanism.
20070626	Removing the cc/ld native code generation stuff, program
		counter sampling, etc; it would not have worked well in the
		general case.
20070627	Removing everything related to native code generation.
20070629	Removing the (practically unusable) support for multiple
		emulations. (The single emulation allowed now still supports
		multiple simultaneous machines, as before.)
		Beginning on PCCTWO and M88K interrupts.
20070723	Adding a dummy skeleton for emulation of M32R processors.
20070901	Fixing a warning found by "gcc version 4.3.0 20070817
		(experimental)" on amd64.
20070905	Removing some more traces of the old "multiple emulations"
		code.
		Also looking in /usr/local/include and /usr/local/lib for
		X11 libs, when running configure.
20070909	Minor updates to the guest OS install instructions, in
		preparation for the NetBSD 4.0 release.
20070918	More testing of NetBSD 4.0 RC1.

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 44 * $Id: dev_jazz.c,v 1.30 2007/08/29 20:36:49 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 dpavlin 44 * machine[y].cpu[z].jazz.%i (native)
639     * machine[y].cpu[z].jazz.isa.%i (ISA)
640 dpavlin 34 */
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