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

Parent Directory Parent Directory | Revision Log Revision Log


Revision 3 - (show annotations)
Mon Oct 8 16:17:52 2007 UTC (16 years, 7 months ago) by dpavlin
File MIME type: text/plain
File size: 13888 byte(s)
0.3.1
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.18 2005/04/04 21:50:04 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 idata = memory_readmax64(cpu, data, len);
173 regnr = relative_addr / sizeof(uint32_t);
174
175 switch (relative_addr) {
176 case R4030_SYS_CONFIG:
177 if (writeflag == MEM_WRITE) {
178 fatal("[ jazz: unimplemented write to R4030_SYS_CONFIG"
179 ", data=0x%08x ]\n", (int)idata);
180 } else {
181 /* Reading the config register should give
182 0x0104 or 0x0410. Why? TODO */
183 odata = 0x104;
184 }
185 break;
186 case R4030_SYS_TL_BASE:
187 if (writeflag == MEM_WRITE) {
188 d->dma_translation_table_base = idata;
189 } else {
190 odata = d->dma_translation_table_base;
191 }
192 break;
193 case R4030_SYS_TL_LIMIT:
194 if (writeflag == MEM_WRITE) {
195 d->dma_translation_table_limit = idata;
196 } else {
197 odata = d->dma_translation_table_limit;
198 }
199 break;
200 case R4030_SYS_TL_IVALID:
201 /* TODO: Does invalidation actually need to be implemented? */
202 break;
203 case R4030_SYS_DMA0_REGS:
204 if (writeflag == MEM_WRITE) {
205 d->dma0_mode = idata;
206 } else {
207 odata = d->dma0_mode;
208 }
209 break;
210 case R4030_SYS_DMA0_REGS + 0x8:
211 if (writeflag == MEM_WRITE) {
212 d->dma0_enable = idata;
213 } else {
214 odata = d->dma0_enable;
215 }
216 break;
217 case R4030_SYS_DMA0_REGS + 0x10:
218 if (writeflag == MEM_WRITE) {
219 d->dma0_count = idata;
220 } else {
221 odata = d->dma0_count;
222 }
223 break;
224 case R4030_SYS_DMA0_REGS + 0x18:
225 if (writeflag == MEM_WRITE) {
226 d->dma0_addr = idata;
227 } else {
228 odata = d->dma0_addr;
229 }
230 break;
231 case R4030_SYS_DMA1_REGS:
232 if (writeflag == MEM_WRITE) {
233 d->dma1_mode = idata;
234 } else {
235 odata = d->dma1_mode;
236 }
237 break;
238 case R4030_SYS_ISA_VECTOR:
239 /* ? */
240 printf("R4030_SYS_ISA_VECTOR: w=%i\n", writeflag);
241 {
242 uint32_t x = d->isa_int_asserted
243 & d->isa_int_enable_mask;
244 odata = 0;
245 while (odata < 16) {
246 if (x & (1 << odata))
247 break;
248 odata ++;
249 }
250 if (odata >= 16)
251 odata = 0;
252 }
253 break;
254 case R4030_SYS_IT_VALUE: /* Interval timer reload value */
255 if (writeflag == MEM_WRITE) {
256 d->interval_start = idata;
257 d->interval = d->interval_start;
258 } else
259 odata = d->interval_start;
260 break;
261 case R4030_SYS_IT_STAT:
262 /* Accessing this word seems to acknowledge interrupts? */
263 cpu_interrupt_ack(cpu, 8 + PICA_TIMER_IRQ);
264 if (writeflag == MEM_WRITE)
265 d->interval = idata;
266 else
267 odata = d->interval;
268 d->interval = d->interval_start;
269 break;
270 case R4030_SYS_EXT_IMASK:
271 if (writeflag == MEM_WRITE) {
272 d->int_enable_mask = idata;
273 /* Do a "nonsense" interrupt recalibration: */
274 cpu_interrupt_ack(cpu, 8);
275 } else
276 odata = d->int_enable_mask;
277 break;
278 default:
279 if (writeflag == MEM_WRITE) {
280 fatal("[ jazz: unimplemented write to address 0x%x"
281 ", data=0x%02x ]\n", (int)relative_addr,
282 (int)idata);
283 } else {
284 fatal("[ jazz: unimplemented read from address 0x%x"
285 " ]\n", (int)relative_addr);
286 }
287 }
288
289 if (writeflag == MEM_READ)
290 memory_writemax64(cpu, data, len, odata);
291
292 return 1;
293 }
294
295
296 /*
297 * dev_jazz_led_access():
298 */
299 int dev_jazz_led_access(struct cpu *cpu, struct memory *mem,
300 uint64_t relative_addr, unsigned char *data, size_t len,
301 int writeflag, void *extra)
302 {
303 struct jazz_data *d = (struct jazz_data *) extra;
304 uint64_t idata = 0, odata = 0;
305 int regnr;
306
307 idata = memory_readmax64(cpu, data, len);
308 regnr = relative_addr / sizeof(uint32_t);
309
310 switch (relative_addr) {
311 case 0:
312 if (writeflag == MEM_WRITE) {
313 d->led = idata;
314 debug("[ jazz_led: write to LED: 0x%02x ]\n",
315 (int)idata);
316 } else {
317 odata = d->led;
318 }
319 break;
320 default:
321 if (writeflag == MEM_WRITE) {
322 fatal("[ jazz_led: unimplemented write to address 0x%x"
323 ", data=0x%02x ]\n", (int)relative_addr,
324 (int)idata);
325 } else {
326 fatal("[ jazz_led: unimplemented read from address 0x%x"
327 " ]\n", (int)relative_addr);
328 }
329 }
330
331 if (writeflag == MEM_READ)
332 memory_writemax64(cpu, data, len, odata);
333
334 return 1;
335 }
336
337
338 /*
339 * dev_jazz_access_a0():
340 *
341 * ISA interrupt stuff, high 8 interrupts.
342 */
343 int dev_jazz_access_a0(struct cpu *cpu, struct memory *mem,
344 uint64_t relative_addr, unsigned char *data, size_t len,
345 int writeflag, void *extra)
346 {
347 struct jazz_data *d = (struct jazz_data *) extra;
348 uint64_t idata = 0, odata = 0;
349
350 idata = memory_readmax64(cpu, data, len);
351 odata = 0;
352
353 switch (relative_addr) {
354 case 0:
355 if (writeflag == MEM_WRITE) {
356 /* TODO: only if idata == 0x20? */
357 d->isa_int_asserted &= 0xff;
358 cpu_interrupt_ack(cpu, 8 + 0);
359 }
360 break;
361 case 1:
362 if (writeflag == MEM_WRITE) {
363 idata = ((idata ^ 0xff) & 0xff) << 8;
364 d->isa_int_enable_mask =
365 (d->isa_int_enable_mask & 0xff) | idata;
366 debug("[ jazz_isa_a0: setting isa_int_enable_mask "
367 "to 0x%04x ]\n", (int)d->isa_int_enable_mask);
368 /* Recompute interrupt stuff: */
369 cpu_interrupt_ack(cpu, 8 + 0);
370 } else
371 odata = d->isa_int_enable_mask;
372 break;
373 default:
374 if (writeflag == MEM_WRITE) {
375 fatal("[ jazz_isa_a0: unimplemented write to "
376 "address 0x%x, data=0x%02x ]\n",
377 (int)relative_addr, (int)idata);
378 } else {
379 fatal("[ jazz_isa_a0: unimplemented read from "
380 "address 0x%x ]\n", (int)relative_addr);
381 }
382 }
383
384 if (writeflag == MEM_READ)
385 memory_writemax64(cpu, data, len, odata);
386
387 return 1;
388 }
389
390
391 /*
392 * dev_jazz_access_20():
393 *
394 * ISA interrupt stuff, low 8 interrupts.
395 */
396 int dev_jazz_access_20(struct cpu *cpu, struct memory *mem,
397 uint64_t relative_addr, unsigned char *data, size_t len,
398 int writeflag, void *extra)
399 {
400 struct jazz_data *d = (struct jazz_data *) extra;
401 uint64_t idata = 0, odata = 0;
402
403 idata = memory_readmax64(cpu, data, len);
404 odata = 0;
405
406 switch (relative_addr) {
407 case 0:
408 if (writeflag == MEM_WRITE) {
409 /* TODO: only if idata == 0x20? */
410 d->isa_int_asserted &= 0xff00;
411 cpu_interrupt_ack(cpu, 8 + 0);
412 }
413 break;
414 case 1:
415 if (writeflag == MEM_WRITE) {
416 idata = (idata ^ 0xff) & 0xff;
417 d->isa_int_enable_mask =
418 (d->isa_int_enable_mask & 0xff00) | idata;
419 debug("[ jazz_isa_20: setting isa_int_enable_mask "
420 "to 0x%04x ]\n", (int)d->isa_int_enable_mask);
421 /* Recompute interrupt stuff: */
422 cpu_interrupt_ack(cpu, 8 + 0);
423 } else
424 odata = d->isa_int_enable_mask;
425 break;
426 default:
427 if (writeflag == MEM_WRITE) {
428 fatal("[ jazz_isa_20: unimplemented write to "
429 "address 0x%x, data=0x%02x ]\n",
430 (int)relative_addr, (int)idata);
431 } else {
432 fatal("[ jazz_isa_20: unimplemented read from "
433 "address 0x%x ]\n", (int)relative_addr);
434 }
435 }
436
437 if (writeflag == MEM_READ)
438 memory_writemax64(cpu, data, len, odata);
439
440 return 1;
441 }
442
443
444 /*
445 * dev_jazz_access_jazzio():
446 *
447 * See jazzio_intr() in NetBSD's
448 * /usr/src/sys/arch/arc/jazz/jazzio.c for more info.
449 */
450 int dev_jazz_access_jazzio(struct cpu *cpu, struct memory *mem,
451 uint64_t relative_addr, unsigned char *data, size_t len,
452 int writeflag, void *extra)
453 {
454 struct jazz_data *d = (struct jazz_data *) extra;
455 uint64_t idata = 0, odata = 0;
456 int i, v;
457
458 idata = memory_readmax64(cpu, data, len);
459
460 switch (relative_addr) {
461 case 0:
462 v = 0;
463 for (i=0; i<15; i++) {
464 if (d->int_asserted & (1<<i)) {
465 v = i+1;
466 break;
467 }
468 }
469 odata = v << 2;
470 break;
471 case 2:
472 /* TODO: Should this be here?! */
473
474 if (writeflag == MEM_WRITE)
475 d->jazz_timer_value = idata;
476 else
477 odata = d->jazz_timer_value;
478 break;
479 default:
480 if (writeflag == MEM_WRITE) {
481 fatal("[ jazzio: unimplemented write to address 0x%x"
482 ", data=0x%02x ]\n", (int)relative_addr,
483 (int)idata);
484 } else {
485 fatal("[ jazzio: unimplemented read from address 0x%x"
486 " ]\n", (int)relative_addr);
487 }
488 }
489
490 /* This is needed by Windows NT during startup: */
491 cpu_interrupt_ack(cpu, 3);
492
493 if (writeflag == MEM_READ)
494 memory_writemax64(cpu, data, len, odata);
495
496 return 1;
497 }
498
499
500 /*
501 * devinit_jazz():
502 */
503 int devinit_jazz(struct devinit *devinit)
504 {
505 struct jazz_data *d = malloc(sizeof(struct jazz_data));
506 if (d == NULL) {
507 fprintf(stderr, "out of memory\n");
508 exit(1);
509 }
510 memset(d, 0, sizeof(struct jazz_data));
511
512 d->cpu = devinit->machine->cpus[0]; /* TODO */
513
514 d->isa_int_enable_mask = 0xffff;
515
516 memory_device_register(devinit->machine->memory, "jazz",
517 devinit->addr, DEV_JAZZ_LENGTH,
518 dev_jazz_access, (void *)d, MEM_DEFAULT, NULL);
519
520 /* At least for Magnum and Pica-61: */
521 memory_device_register(devinit->machine->memory, "jazz_led",
522 0x08000f000ULL, 4, dev_jazz_led_access, (void *)d,
523 MEM_DEFAULT, NULL);
524
525 memory_device_register(devinit->machine->memory, "jazz_isa_20",
526 0x90000020ULL, 2, dev_jazz_access_20, (void *)d, MEM_DEFAULT, NULL);
527
528 memory_device_register(devinit->machine->memory, "jazz_isa_a0",
529 0x900000a0ULL, 2, dev_jazz_access_a0, (void *)d, MEM_DEFAULT, NULL);
530
531 memory_device_register(devinit->machine->memory, "pica_jazzio",
532 0xf0000000ULL, 4, dev_jazz_access_jazzio, (void *)d,
533 MEM_DEFAULT, NULL);
534
535 machine_add_tickfunction(devinit->machine, dev_jazz_tick,
536 d, DEV_JAZZ_TICKSHIFT);
537
538 devinit->return_ptr = d;
539
540 return 1;
541 }
542

  ViewVC Help
Powered by ViewVC 1.1.26