Statistics
| Branch: | Revision:

root / hw / rc4030.c @ ba7349cd

History | View | Annotate | Download (18.8 kB)

1
/*
2
 * QEMU JAZZ RC4030 chipset
3
 *
4
 * Copyright (c) 2007-2008 Hervé Poussineau
5
 *
6
 * Permission is hereby granted, free of charge, to any person obtaining a copy
7
 * of this software and associated documentation files (the "Software"), to deal
8
 * in the Software without restriction, including without limitation the rights
9
 * to use, copy, modify, merge, publish, distribute, sublicense, and/or sell
10
 * copies of the Software, and to permit persons to whom the Software is
11
 * furnished to do so, subject to the following conditions:
12
 *
13
 * The above copyright notice and this permission notice shall be included in
14
 * all copies or substantial portions of the Software.
15
 *
16
 * THE SOFTWARE IS PROVIDED "AS IS", WITHOUT WARRANTY OF ANY KIND, EXPRESS OR
17
 * IMPLIED, INCLUDING BUT NOT LIMITED TO THE WARRANTIES OF MERCHANTABILITY,
18
 * FITNESS FOR A PARTICULAR PURPOSE AND NONINFRINGEMENT. IN NO EVENT SHALL
19
 * THE AUTHORS OR COPYRIGHT HOLDERS BE LIABLE FOR ANY CLAIM, DAMAGES OR OTHER
20
 * LIABILITY, WHETHER IN AN ACTION OF CONTRACT, TORT OR OTHERWISE, ARISING FROM,
21
 * OUT OF OR IN CONNECTION WITH THE SOFTWARE OR THE USE OR OTHER DEALINGS IN
22
 * THE SOFTWARE.
23
 */
24

    
25
#include "hw.h"
26
#include "mips.h"
27
#include "qemu-timer.h"
28

    
29
/********************************************************/
30
/* debug rc4030 */
31

    
32
//#define DEBUG_RC4030
33
//#define DEBUG_RC4030_DMA
34

    
35
#ifdef DEBUG_RC4030
36
#define DPRINTF(fmt, args...) \
37
do { printf("rc4030: " fmt , ##args); } while (0)
38
static const char* irq_names[] = { "parallel", "floppy", "sound", "video",
39
            "network", "scsi", "keyboard", "mouse", "serial0", "serial1" };
40
#else
41
#define DPRINTF(fmt, args...)
42
#endif
43

    
44
#define RC4030_ERROR(fmt, args...) \
45
do { fprintf(stderr, "rc4030 ERROR: %s: " fmt, __func__ , ##args); } while (0)
46

    
47
/********************************************************/
48
/* rc4030 emulation                                     */
49

    
50
typedef struct dma_pagetable_entry {
51
    int32_t frame;
52
    int32_t owner;
53
} __attribute__((packed)) dma_pagetable_entry;
54

    
55
#define DMA_PAGESIZE    4096
56
#define DMA_REG_ENABLE  1
57
#define DMA_REG_COUNT   2
58
#define DMA_REG_ADDRESS 3
59

    
60
#define DMA_FLAG_ENABLE     0x0001
61
#define DMA_FLAG_MEM_TO_DEV 0x0002
62
#define DMA_FLAG_TC_INTR    0x0100
63
#define DMA_FLAG_MEM_INTR   0x0200
64
#define DMA_FLAG_ADDR_INTR  0x0400
65

    
66
typedef struct rc4030State
67
{
68
    uint32_t config; /* 0x0000: RC4030 config register */
69
    uint32_t invalid_address_register; /* 0x0010: Invalid Address register */
70

    
71
    /* DMA */
72
    uint32_t dma_regs[8][4];
73
    uint32_t dma_tl_base; /* 0x0018: DMA transl. table base */
74
    uint32_t dma_tl_limit; /* 0x0020: DMA transl. table limit */
75

    
76
    /* cache */
77
    uint32_t remote_failed_address; /* 0x0038: Remote Failed Address */
78
    uint32_t memory_failed_address; /* 0x0040: Memory Failed Address */
79
    uint32_t cache_ptag; /* 0x0048: I/O Cache Physical Tag */
80
    uint32_t cache_ltag; /* 0x0050: I/O Cache Logical Tag */
81
    uint32_t cache_bmask; /* 0x0058: I/O Cache Byte Mask */
82
    uint32_t cache_bwin; /* 0x0060: I/O Cache Buffer Window */
83

    
84
    uint32_t offset210;
85
    uint32_t nvram_protect; /* 0x0220: NV ram protect register */
86
    uint32_t offset238;
87
    uint32_t rem_speed[15];
88
    uint32_t imr_jazz; /* Local bus int enable mask */
89
    uint32_t isr_jazz; /* Local bus int source */
90

    
91
    /* timer */
92
    QEMUTimer *periodic_timer;
93
    uint32_t itr; /* Interval timer reload */
94

    
95
    qemu_irq timer_irq;
96
    qemu_irq jazz_bus_irq;
97
} rc4030State;
98

    
99
static void set_next_tick(rc4030State *s)
100
{
101
    qemu_irq_lower(s->timer_irq);
102
    uint32_t tm_hz;
103

    
104
    tm_hz = 1000 / (s->itr + 1);
105

    
106
    qemu_mod_timer(s->periodic_timer, qemu_get_clock(vm_clock) + ticks_per_sec / tm_hz);
107
}
108

    
109
/* called for accesses to rc4030 */
110
static uint32_t rc4030_readl(void *opaque, target_phys_addr_t addr)
111
{
112
    rc4030State *s = opaque;
113
    uint32_t val;
114

    
115
    addr &= 0x3fff;
116
    switch (addr & ~0x3) {
117
    /* Global config register */
118
    case 0x0000:
119
        val = s->config;
120
        break;
121
    /* Invalid Address register */
122
    case 0x0010:
123
        val = s->invalid_address_register;
124
        break;
125
    /* DMA transl. table base */
126
    case 0x0018:
127
        val = s->dma_tl_base;
128
        break;
129
    /* DMA transl. table limit */
130
    case 0x0020:
131
        val = s->dma_tl_limit;
132
        break;
133
    /* Remote Failed Address */
134
    case 0x0038:
135
        val = s->remote_failed_address;
136
        break;
137
    /* Memory Failed Address */
138
    case 0x0040:
139
        val = s->memory_failed_address;
140
        break;
141
    /* I/O Cache Byte Mask */
142
    case 0x0058:
143
        val = s->cache_bmask;
144
        /* HACK */
145
        if (s->cache_bmask == (uint32_t)-1)
146
            s->cache_bmask = 0;
147
        break;
148
    /* Remote Speed Registers */
149
    case 0x0070:
150
    case 0x0078:
151
    case 0x0080:
152
    case 0x0088:
153
    case 0x0090:
154
    case 0x0098:
155
    case 0x00a0:
156
    case 0x00a8:
157
    case 0x00b0:
158
    case 0x00b8:
159
    case 0x00c0:
160
    case 0x00c8:
161
    case 0x00d0:
162
    case 0x00d8:
163
    case 0x00e0:
164
        val = s->rem_speed[(addr - 0x0070) >> 3];
165
        break;
166
    /* DMA channel base address */
167
    case 0x0100:
168
    case 0x0108:
169
    case 0x0110:
170
    case 0x0118:
171
    case 0x0120:
172
    case 0x0128:
173
    case 0x0130:
174
    case 0x0138:
175
    case 0x0140:
176
    case 0x0148:
177
    case 0x0150:
178
    case 0x0158:
179
    case 0x0160:
180
    case 0x0168:
181
    case 0x0170:
182
    case 0x0178:
183
    case 0x0180:
184
    case 0x0188:
185
    case 0x0190:
186
    case 0x0198:
187
    case 0x01a0:
188
    case 0x01a8:
189
    case 0x01b0:
190
    case 0x01b8:
191
    case 0x01c0:
192
    case 0x01c8:
193
    case 0x01d0:
194
    case 0x01d8:
195
    case 0x01e0:
196
    case 0x01e8:
197
    case 0x01f0:
198
    case 0x01f8:
199
        {
200
            int entry = (addr - 0x0100) >> 5;
201
            int idx = (addr & 0x1f) >> 3;
202
            val = s->dma_regs[entry][idx];
203
        }
204
        break;
205
    /* Offset 0x0208 */
206
    case 0x0208:
207
        val = 0;
208
        break;
209
    /* Offset 0x0210 */
210
    case 0x0210:
211
        val = s->offset210;
212
        break;
213
    /* NV ram protect register */
214
    case 0x0220:
215
        val = s->nvram_protect;
216
        break;
217
    /* Interval timer count */
218
    case 0x0230:
219
        val = 0;
220
        qemu_irq_lower(s->timer_irq);
221
        break;
222
    /* Offset 0x0238 */
223
    case 0x0238:
224
        val = s->offset238;
225
        break;
226
    default:
227
        RC4030_ERROR("invalid read [" TARGET_FMT_plx "]\n", addr);
228
        val = 0;
229
        break;
230
    }
231

    
232
    if ((addr & ~3) != 0x230)
233
        DPRINTF("read 0x%02x at " TARGET_FMT_plx "\n", val, addr);
234

    
235
    return val;
236
}
237

    
238
static uint32_t rc4030_readw(void *opaque, target_phys_addr_t addr)
239
{
240
    uint32_t v = rc4030_readl(opaque, addr & ~0x3);
241
    if (addr & 0x2)
242
        return v >> 16;
243
    else
244
        return v & 0xffff;
245
}
246

    
247
static uint32_t rc4030_readb(void *opaque, target_phys_addr_t addr)
248
{
249
    uint32_t v = rc4030_readl(opaque, addr & ~0x3);
250
    return (v >> (8 * (addr & 0x3))) & 0xff;
251
}
252

    
253
static void rc4030_writel(void *opaque, target_phys_addr_t addr, uint32_t val)
254
{
255
    rc4030State *s = opaque;
256
    addr &= 0x3fff;
257

    
258
    DPRINTF("write 0x%02x at " TARGET_FMT_plx "\n", val, addr);
259

    
260
    switch (addr & ~0x3) {
261
    /* Global config register */
262
    case 0x0000:
263
        s->config = val;
264
        break;
265
    /* DMA transl. table base */
266
    case 0x0018:
267
        s->dma_tl_base = val;
268
        break;
269
    /* DMA transl. table limit */
270
    case 0x0020:
271
        s->dma_tl_limit = val;
272
        break;
273
    /* DMA transl. table invalidated */
274
    case 0x0028:
275
        break;
276
    /* Cache Maintenance */
277
    case 0x0030:
278
        RC4030_ERROR("Cache maintenance not handled yet (val 0x%02x)\n", val);
279
        break;
280
    /* I/O Cache Physical Tag */
281
    case 0x0048:
282
        s->cache_ptag = val;
283
        break;
284
    /* I/O Cache Logical Tag */
285
    case 0x0050:
286
        s->cache_ltag = val;
287
        break;
288
    /* I/O Cache Byte Mask */
289
    case 0x0058:
290
        s->cache_bmask |= val; /* HACK */
291
        break;
292
    /* I/O Cache Buffer Window */
293
    case 0x0060:
294
        s->cache_bwin = val;
295
        /* HACK */
296
        if (s->cache_ltag == 0x80000001 && s->cache_bmask == 0xf0f0f0f) {
297
            target_phys_addr_t dests[] = { 4, 0, 8, 0x10 };
298
            static int current = 0;
299
            target_phys_addr_t dest = 0 + dests[current];
300
            uint8_t buf;
301
            current = (current + 1) % (ARRAY_SIZE(dests));
302
            buf = s->cache_bwin - 1;
303
            cpu_physical_memory_rw(dest, &buf, 1, 1);
304
        }
305
        break;
306
    /* Remote Speed Registers */
307
    case 0x0070:
308
    case 0x0078:
309
    case 0x0080:
310
    case 0x0088:
311
    case 0x0090:
312
    case 0x0098:
313
    case 0x00a0:
314
    case 0x00a8:
315
    case 0x00b0:
316
    case 0x00b8:
317
    case 0x00c0:
318
    case 0x00c8:
319
    case 0x00d0:
320
    case 0x00d8:
321
    case 0x00e0:
322
        s->rem_speed[(addr - 0x0070) >> 3] = val;
323
        break;
324
    /* DMA channel base address */
325
    case 0x0100:
326
    case 0x0108:
327
    case 0x0110:
328
    case 0x0118:
329
    case 0x0120:
330
    case 0x0128:
331
    case 0x0130:
332
    case 0x0138:
333
    case 0x0140:
334
    case 0x0148:
335
    case 0x0150:
336
    case 0x0158:
337
    case 0x0160:
338
    case 0x0168:
339
    case 0x0170:
340
    case 0x0178:
341
    case 0x0180:
342
    case 0x0188:
343
    case 0x0190:
344
    case 0x0198:
345
    case 0x01a0:
346
    case 0x01a8:
347
    case 0x01b0:
348
    case 0x01b8:
349
    case 0x01c0:
350
    case 0x01c8:
351
    case 0x01d0:
352
    case 0x01d8:
353
    case 0x01e0:
354
    case 0x01e8:
355
    case 0x01f0:
356
    case 0x01f8:
357
        {
358
            int entry = (addr - 0x0100) >> 5;
359
            int idx = (addr & 0x1f) >> 3;
360
            s->dma_regs[entry][idx] = val;
361
        }
362
        break;
363
    /* Offset 0x0210 */
364
    case 0x0210:
365
        s->offset210 = val;
366
        break;
367
    /* Interval timer reload */
368
    case 0x0228:
369
        s->itr = val;
370
        qemu_irq_lower(s->timer_irq);
371
        set_next_tick(s);
372
        break;
373
    default:
374
        RC4030_ERROR("invalid write of 0x%02x at [" TARGET_FMT_plx "]\n", val, addr);
375
        break;
376
    }
377
}
378

    
379
static void rc4030_writew(void *opaque, target_phys_addr_t addr, uint32_t val)
380
{
381
    uint32_t old_val = rc4030_readl(opaque, addr & ~0x3);
382

    
383
    if (addr & 0x2)
384
        val = (val << 16) | (old_val & 0x0000ffff);
385
    else
386
        val = val | (old_val & 0xffff0000);
387
    rc4030_writel(opaque, addr & ~0x3, val);
388
}
389

    
390
static void rc4030_writeb(void *opaque, target_phys_addr_t addr, uint32_t val)
391
{
392
    uint32_t old_val = rc4030_readl(opaque, addr & ~0x3);
393

    
394
    switch (addr & 3) {
395
    case 0:
396
        val = val | (old_val & 0xffffff00);
397
        break;
398
    case 1:
399
        val = (val << 8) | (old_val & 0xffff00ff);
400
        break;
401
    case 2:
402
        val = (val << 16) | (old_val & 0xff00ffff);
403
        break;
404
    case 3:
405
        val = (val << 24) | (old_val & 0x00ffffff);
406
        break;
407
    }
408
    rc4030_writel(opaque, addr & ~0x3, val);
409
}
410

    
411
static CPUReadMemoryFunc *rc4030_read[3] = {
412
    rc4030_readb,
413
    rc4030_readw,
414
    rc4030_readl,
415
};
416

    
417
static CPUWriteMemoryFunc *rc4030_write[3] = {
418
    rc4030_writeb,
419
    rc4030_writew,
420
    rc4030_writel,
421
};
422

    
423
static void update_jazz_irq(rc4030State *s)
424
{
425
    uint16_t pending;
426

    
427
    pending = s->isr_jazz & s->imr_jazz;
428

    
429
#ifdef DEBUG_RC4030
430
    if (s->isr_jazz != 0) {
431
        uint32_t irq = 0;
432
        DPRINTF("pending irqs:");
433
        for (irq = 0; irq < ARRAY_SIZE(irq_names); irq++) {
434
            if (s->isr_jazz & (1 << irq)) {
435
                printf(" %s", irq_names[irq]);
436
                if (!(s->imr_jazz & (1 << irq))) {
437
                    printf("(ignored)");
438
                }
439
            }
440
        }
441
        printf("\n");
442
    }
443
#endif
444

    
445
    if (pending != 0)
446
        qemu_irq_raise(s->jazz_bus_irq);
447
    else
448
        qemu_irq_lower(s->jazz_bus_irq);
449
}
450

    
451
static void rc4030_irq_jazz_request(void *opaque, int irq, int level)
452
{
453
    rc4030State *s = opaque;
454

    
455
    if (level) {
456
        s->isr_jazz |= 1 << irq;
457
    } else {
458
        s->isr_jazz &= ~(1 << irq);
459
    }
460

    
461
    update_jazz_irq(s);
462
}
463

    
464
static void rc4030_periodic_timer(void *opaque)
465
{
466
    rc4030State *s = opaque;
467

    
468
    set_next_tick(s);
469
    qemu_irq_raise(s->timer_irq);
470
}
471

    
472
static uint32_t jazzio_readw(void *opaque, target_phys_addr_t addr)
473
{
474
    rc4030State *s = opaque;
475
    uint32_t val;
476
    uint32_t irq;
477
    addr &= 0xfff;
478

    
479
    switch (addr) {
480
    /* Local bus int source */
481
    case 0x00: {
482
        uint32_t pending = s->isr_jazz & s->imr_jazz;
483
        val = 0;
484
        irq = 0;
485
        while (pending) {
486
            if (pending & 1) {
487
                DPRINTF("returning irq %s\n", irq_names[irq]);
488
                val = (irq + 1) << 2;
489
                break;
490
            }
491
            irq++;
492
            pending >>= 1;
493
        }
494
        break;
495
    }
496
    /* Local bus int enable mask */
497
    case 0x02:
498
        val = s->imr_jazz;
499
        break;
500
    default:
501
        RC4030_ERROR("(jazz io controller) invalid read [" TARGET_FMT_plx "]\n", addr);
502
        val = 0;
503
    }
504

    
505
    DPRINTF("(jazz io controller) read 0x%04x at " TARGET_FMT_plx "\n", val, addr);
506

    
507
    return val;
508
}
509

    
510
static uint32_t jazzio_readb(void *opaque, target_phys_addr_t addr)
511
{
512
    uint32_t v;
513
    v = jazzio_readw(opaque, addr & ~0x1);
514
    return (v >> (8 * (addr & 0x1))) & 0xff;
515
}
516

    
517
static uint32_t jazzio_readl(void *opaque, target_phys_addr_t addr)
518
{
519
    uint32_t v;
520
    v = jazzio_readw(opaque, addr);
521
    v |= jazzio_readw(opaque, addr + 2) << 16;
522
    return v;
523
}
524

    
525
static void jazzio_writew(void *opaque, target_phys_addr_t addr, uint32_t val)
526
{
527
    rc4030State *s = opaque;
528
    addr &= 0xfff;
529

    
530
    DPRINTF("(jazz io controller) write 0x%04x at " TARGET_FMT_plx "\n", val, addr);
531

    
532
    switch (addr) {
533
    /* Local bus int enable mask */
534
    case 0x02:
535
        s->imr_jazz = val;
536
        update_jazz_irq(s);
537
        break;
538
    default:
539
        RC4030_ERROR("(jazz io controller) invalid write of 0x%04x at [" TARGET_FMT_plx "]\n", val, addr);
540
        break;
541
    }
542
}
543

    
544
static void jazzio_writeb(void *opaque, target_phys_addr_t addr, uint32_t val)
545
{
546
    uint32_t old_val = jazzio_readw(opaque, addr & ~0x1);
547

    
548
    switch (addr & 1) {
549
    case 0:
550
        val = val | (old_val & 0xff00);
551
        break;
552
    case 1:
553
        val = (val << 8) | (old_val & 0x00ff);
554
        break;
555
    }
556
    jazzio_writew(opaque, addr & ~0x1, val);
557
}
558

    
559
static void jazzio_writel(void *opaque, target_phys_addr_t addr, uint32_t val)
560
{
561
    jazzio_writew(opaque, addr, val & 0xffff);
562
    jazzio_writew(opaque, addr + 2, (val >> 16) & 0xffff);
563
}
564

    
565
static CPUReadMemoryFunc *jazzio_read[3] = {
566
    jazzio_readb,
567
    jazzio_readw,
568
    jazzio_readl,
569
};
570

    
571
static CPUWriteMemoryFunc *jazzio_write[3] = {
572
    jazzio_writeb,
573
    jazzio_writew,
574
    jazzio_writel,
575
};
576

    
577
static void rc4030_reset(void *opaque)
578
{
579
    rc4030State *s = opaque;
580
    int i;
581

    
582
    s->config = 0x410; /* some boards seem to accept 0x104 too */
583
    s->invalid_address_register = 0;
584

    
585
    memset(s->dma_regs, 0, sizeof(s->dma_regs));
586
    s->dma_tl_base = s->dma_tl_limit = 0;
587

    
588
    s->remote_failed_address = s->memory_failed_address = 0;
589
    s->cache_ptag = s->cache_ltag = 0;
590
    s->cache_bmask = s->cache_bwin = 0;
591

    
592
    s->offset210 = 0x18186;
593
    s->nvram_protect = 7;
594
    s->offset238 = 7;
595
    for (i = 0; i < 15; i++)
596
        s->rem_speed[i] = 7;
597
    s->imr_jazz = s->isr_jazz = 0;
598

    
599
    s->itr = 0;
600

    
601
    qemu_irq_lower(s->timer_irq);
602
    qemu_irq_lower(s->jazz_bus_irq);
603
}
604

    
605
static void rc4030_do_dma(void *opaque, int n, uint8_t *buf, int len, int is_write)
606
{
607
    rc4030State *s = opaque;
608
    target_phys_addr_t entry_addr;
609
    target_phys_addr_t dma_addr, phys_addr;
610
    dma_pagetable_entry entry;
611
    int index, dev_to_mem;
612
    int ncpy, i;
613

    
614
    s->dma_regs[n][DMA_REG_ENABLE] &= ~(DMA_FLAG_TC_INTR | DMA_FLAG_MEM_INTR | DMA_FLAG_ADDR_INTR);
615

    
616
    /* Check DMA channel consistency */
617
    dev_to_mem = (s->dma_regs[n][DMA_REG_ENABLE] & DMA_FLAG_MEM_TO_DEV) ? 0 : 1;
618
    if (!(s->dma_regs[n][DMA_REG_ENABLE] & DMA_FLAG_ENABLE) ||
619
        (is_write != dev_to_mem)) {
620
        s->dma_regs[n][DMA_REG_ENABLE] |= DMA_FLAG_MEM_INTR;
621
        return;
622
    }
623

    
624
    if (len > s->dma_regs[n][DMA_REG_COUNT])
625
        len = s->dma_regs[n][DMA_REG_COUNT];
626

    
627
    dma_addr = s->dma_regs[n][DMA_REG_ADDRESS];
628
    i = 0;
629
    for (;;) {
630
        if (i == len) {
631
            s->dma_regs[n][DMA_REG_ENABLE] |= DMA_FLAG_TC_INTR;
632
            break;
633
        }
634

    
635
        ncpy = DMA_PAGESIZE - (dma_addr & (DMA_PAGESIZE - 1));
636
        if (ncpy > len - i)
637
            ncpy = len - i;
638

    
639
        /* Get DMA translation table entry */
640
        index = dma_addr / DMA_PAGESIZE;
641
        if (index >= s->dma_tl_limit / sizeof(dma_pagetable_entry)) {
642
            s->dma_regs[n][DMA_REG_ENABLE] |= DMA_FLAG_MEM_INTR;
643
            break;
644
        }
645
        entry_addr = s->dma_tl_base + index * sizeof(dma_pagetable_entry);
646
        /* XXX: not sure. should we really use only lowest bits? */
647
        entry_addr &= 0x7fffffff;
648
        cpu_physical_memory_rw(entry_addr, (uint8_t *)&entry, sizeof(entry), 0);
649

    
650
        /* Read/write data at right place */
651
        phys_addr = entry.frame + (dma_addr & (DMA_PAGESIZE - 1));
652
        cpu_physical_memory_rw(phys_addr, &buf[i], ncpy, is_write);
653

    
654
        i += ncpy;
655
        dma_addr += ncpy;
656
        s->dma_regs[n][DMA_REG_COUNT] -= ncpy;
657
    }
658

    
659
#ifdef DEBUG_RC4030_DMA
660
    {
661
        int i, j;
662
        printf("rc4030 dma: Copying %d bytes %s host %p\n",
663
            len, is_write ? "from" : "to", buf);
664
        for (i = 0; i < len; i += 16) {
665
            int n = min(16, len - i);
666
            for (j = 0; j < n; j++)
667
                printf("%02x ", buf[i + j]);
668
            while (j++ < 16)
669
                printf("   ");
670
            printf("| ");
671
            for (j = 0; j < n; j++)
672
                printf("%c", isprint(buf[i + j]) ? buf[i + j] : '.');
673
            printf("\n");
674
        }
675
    }
676
#endif
677
}
678

    
679
struct rc4030DMAState {
680
    void *opaque;
681
    int n;
682
};
683

    
684
static void rc4030_dma_read(void *dma, uint8_t *buf, int len)
685
{
686
    rc4030_dma s = dma;
687
    rc4030_do_dma(s->opaque, s->n, buf, len, 0);
688
}
689

    
690
static void rc4030_dma_write(void *dma, uint8_t *buf, int len)
691
{
692
    rc4030_dma s = dma;
693
    rc4030_do_dma(s->opaque, s->n, buf, len, 1);
694
}
695

    
696
static rc4030_dma *rc4030_allocate_dmas(void *opaque, int n)
697
{
698
    rc4030_dma *s;
699
    struct rc4030DMAState *p;
700
    int i;
701

    
702
    s = (rc4030_dma *)qemu_mallocz(sizeof(rc4030_dma) * n);
703
    p = (struct rc4030DMAState *)qemu_mallocz(sizeof(struct rc4030DMAState) * n);
704
    for (i = 0; i < n; i++) {
705
        p->opaque = opaque;
706
        p->n = i;
707
        s[i] = p;
708
        p++;
709
    }
710
    return s;
711
}
712

    
713
qemu_irq *rc4030_init(qemu_irq timer, qemu_irq jazz_bus,
714
                      rc4030_dma **dmas,
715
                      rc4030_dma_function *dma_read, rc4030_dma_function *dma_write)
716
{
717
    rc4030State *s;
718
    int s_chipset, s_jazzio;
719

    
720
    s = qemu_mallocz(sizeof(rc4030State));
721
    if (!s)
722
        return NULL;
723

    
724
    *dmas = rc4030_allocate_dmas(s, 4);
725
    *dma_read = rc4030_dma_read;
726
    *dma_write = rc4030_dma_write;
727

    
728
    s->periodic_timer = qemu_new_timer(vm_clock, rc4030_periodic_timer, s);
729
    s->timer_irq = timer;
730
    s->jazz_bus_irq = jazz_bus;
731

    
732
    qemu_register_reset(rc4030_reset, s);
733
    rc4030_reset(s);
734

    
735
    s_chipset = cpu_register_io_memory(0, rc4030_read, rc4030_write, s);
736
    cpu_register_physical_memory(0x80000000, 0x300, s_chipset);
737
    s_jazzio = cpu_register_io_memory(0, jazzio_read, jazzio_write, s);
738
    cpu_register_physical_memory(0xf0000000, 0x00001000, s_jazzio);
739

    
740
    return qemu_allocate_irqs(rc4030_irq_jazz_request, s, 16);
741
}