/[gxemul]/upstream/0.3.8/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 /upstream/0.3.8/src/devices/dev_jazz.c

Parent Directory Parent Directory | Revision Log Revision Log


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

  ViewVC Help
Powered by ViewVC 1.1.26