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

Parent Directory Parent Directory | Revision Log Revision Log


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

  ViewVC Help
Powered by ViewVC 1.1.26