/[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

Annotation of /upstream/0.3.8/src/devices/dev_jazz.c

Parent Directory Parent Directory | Revision Log Revision Log


Revision 23 - (hide annotations)
Mon Oct 8 16:19:43 2007 UTC (16 years, 8 months ago) by dpavlin
File MIME type: text/plain
File size: 13574 byte(s)
0.3.8
1 dpavlin 4 /*
2 dpavlin 22 * Copyright (C) 2004-2006 Anders Gavare. All rights reserved.
3 dpavlin 4 *
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 dpavlin 22 * $Id: dev_jazz.c,v 1.23 2006/02/09 20:02:59 debug Exp $
29 dpavlin 4 *
30     * Microsoft Jazz-related stuff (Acer PICA-61, etc).
31 dpavlin 22 *
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 dpavlin 4 */
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 dpavlin 22 while (dma_addr < d->dma0_addr + d->dma0_count && i < (int32_t)len) {
99 dpavlin 4
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 dpavlin 22 if ((phys_addr & 15) == 0 && i + 15 <= (int32_t)len)
119 dpavlin 4 ncpy = 15;
120 dpavlin 22 if ((phys_addr & 255) == 0 && i + 255 <= (int32_t)len)
121 dpavlin 4 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 dpavlin 22 DEVICE_ACCESS(jazz)
169 dpavlin 4 {
170     struct jazz_data *d = (struct jazz_data *) extra;
171     uint64_t idata = 0, odata = 0;
172     int regnr;
173    
174 dpavlin 18 if (writeflag == MEM_WRITE)
175     idata = memory_readmax64(cpu, data, len);
176    
177 dpavlin 4 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 dpavlin 22 DEVICE_ACCESS(jazz_led)
304 dpavlin 4 {
305     struct jazz_data *d = (struct jazz_data *) extra;
306     uint64_t idata = 0, odata = 0;
307     int regnr;
308    
309 dpavlin 18 if (writeflag == MEM_WRITE)
310     idata = memory_readmax64(cpu, data, len);
311    
312 dpavlin 4 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 dpavlin 22 * dev_jazz_a0_access():
344 dpavlin 4 *
345     * ISA interrupt stuff, high 8 interrupts.
346 dpavlin 22 *
347     * TODO: use isa8 stuff instead!
348 dpavlin 4 */
349 dpavlin 22 DEVICE_ACCESS(jazz_a0)
350 dpavlin 4 {
351     struct jazz_data *d = (struct jazz_data *) extra;
352     uint64_t idata = 0, odata = 0;
353    
354 dpavlin 18 if (writeflag == MEM_WRITE)
355     idata = memory_readmax64(cpu, data, len);
356 dpavlin 4
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 dpavlin 22 * dev_jazz_20_access():
397 dpavlin 4 *
398     * ISA interrupt stuff, low 8 interrupts.
399     */
400 dpavlin 22 DEVICE_ACCESS(jazz_20)
401 dpavlin 4 {
402     struct jazz_data *d = (struct jazz_data *) extra;
403     uint64_t idata = 0, odata = 0;
404    
405 dpavlin 18 if (writeflag == MEM_WRITE)
406     idata = memory_readmax64(cpu, data, len);
407 dpavlin 4
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 dpavlin 22 * dev_jazz_jazzio_access():
448 dpavlin 4 *
449     * See jazzio_intr() in NetBSD's
450     * /usr/src/sys/arch/arc/jazz/jazzio.c for more info.
451     */
452 dpavlin 22 DEVICE_ACCESS(jazz_jazzio)
453 dpavlin 4 {
454     struct jazz_data *d = (struct jazz_data *) extra;
455     uint64_t idata = 0, odata = 0;
456     int i, v;
457    
458 dpavlin 18 if (writeflag == MEM_WRITE)
459     idata = memory_readmax64(cpu, data, len);
460 dpavlin 4
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 dpavlin 22 DEVINIT(jazz)
502 dpavlin 4 {
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 dpavlin 20 dev_jazz_access, (void *)d, DM_DEFAULT, NULL);
517 dpavlin 4
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 dpavlin 20 DM_DEFAULT, NULL);
522 dpavlin 4
523     memory_device_register(devinit->machine->memory, "jazz_isa_20",
524 dpavlin 22 0x90000020ULL, 2, dev_jazz_20_access, (void *)d, DM_DEFAULT, NULL);
525 dpavlin 4
526     memory_device_register(devinit->machine->memory, "jazz_isa_a0",
527 dpavlin 22 0x900000a0ULL, 2, dev_jazz_a0_access, (void *)d, DM_DEFAULT, NULL);
528 dpavlin 4
529     memory_device_register(devinit->machine->memory, "pica_jazzio",
530 dpavlin 22 0xf0000000ULL, 4, dev_jazz_jazzio_access, (void *)d,
531 dpavlin 20 DM_DEFAULT, NULL);
532 dpavlin 4
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