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