/[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

Contents of /trunk/src/devices/dev_jazz.c

Parent Directory Parent Directory | Revision Log Revision Log


Revision 44 - (show annotations)
Mon Oct 8 16:22:56 2007 UTC (16 years, 6 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 /*
2 * Copyright (C) 2004-2007 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.30 2007/08/29 20:36:49 debug Exp $
29 *
30 * COMMENT: Microsoft Jazz-related stuff (Acer PICA-61, etc)
31 *
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 *
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 */
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 #include "interrupt.h"
54 #include "machine.h"
55 #include "memory.h"
56 #include "misc.h"
57 #include "timer.h"
58
59 #include "jazz_r4030_dma.h"
60 #include "pica.h"
61
62
63 #define DEV_JAZZ_LENGTH 0x280
64 #define DEV_JAZZ_TICKSHIFT 14
65 #define PICA_TIMER_IRQ 15
66
67 struct jazz_data {
68 struct interrupt mips_irq_3;
69 struct interrupt mips_irq_4;
70 struct interrupt mips_irq_6;
71
72 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 /*
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 while (dma_addr < d->dma0_addr + d->dma0_count && i < (int32_t)len) {
191
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 if ((phys_addr & 15) == 0 && i + 15 <= (int32_t)len)
211 ncpy = 15;
212 if ((phys_addr & 255) == 0 && i + 255 <= (int32_t)len)
213 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 static void timer_tick(struct timer *t, void *extra)
230 {
231 struct jazz_data *d = extra;
232 d->pending_timer_interrupts ++;
233 }
234
235
236 DEVICE_TICK(jazz)
237 {
238 struct jazz_data *d = extra;
239
240 /* 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 /* debug("[ jazz: interval timer interrupt ]\n");
246 INTERRUPT_ASSERT(d->jazz_timer_irq); */
247 }
248
249 /* New timer system: */
250 if (d->pending_timer_interrupts > 0)
251 INTERRUPT_ASSERT(d->jazz_timer_irq);
252 }
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 /* INTERRUPT_ASSERT(d->mips_irq_6); */
260 }
261
262 /* New timer system: */
263 if (d->pending_timer_interrupts > 0)
264 INTERRUPT_ASSERT(d->mips_irq_6);
265 }
266 }
267
268
269 DEVICE_ACCESS(jazz)
270 {
271 struct jazz_data *d = extra;
272 uint64_t idata = 0, odata = 0;
273 int regnr;
274
275 if (writeflag == MEM_WRITE)
276 idata = memory_readmax64(cpu, data, len);
277
278 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 INTERRUPT_DEASSERT(d->jazz_timer_irq);
369 if (d->pending_timer_interrupts > 0)
370 d->pending_timer_interrupts --;
371
372 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 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 d->int_enable_mask = idata;
387
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 } 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 DEVICE_ACCESS(jazz_led)
424 {
425 struct jazz_data *d = extra;
426 uint64_t idata = 0, odata = 0;
427 int regnr;
428
429 if (writeflag == MEM_WRITE)
430 idata = memory_readmax64(cpu, data, len);
431
432 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 * dev_jazz_a0_access():
464 *
465 * ISA interrupt stuff, high 8 interrupts.
466 *
467 * TODO: use isa8 stuff instead!
468 */
469 DEVICE_ACCESS(jazz_a0)
470 {
471 struct jazz_data *d = extra;
472 uint64_t idata = 0, odata = 0;
473
474 if (writeflag == MEM_WRITE)
475 idata = memory_readmax64(cpu, data, len);
476
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
483 reassert_isa_interrupts(d);
484 }
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
494 reassert_isa_interrupts(d);
495 } 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 * dev_jazz_20_access():
518 *
519 * ISA interrupt stuff, low 8 interrupts.
520 */
521 DEVICE_ACCESS(jazz_20)
522 {
523 struct jazz_data *d = extra;
524 uint64_t idata = 0, odata = 0;
525
526 if (writeflag == MEM_WRITE)
527 idata = memory_readmax64(cpu, data, len);
528
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 reassert_isa_interrupts(d);
535 }
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
545 reassert_isa_interrupts(d);
546 } 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 * dev_jazz_jazzio_access():
569 *
570 * See jazzio_intr() in NetBSD's
571 * /usr/src/sys/arch/arc/jazz/jazzio.c for more info.
572 */
573 DEVICE_ACCESS(jazz_jazzio)
574 {
575 struct jazz_data *d = extra;
576 uint64_t idata = 0, odata = 0;
577 int i, v;
578
579 if (writeflag == MEM_WRITE)
580 idata = memory_readmax64(cpu, data, len);
581
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 INTERRUPT_DEASSERT(d->mips_irq_3);
614
615 if (writeflag == MEM_READ)
616 memory_writemax64(cpu, data, len, odata);
617
618 return 1;
619 }
620
621
622 DEVINIT(jazz)
623 {
624 struct jazz_data *d;
625 char tmpstr[300];
626 int i;
627
628 CHECK_ALLOCATION(d = malloc(sizeof(struct jazz_data)));
629 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 /*
636 * Register 16 native JAZZ irqs, and 16 ISA irqs:
637 *
638 * machine[y].cpu[z].jazz.%i (native)
639 * 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 memory_device_register(devinit->machine->memory, "jazz",
682 devinit->addr, DEV_JAZZ_LENGTH,
683 dev_jazz_access, (void *)d, DM_DEFAULT, NULL);
684
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 DM_DEFAULT, NULL);
689
690 memory_device_register(devinit->machine->memory, "jazz_isa_20",
691 0x90000020ULL, 2, dev_jazz_20_access, (void *)d, DM_DEFAULT, NULL);
692
693 memory_device_register(devinit->machine->memory, "jazz_isa_a0",
694 0x900000a0ULL, 2, dev_jazz_a0_access, (void *)d, DM_DEFAULT, NULL);
695
696 memory_device_register(devinit->machine->memory, "pica_jazzio",
697 0xf0000000ULL, 4, dev_jazz_jazzio_access, (void *)d,
698 DM_DEFAULT, NULL);
699
700 /* Add a timer, hardcoded to 100 Hz. TODO: Don't hardcode! */
701 d->timer = timer_add(100.0, timer_tick, d);
702 machine_add_tickfunction(devinit->machine, dev_jazz_tick,
703 d, DEV_JAZZ_TICKSHIFT);
704
705 devinit->return_ptr = d;
706
707 return 1;
708 }
709

  ViewVC Help
Powered by ViewVC 1.1.26