Statistics
| Branch: | Revision:

root / hw / openpic.c @ 38898d7e

History | View | Annotate | Download (43.3 kB)

1
/*
2
 * OpenPIC emulation
3
 *
4
 * Copyright (c) 2004 Jocelyn Mayer
5
 *               2011 Alexander Graf
6
 *
7
 * Permission is hereby granted, free of charge, to any person obtaining a copy
8
 * of this software and associated documentation files (the "Software"), to deal
9
 * in the Software without restriction, including without limitation the rights
10
 * to use, copy, modify, merge, publish, distribute, sublicense, and/or sell
11
 * copies of the Software, and to permit persons to whom the Software is
12
 * furnished to do so, subject to the following conditions:
13
 *
14
 * The above copyright notice and this permission notice shall be included in
15
 * all copies or substantial portions of the Software.
16
 *
17
 * THE SOFTWARE IS PROVIDED "AS IS", WITHOUT WARRANTY OF ANY KIND, EXPRESS OR
18
 * IMPLIED, INCLUDING BUT NOT LIMITED TO THE WARRANTIES OF MERCHANTABILITY,
19
 * FITNESS FOR A PARTICULAR PURPOSE AND NONINFRINGEMENT. IN NO EVENT SHALL
20
 * THE AUTHORS OR COPYRIGHT HOLDERS BE LIABLE FOR ANY CLAIM, DAMAGES OR OTHER
21
 * LIABILITY, WHETHER IN AN ACTION OF CONTRACT, TORT OR OTHERWISE, ARISING FROM,
22
 * OUT OF OR IN CONNECTION WITH THE SOFTWARE OR THE USE OR OTHER DEALINGS IN
23
 * THE SOFTWARE.
24
 */
25
/*
26
 *
27
 * Based on OpenPic implementations:
28
 * - Intel GW80314 I/O companion chip developer's manual
29
 * - Motorola MPC8245 & MPC8540 user manuals.
30
 * - Motorola MCP750 (aka Raven) programmer manual.
31
 * - Motorola Harrier programmer manuel
32
 *
33
 * Serial interrupts, as implemented in Raven chipset are not supported yet.
34
 *
35
 */
36
#include "hw.h"
37
#include "ppc_mac.h"
38
#include "pci.h"
39
#include "openpic.h"
40

    
41
//#define DEBUG_OPENPIC
42

    
43
#ifdef DEBUG_OPENPIC
44
#define DPRINTF(fmt, ...) do { printf(fmt , ## __VA_ARGS__); } while (0)
45
#else
46
#define DPRINTF(fmt, ...) do { } while (0)
47
#endif
48

    
49
#define MAX_CPU    15
50
#define MAX_IRQ   128
51
#define MAX_TMR     4
52
#define VECTOR_BITS 8
53
#define MAX_IPI     4
54
#define VID         0x03 /* MPIC version ID */
55
#define VENI        0x00000000 /* Vendor ID */
56

    
57
enum {
58
    IRQ_IPVP = 0,
59
    IRQ_IDE,
60
};
61

    
62
/* OpenPIC */
63
#define OPENPIC_MAX_CPU      2
64
#define OPENPIC_MAX_IRQ     64
65
#define OPENPIC_EXT_IRQ     48
66
#define OPENPIC_MAX_TMR      MAX_TMR
67
#define OPENPIC_MAX_IPI      MAX_IPI
68

    
69
/* Interrupt definitions */
70
#define OPENPIC_IRQ_FE     (OPENPIC_EXT_IRQ)     /* Internal functional IRQ */
71
#define OPENPIC_IRQ_ERR    (OPENPIC_EXT_IRQ + 1) /* Error IRQ */
72
#define OPENPIC_IRQ_TIM0   (OPENPIC_EXT_IRQ + 2) /* First timer IRQ */
73
#if OPENPIC_MAX_IPI > 0
74
#define OPENPIC_IRQ_IPI0   (OPENPIC_IRQ_TIM0 + OPENPIC_MAX_TMR) /* First IPI IRQ */
75
#define OPENPIC_IRQ_DBL0   (OPENPIC_IRQ_IPI0 + (OPENPIC_MAX_CPU * OPENPIC_MAX_IPI)) /* First doorbell IRQ */
76
#else
77
#define OPENPIC_IRQ_DBL0   (OPENPIC_IRQ_TIM0 + OPENPIC_MAX_TMR) /* First doorbell IRQ */
78
#define OPENPIC_IRQ_MBX0   (OPENPIC_IRQ_DBL0 + OPENPIC_MAX_DBL) /* First mailbox IRQ */
79
#endif
80

    
81
/* MPIC */
82
#define MPIC_MAX_CPU      1
83
#define MPIC_MAX_EXT     12
84
#define MPIC_MAX_INT     64
85
#define MPIC_MAX_MSG      4
86
#define MPIC_MAX_MSI      8
87
#define MPIC_MAX_TMR      MAX_TMR
88
#define MPIC_MAX_IPI      MAX_IPI
89
#define MPIC_MAX_IRQ     (MPIC_MAX_EXT + MPIC_MAX_INT + MPIC_MAX_TMR + MPIC_MAX_MSG + MPIC_MAX_MSI + (MPIC_MAX_IPI * MPIC_MAX_CPU))
90

    
91
/* Interrupt definitions */
92
#define MPIC_EXT_IRQ      0
93
#define MPIC_INT_IRQ      (MPIC_EXT_IRQ + MPIC_MAX_EXT)
94
#define MPIC_TMR_IRQ      (MPIC_INT_IRQ + MPIC_MAX_INT)
95
#define MPIC_MSG_IRQ      (MPIC_TMR_IRQ + MPIC_MAX_TMR)
96
#define MPIC_MSI_IRQ      (MPIC_MSG_IRQ + MPIC_MAX_MSG)
97
#define MPIC_IPI_IRQ      (MPIC_MSI_IRQ + MPIC_MAX_MSI)
98

    
99
#define MPIC_GLB_REG_START        0x0
100
#define MPIC_GLB_REG_SIZE         0x10F0
101
#define MPIC_TMR_REG_START        0x10F0
102
#define MPIC_TMR_REG_SIZE         0x220
103
#define MPIC_EXT_REG_START        0x10000
104
#define MPIC_EXT_REG_SIZE         0x180
105
#define MPIC_INT_REG_START        0x10200
106
#define MPIC_INT_REG_SIZE         0x800
107
#define MPIC_MSG_REG_START        0x11600
108
#define MPIC_MSG_REG_SIZE         0x100
109
#define MPIC_MSI_REG_START        0x11C00
110
#define MPIC_MSI_REG_SIZE         0x100
111
#define MPIC_CPU_REG_START        0x20000
112
#define MPIC_CPU_REG_SIZE         0x100 + ((MAX_CPU - 1) * 0x1000)
113

    
114
/*
115
 * Block Revision Register1 (BRR1): QEMU does not fully emulate
116
 * any version on MPIC. So to start with, set the IP version to 0.
117
 *
118
 * NOTE: This is Freescale MPIC specific register. Keep it here till
119
 * this code is refactored for different variants of OPENPIC and MPIC.
120
 */
121
#define FSL_BRR1_IPID (0x0040 << 16) /* 16 bit IP-block ID */
122
#define FSL_BRR1_IPMJ (0x00 << 8) /* 8 bit IP major number */
123
#define FSL_BRR1_IPMN 0x00 /* 8 bit IP minor number */
124

    
125
enum mpic_ide_bits {
126
    IDR_EP     = 31,
127
    IDR_CI0     = 30,
128
    IDR_CI1     = 29,
129
    IDR_P1     = 1,
130
    IDR_P0     = 0,
131
};
132

    
133
#define BF_WIDTH(_bits_) \
134
(((_bits_) + (sizeof(uint32_t) * 8) - 1) / (sizeof(uint32_t) * 8))
135

    
136
static inline void set_bit (uint32_t *field, int bit)
137
{
138
    field[bit >> 5] |= 1 << (bit & 0x1F);
139
}
140

    
141
static inline void reset_bit (uint32_t *field, int bit)
142
{
143
    field[bit >> 5] &= ~(1 << (bit & 0x1F));
144
}
145

    
146
static inline int test_bit (uint32_t *field, int bit)
147
{
148
    return (field[bit >> 5] & 1 << (bit & 0x1F)) != 0;
149
}
150

    
151
static int get_current_cpu(void)
152
{
153
  return cpu_single_env->cpu_index;
154
}
155

    
156
static uint32_t openpic_cpu_read_internal(void *opaque, hwaddr addr,
157
                                          int idx);
158
static void openpic_cpu_write_internal(void *opaque, hwaddr addr,
159
                                       uint32_t val, int idx);
160

    
161
enum {
162
    IRQ_EXTERNAL = 0x01,
163
    IRQ_INTERNAL = 0x02,
164
    IRQ_TIMER    = 0x04,
165
    IRQ_SPECIAL  = 0x08,
166
};
167

    
168
typedef struct IRQ_queue_t {
169
    uint32_t queue[BF_WIDTH(MAX_IRQ)];
170
    int next;
171
    int priority;
172
} IRQ_queue_t;
173

    
174
typedef struct IRQ_src_t {
175
    uint32_t ipvp;  /* IRQ vector/priority register */
176
    uint32_t ide;   /* IRQ destination register */
177
    int type;
178
    int last_cpu;
179
    int pending;    /* TRUE if IRQ is pending */
180
} IRQ_src_t;
181

    
182
enum IPVP_bits {
183
    IPVP_MASK     = 31,
184
    IPVP_ACTIVITY = 30,
185
    IPVP_MODE     = 29,
186
    IPVP_POLARITY = 23,
187
    IPVP_SENSE    = 22,
188
};
189
#define IPVP_PRIORITY_MASK     (0x1F << 16)
190
#define IPVP_PRIORITY(_ipvpr_) ((int)(((_ipvpr_) & IPVP_PRIORITY_MASK) >> 16))
191
#define IPVP_VECTOR_MASK       ((1 << VECTOR_BITS) - 1)
192
#define IPVP_VECTOR(_ipvpr_)   ((_ipvpr_) & IPVP_VECTOR_MASK)
193

    
194
typedef struct IRQ_dst_t {
195
    uint32_t tfrr;
196
    uint32_t pctp; /* CPU current task priority */
197
    uint32_t pcsr; /* CPU sensitivity register */
198
    IRQ_queue_t raised;
199
    IRQ_queue_t servicing;
200
    qemu_irq *irqs;
201
} IRQ_dst_t;
202

    
203
typedef struct openpic_t {
204
    PCIDevice pci_dev;
205
    MemoryRegion mem;
206

    
207
    /* Sub-regions */
208
    MemoryRegion sub_io_mem[7];
209

    
210
    /* Global registers */
211
    uint32_t frep; /* Feature reporting register */
212
    uint32_t glbc; /* Global configuration register  */
213
    uint32_t micr; /* MPIC interrupt configuration register */
214
    uint32_t veni; /* Vendor identification register */
215
    uint32_t pint; /* Processor initialization register */
216
    uint32_t spve; /* Spurious vector register */
217
    uint32_t tifr; /* Timer frequency reporting register */
218
    /* Source registers */
219
    IRQ_src_t src[MAX_IRQ];
220
    /* Local registers per output pin */
221
    IRQ_dst_t dst[MAX_CPU];
222
    int nb_cpus;
223
    /* Timer registers */
224
    struct {
225
        uint32_t ticc;  /* Global timer current count register */
226
        uint32_t tibc;  /* Global timer base count register */
227
    } timers[MAX_TMR];
228
    /* IRQ out is used when in bypass mode (not implemented) */
229
    qemu_irq irq_out;
230
    int max_irq;
231
    int irq_ipi0;
232
    int irq_tim0;
233
    void (*reset) (void *);
234
    void (*irq_raise) (struct openpic_t *, int, IRQ_src_t *);
235
} openpic_t;
236

    
237
static inline void IRQ_setbit (IRQ_queue_t *q, int n_IRQ)
238
{
239
    set_bit(q->queue, n_IRQ);
240
}
241

    
242
static inline void IRQ_resetbit (IRQ_queue_t *q, int n_IRQ)
243
{
244
    reset_bit(q->queue, n_IRQ);
245
}
246

    
247
static inline int IRQ_testbit (IRQ_queue_t *q, int n_IRQ)
248
{
249
    return test_bit(q->queue, n_IRQ);
250
}
251

    
252
static void IRQ_check (openpic_t *opp, IRQ_queue_t *q)
253
{
254
    int next, i;
255
    int priority;
256

    
257
    next = -1;
258
    priority = -1;
259
    for (i = 0; i < opp->max_irq; i++) {
260
        if (IRQ_testbit(q, i)) {
261
            DPRINTF("IRQ_check: irq %d set ipvp_pr=%d pr=%d\n",
262
                    i, IPVP_PRIORITY(opp->src[i].ipvp), priority);
263
            if (IPVP_PRIORITY(opp->src[i].ipvp) > priority) {
264
                next = i;
265
                priority = IPVP_PRIORITY(opp->src[i].ipvp);
266
            }
267
        }
268
    }
269
    q->next = next;
270
    q->priority = priority;
271
}
272

    
273
static int IRQ_get_next (openpic_t *opp, IRQ_queue_t *q)
274
{
275
    if (q->next == -1) {
276
        /* XXX: optimize */
277
        IRQ_check(opp, q);
278
    }
279

    
280
    return q->next;
281
}
282

    
283
static void IRQ_local_pipe (openpic_t *opp, int n_CPU, int n_IRQ)
284
{
285
    IRQ_dst_t *dst;
286
    IRQ_src_t *src;
287
    int priority;
288

    
289
    dst = &opp->dst[n_CPU];
290
    src = &opp->src[n_IRQ];
291
    priority = IPVP_PRIORITY(src->ipvp);
292
    if (priority <= dst->pctp) {
293
        /* Too low priority */
294
        DPRINTF("%s: IRQ %d has too low priority on CPU %d\n",
295
                __func__, n_IRQ, n_CPU);
296
        return;
297
    }
298
    if (IRQ_testbit(&dst->raised, n_IRQ)) {
299
        /* Interrupt miss */
300
        DPRINTF("%s: IRQ %d was missed on CPU %d\n",
301
                __func__, n_IRQ, n_CPU);
302
        return;
303
    }
304
    set_bit(&src->ipvp, IPVP_ACTIVITY);
305
    IRQ_setbit(&dst->raised, n_IRQ);
306
    if (priority < dst->raised.priority) {
307
        /* An higher priority IRQ is already raised */
308
        DPRINTF("%s: IRQ %d is hidden by raised IRQ %d on CPU %d\n",
309
                __func__, n_IRQ, dst->raised.next, n_CPU);
310
        return;
311
    }
312
    IRQ_get_next(opp, &dst->raised);
313
    if (IRQ_get_next(opp, &dst->servicing) != -1 &&
314
        priority <= dst->servicing.priority) {
315
        DPRINTF("%s: IRQ %d is hidden by servicing IRQ %d on CPU %d\n",
316
                __func__, n_IRQ, dst->servicing.next, n_CPU);
317
        /* Already servicing a higher priority IRQ */
318
        return;
319
    }
320
    DPRINTF("Raise OpenPIC INT output cpu %d irq %d\n", n_CPU, n_IRQ);
321
    opp->irq_raise(opp, n_CPU, src);
322
}
323

    
324
/* update pic state because registers for n_IRQ have changed value */
325
static void openpic_update_irq(openpic_t *opp, int n_IRQ)
326
{
327
    IRQ_src_t *src;
328
    int i;
329

    
330
    src = &opp->src[n_IRQ];
331

    
332
    if (!src->pending) {
333
        /* no irq pending */
334
        DPRINTF("%s: IRQ %d is not pending\n", __func__, n_IRQ);
335
        return;
336
    }
337
    if (test_bit(&src->ipvp, IPVP_MASK)) {
338
        /* Interrupt source is disabled */
339
        DPRINTF("%s: IRQ %d is disabled\n", __func__, n_IRQ);
340
        return;
341
    }
342
    if (IPVP_PRIORITY(src->ipvp) == 0) {
343
        /* Priority set to zero */
344
        DPRINTF("%s: IRQ %d has 0 priority\n", __func__, n_IRQ);
345
        return;
346
    }
347
    if (test_bit(&src->ipvp, IPVP_ACTIVITY)) {
348
        /* IRQ already active */
349
        DPRINTF("%s: IRQ %d is already active\n", __func__, n_IRQ);
350
        return;
351
    }
352
    if (src->ide == 0x00000000) {
353
        /* No target */
354
        DPRINTF("%s: IRQ %d has no target\n", __func__, n_IRQ);
355
        return;
356
    }
357

    
358
    if (src->ide == (1 << src->last_cpu)) {
359
        /* Only one CPU is allowed to receive this IRQ */
360
        IRQ_local_pipe(opp, src->last_cpu, n_IRQ);
361
    } else if (!test_bit(&src->ipvp, IPVP_MODE)) {
362
        /* Directed delivery mode */
363
        for (i = 0; i < opp->nb_cpus; i++) {
364
            if (test_bit(&src->ide, i))
365
                IRQ_local_pipe(opp, i, n_IRQ);
366
        }
367
    } else {
368
        /* Distributed delivery mode */
369
        for (i = src->last_cpu + 1; i != src->last_cpu; i++) {
370
            if (i == opp->nb_cpus)
371
                i = 0;
372
            if (test_bit(&src->ide, i)) {
373
                IRQ_local_pipe(opp, i, n_IRQ);
374
                src->last_cpu = i;
375
                break;
376
            }
377
        }
378
    }
379
}
380

    
381
static void openpic_set_irq(void *opaque, int n_IRQ, int level)
382
{
383
    openpic_t *opp = opaque;
384
    IRQ_src_t *src;
385

    
386
    src = &opp->src[n_IRQ];
387
    DPRINTF("openpic: set irq %d = %d ipvp=%08x\n",
388
            n_IRQ, level, src->ipvp);
389
    if (test_bit(&src->ipvp, IPVP_SENSE)) {
390
        /* level-sensitive irq */
391
        src->pending = level;
392
        if (!level)
393
            reset_bit(&src->ipvp, IPVP_ACTIVITY);
394
    } else {
395
        /* edge-sensitive irq */
396
        if (level)
397
            src->pending = 1;
398
    }
399
    openpic_update_irq(opp, n_IRQ);
400
}
401

    
402
static void openpic_reset (void *opaque)
403
{
404
    openpic_t *opp = (openpic_t *)opaque;
405
    int i;
406

    
407
    opp->glbc = 0x80000000;
408
    /* Initialise controller registers */
409
    opp->frep = ((OPENPIC_EXT_IRQ - 1) << 16) | ((MAX_CPU - 1) << 8) | VID;
410
    opp->veni = VENI;
411
    opp->pint = 0x00000000;
412
    opp->spve = 0x000000FF;
413
    opp->tifr = 0x003F7A00;
414
    /* ? */
415
    opp->micr = 0x00000000;
416
    /* Initialise IRQ sources */
417
    for (i = 0; i < opp->max_irq; i++) {
418
        opp->src[i].ipvp = 0xA0000000;
419
        opp->src[i].ide  = 0x00000000;
420
    }
421
    /* Initialise IRQ destinations */
422
    for (i = 0; i < MAX_CPU; i++) {
423
        opp->dst[i].pctp      = 0x0000000F;
424
        opp->dst[i].pcsr      = 0x00000000;
425
        memset(&opp->dst[i].raised, 0, sizeof(IRQ_queue_t));
426
        opp->dst[i].raised.next = -1;
427
        memset(&opp->dst[i].servicing, 0, sizeof(IRQ_queue_t));
428
        opp->dst[i].servicing.next = -1;
429
    }
430
    /* Initialise timers */
431
    for (i = 0; i < MAX_TMR; i++) {
432
        opp->timers[i].ticc = 0x00000000;
433
        opp->timers[i].tibc = 0x80000000;
434
    }
435
    /* Go out of RESET state */
436
    opp->glbc = 0x00000000;
437
}
438

    
439
static inline uint32_t read_IRQreg_ide(openpic_t *opp, int n_IRQ)
440
{
441
    return opp->src[n_IRQ].ide;
442
}
443

    
444
static inline uint32_t read_IRQreg_ipvp(openpic_t *opp, int n_IRQ)
445
{
446
    return opp->src[n_IRQ].ipvp;
447
}
448

    
449
static inline void write_IRQreg_ide(openpic_t *opp, int n_IRQ, uint32_t val)
450
{
451
    uint32_t tmp;
452

    
453
    tmp = val & 0xC0000000;
454
    tmp |= val & ((1ULL << MAX_CPU) - 1);
455
    opp->src[n_IRQ].ide = tmp;
456
    DPRINTF("Set IDE %d to 0x%08x\n", n_IRQ, opp->src[n_IRQ].ide);
457
}
458

    
459
static inline void write_IRQreg_ipvp(openpic_t *opp, int n_IRQ, uint32_t val)
460
{
461
    /* NOTE: not fully accurate for special IRQs, but simple and sufficient */
462
    /* ACTIVITY bit is read-only */
463
    opp->src[n_IRQ].ipvp = (opp->src[n_IRQ].ipvp & 0x40000000)
464
                         | (val & 0x800F00FF);
465
    openpic_update_irq(opp, n_IRQ);
466
    DPRINTF("Set IPVP %d to 0x%08x -> 0x%08x\n", n_IRQ, val,
467
            opp->src[n_IRQ].ipvp);
468
}
469

    
470
static void openpic_gbl_write (void *opaque, hwaddr addr, uint32_t val)
471
{
472
    openpic_t *opp = opaque;
473
    IRQ_dst_t *dst;
474
    int idx;
475

    
476
    DPRINTF("%s: addr " TARGET_FMT_plx " <= %08x\n", __func__, addr, val);
477
    if (addr & 0xF)
478
        return;
479
    switch (addr) {
480
    case 0x00: /* Block Revision Register1 (BRR1) is Readonly */
481
        break;
482
    case 0x40:
483
    case 0x50:
484
    case 0x60:
485
    case 0x70:
486
    case 0x80:
487
    case 0x90:
488
    case 0xA0:
489
    case 0xB0:
490
        openpic_cpu_write_internal(opp, addr, val, get_current_cpu());
491
        break;
492
    case 0x1000: /* FREP */
493
        break;
494
    case 0x1020: /* GLBC */
495
        if (val & 0x80000000 && opp->reset)
496
            opp->reset(opp);
497
        opp->glbc = val & ~0x80000000;
498
        break;
499
    case 0x1080: /* VENI */
500
        break;
501
    case 0x1090: /* PINT */
502
        for (idx = 0; idx < opp->nb_cpus; idx++) {
503
            if ((val & (1 << idx)) && !(opp->pint & (1 << idx))) {
504
                DPRINTF("Raise OpenPIC RESET output for CPU %d\n", idx);
505
                dst = &opp->dst[idx];
506
                qemu_irq_raise(dst->irqs[OPENPIC_OUTPUT_RESET]);
507
            } else if (!(val & (1 << idx)) && (opp->pint & (1 << idx))) {
508
                DPRINTF("Lower OpenPIC RESET output for CPU %d\n", idx);
509
                dst = &opp->dst[idx];
510
                qemu_irq_lower(dst->irqs[OPENPIC_OUTPUT_RESET]);
511
            }
512
        }
513
        opp->pint = val;
514
        break;
515
    case 0x10A0: /* IPI_IPVP */
516
    case 0x10B0:
517
    case 0x10C0:
518
    case 0x10D0:
519
        {
520
            int idx;
521
            idx = (addr - 0x10A0) >> 4;
522
            write_IRQreg_ipvp(opp, opp->irq_ipi0 + idx, val);
523
        }
524
        break;
525
    case 0x10E0: /* SPVE */
526
        opp->spve = val & 0x000000FF;
527
        break;
528
    case 0x10F0: /* TIFR */
529
        opp->tifr = val;
530
        break;
531
    default:
532
        break;
533
    }
534
}
535

    
536
static uint32_t openpic_gbl_read (void *opaque, hwaddr addr)
537
{
538
    openpic_t *opp = opaque;
539
    uint32_t retval;
540

    
541
    DPRINTF("%s: addr " TARGET_FMT_plx "\n", __func__, addr);
542
    retval = 0xFFFFFFFF;
543
    if (addr & 0xF)
544
        return retval;
545
    switch (addr) {
546
    case 0x1000: /* FREP */
547
        retval = opp->frep;
548
        break;
549
    case 0x1020: /* GLBC */
550
        retval = opp->glbc;
551
        break;
552
    case 0x1080: /* VENI */
553
        retval = opp->veni;
554
        break;
555
    case 0x1090: /* PINT */
556
        retval = 0x00000000;
557
        break;
558
    case 0x00: /* Block Revision Register1 (BRR1) */
559
    case 0x40:
560
    case 0x50:
561
    case 0x60:
562
    case 0x70:
563
    case 0x80:
564
    case 0x90:
565
    case 0xA0:
566
    case 0xB0:
567
        retval = openpic_cpu_read_internal(opp, addr, get_current_cpu());
568
        break;
569
    case 0x10A0: /* IPI_IPVP */
570
    case 0x10B0:
571
    case 0x10C0:
572
    case 0x10D0:
573
        {
574
            int idx;
575
            idx = (addr - 0x10A0) >> 4;
576
            retval = read_IRQreg_ipvp(opp, opp->irq_ipi0 + idx);
577
        }
578
        break;
579
    case 0x10E0: /* SPVE */
580
        retval = opp->spve;
581
        break;
582
    case 0x10F0: /* TIFR */
583
        retval = opp->tifr;
584
        break;
585
    default:
586
        break;
587
    }
588
    DPRINTF("%s: => %08x\n", __func__, retval);
589

    
590
    return retval;
591
}
592

    
593
static void openpic_timer_write (void *opaque, uint32_t addr, uint32_t val)
594
{
595
    openpic_t *opp = opaque;
596
    int idx;
597

    
598
    DPRINTF("%s: addr %08x <= %08x\n", __func__, addr, val);
599
    if (addr & 0xF)
600
        return;
601
    addr -= 0x10;
602
    addr &= 0xFFFF;
603
    idx = (addr & 0xFFF0) >> 6;
604
    addr = addr & 0x30;
605
    switch (addr) {
606
    case 0x00: /* TICC */
607
        break;
608
    case 0x10: /* TIBC */
609
        if ((opp->timers[idx].ticc & 0x80000000) != 0 &&
610
            (val & 0x80000000) == 0 &&
611
            (opp->timers[idx].tibc & 0x80000000) != 0)
612
            opp->timers[idx].ticc &= ~0x80000000;
613
        opp->timers[idx].tibc = val;
614
        break;
615
    case 0x20: /* TIVP */
616
        write_IRQreg_ipvp(opp, opp->irq_tim0 + idx, val);
617
        break;
618
    case 0x30: /* TIDE */
619
        write_IRQreg_ide(opp, opp->irq_tim0 + idx, val);
620
        break;
621
    }
622
}
623

    
624
static uint32_t openpic_timer_read (void *opaque, uint32_t addr)
625
{
626
    openpic_t *opp = opaque;
627
    uint32_t retval;
628
    int idx;
629

    
630
    DPRINTF("%s: addr %08x\n", __func__, addr);
631
    retval = 0xFFFFFFFF;
632
    if (addr & 0xF)
633
        return retval;
634
    addr -= 0x10;
635
    addr &= 0xFFFF;
636
    idx = (addr & 0xFFF0) >> 6;
637
    addr = addr & 0x30;
638
    switch (addr) {
639
    case 0x00: /* TICC */
640
        retval = opp->timers[idx].ticc;
641
        break;
642
    case 0x10: /* TIBC */
643
        retval = opp->timers[idx].tibc;
644
        break;
645
    case 0x20: /* TIPV */
646
        retval = read_IRQreg_ipvp(opp, opp->irq_tim0 + idx);
647
        break;
648
    case 0x30: /* TIDE */
649
        retval = read_IRQreg_ide(opp, opp->irq_tim0 + idx);
650
        break;
651
    }
652
    DPRINTF("%s: => %08x\n", __func__, retval);
653

    
654
    return retval;
655
}
656

    
657
static void openpic_src_write (void *opaque, uint32_t addr, uint32_t val)
658
{
659
    openpic_t *opp = opaque;
660
    int idx;
661

    
662
    DPRINTF("%s: addr %08x <= %08x\n", __func__, addr, val);
663
    if (addr & 0xF)
664
        return;
665
    addr = addr & 0xFFF0;
666
    idx = addr >> 5;
667
    if (addr & 0x10) {
668
        /* EXDE / IFEDE / IEEDE */
669
        write_IRQreg_ide(opp, idx, val);
670
    } else {
671
        /* EXVP / IFEVP / IEEVP */
672
        write_IRQreg_ipvp(opp, idx, val);
673
    }
674
}
675

    
676
static uint32_t openpic_src_read (void *opaque, uint32_t addr)
677
{
678
    openpic_t *opp = opaque;
679
    uint32_t retval;
680
    int idx;
681

    
682
    DPRINTF("%s: addr %08x\n", __func__, addr);
683
    retval = 0xFFFFFFFF;
684
    if (addr & 0xF)
685
        return retval;
686
    addr = addr & 0xFFF0;
687
    idx = addr >> 5;
688
    if (addr & 0x10) {
689
        /* EXDE / IFEDE / IEEDE */
690
        retval = read_IRQreg_ide(opp, idx);
691
    } else {
692
        /* EXVP / IFEVP / IEEVP */
693
        retval = read_IRQreg_ipvp(opp, idx);
694
    }
695
    DPRINTF("%s: => %08x\n", __func__, retval);
696

    
697
    return retval;
698
}
699

    
700
static void openpic_cpu_write_internal(void *opaque, hwaddr addr,
701
                                       uint32_t val, int idx)
702
{
703
    openpic_t *opp = opaque;
704
    IRQ_src_t *src;
705
    IRQ_dst_t *dst;
706
    int s_IRQ, n_IRQ;
707

    
708
    DPRINTF("%s: cpu %d addr " TARGET_FMT_plx " <= %08x\n", __func__, idx,
709
            addr, val);
710
    if (addr & 0xF)
711
        return;
712
    dst = &opp->dst[idx];
713
    addr &= 0xFF0;
714
    switch (addr) {
715
    case 0x40: /* IPIDR */
716
    case 0x50:
717
    case 0x60:
718
    case 0x70:
719
        idx = (addr - 0x40) >> 4;
720
        /* we use IDE as mask which CPUs to deliver the IPI to still. */
721
        write_IRQreg_ide(opp, opp->irq_ipi0 + idx,
722
                         opp->src[opp->irq_ipi0 + idx].ide | val);
723
        openpic_set_irq(opp, opp->irq_ipi0 + idx, 1);
724
        openpic_set_irq(opp, opp->irq_ipi0 + idx, 0);
725
        break;
726
    case 0x80: /* PCTP */
727
        dst->pctp = val & 0x0000000F;
728
        break;
729
    case 0x90: /* WHOAMI */
730
        /* Read-only register */
731
        break;
732
    case 0xA0: /* PIAC */
733
        /* Read-only register */
734
        break;
735
    case 0xB0: /* PEOI */
736
        DPRINTF("PEOI\n");
737
        s_IRQ = IRQ_get_next(opp, &dst->servicing);
738
        IRQ_resetbit(&dst->servicing, s_IRQ);
739
        dst->servicing.next = -1;
740
        /* Set up next servicing IRQ */
741
        s_IRQ = IRQ_get_next(opp, &dst->servicing);
742
        /* Check queued interrupts. */
743
        n_IRQ = IRQ_get_next(opp, &dst->raised);
744
        src = &opp->src[n_IRQ];
745
        if (n_IRQ != -1 &&
746
            (s_IRQ == -1 ||
747
             IPVP_PRIORITY(src->ipvp) > dst->servicing.priority)) {
748
            DPRINTF("Raise OpenPIC INT output cpu %d irq %d\n",
749
                    idx, n_IRQ);
750
            opp->irq_raise(opp, idx, src);
751
        }
752
        break;
753
    default:
754
        break;
755
    }
756
}
757

    
758
static void openpic_cpu_write(void *opaque, hwaddr addr, uint32_t val)
759
{
760
    openpic_cpu_write_internal(opaque, addr, val, (addr & 0x1f000) >> 12);
761
}
762

    
763
static uint32_t openpic_cpu_read_internal(void *opaque, hwaddr addr,
764
                                          int idx)
765
{
766
    openpic_t *opp = opaque;
767
    IRQ_src_t *src;
768
    IRQ_dst_t *dst;
769
    uint32_t retval;
770
    int n_IRQ;
771

    
772
    DPRINTF("%s: cpu %d addr " TARGET_FMT_plx "\n", __func__, idx, addr);
773
    retval = 0xFFFFFFFF;
774
    if (addr & 0xF)
775
        return retval;
776
    dst = &opp->dst[idx];
777
    addr &= 0xFF0;
778
    switch (addr) {
779
    case 0x00: /* Block Revision Register1 (BRR1) */
780
        retval = FSL_BRR1_IPID | FSL_BRR1_IPMJ | FSL_BRR1_IPMN;
781
        break;
782
    case 0x80: /* PCTP */
783
        retval = dst->pctp;
784
        break;
785
    case 0x90: /* WHOAMI */
786
        retval = idx;
787
        break;
788
    case 0xA0: /* PIAC */
789
        DPRINTF("Lower OpenPIC INT output\n");
790
        qemu_irq_lower(dst->irqs[OPENPIC_OUTPUT_INT]);
791
        n_IRQ = IRQ_get_next(opp, &dst->raised);
792
        DPRINTF("PIAC: irq=%d\n", n_IRQ);
793
        if (n_IRQ == -1) {
794
            /* No more interrupt pending */
795
            retval = IPVP_VECTOR(opp->spve);
796
        } else {
797
            src = &opp->src[n_IRQ];
798
            if (!test_bit(&src->ipvp, IPVP_ACTIVITY) ||
799
                !(IPVP_PRIORITY(src->ipvp) > dst->pctp)) {
800
                /* - Spurious level-sensitive IRQ
801
                 * - Priorities has been changed
802
                 *   and the pending IRQ isn't allowed anymore
803
                 */
804
                reset_bit(&src->ipvp, IPVP_ACTIVITY);
805
                retval = IPVP_VECTOR(opp->spve);
806
            } else {
807
                /* IRQ enter servicing state */
808
                IRQ_setbit(&dst->servicing, n_IRQ);
809
                retval = IPVP_VECTOR(src->ipvp);
810
            }
811
            IRQ_resetbit(&dst->raised, n_IRQ);
812
            dst->raised.next = -1;
813
            if (!test_bit(&src->ipvp, IPVP_SENSE)) {
814
                /* edge-sensitive IRQ */
815
                reset_bit(&src->ipvp, IPVP_ACTIVITY);
816
                src->pending = 0;
817
            }
818

    
819
            if ((n_IRQ >= opp->irq_ipi0) &&  (n_IRQ < (opp->irq_ipi0 + MAX_IPI))) {
820
                src->ide &= ~(1 << idx);
821
                if (src->ide && !test_bit(&src->ipvp, IPVP_SENSE)) {
822
                    /* trigger on CPUs that didn't know about it yet */
823
                    openpic_set_irq(opp, n_IRQ, 1);
824
                    openpic_set_irq(opp, n_IRQ, 0);
825
                    /* if all CPUs knew about it, set active bit again */
826
                    set_bit(&src->ipvp, IPVP_ACTIVITY);
827
                }
828
            }
829
        }
830
        break;
831
    case 0xB0: /* PEOI */
832
        retval = 0;
833
        break;
834
    default:
835
        break;
836
    }
837
    DPRINTF("%s: => %08x\n", __func__, retval);
838

    
839
    return retval;
840
}
841

    
842
static uint32_t openpic_cpu_read(void *opaque, hwaddr addr)
843
{
844
    return openpic_cpu_read_internal(opaque, addr, (addr & 0x1f000) >> 12);
845
}
846

    
847
static void openpic_buggy_write (void *opaque,
848
                                 hwaddr addr, uint32_t val)
849
{
850
    printf("Invalid OPENPIC write access !\n");
851
}
852

    
853
static uint32_t openpic_buggy_read (void *opaque, hwaddr addr)
854
{
855
    printf("Invalid OPENPIC read access !\n");
856

    
857
    return -1;
858
}
859

    
860
static void openpic_writel (void *opaque,
861
                            hwaddr addr, uint32_t val)
862
{
863
    openpic_t *opp = opaque;
864

    
865
    addr &= 0x3FFFF;
866
    DPRINTF("%s: offset %08x val: %08x\n", __func__, (int)addr, val);
867
    if (addr < 0x1100) {
868
        /* Global registers */
869
        openpic_gbl_write(opp, addr, val);
870
    } else if (addr < 0x10000) {
871
        /* Timers registers */
872
        openpic_timer_write(opp, addr, val);
873
    } else if (addr < 0x20000) {
874
        /* Source registers */
875
        openpic_src_write(opp, addr, val);
876
    } else {
877
        /* CPU registers */
878
        openpic_cpu_write(opp, addr, val);
879
    }
880
}
881

    
882
static uint32_t openpic_readl (void *opaque,hwaddr addr)
883
{
884
    openpic_t *opp = opaque;
885
    uint32_t retval;
886

    
887
    addr &= 0x3FFFF;
888
    DPRINTF("%s: offset %08x\n", __func__, (int)addr);
889
    if (addr < 0x1100) {
890
        /* Global registers */
891
        retval = openpic_gbl_read(opp, addr);
892
    } else if (addr < 0x10000) {
893
        /* Timers registers */
894
        retval = openpic_timer_read(opp, addr);
895
    } else if (addr < 0x20000) {
896
        /* Source registers */
897
        retval = openpic_src_read(opp, addr);
898
    } else {
899
        /* CPU registers */
900
        retval = openpic_cpu_read(opp, addr);
901
    }
902

    
903
    return retval;
904
}
905

    
906
static uint64_t openpic_read(void *opaque, hwaddr addr,
907
                             unsigned size)
908
{
909
    openpic_t *opp = opaque;
910

    
911
    switch (size) {
912
    case 4: return openpic_readl(opp, addr);
913
    default: return openpic_buggy_read(opp, addr);
914
    }
915
}
916

    
917
static void openpic_write(void *opaque, hwaddr addr,
918
                          uint64_t data, unsigned size)
919
{
920
    openpic_t *opp = opaque;
921

    
922
    switch (size) {
923
    case 4: return openpic_writel(opp, addr, data);
924
    default: return openpic_buggy_write(opp, addr, data);
925
    }
926
}
927

    
928
static const MemoryRegionOps openpic_ops = {
929
    .read = openpic_read,
930
    .write = openpic_write,
931
    .endianness = DEVICE_LITTLE_ENDIAN,
932
};
933

    
934
static void openpic_save_IRQ_queue(QEMUFile* f, IRQ_queue_t *q)
935
{
936
    unsigned int i;
937

    
938
    for (i = 0; i < BF_WIDTH(MAX_IRQ); i++)
939
        qemu_put_be32s(f, &q->queue[i]);
940

    
941
    qemu_put_sbe32s(f, &q->next);
942
    qemu_put_sbe32s(f, &q->priority);
943
}
944

    
945
static void openpic_save(QEMUFile* f, void *opaque)
946
{
947
    openpic_t *opp = (openpic_t *)opaque;
948
    unsigned int i;
949

    
950
    qemu_put_be32s(f, &opp->frep);
951
    qemu_put_be32s(f, &opp->glbc);
952
    qemu_put_be32s(f, &opp->micr);
953
    qemu_put_be32s(f, &opp->veni);
954
    qemu_put_be32s(f, &opp->pint);
955
    qemu_put_be32s(f, &opp->spve);
956
    qemu_put_be32s(f, &opp->tifr);
957

    
958
    for (i = 0; i < opp->max_irq; i++) {
959
        qemu_put_be32s(f, &opp->src[i].ipvp);
960
        qemu_put_be32s(f, &opp->src[i].ide);
961
        qemu_put_sbe32s(f, &opp->src[i].type);
962
        qemu_put_sbe32s(f, &opp->src[i].last_cpu);
963
        qemu_put_sbe32s(f, &opp->src[i].pending);
964
    }
965

    
966
    qemu_put_sbe32s(f, &opp->nb_cpus);
967

    
968
    for (i = 0; i < opp->nb_cpus; i++) {
969
        qemu_put_be32s(f, &opp->dst[i].tfrr);
970
        qemu_put_be32s(f, &opp->dst[i].pctp);
971
        qemu_put_be32s(f, &opp->dst[i].pcsr);
972
        openpic_save_IRQ_queue(f, &opp->dst[i].raised);
973
        openpic_save_IRQ_queue(f, &opp->dst[i].servicing);
974
    }
975

    
976
    for (i = 0; i < MAX_TMR; i++) {
977
        qemu_put_be32s(f, &opp->timers[i].ticc);
978
        qemu_put_be32s(f, &opp->timers[i].tibc);
979
    }
980

    
981
    pci_device_save(&opp->pci_dev, f);
982
}
983

    
984
static void openpic_load_IRQ_queue(QEMUFile* f, IRQ_queue_t *q)
985
{
986
    unsigned int i;
987

    
988
    for (i = 0; i < BF_WIDTH(MAX_IRQ); i++)
989
        qemu_get_be32s(f, &q->queue[i]);
990

    
991
    qemu_get_sbe32s(f, &q->next);
992
    qemu_get_sbe32s(f, &q->priority);
993
}
994

    
995
static int openpic_load(QEMUFile* f, void *opaque, int version_id)
996
{
997
    openpic_t *opp = (openpic_t *)opaque;
998
    unsigned int i;
999

    
1000
    if (version_id != 1)
1001
        return -EINVAL;
1002

    
1003
    qemu_get_be32s(f, &opp->frep);
1004
    qemu_get_be32s(f, &opp->glbc);
1005
    qemu_get_be32s(f, &opp->micr);
1006
    qemu_get_be32s(f, &opp->veni);
1007
    qemu_get_be32s(f, &opp->pint);
1008
    qemu_get_be32s(f, &opp->spve);
1009
    qemu_get_be32s(f, &opp->tifr);
1010

    
1011
    for (i = 0; i < opp->max_irq; i++) {
1012
        qemu_get_be32s(f, &opp->src[i].ipvp);
1013
        qemu_get_be32s(f, &opp->src[i].ide);
1014
        qemu_get_sbe32s(f, &opp->src[i].type);
1015
        qemu_get_sbe32s(f, &opp->src[i].last_cpu);
1016
        qemu_get_sbe32s(f, &opp->src[i].pending);
1017
    }
1018

    
1019
    qemu_get_sbe32s(f, &opp->nb_cpus);
1020

    
1021
    for (i = 0; i < opp->nb_cpus; i++) {
1022
        qemu_get_be32s(f, &opp->dst[i].tfrr);
1023
        qemu_get_be32s(f, &opp->dst[i].pctp);
1024
        qemu_get_be32s(f, &opp->dst[i].pcsr);
1025
        openpic_load_IRQ_queue(f, &opp->dst[i].raised);
1026
        openpic_load_IRQ_queue(f, &opp->dst[i].servicing);
1027
    }
1028

    
1029
    for (i = 0; i < MAX_TMR; i++) {
1030
        qemu_get_be32s(f, &opp->timers[i].ticc);
1031
        qemu_get_be32s(f, &opp->timers[i].tibc);
1032
    }
1033

    
1034
    return pci_device_load(&opp->pci_dev, f);
1035
}
1036

    
1037
static void openpic_irq_raise(openpic_t *opp, int n_CPU, IRQ_src_t *src)
1038
{
1039
    qemu_irq_raise(opp->dst[n_CPU].irqs[OPENPIC_OUTPUT_INT]);
1040
}
1041

    
1042
qemu_irq *openpic_init (MemoryRegion **pmem, int nb_cpus,
1043
                        qemu_irq **irqs, qemu_irq irq_out)
1044
{
1045
    openpic_t *opp;
1046
    int i, m;
1047

    
1048
    /* XXX: for now, only one CPU is supported */
1049
    if (nb_cpus != 1)
1050
        return NULL;
1051
    opp = g_malloc0(sizeof(openpic_t));
1052
    memory_region_init_io(&opp->mem, &openpic_ops, opp, "openpic", 0x40000);
1053

    
1054
    //    isu_base &= 0xFFFC0000;
1055
    opp->nb_cpus = nb_cpus;
1056
    opp->max_irq = OPENPIC_MAX_IRQ;
1057
    opp->irq_ipi0 = OPENPIC_IRQ_IPI0;
1058
    opp->irq_tim0 = OPENPIC_IRQ_TIM0;
1059
    /* Set IRQ types */
1060
    for (i = 0; i < OPENPIC_EXT_IRQ; i++) {
1061
        opp->src[i].type = IRQ_EXTERNAL;
1062
    }
1063
    for (; i < OPENPIC_IRQ_TIM0; i++) {
1064
        opp->src[i].type = IRQ_SPECIAL;
1065
    }
1066
    m = OPENPIC_IRQ_IPI0;
1067
    for (; i < m; i++) {
1068
        opp->src[i].type = IRQ_TIMER;
1069
    }
1070
    for (; i < OPENPIC_MAX_IRQ; i++) {
1071
        opp->src[i].type = IRQ_INTERNAL;
1072
    }
1073
    for (i = 0; i < nb_cpus; i++)
1074
        opp->dst[i].irqs = irqs[i];
1075
    opp->irq_out = irq_out;
1076

    
1077
    register_savevm(&opp->pci_dev.qdev, "openpic", 0, 2,
1078
                    openpic_save, openpic_load, opp);
1079
    qemu_register_reset(openpic_reset, opp);
1080

    
1081
    opp->irq_raise = openpic_irq_raise;
1082
    opp->reset = openpic_reset;
1083

    
1084
    if (pmem)
1085
        *pmem = &opp->mem;
1086

    
1087
    return qemu_allocate_irqs(openpic_set_irq, opp, opp->max_irq);
1088
}
1089

    
1090
static void mpic_irq_raise(openpic_t *mpp, int n_CPU, IRQ_src_t *src)
1091
{
1092
    int n_ci = IDR_CI0 - n_CPU;
1093

    
1094
    if(test_bit(&src->ide, n_ci)) {
1095
        qemu_irq_raise(mpp->dst[n_CPU].irqs[OPENPIC_OUTPUT_CINT]);
1096
    }
1097
    else {
1098
        qemu_irq_raise(mpp->dst[n_CPU].irqs[OPENPIC_OUTPUT_INT]);
1099
    }
1100
}
1101

    
1102
static void mpic_reset (void *opaque)
1103
{
1104
    openpic_t *mpp = (openpic_t *)opaque;
1105
    int i;
1106

    
1107
    mpp->glbc = 0x80000000;
1108
    /* Initialise controller registers */
1109
    mpp->frep = 0x004f0002 | ((mpp->nb_cpus - 1) << 8);
1110
    mpp->veni = VENI;
1111
    mpp->pint = 0x00000000;
1112
    mpp->spve = 0x0000FFFF;
1113
    /* Initialise IRQ sources */
1114
    for (i = 0; i < mpp->max_irq; i++) {
1115
        mpp->src[i].ipvp = 0x80800000;
1116
        mpp->src[i].ide  = 0x00000001;
1117
    }
1118
    /* Set IDE for IPIs to 0 so we don't get spurious interrupts */
1119
    for (i = mpp->irq_ipi0; i < (mpp->irq_ipi0 + MAX_IPI); i++) {
1120
        mpp->src[i].ide = 0;
1121
    }
1122
    /* Initialise IRQ destinations */
1123
    for (i = 0; i < MAX_CPU; i++) {
1124
        mpp->dst[i].pctp      = 0x0000000F;
1125
        mpp->dst[i].tfrr      = 0x00000000;
1126
        memset(&mpp->dst[i].raised, 0, sizeof(IRQ_queue_t));
1127
        mpp->dst[i].raised.next = -1;
1128
        memset(&mpp->dst[i].servicing, 0, sizeof(IRQ_queue_t));
1129
        mpp->dst[i].servicing.next = -1;
1130
    }
1131
    /* Initialise timers */
1132
    for (i = 0; i < MAX_TMR; i++) {
1133
        mpp->timers[i].ticc = 0x00000000;
1134
        mpp->timers[i].tibc = 0x80000000;
1135
    }
1136
    /* Go out of RESET state */
1137
    mpp->glbc = 0x00000000;
1138
}
1139

    
1140
static void mpic_timer_write (void *opaque, hwaddr addr, uint32_t val)
1141
{
1142
    openpic_t *mpp = opaque;
1143
    int idx, cpu;
1144

    
1145
    DPRINTF("%s: addr " TARGET_FMT_plx " <= %08x\n", __func__, addr, val);
1146
    if (addr & 0xF)
1147
        return;
1148
    addr &= 0xFFFF;
1149
    cpu = addr >> 12;
1150
    idx = (addr >> 6) & 0x3;
1151
    switch (addr & 0x30) {
1152
    case 0x00: /* gtccr */
1153
        break;
1154
    case 0x10: /* gtbcr */
1155
        if ((mpp->timers[idx].ticc & 0x80000000) != 0 &&
1156
            (val & 0x80000000) == 0 &&
1157
            (mpp->timers[idx].tibc & 0x80000000) != 0)
1158
            mpp->timers[idx].ticc &= ~0x80000000;
1159
        mpp->timers[idx].tibc = val;
1160
        break;
1161
    case 0x20: /* GTIVPR */
1162
        write_IRQreg_ipvp(mpp, MPIC_TMR_IRQ + idx, val);
1163
        break;
1164
    case 0x30: /* GTIDR & TFRR */
1165
        if ((addr & 0xF0) == 0xF0)
1166
            mpp->dst[cpu].tfrr = val;
1167
        else
1168
            write_IRQreg_ide(mpp, MPIC_TMR_IRQ + idx, val);
1169
        break;
1170
    }
1171
}
1172

    
1173
static uint32_t mpic_timer_read (void *opaque, hwaddr addr)
1174
{
1175
    openpic_t *mpp = opaque;
1176
    uint32_t retval;
1177
    int idx, cpu;
1178

    
1179
    DPRINTF("%s: addr " TARGET_FMT_plx "\n", __func__, addr);
1180
    retval = 0xFFFFFFFF;
1181
    if (addr & 0xF)
1182
        return retval;
1183
    addr &= 0xFFFF;
1184
    cpu = addr >> 12;
1185
    idx = (addr >> 6) & 0x3;
1186
    switch (addr & 0x30) {
1187
    case 0x00: /* gtccr */
1188
        retval = mpp->timers[idx].ticc;
1189
        break;
1190
    case 0x10: /* gtbcr */
1191
        retval = mpp->timers[idx].tibc;
1192
        break;
1193
    case 0x20: /* TIPV */
1194
        retval = read_IRQreg_ipvp(mpp, MPIC_TMR_IRQ + idx);
1195
        break;
1196
    case 0x30: /* TIDR */
1197
        if ((addr &0xF0) == 0XF0)
1198
            retval = mpp->dst[cpu].tfrr;
1199
        else
1200
            retval = read_IRQreg_ide(mpp, MPIC_TMR_IRQ + idx);
1201
        break;
1202
    }
1203
    DPRINTF("%s: => %08x\n", __func__, retval);
1204

    
1205
    return retval;
1206
}
1207

    
1208
static void mpic_src_ext_write (void *opaque, hwaddr addr,
1209
                                uint32_t val)
1210
{
1211
    openpic_t *mpp = opaque;
1212
    int idx = MPIC_EXT_IRQ;
1213

    
1214
    DPRINTF("%s: addr " TARGET_FMT_plx " <= %08x\n", __func__, addr, val);
1215
    if (addr & 0xF)
1216
        return;
1217

    
1218
    if (addr < MPIC_EXT_REG_SIZE) {
1219
        idx += (addr & 0xFFF0) >> 5;
1220
        if (addr & 0x10) {
1221
            /* EXDE / IFEDE / IEEDE */
1222
            write_IRQreg_ide(mpp, idx, val);
1223
        } else {
1224
            /* EXVP / IFEVP / IEEVP */
1225
            write_IRQreg_ipvp(mpp, idx, val);
1226
        }
1227
    }
1228
}
1229

    
1230
static uint32_t mpic_src_ext_read (void *opaque, hwaddr addr)
1231
{
1232
    openpic_t *mpp = opaque;
1233
    uint32_t retval;
1234
    int idx = MPIC_EXT_IRQ;
1235

    
1236
    DPRINTF("%s: addr " TARGET_FMT_plx "\n", __func__, addr);
1237
    retval = 0xFFFFFFFF;
1238
    if (addr & 0xF)
1239
        return retval;
1240

    
1241
    if (addr < MPIC_EXT_REG_SIZE) {
1242
        idx += (addr & 0xFFF0) >> 5;
1243
        if (addr & 0x10) {
1244
            /* EXDE / IFEDE / IEEDE */
1245
            retval = read_IRQreg_ide(mpp, idx);
1246
        } else {
1247
            /* EXVP / IFEVP / IEEVP */
1248
            retval = read_IRQreg_ipvp(mpp, idx);
1249
        }
1250
        DPRINTF("%s: => %08x\n", __func__, retval);
1251
    }
1252

    
1253
    return retval;
1254
}
1255

    
1256
static void mpic_src_int_write (void *opaque, hwaddr addr,
1257
                                uint32_t val)
1258
{
1259
    openpic_t *mpp = opaque;
1260
    int idx = MPIC_INT_IRQ;
1261

    
1262
    DPRINTF("%s: addr " TARGET_FMT_plx " <= %08x\n", __func__, addr, val);
1263
    if (addr & 0xF)
1264
        return;
1265

    
1266
    if (addr < MPIC_INT_REG_SIZE) {
1267
        idx += (addr & 0xFFF0) >> 5;
1268
        if (addr & 0x10) {
1269
            /* EXDE / IFEDE / IEEDE */
1270
            write_IRQreg_ide(mpp, idx, val);
1271
        } else {
1272
            /* EXVP / IFEVP / IEEVP */
1273
            write_IRQreg_ipvp(mpp, idx, val);
1274
        }
1275
    }
1276
}
1277

    
1278
static uint32_t mpic_src_int_read (void *opaque, hwaddr addr)
1279
{
1280
    openpic_t *mpp = opaque;
1281
    uint32_t retval;
1282
    int idx = MPIC_INT_IRQ;
1283

    
1284
    DPRINTF("%s: addr " TARGET_FMT_plx "\n", __func__, addr);
1285
    retval = 0xFFFFFFFF;
1286
    if (addr & 0xF)
1287
        return retval;
1288

    
1289
    if (addr < MPIC_INT_REG_SIZE) {
1290
        idx += (addr & 0xFFF0) >> 5;
1291
        if (addr & 0x10) {
1292
            /* EXDE / IFEDE / IEEDE */
1293
            retval = read_IRQreg_ide(mpp, idx);
1294
        } else {
1295
            /* EXVP / IFEVP / IEEVP */
1296
            retval = read_IRQreg_ipvp(mpp, idx);
1297
        }
1298
        DPRINTF("%s: => %08x\n", __func__, retval);
1299
    }
1300

    
1301
    return retval;
1302
}
1303

    
1304
static void mpic_src_msg_write (void *opaque, hwaddr addr,
1305
                                uint32_t val)
1306
{
1307
    openpic_t *mpp = opaque;
1308
    int idx = MPIC_MSG_IRQ;
1309

    
1310
    DPRINTF("%s: addr " TARGET_FMT_plx " <= %08x\n", __func__, addr, val);
1311
    if (addr & 0xF)
1312
        return;
1313

    
1314
    if (addr < MPIC_MSG_REG_SIZE) {
1315
        idx += (addr & 0xFFF0) >> 5;
1316
        if (addr & 0x10) {
1317
            /* EXDE / IFEDE / IEEDE */
1318
            write_IRQreg_ide(mpp, idx, val);
1319
        } else {
1320
            /* EXVP / IFEVP / IEEVP */
1321
            write_IRQreg_ipvp(mpp, idx, val);
1322
        }
1323
    }
1324
}
1325

    
1326
static uint32_t mpic_src_msg_read (void *opaque, hwaddr addr)
1327
{
1328
    openpic_t *mpp = opaque;
1329
    uint32_t retval;
1330
    int idx = MPIC_MSG_IRQ;
1331

    
1332
    DPRINTF("%s: addr " TARGET_FMT_plx "\n", __func__, addr);
1333
    retval = 0xFFFFFFFF;
1334
    if (addr & 0xF)
1335
        return retval;
1336

    
1337
    if (addr < MPIC_MSG_REG_SIZE) {
1338
        idx += (addr & 0xFFF0) >> 5;
1339
        if (addr & 0x10) {
1340
            /* EXDE / IFEDE / IEEDE */
1341
            retval = read_IRQreg_ide(mpp, idx);
1342
        } else {
1343
            /* EXVP / IFEVP / IEEVP */
1344
            retval = read_IRQreg_ipvp(mpp, idx);
1345
        }
1346
        DPRINTF("%s: => %08x\n", __func__, retval);
1347
    }
1348

    
1349
    return retval;
1350
}
1351

    
1352
static void mpic_src_msi_write (void *opaque, hwaddr addr,
1353
                                uint32_t val)
1354
{
1355
    openpic_t *mpp = opaque;
1356
    int idx = MPIC_MSI_IRQ;
1357

    
1358
    DPRINTF("%s: addr " TARGET_FMT_plx " <= %08x\n", __func__, addr, val);
1359
    if (addr & 0xF)
1360
        return;
1361

    
1362
    if (addr < MPIC_MSI_REG_SIZE) {
1363
        idx += (addr & 0xFFF0) >> 5;
1364
        if (addr & 0x10) {
1365
            /* EXDE / IFEDE / IEEDE */
1366
            write_IRQreg_ide(mpp, idx, val);
1367
        } else {
1368
            /* EXVP / IFEVP / IEEVP */
1369
            write_IRQreg_ipvp(mpp, idx, val);
1370
        }
1371
    }
1372
}
1373
static uint32_t mpic_src_msi_read (void *opaque, hwaddr addr)
1374
{
1375
    openpic_t *mpp = opaque;
1376
    uint32_t retval;
1377
    int idx = MPIC_MSI_IRQ;
1378

    
1379
    DPRINTF("%s: addr " TARGET_FMT_plx "\n", __func__, addr);
1380
    retval = 0xFFFFFFFF;
1381
    if (addr & 0xF)
1382
        return retval;
1383

    
1384
    if (addr < MPIC_MSI_REG_SIZE) {
1385
        idx += (addr & 0xFFF0) >> 5;
1386
        if (addr & 0x10) {
1387
            /* EXDE / IFEDE / IEEDE */
1388
            retval = read_IRQreg_ide(mpp, idx);
1389
        } else {
1390
            /* EXVP / IFEVP / IEEVP */
1391
            retval = read_IRQreg_ipvp(mpp, idx);
1392
        }
1393
        DPRINTF("%s: => %08x\n", __func__, retval);
1394
    }
1395

    
1396
    return retval;
1397
}
1398

    
1399
static const MemoryRegionOps mpic_glb_ops = {
1400
    .old_mmio = {
1401
        .write = { openpic_buggy_write,
1402
                   openpic_buggy_write,
1403
                   openpic_gbl_write,
1404
        },
1405
        .read  = { openpic_buggy_read,
1406
                   openpic_buggy_read,
1407
                   openpic_gbl_read,
1408
        },
1409
    },
1410
    .endianness = DEVICE_BIG_ENDIAN,
1411
};
1412

    
1413
static const MemoryRegionOps mpic_tmr_ops = {
1414
    .old_mmio = {
1415
        .write = { openpic_buggy_write,
1416
                   openpic_buggy_write,
1417
                   mpic_timer_write,
1418
        },
1419
        .read  = { openpic_buggy_read,
1420
                   openpic_buggy_read,
1421
                   mpic_timer_read,
1422
        },
1423
    },
1424
    .endianness = DEVICE_BIG_ENDIAN,
1425
};
1426

    
1427
static const MemoryRegionOps mpic_cpu_ops = {
1428
    .old_mmio = {
1429
        .write = { openpic_buggy_write,
1430
                   openpic_buggy_write,
1431
                   openpic_cpu_write,
1432
        },
1433
        .read  = { openpic_buggy_read,
1434
                   openpic_buggy_read,
1435
                   openpic_cpu_read,
1436
        },
1437
    },
1438
    .endianness = DEVICE_BIG_ENDIAN,
1439
};
1440

    
1441
static const MemoryRegionOps mpic_ext_ops = {
1442
    .old_mmio = {
1443
        .write = { openpic_buggy_write,
1444
                   openpic_buggy_write,
1445
                   mpic_src_ext_write,
1446
        },
1447
        .read  = { openpic_buggy_read,
1448
                   openpic_buggy_read,
1449
                   mpic_src_ext_read,
1450
        },
1451
    },
1452
    .endianness = DEVICE_BIG_ENDIAN,
1453
};
1454

    
1455
static const MemoryRegionOps mpic_int_ops = {
1456
    .old_mmio = {
1457
        .write = { openpic_buggy_write,
1458
                   openpic_buggy_write,
1459
                   mpic_src_int_write,
1460
        },
1461
        .read  = { openpic_buggy_read,
1462
                   openpic_buggy_read,
1463
                   mpic_src_int_read,
1464
        },
1465
    },
1466
    .endianness = DEVICE_BIG_ENDIAN,
1467
};
1468

    
1469
static const MemoryRegionOps mpic_msg_ops = {
1470
    .old_mmio = {
1471
        .write = { openpic_buggy_write,
1472
                   openpic_buggy_write,
1473
                   mpic_src_msg_write,
1474
        },
1475
        .read  = { openpic_buggy_read,
1476
                   openpic_buggy_read,
1477
                   mpic_src_msg_read,
1478
        },
1479
    },
1480
    .endianness = DEVICE_BIG_ENDIAN,
1481
};
1482

    
1483
static const MemoryRegionOps mpic_msi_ops = {
1484
    .old_mmio = {
1485
        .write = { openpic_buggy_write,
1486
                   openpic_buggy_write,
1487
                   mpic_src_msi_write,
1488
        },
1489
        .read  = { openpic_buggy_read,
1490
                   openpic_buggy_read,
1491
                   mpic_src_msi_read,
1492
        },
1493
    },
1494
    .endianness = DEVICE_BIG_ENDIAN,
1495
};
1496

    
1497
qemu_irq *mpic_init (MemoryRegion *address_space, hwaddr base,
1498
                     int nb_cpus, qemu_irq **irqs, qemu_irq irq_out)
1499
{
1500
    openpic_t    *mpp;
1501
    int           i;
1502
    struct {
1503
        const char             *name;
1504
        MemoryRegionOps const  *ops;
1505
        hwaddr      start_addr;
1506
        ram_addr_t              size;
1507
    } const list[] = {
1508
        {"glb", &mpic_glb_ops, MPIC_GLB_REG_START, MPIC_GLB_REG_SIZE},
1509
        {"tmr", &mpic_tmr_ops, MPIC_TMR_REG_START, MPIC_TMR_REG_SIZE},
1510
        {"ext", &mpic_ext_ops, MPIC_EXT_REG_START, MPIC_EXT_REG_SIZE},
1511
        {"int", &mpic_int_ops, MPIC_INT_REG_START, MPIC_INT_REG_SIZE},
1512
        {"msg", &mpic_msg_ops, MPIC_MSG_REG_START, MPIC_MSG_REG_SIZE},
1513
        {"msi", &mpic_msi_ops, MPIC_MSI_REG_START, MPIC_MSI_REG_SIZE},
1514
        {"cpu", &mpic_cpu_ops, MPIC_CPU_REG_START, MPIC_CPU_REG_SIZE},
1515
    };
1516

    
1517
    mpp = g_malloc0(sizeof(openpic_t));
1518

    
1519
    memory_region_init(&mpp->mem, "mpic", 0x40000);
1520
    memory_region_add_subregion(address_space, base, &mpp->mem);
1521

    
1522
    for (i = 0; i < sizeof(list)/sizeof(list[0]); i++) {
1523

    
1524
        memory_region_init_io(&mpp->sub_io_mem[i], list[i].ops, mpp,
1525
                              list[i].name, list[i].size);
1526

    
1527
        memory_region_add_subregion(&mpp->mem, list[i].start_addr,
1528
                                    &mpp->sub_io_mem[i]);
1529
    }
1530

    
1531
    mpp->nb_cpus = nb_cpus;
1532
    mpp->max_irq = MPIC_MAX_IRQ;
1533
    mpp->irq_ipi0 = MPIC_IPI_IRQ;
1534
    mpp->irq_tim0 = MPIC_TMR_IRQ;
1535

    
1536
    for (i = 0; i < nb_cpus; i++)
1537
        mpp->dst[i].irqs = irqs[i];
1538
    mpp->irq_out = irq_out;
1539

    
1540
    mpp->irq_raise = mpic_irq_raise;
1541
    mpp->reset = mpic_reset;
1542

    
1543
    register_savevm(NULL, "mpic", 0, 2, openpic_save, openpic_load, mpp);
1544
    qemu_register_reset(mpic_reset, mpp);
1545

    
1546
    return qemu_allocate_irqs(openpic_set_irq, mpp, mpp->max_irq);
1547
}