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