Statistics
| Branch: | Revision:

root / hw / openpic.c @ 3204db98

History | View | Annotate | Download (48.1 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 USE_MPCxxx /* Intel model is broken, for now */
50

    
51
#if defined (USE_INTEL_GW80314)
52
/* Intel GW80314 I/O Companion chip */
53

    
54
#define MAX_CPU     4
55
#define MAX_IRQ    32
56
#define MAX_DBL     4
57
#define MAX_MBX     4
58
#define MAX_TMR     4
59
#define VECTOR_BITS 8
60
#define MAX_IPI     4
61

    
62
#define VID (0x00000000)
63

    
64
#elif defined(USE_MPCxxx)
65

    
66
#define MAX_CPU    15
67
#define MAX_IRQ   128
68
#define MAX_DBL     0
69
#define MAX_MBX     0
70
#define MAX_TMR     4
71
#define VECTOR_BITS 8
72
#define MAX_IPI     4
73
#define VID         0x03 /* MPIC version ID */
74
#define VENI        0x00000000 /* Vendor ID */
75

    
76
enum {
77
    IRQ_IPVP = 0,
78
    IRQ_IDE,
79
};
80

    
81
/* OpenPIC */
82
#define OPENPIC_MAX_CPU      2
83
#define OPENPIC_MAX_IRQ     64
84
#define OPENPIC_EXT_IRQ     48
85
#define OPENPIC_MAX_TMR      MAX_TMR
86
#define OPENPIC_MAX_IPI      MAX_IPI
87

    
88
/* Interrupt definitions */
89
#define OPENPIC_IRQ_FE     (OPENPIC_EXT_IRQ)     /* Internal functional IRQ */
90
#define OPENPIC_IRQ_ERR    (OPENPIC_EXT_IRQ + 1) /* Error IRQ */
91
#define OPENPIC_IRQ_TIM0   (OPENPIC_EXT_IRQ + 2) /* First timer IRQ */
92
#if OPENPIC_MAX_IPI > 0
93
#define OPENPIC_IRQ_IPI0   (OPENPIC_IRQ_TIM0 + OPENPIC_MAX_TMR) /* First IPI IRQ */
94
#define OPENPIC_IRQ_DBL0   (OPENPIC_IRQ_IPI0 + (OPENPIC_MAX_CPU * OPENPIC_MAX_IPI)) /* First doorbell IRQ */
95
#else
96
#define OPENPIC_IRQ_DBL0   (OPENPIC_IRQ_TIM0 + OPENPIC_MAX_TMR) /* First doorbell IRQ */
97
#define OPENPIC_IRQ_MBX0   (OPENPIC_IRQ_DBL0 + OPENPIC_MAX_DBL) /* First mailbox IRQ */
98
#endif
99

    
100
/* MPIC */
101
#define MPIC_MAX_CPU      1
102
#define MPIC_MAX_EXT     12
103
#define MPIC_MAX_INT     64
104
#define MPIC_MAX_MSG      4
105
#define MPIC_MAX_MSI      8
106
#define MPIC_MAX_TMR      MAX_TMR
107
#define MPIC_MAX_IPI      MAX_IPI
108
#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))
109

    
110
/* Interrupt definitions */
111
#define MPIC_EXT_IRQ      0
112
#define MPIC_INT_IRQ      (MPIC_EXT_IRQ + MPIC_MAX_EXT)
113
#define MPIC_TMR_IRQ      (MPIC_INT_IRQ + MPIC_MAX_INT)
114
#define MPIC_MSG_IRQ      (MPIC_TMR_IRQ + MPIC_MAX_TMR)
115
#define MPIC_MSI_IRQ      (MPIC_MSG_IRQ + MPIC_MAX_MSG)
116
#define MPIC_IPI_IRQ      (MPIC_MSI_IRQ + MPIC_MAX_MSI)
117

    
118
#define MPIC_GLB_REG_START        0x0
119
#define MPIC_GLB_REG_SIZE         0x10F0
120
#define MPIC_TMR_REG_START        0x10F0
121
#define MPIC_TMR_REG_SIZE         0x220
122
#define MPIC_EXT_REG_START        0x10000
123
#define MPIC_EXT_REG_SIZE         0x180
124
#define MPIC_INT_REG_START        0x10200
125
#define MPIC_INT_REG_SIZE         0x800
126
#define MPIC_MSG_REG_START        0x11600
127
#define MPIC_MSG_REG_SIZE         0x100
128
#define MPIC_MSI_REG_START        0x11C00
129
#define MPIC_MSI_REG_SIZE         0x100
130
#define MPIC_CPU_REG_START        0x20000
131
#define MPIC_CPU_REG_SIZE         0x100 + ((MAX_CPU - 1) * 0x1000)
132

    
133
enum mpic_ide_bits {
134
    IDR_EP     = 31,
135
    IDR_CI0     = 30,
136
    IDR_CI1     = 29,
137
    IDR_P1     = 1,
138
    IDR_P0     = 0,
139
};
140

    
141
#else
142
#error "Please select which OpenPic implementation is to be emulated"
143
#endif
144

    
145
#define OPENPIC_PAGE_SIZE 4096
146

    
147
#define BF_WIDTH(_bits_) \
148
(((_bits_) + (sizeof(uint32_t) * 8) - 1) / (sizeof(uint32_t) * 8))
149

    
150
static inline void set_bit (uint32_t *field, int bit)
151
{
152
    field[bit >> 5] |= 1 << (bit & 0x1F);
153
}
154

    
155
static inline void reset_bit (uint32_t *field, int bit)
156
{
157
    field[bit >> 5] &= ~(1 << (bit & 0x1F));
158
}
159

    
160
static inline int test_bit (uint32_t *field, int bit)
161
{
162
    return (field[bit >> 5] & 1 << (bit & 0x1F)) != 0;
163
}
164

    
165
static int get_current_cpu(void)
166
{
167
  return cpu_single_env->cpu_index;
168
}
169

    
170
static uint32_t openpic_cpu_read_internal(void *opaque, target_phys_addr_t addr,
171
                                          int idx);
172
static void openpic_cpu_write_internal(void *opaque, target_phys_addr_t addr,
173
                                       uint32_t val, int idx);
174

    
175
enum {
176
    IRQ_EXTERNAL = 0x01,
177
    IRQ_INTERNAL = 0x02,
178
    IRQ_TIMER    = 0x04,
179
    IRQ_SPECIAL  = 0x08,
180
};
181

    
182
typedef struct IRQ_queue_t {
183
    uint32_t queue[BF_WIDTH(MAX_IRQ)];
184
    int next;
185
    int priority;
186
} IRQ_queue_t;
187

    
188
typedef struct IRQ_src_t {
189
    uint32_t ipvp;  /* IRQ vector/priority register */
190
    uint32_t ide;   /* IRQ destination register */
191
    int type;
192
    int last_cpu;
193
    int pending;    /* TRUE if IRQ is pending */
194
} IRQ_src_t;
195

    
196
enum IPVP_bits {
197
    IPVP_MASK     = 31,
198
    IPVP_ACTIVITY = 30,
199
    IPVP_MODE     = 29,
200
    IPVP_POLARITY = 23,
201
    IPVP_SENSE    = 22,
202
};
203
#define IPVP_PRIORITY_MASK     (0x1F << 16)
204
#define IPVP_PRIORITY(_ipvpr_) ((int)(((_ipvpr_) & IPVP_PRIORITY_MASK) >> 16))
205
#define IPVP_VECTOR_MASK       ((1 << VECTOR_BITS) - 1)
206
#define IPVP_VECTOR(_ipvpr_)   ((_ipvpr_) & IPVP_VECTOR_MASK)
207

    
208
typedef struct IRQ_dst_t {
209
    uint32_t tfrr;
210
    uint32_t pctp; /* CPU current task priority */
211
    uint32_t pcsr; /* CPU sensitivity register */
212
    IRQ_queue_t raised;
213
    IRQ_queue_t servicing;
214
    qemu_irq *irqs;
215
} IRQ_dst_t;
216

    
217
typedef struct openpic_t {
218
    PCIDevice pci_dev;
219
    MemoryRegion mem;
220

    
221
    /* Sub-regions */
222
    MemoryRegion sub_io_mem[7];
223

    
224
    /* Global registers */
225
    uint32_t frep; /* Feature reporting register */
226
    uint32_t glbc; /* Global configuration register  */
227
    uint32_t micr; /* MPIC interrupt configuration register */
228
    uint32_t veni; /* Vendor identification register */
229
    uint32_t pint; /* Processor initialization register */
230
    uint32_t spve; /* Spurious vector register */
231
    uint32_t tifr; /* Timer frequency reporting register */
232
    /* Source registers */
233
    IRQ_src_t src[MAX_IRQ];
234
    /* Local registers per output pin */
235
    IRQ_dst_t dst[MAX_CPU];
236
    int nb_cpus;
237
    /* Timer registers */
238
    struct {
239
        uint32_t ticc;  /* Global timer current count register */
240
        uint32_t tibc;  /* Global timer base count register */
241
    } timers[MAX_TMR];
242
#if MAX_DBL > 0
243
    /* Doorbell registers */
244
    uint32_t dar;        /* Doorbell activate register */
245
    struct {
246
        uint32_t dmr;    /* Doorbell messaging register */
247
    } doorbells[MAX_DBL];
248
#endif
249
#if MAX_MBX > 0
250
    /* Mailbox registers */
251
    struct {
252
        uint32_t mbr;    /* Mailbox register */
253
    } mailboxes[MAX_MAILBOXES];
254
#endif
255
    /* IRQ out is used when in bypass mode (not implemented) */
256
    qemu_irq irq_out;
257
    int max_irq;
258
    int irq_ipi0;
259
    int irq_tim0;
260
    void (*reset) (void *);
261
    void (*irq_raise) (struct openpic_t *, int, IRQ_src_t *);
262
} openpic_t;
263

    
264
static inline void IRQ_setbit (IRQ_queue_t *q, int n_IRQ)
265
{
266
    set_bit(q->queue, n_IRQ);
267
}
268

    
269
static inline void IRQ_resetbit (IRQ_queue_t *q, int n_IRQ)
270
{
271
    reset_bit(q->queue, n_IRQ);
272
}
273

    
274
static inline int IRQ_testbit (IRQ_queue_t *q, int n_IRQ)
275
{
276
    return test_bit(q->queue, n_IRQ);
277
}
278

    
279
static void IRQ_check (openpic_t *opp, IRQ_queue_t *q)
280
{
281
    int next, i;
282
    int priority;
283

    
284
    next = -1;
285
    priority = -1;
286
    for (i = 0; i < opp->max_irq; i++) {
287
        if (IRQ_testbit(q, i)) {
288
            DPRINTF("IRQ_check: irq %d set ipvp_pr=%d pr=%d\n",
289
                    i, IPVP_PRIORITY(opp->src[i].ipvp), priority);
290
            if (IPVP_PRIORITY(opp->src[i].ipvp) > priority) {
291
                next = i;
292
                priority = IPVP_PRIORITY(opp->src[i].ipvp);
293
            }
294
        }
295
    }
296
    q->next = next;
297
    q->priority = priority;
298
}
299

    
300
static int IRQ_get_next (openpic_t *opp, IRQ_queue_t *q)
301
{
302
    if (q->next == -1) {
303
        /* XXX: optimize */
304
        IRQ_check(opp, q);
305
    }
306

    
307
    return q->next;
308
}
309

    
310
static void IRQ_local_pipe (openpic_t *opp, int n_CPU, int n_IRQ)
311
{
312
    IRQ_dst_t *dst;
313
    IRQ_src_t *src;
314
    int priority;
315

    
316
    dst = &opp->dst[n_CPU];
317
    src = &opp->src[n_IRQ];
318
    priority = IPVP_PRIORITY(src->ipvp);
319
    if (priority <= dst->pctp) {
320
        /* Too low priority */
321
        DPRINTF("%s: IRQ %d has too low priority on CPU %d\n",
322
                __func__, n_IRQ, n_CPU);
323
        return;
324
    }
325
    if (IRQ_testbit(&dst->raised, n_IRQ)) {
326
        /* Interrupt miss */
327
        DPRINTF("%s: IRQ %d was missed on CPU %d\n",
328
                __func__, n_IRQ, n_CPU);
329
        return;
330
    }
331
    set_bit(&src->ipvp, IPVP_ACTIVITY);
332
    IRQ_setbit(&dst->raised, n_IRQ);
333
    if (priority < dst->raised.priority) {
334
        /* An higher priority IRQ is already raised */
335
        DPRINTF("%s: IRQ %d is hidden by raised IRQ %d on CPU %d\n",
336
                __func__, n_IRQ, dst->raised.next, n_CPU);
337
        return;
338
    }
339
    IRQ_get_next(opp, &dst->raised);
340
    if (IRQ_get_next(opp, &dst->servicing) != -1 &&
341
        priority <= dst->servicing.priority) {
342
        DPRINTF("%s: IRQ %d is hidden by servicing IRQ %d on CPU %d\n",
343
                __func__, n_IRQ, dst->servicing.next, n_CPU);
344
        /* Already servicing a higher priority IRQ */
345
        return;
346
    }
347
    DPRINTF("Raise OpenPIC INT output cpu %d irq %d\n", n_CPU, n_IRQ);
348
    opp->irq_raise(opp, n_CPU, src);
349
}
350

    
351
/* update pic state because registers for n_IRQ have changed value */
352
static void openpic_update_irq(openpic_t *opp, int n_IRQ)
353
{
354
    IRQ_src_t *src;
355
    int i;
356

    
357
    src = &opp->src[n_IRQ];
358

    
359
    if (!src->pending) {
360
        /* no irq pending */
361
        DPRINTF("%s: IRQ %d is not pending\n", __func__, n_IRQ);
362
        return;
363
    }
364
    if (test_bit(&src->ipvp, IPVP_MASK)) {
365
        /* Interrupt source is disabled */
366
        DPRINTF("%s: IRQ %d is disabled\n", __func__, n_IRQ);
367
        return;
368
    }
369
    if (IPVP_PRIORITY(src->ipvp) == 0) {
370
        /* Priority set to zero */
371
        DPRINTF("%s: IRQ %d has 0 priority\n", __func__, n_IRQ);
372
        return;
373
    }
374
    if (test_bit(&src->ipvp, IPVP_ACTIVITY)) {
375
        /* IRQ already active */
376
        DPRINTF("%s: IRQ %d is already active\n", __func__, n_IRQ);
377
        return;
378
    }
379
    if (src->ide == 0x00000000) {
380
        /* No target */
381
        DPRINTF("%s: IRQ %d has no target\n", __func__, n_IRQ);
382
        return;
383
    }
384

    
385
    if (src->ide == (1 << src->last_cpu)) {
386
        /* Only one CPU is allowed to receive this IRQ */
387
        IRQ_local_pipe(opp, src->last_cpu, n_IRQ);
388
    } else if (!test_bit(&src->ipvp, IPVP_MODE)) {
389
        /* Directed delivery mode */
390
        for (i = 0; i < opp->nb_cpus; i++) {
391
            if (test_bit(&src->ide, i))
392
                IRQ_local_pipe(opp, i, n_IRQ);
393
        }
394
    } else {
395
        /* Distributed delivery mode */
396
        for (i = src->last_cpu + 1; i != src->last_cpu; i++) {
397
            if (i == opp->nb_cpus)
398
                i = 0;
399
            if (test_bit(&src->ide, i)) {
400
                IRQ_local_pipe(opp, i, n_IRQ);
401
                src->last_cpu = i;
402
                break;
403
            }
404
        }
405
    }
406
}
407

    
408
static void openpic_set_irq(void *opaque, int n_IRQ, int level)
409
{
410
    openpic_t *opp = opaque;
411
    IRQ_src_t *src;
412

    
413
    src = &opp->src[n_IRQ];
414
    DPRINTF("openpic: set irq %d = %d ipvp=%08x\n",
415
            n_IRQ, level, src->ipvp);
416
    if (test_bit(&src->ipvp, IPVP_SENSE)) {
417
        /* level-sensitive irq */
418
        src->pending = level;
419
        if (!level)
420
            reset_bit(&src->ipvp, IPVP_ACTIVITY);
421
    } else {
422
        /* edge-sensitive irq */
423
        if (level)
424
            src->pending = 1;
425
    }
426
    openpic_update_irq(opp, n_IRQ);
427
}
428

    
429
static void openpic_reset (void *opaque)
430
{
431
    openpic_t *opp = (openpic_t *)opaque;
432
    int i;
433

    
434
    opp->glbc = 0x80000000;
435
    /* Initialise controller registers */
436
    opp->frep = ((OPENPIC_EXT_IRQ - 1) << 16) | ((MAX_CPU - 1) << 8) | VID;
437
    opp->veni = VENI;
438
    opp->pint = 0x00000000;
439
    opp->spve = 0x000000FF;
440
    opp->tifr = 0x003F7A00;
441
    /* ? */
442
    opp->micr = 0x00000000;
443
    /* Initialise IRQ sources */
444
    for (i = 0; i < opp->max_irq; i++) {
445
        opp->src[i].ipvp = 0xA0000000;
446
        opp->src[i].ide  = 0x00000000;
447
    }
448
    /* Initialise IRQ destinations */
449
    for (i = 0; i < MAX_CPU; i++) {
450
        opp->dst[i].pctp      = 0x0000000F;
451
        opp->dst[i].pcsr      = 0x00000000;
452
        memset(&opp->dst[i].raised, 0, sizeof(IRQ_queue_t));
453
        opp->dst[i].raised.next = -1;
454
        memset(&opp->dst[i].servicing, 0, sizeof(IRQ_queue_t));
455
        opp->dst[i].servicing.next = -1;
456
    }
457
    /* Initialise timers */
458
    for (i = 0; i < MAX_TMR; i++) {
459
        opp->timers[i].ticc = 0x00000000;
460
        opp->timers[i].tibc = 0x80000000;
461
    }
462
    /* Initialise doorbells */
463
#if MAX_DBL > 0
464
    opp->dar = 0x00000000;
465
    for (i = 0; i < MAX_DBL; i++) {
466
        opp->doorbells[i].dmr  = 0x00000000;
467
    }
468
#endif
469
    /* Initialise mailboxes */
470
#if MAX_MBX > 0
471
    for (i = 0; i < MAX_MBX; i++) { /* ? */
472
        opp->mailboxes[i].mbr   = 0x00000000;
473
    }
474
#endif
475
    /* Go out of RESET state */
476
    opp->glbc = 0x00000000;
477
}
478

    
479
static inline uint32_t read_IRQreg_ide(openpic_t *opp, int n_IRQ)
480
{
481
    return opp->src[n_IRQ].ide;
482
}
483

    
484
static inline uint32_t read_IRQreg_ipvp(openpic_t *opp, int n_IRQ)
485
{
486
    return opp->src[n_IRQ].ipvp;
487
}
488

    
489
static inline void write_IRQreg_ide(openpic_t *opp, int n_IRQ, uint32_t val)
490
{
491
    uint32_t tmp;
492

    
493
    tmp = val & 0xC0000000;
494
    tmp |= val & ((1ULL << MAX_CPU) - 1);
495
    opp->src[n_IRQ].ide = tmp;
496
    DPRINTF("Set IDE %d to 0x%08x\n", n_IRQ, opp->src[n_IRQ].ide);
497
}
498

    
499
static inline void write_IRQreg_ipvp(openpic_t *opp, int n_IRQ, uint32_t val)
500
{
501
    /* NOTE: not fully accurate for special IRQs, but simple and sufficient */
502
    /* ACTIVITY bit is read-only */
503
    opp->src[n_IRQ].ipvp = (opp->src[n_IRQ].ipvp & 0x40000000)
504
                         | (val & 0x800F00FF);
505
    openpic_update_irq(opp, n_IRQ);
506
    DPRINTF("Set IPVP %d to 0x%08x -> 0x%08x\n", n_IRQ, val,
507
            opp->src[n_IRQ].ipvp);
508
}
509

    
510
#if 0 // Code provision for Intel model
511
#if MAX_DBL > 0
512
static uint32_t read_doorbell_register (openpic_t *opp,
513
                                        int n_dbl, uint32_t offset)
514
{
515
    uint32_t retval;
516

517
    switch (offset) {
518
    case DBL_IPVP_OFFSET:
519
        retval = read_IRQreg_ipvp(opp, IRQ_DBL0 + n_dbl);
520
        break;
521
    case DBL_IDE_OFFSET:
522
        retval = read_IRQreg_ide(opp, IRQ_DBL0 + n_dbl);
523
        break;
524
    case DBL_DMR_OFFSET:
525
        retval = opp->doorbells[n_dbl].dmr;
526
        break;
527
    }
528

529
    return retval;
530
}
531

532
static void write_doorbell_register (penpic_t *opp, int n_dbl,
533
                                     uint32_t offset, uint32_t value)
534
{
535
    switch (offset) {
536
    case DBL_IVPR_OFFSET:
537
        write_IRQreg_ipvp(opp, IRQ_DBL0 + n_dbl, value);
538
        break;
539
    case DBL_IDE_OFFSET:
540
        write_IRQreg_ide(opp, IRQ_DBL0 + n_dbl, value);
541
        break;
542
    case DBL_DMR_OFFSET:
543
        opp->doorbells[n_dbl].dmr = value;
544
        break;
545
    }
546
}
547
#endif
548

    
549
#if MAX_MBX > 0
550
static uint32_t read_mailbox_register (openpic_t *opp,
551
                                       int n_mbx, uint32_t offset)
552
{
553
    uint32_t retval;
554

    
555
    switch (offset) {
556
    case MBX_MBR_OFFSET:
557
        retval = opp->mailboxes[n_mbx].mbr;
558
        break;
559
    case MBX_IVPR_OFFSET:
560
        retval = read_IRQreg_ipvp(opp, IRQ_MBX0 + n_mbx);
561
        break;
562
    case MBX_DMR_OFFSET:
563
        retval = read_IRQreg_ide(opp, IRQ_MBX0 + n_mbx);
564
        break;
565
    }
566

    
567
    return retval;
568
}
569

    
570
static void write_mailbox_register (openpic_t *opp, int n_mbx,
571
                                    uint32_t address, uint32_t value)
572
{
573
    switch (offset) {
574
    case MBX_MBR_OFFSET:
575
        opp->mailboxes[n_mbx].mbr = value;
576
        break;
577
    case MBX_IVPR_OFFSET:
578
        write_IRQreg_ipvp(opp, IRQ_MBX0 + n_mbx, value);
579
        break;
580
    case MBX_DMR_OFFSET:
581
        write_IRQreg_ide(opp, IRQ_MBX0 + n_mbx, value);
582
        break;
583
    }
584
}
585
#endif
586
#endif /* 0 : Code provision for Intel model */
587

    
588
static void openpic_gbl_write (void *opaque, target_phys_addr_t addr, uint32_t val)
589
{
590
    openpic_t *opp = opaque;
591
    IRQ_dst_t *dst;
592
    int idx;
593

    
594
    DPRINTF("%s: addr " TARGET_FMT_plx " <= %08x\n", __func__, addr, val);
595
    if (addr & 0xF)
596
        return;
597
    switch (addr) {
598
    case 0x40:
599
    case 0x50:
600
    case 0x60:
601
    case 0x70:
602
    case 0x80:
603
    case 0x90:
604
    case 0xA0:
605
    case 0xB0:
606
        openpic_cpu_write_internal(opp, addr, val, get_current_cpu());
607
        break;
608
    case 0x1000: /* FREP */
609
        break;
610
    case 0x1020: /* GLBC */
611
        if (val & 0x80000000 && opp->reset)
612
            opp->reset(opp);
613
        opp->glbc = val & ~0x80000000;
614
        break;
615
    case 0x1080: /* VENI */
616
        break;
617
    case 0x1090: /* PINT */
618
        for (idx = 0; idx < opp->nb_cpus; idx++) {
619
            if ((val & (1 << idx)) && !(opp->pint & (1 << idx))) {
620
                DPRINTF("Raise OpenPIC RESET output for CPU %d\n", idx);
621
                dst = &opp->dst[idx];
622
                qemu_irq_raise(dst->irqs[OPENPIC_OUTPUT_RESET]);
623
            } else if (!(val & (1 << idx)) && (opp->pint & (1 << idx))) {
624
                DPRINTF("Lower OpenPIC RESET output for CPU %d\n", idx);
625
                dst = &opp->dst[idx];
626
                qemu_irq_lower(dst->irqs[OPENPIC_OUTPUT_RESET]);
627
            }
628
        }
629
        opp->pint = val;
630
        break;
631
    case 0x10A0: /* IPI_IPVP */
632
    case 0x10B0:
633
    case 0x10C0:
634
    case 0x10D0:
635
        {
636
            int idx;
637
            idx = (addr - 0x10A0) >> 4;
638
            write_IRQreg_ipvp(opp, opp->irq_ipi0 + idx, val);
639
        }
640
        break;
641
    case 0x10E0: /* SPVE */
642
        opp->spve = val & 0x000000FF;
643
        break;
644
    case 0x10F0: /* TIFR */
645
        opp->tifr = val;
646
        break;
647
    default:
648
        break;
649
    }
650
}
651

    
652
static uint32_t openpic_gbl_read (void *opaque, target_phys_addr_t addr)
653
{
654
    openpic_t *opp = opaque;
655
    uint32_t retval;
656

    
657
    DPRINTF("%s: addr " TARGET_FMT_plx "\n", __func__, addr);
658
    retval = 0xFFFFFFFF;
659
    if (addr & 0xF)
660
        return retval;
661
    switch (addr) {
662
    case 0x1000: /* FREP */
663
        retval = opp->frep;
664
        break;
665
    case 0x1020: /* GLBC */
666
        retval = opp->glbc;
667
        break;
668
    case 0x1080: /* VENI */
669
        retval = opp->veni;
670
        break;
671
    case 0x1090: /* PINT */
672
        retval = 0x00000000;
673
        break;
674
    case 0x40:
675
    case 0x50:
676
    case 0x60:
677
    case 0x70:
678
    case 0x80:
679
    case 0x90:
680
    case 0xA0:
681
    case 0xB0:
682
        retval = openpic_cpu_read_internal(opp, addr, get_current_cpu());
683
        break;
684
    case 0x10A0: /* IPI_IPVP */
685
    case 0x10B0:
686
    case 0x10C0:
687
    case 0x10D0:
688
        {
689
            int idx;
690
            idx = (addr - 0x10A0) >> 4;
691
            retval = read_IRQreg_ipvp(opp, opp->irq_ipi0 + idx);
692
        }
693
        break;
694
    case 0x10E0: /* SPVE */
695
        retval = opp->spve;
696
        break;
697
    case 0x10F0: /* TIFR */
698
        retval = opp->tifr;
699
        break;
700
    default:
701
        break;
702
    }
703
    DPRINTF("%s: => %08x\n", __func__, retval);
704

    
705
    return retval;
706
}
707

    
708
static void openpic_timer_write (void *opaque, uint32_t addr, uint32_t val)
709
{
710
    openpic_t *opp = opaque;
711
    int idx;
712

    
713
    DPRINTF("%s: addr %08x <= %08x\n", __func__, addr, val);
714
    if (addr & 0xF)
715
        return;
716
    addr -= 0x1100;
717
    addr &= 0xFFFF;
718
    idx = (addr & 0xFFF0) >> 6;
719
    addr = addr & 0x30;
720
    switch (addr) {
721
    case 0x00: /* TICC */
722
        break;
723
    case 0x10: /* TIBC */
724
        if ((opp->timers[idx].ticc & 0x80000000) != 0 &&
725
            (val & 0x80000000) == 0 &&
726
            (opp->timers[idx].tibc & 0x80000000) != 0)
727
            opp->timers[idx].ticc &= ~0x80000000;
728
        opp->timers[idx].tibc = val;
729
        break;
730
    case 0x20: /* TIVP */
731
        write_IRQreg_ipvp(opp, opp->irq_tim0 + idx, val);
732
        break;
733
    case 0x30: /* TIDE */
734
        write_IRQreg_ide(opp, opp->irq_tim0 + idx, val);
735
        break;
736
    }
737
}
738

    
739
static uint32_t openpic_timer_read (void *opaque, uint32_t addr)
740
{
741
    openpic_t *opp = opaque;
742
    uint32_t retval;
743
    int idx;
744

    
745
    DPRINTF("%s: addr %08x\n", __func__, addr);
746
    retval = 0xFFFFFFFF;
747
    if (addr & 0xF)
748
        return retval;
749
    addr -= 0x1100;
750
    addr &= 0xFFFF;
751
    idx = (addr & 0xFFF0) >> 6;
752
    addr = addr & 0x30;
753
    switch (addr) {
754
    case 0x00: /* TICC */
755
        retval = opp->timers[idx].ticc;
756
        break;
757
    case 0x10: /* TIBC */
758
        retval = opp->timers[idx].tibc;
759
        break;
760
    case 0x20: /* TIPV */
761
        retval = read_IRQreg_ipvp(opp, opp->irq_tim0 + idx);
762
        break;
763
    case 0x30: /* TIDE */
764
        retval = read_IRQreg_ide(opp, opp->irq_tim0 + idx);
765
        break;
766
    }
767
    DPRINTF("%s: => %08x\n", __func__, retval);
768

    
769
    return retval;
770
}
771

    
772
static void openpic_src_write (void *opaque, uint32_t addr, uint32_t val)
773
{
774
    openpic_t *opp = opaque;
775
    int idx;
776

    
777
    DPRINTF("%s: addr %08x <= %08x\n", __func__, addr, val);
778
    if (addr & 0xF)
779
        return;
780
    addr = addr & 0xFFF0;
781
    idx = addr >> 5;
782
    if (addr & 0x10) {
783
        /* EXDE / IFEDE / IEEDE */
784
        write_IRQreg_ide(opp, idx, val);
785
    } else {
786
        /* EXVP / IFEVP / IEEVP */
787
        write_IRQreg_ipvp(opp, idx, val);
788
    }
789
}
790

    
791
static uint32_t openpic_src_read (void *opaque, uint32_t addr)
792
{
793
    openpic_t *opp = opaque;
794
    uint32_t retval;
795
    int idx;
796

    
797
    DPRINTF("%s: addr %08x\n", __func__, addr);
798
    retval = 0xFFFFFFFF;
799
    if (addr & 0xF)
800
        return retval;
801
    addr = addr & 0xFFF0;
802
    idx = addr >> 5;
803
    if (addr & 0x10) {
804
        /* EXDE / IFEDE / IEEDE */
805
        retval = read_IRQreg_ide(opp, idx);
806
    } else {
807
        /* EXVP / IFEVP / IEEVP */
808
        retval = read_IRQreg_ipvp(opp, idx);
809
    }
810
    DPRINTF("%s: => %08x\n", __func__, retval);
811

    
812
    return retval;
813
}
814

    
815
static void openpic_cpu_write_internal(void *opaque, target_phys_addr_t addr,
816
                                       uint32_t val, int idx)
817
{
818
    openpic_t *opp = opaque;
819
    IRQ_src_t *src;
820
    IRQ_dst_t *dst;
821
    int s_IRQ, n_IRQ;
822

    
823
    DPRINTF("%s: cpu %d addr " TARGET_FMT_plx " <= %08x\n", __func__, idx,
824
            addr, val);
825
    if (addr & 0xF)
826
        return;
827
    dst = &opp->dst[idx];
828
    addr &= 0xFF0;
829
    switch (addr) {
830
#if MAX_IPI > 0
831
    case 0x40: /* IPIDR */
832
    case 0x50:
833
    case 0x60:
834
    case 0x70:
835
        idx = (addr - 0x40) >> 4;
836
        /* we use IDE as mask which CPUs to deliver the IPI to still. */
837
        write_IRQreg_ide(opp, opp->irq_ipi0 + idx,
838
                         opp->src[opp->irq_ipi0 + idx].ide | val);
839
        openpic_set_irq(opp, opp->irq_ipi0 + idx, 1);
840
        openpic_set_irq(opp, opp->irq_ipi0 + idx, 0);
841
        break;
842
#endif
843
    case 0x80: /* PCTP */
844
        dst->pctp = val & 0x0000000F;
845
        break;
846
    case 0x90: /* WHOAMI */
847
        /* Read-only register */
848
        break;
849
    case 0xA0: /* PIAC */
850
        /* Read-only register */
851
        break;
852
    case 0xB0: /* PEOI */
853
        DPRINTF("PEOI\n");
854
        s_IRQ = IRQ_get_next(opp, &dst->servicing);
855
        IRQ_resetbit(&dst->servicing, s_IRQ);
856
        dst->servicing.next = -1;
857
        /* Set up next servicing IRQ */
858
        s_IRQ = IRQ_get_next(opp, &dst->servicing);
859
        /* Check queued interrupts. */
860
        n_IRQ = IRQ_get_next(opp, &dst->raised);
861
        src = &opp->src[n_IRQ];
862
        if (n_IRQ != -1 &&
863
            (s_IRQ == -1 ||
864
             IPVP_PRIORITY(src->ipvp) > dst->servicing.priority)) {
865
            DPRINTF("Raise OpenPIC INT output cpu %d irq %d\n",
866
                    idx, n_IRQ);
867
            opp->irq_raise(opp, idx, src);
868
        }
869
        break;
870
    default:
871
        break;
872
    }
873
}
874

    
875
static void openpic_cpu_write(void *opaque, target_phys_addr_t addr, uint32_t val)
876
{
877
    openpic_cpu_write_internal(opaque, addr, val, (addr & 0x1f000) >> 12);
878
}
879

    
880
static uint32_t openpic_cpu_read_internal(void *opaque, target_phys_addr_t addr,
881
                                          int idx)
882
{
883
    openpic_t *opp = opaque;
884
    IRQ_src_t *src;
885
    IRQ_dst_t *dst;
886
    uint32_t retval;
887
    int n_IRQ;
888

    
889
    DPRINTF("%s: cpu %d addr " TARGET_FMT_plx "\n", __func__, idx, addr);
890
    retval = 0xFFFFFFFF;
891
    if (addr & 0xF)
892
        return retval;
893
    dst = &opp->dst[idx];
894
    addr &= 0xFF0;
895
    switch (addr) {
896
    case 0x80: /* PCTP */
897
        retval = dst->pctp;
898
        break;
899
    case 0x90: /* WHOAMI */
900
        retval = idx;
901
        break;
902
    case 0xA0: /* PIAC */
903
        DPRINTF("Lower OpenPIC INT output\n");
904
        qemu_irq_lower(dst->irqs[OPENPIC_OUTPUT_INT]);
905
        n_IRQ = IRQ_get_next(opp, &dst->raised);
906
        DPRINTF("PIAC: irq=%d\n", n_IRQ);
907
        if (n_IRQ == -1) {
908
            /* No more interrupt pending */
909
            retval = IPVP_VECTOR(opp->spve);
910
        } else {
911
            src = &opp->src[n_IRQ];
912
            if (!test_bit(&src->ipvp, IPVP_ACTIVITY) ||
913
                !(IPVP_PRIORITY(src->ipvp) > dst->pctp)) {
914
                /* - Spurious level-sensitive IRQ
915
                 * - Priorities has been changed
916
                 *   and the pending IRQ isn't allowed anymore
917
                 */
918
                reset_bit(&src->ipvp, IPVP_ACTIVITY);
919
                retval = IPVP_VECTOR(opp->spve);
920
            } else {
921
                /* IRQ enter servicing state */
922
                IRQ_setbit(&dst->servicing, n_IRQ);
923
                retval = IPVP_VECTOR(src->ipvp);
924
            }
925
            IRQ_resetbit(&dst->raised, n_IRQ);
926
            dst->raised.next = -1;
927
            if (!test_bit(&src->ipvp, IPVP_SENSE)) {
928
                /* edge-sensitive IRQ */
929
                reset_bit(&src->ipvp, IPVP_ACTIVITY);
930
                src->pending = 0;
931
            }
932

    
933
            if ((n_IRQ >= opp->irq_ipi0) &&  (n_IRQ < (opp->irq_ipi0 + MAX_IPI))) {
934
                src->ide &= ~(1 << idx);
935
                if (src->ide && !test_bit(&src->ipvp, IPVP_SENSE)) {
936
                    /* trigger on CPUs that didn't know about it yet */
937
                    openpic_set_irq(opp, n_IRQ, 1);
938
                    openpic_set_irq(opp, n_IRQ, 0);
939
                    /* if all CPUs knew about it, set active bit again */
940
                    set_bit(&src->ipvp, IPVP_ACTIVITY);
941
                }
942
            }
943
        }
944
        break;
945
    case 0xB0: /* PEOI */
946
        retval = 0;
947
        break;
948
    default:
949
        break;
950
    }
951
    DPRINTF("%s: => %08x\n", __func__, retval);
952

    
953
    return retval;
954
}
955

    
956
static uint32_t openpic_cpu_read(void *opaque, target_phys_addr_t addr)
957
{
958
    return openpic_cpu_read_internal(opaque, addr, (addr & 0x1f000) >> 12);
959
}
960

    
961
static void openpic_buggy_write (void *opaque,
962
                                 target_phys_addr_t addr, uint32_t val)
963
{
964
    printf("Invalid OPENPIC write access !\n");
965
}
966

    
967
static uint32_t openpic_buggy_read (void *opaque, target_phys_addr_t addr)
968
{
969
    printf("Invalid OPENPIC read access !\n");
970

    
971
    return -1;
972
}
973

    
974
static void openpic_writel (void *opaque,
975
                            target_phys_addr_t addr, uint32_t val)
976
{
977
    openpic_t *opp = opaque;
978

    
979
    addr &= 0x3FFFF;
980
    DPRINTF("%s: offset %08x val: %08x\n", __func__, (int)addr, val);
981
    if (addr < 0x1100) {
982
        /* Global registers */
983
        openpic_gbl_write(opp, addr, val);
984
    } else if (addr < 0x10000) {
985
        /* Timers registers */
986
        openpic_timer_write(opp, addr, val);
987
    } else if (addr < 0x20000) {
988
        /* Source registers */
989
        openpic_src_write(opp, addr, val);
990
    } else {
991
        /* CPU registers */
992
        openpic_cpu_write(opp, addr, val);
993
    }
994
}
995

    
996
static uint32_t openpic_readl (void *opaque,target_phys_addr_t addr)
997
{
998
    openpic_t *opp = opaque;
999
    uint32_t retval;
1000

    
1001
    addr &= 0x3FFFF;
1002
    DPRINTF("%s: offset %08x\n", __func__, (int)addr);
1003
    if (addr < 0x1100) {
1004
        /* Global registers */
1005
        retval = openpic_gbl_read(opp, addr);
1006
    } else if (addr < 0x10000) {
1007
        /* Timers registers */
1008
        retval = openpic_timer_read(opp, addr);
1009
    } else if (addr < 0x20000) {
1010
        /* Source registers */
1011
        retval = openpic_src_read(opp, addr);
1012
    } else {
1013
        /* CPU registers */
1014
        retval = openpic_cpu_read(opp, addr);
1015
    }
1016

    
1017
    return retval;
1018
}
1019

    
1020
static uint64_t openpic_read(void *opaque, target_phys_addr_t addr,
1021
                             unsigned size)
1022
{
1023
    openpic_t *opp = opaque;
1024

    
1025
    switch (size) {
1026
    case 4: return openpic_readl(opp, addr);
1027
    default: return openpic_buggy_read(opp, addr);
1028
    }
1029
}
1030

    
1031
static void openpic_write(void *opaque, target_phys_addr_t addr,
1032
                          uint64_t data, unsigned size)
1033
{
1034
    openpic_t *opp = opaque;
1035

    
1036
    switch (size) {
1037
    case 4: return openpic_writel(opp, addr, data);
1038
    default: return openpic_buggy_write(opp, addr, data);
1039
    }
1040
}
1041

    
1042
static const MemoryRegionOps openpic_ops = {
1043
    .read = openpic_read,
1044
    .write = openpic_write,
1045
    .endianness = DEVICE_LITTLE_ENDIAN,
1046
};
1047

    
1048
static void openpic_save_IRQ_queue(QEMUFile* f, IRQ_queue_t *q)
1049
{
1050
    unsigned int i;
1051

    
1052
    for (i = 0; i < BF_WIDTH(MAX_IRQ); i++)
1053
        qemu_put_be32s(f, &q->queue[i]);
1054

    
1055
    qemu_put_sbe32s(f, &q->next);
1056
    qemu_put_sbe32s(f, &q->priority);
1057
}
1058

    
1059
static void openpic_save(QEMUFile* f, void *opaque)
1060
{
1061
    openpic_t *opp = (openpic_t *)opaque;
1062
    unsigned int i;
1063

    
1064
    qemu_put_be32s(f, &opp->frep);
1065
    qemu_put_be32s(f, &opp->glbc);
1066
    qemu_put_be32s(f, &opp->micr);
1067
    qemu_put_be32s(f, &opp->veni);
1068
    qemu_put_be32s(f, &opp->pint);
1069
    qemu_put_be32s(f, &opp->spve);
1070
    qemu_put_be32s(f, &opp->tifr);
1071

    
1072
    for (i = 0; i < opp->max_irq; i++) {
1073
        qemu_put_be32s(f, &opp->src[i].ipvp);
1074
        qemu_put_be32s(f, &opp->src[i].ide);
1075
        qemu_put_sbe32s(f, &opp->src[i].type);
1076
        qemu_put_sbe32s(f, &opp->src[i].last_cpu);
1077
        qemu_put_sbe32s(f, &opp->src[i].pending);
1078
    }
1079

    
1080
    qemu_put_sbe32s(f, &opp->nb_cpus);
1081

    
1082
    for (i = 0; i < opp->nb_cpus; i++) {
1083
        qemu_put_be32s(f, &opp->dst[i].tfrr);
1084
        qemu_put_be32s(f, &opp->dst[i].pctp);
1085
        qemu_put_be32s(f, &opp->dst[i].pcsr);
1086
        openpic_save_IRQ_queue(f, &opp->dst[i].raised);
1087
        openpic_save_IRQ_queue(f, &opp->dst[i].servicing);
1088
    }
1089

    
1090
    for (i = 0; i < MAX_TMR; i++) {
1091
        qemu_put_be32s(f, &opp->timers[i].ticc);
1092
        qemu_put_be32s(f, &opp->timers[i].tibc);
1093
    }
1094

    
1095
#if MAX_DBL > 0
1096
    qemu_put_be32s(f, &opp->dar);
1097

    
1098
    for (i = 0; i < MAX_DBL; i++) {
1099
        qemu_put_be32s(f, &opp->doorbells[i].dmr);
1100
    }
1101
#endif
1102

    
1103
#if MAX_MBX > 0
1104
    for (i = 0; i < MAX_MAILBOXES; i++) {
1105
        qemu_put_be32s(f, &opp->mailboxes[i].mbr);
1106
    }
1107
#endif
1108

    
1109
    pci_device_save(&opp->pci_dev, f);
1110
}
1111

    
1112
static void openpic_load_IRQ_queue(QEMUFile* f, IRQ_queue_t *q)
1113
{
1114
    unsigned int i;
1115

    
1116
    for (i = 0; i < BF_WIDTH(MAX_IRQ); i++)
1117
        qemu_get_be32s(f, &q->queue[i]);
1118

    
1119
    qemu_get_sbe32s(f, &q->next);
1120
    qemu_get_sbe32s(f, &q->priority);
1121
}
1122

    
1123
static int openpic_load(QEMUFile* f, void *opaque, int version_id)
1124
{
1125
    openpic_t *opp = (openpic_t *)opaque;
1126
    unsigned int i;
1127

    
1128
    if (version_id != 1)
1129
        return -EINVAL;
1130

    
1131
    qemu_get_be32s(f, &opp->frep);
1132
    qemu_get_be32s(f, &opp->glbc);
1133
    qemu_get_be32s(f, &opp->micr);
1134
    qemu_get_be32s(f, &opp->veni);
1135
    qemu_get_be32s(f, &opp->pint);
1136
    qemu_get_be32s(f, &opp->spve);
1137
    qemu_get_be32s(f, &opp->tifr);
1138

    
1139
    for (i = 0; i < opp->max_irq; i++) {
1140
        qemu_get_be32s(f, &opp->src[i].ipvp);
1141
        qemu_get_be32s(f, &opp->src[i].ide);
1142
        qemu_get_sbe32s(f, &opp->src[i].type);
1143
        qemu_get_sbe32s(f, &opp->src[i].last_cpu);
1144
        qemu_get_sbe32s(f, &opp->src[i].pending);
1145
    }
1146

    
1147
    qemu_get_sbe32s(f, &opp->nb_cpus);
1148

    
1149
    for (i = 0; i < opp->nb_cpus; i++) {
1150
        qemu_get_be32s(f, &opp->dst[i].tfrr);
1151
        qemu_get_be32s(f, &opp->dst[i].pctp);
1152
        qemu_get_be32s(f, &opp->dst[i].pcsr);
1153
        openpic_load_IRQ_queue(f, &opp->dst[i].raised);
1154
        openpic_load_IRQ_queue(f, &opp->dst[i].servicing);
1155
    }
1156

    
1157
    for (i = 0; i < MAX_TMR; i++) {
1158
        qemu_get_be32s(f, &opp->timers[i].ticc);
1159
        qemu_get_be32s(f, &opp->timers[i].tibc);
1160
    }
1161

    
1162
#if MAX_DBL > 0
1163
    qemu_get_be32s(f, &opp->dar);
1164

    
1165
    for (i = 0; i < MAX_DBL; i++) {
1166
        qemu_get_be32s(f, &opp->doorbells[i].dmr);
1167
    }
1168
#endif
1169

    
1170
#if MAX_MBX > 0
1171
    for (i = 0; i < MAX_MAILBOXES; i++) {
1172
        qemu_get_be32s(f, &opp->mailboxes[i].mbr);
1173
    }
1174
#endif
1175

    
1176
    return pci_device_load(&opp->pci_dev, f);
1177
}
1178

    
1179
static void openpic_irq_raise(openpic_t *opp, int n_CPU, IRQ_src_t *src)
1180
{
1181
    qemu_irq_raise(opp->dst[n_CPU].irqs[OPENPIC_OUTPUT_INT]);
1182
}
1183

    
1184
qemu_irq *openpic_init (PCIBus *bus, MemoryRegion **pmem, int nb_cpus,
1185
                        qemu_irq **irqs, qemu_irq irq_out)
1186
{
1187
    openpic_t *opp;
1188
    uint8_t *pci_conf;
1189
    int i, m;
1190

    
1191
    /* XXX: for now, only one CPU is supported */
1192
    if (nb_cpus != 1)
1193
        return NULL;
1194
    if (bus) {
1195
        opp = (openpic_t *)pci_register_device(bus, "OpenPIC", sizeof(openpic_t),
1196
                                               -1, NULL, NULL);
1197
        pci_conf = opp->pci_dev.config;
1198
        pci_config_set_vendor_id(pci_conf, PCI_VENDOR_ID_IBM);
1199
        pci_config_set_device_id(pci_conf, PCI_DEVICE_ID_IBM_OPENPIC2);
1200
        pci_config_set_class(pci_conf, PCI_CLASS_SYSTEM_OTHER); // FIXME?
1201
        pci_conf[0x3d] = 0x00; // no interrupt pin
1202

    
1203
        memory_region_init_io(&opp->mem, &openpic_ops, opp, "openpic", 0x40000);
1204
#if 0 // Don't implement ISU for now
1205
        opp_io_memory = cpu_register_io_memory(openpic_src_read,
1206
                                               openpic_src_write, NULL
1207
                                               DEVICE_NATIVE_ENDIAN);
1208
        cpu_register_physical_memory(isu_base, 0x20 * (EXT_IRQ + 2),
1209
                                     opp_io_memory);
1210
#endif
1211

    
1212
        /* Register I/O spaces */
1213
        pci_register_bar(&opp->pci_dev, 0,
1214
                         PCI_BASE_ADDRESS_SPACE_MEMORY, &opp->mem);
1215
    } else {
1216
        opp = g_malloc0(sizeof(openpic_t));
1217
        memory_region_init_io(&opp->mem, &openpic_ops, opp, "openpic", 0x40000);
1218
    }
1219

    
1220
    //    isu_base &= 0xFFFC0000;
1221
    opp->nb_cpus = nb_cpus;
1222
    opp->max_irq = OPENPIC_MAX_IRQ;
1223
    opp->irq_ipi0 = OPENPIC_IRQ_IPI0;
1224
    opp->irq_tim0 = OPENPIC_IRQ_TIM0;
1225
    /* Set IRQ types */
1226
    for (i = 0; i < OPENPIC_EXT_IRQ; i++) {
1227
        opp->src[i].type = IRQ_EXTERNAL;
1228
    }
1229
    for (; i < OPENPIC_IRQ_TIM0; i++) {
1230
        opp->src[i].type = IRQ_SPECIAL;
1231
    }
1232
#if MAX_IPI > 0
1233
    m = OPENPIC_IRQ_IPI0;
1234
#else
1235
    m = OPENPIC_IRQ_DBL0;
1236
#endif
1237
    for (; i < m; i++) {
1238
        opp->src[i].type = IRQ_TIMER;
1239
    }
1240
    for (; i < OPENPIC_MAX_IRQ; i++) {
1241
        opp->src[i].type = IRQ_INTERNAL;
1242
    }
1243
    for (i = 0; i < nb_cpus; i++)
1244
        opp->dst[i].irqs = irqs[i];
1245
    opp->irq_out = irq_out;
1246

    
1247
    register_savevm(&opp->pci_dev.qdev, "openpic", 0, 2,
1248
                    openpic_save, openpic_load, opp);
1249
    qemu_register_reset(openpic_reset, opp);
1250

    
1251
    opp->irq_raise = openpic_irq_raise;
1252
    opp->reset = openpic_reset;
1253

    
1254
    if (pmem)
1255
        *pmem = &opp->mem;
1256

    
1257
    return qemu_allocate_irqs(openpic_set_irq, opp, opp->max_irq);
1258
}
1259

    
1260
static void mpic_irq_raise(openpic_t *mpp, int n_CPU, IRQ_src_t *src)
1261
{
1262
    int n_ci = IDR_CI0 - n_CPU;
1263

    
1264
    if(test_bit(&src->ide, n_ci)) {
1265
        qemu_irq_raise(mpp->dst[n_CPU].irqs[OPENPIC_OUTPUT_CINT]);
1266
    }
1267
    else {
1268
        qemu_irq_raise(mpp->dst[n_CPU].irqs[OPENPIC_OUTPUT_INT]);
1269
    }
1270
}
1271

    
1272
static void mpic_reset (void *opaque)
1273
{
1274
    openpic_t *mpp = (openpic_t *)opaque;
1275
    int i;
1276

    
1277
    mpp->glbc = 0x80000000;
1278
    /* Initialise controller registers */
1279
    mpp->frep = 0x004f0002 | ((mpp->nb_cpus - 1) << 8);
1280
    mpp->veni = VENI;
1281
    mpp->pint = 0x00000000;
1282
    mpp->spve = 0x0000FFFF;
1283
    /* Initialise IRQ sources */
1284
    for (i = 0; i < mpp->max_irq; i++) {
1285
        mpp->src[i].ipvp = 0x80800000;
1286
        mpp->src[i].ide  = 0x00000001;
1287
    }
1288
    /* Set IDE for IPIs to 0 so we don't get spurious interrupts */
1289
    for (i = mpp->irq_ipi0; i < (mpp->irq_ipi0 + MAX_IPI); i++) {
1290
        mpp->src[i].ide = 0;
1291
    }
1292
    /* Initialise IRQ destinations */
1293
    for (i = 0; i < MAX_CPU; i++) {
1294
        mpp->dst[i].pctp      = 0x0000000F;
1295
        mpp->dst[i].tfrr      = 0x00000000;
1296
        memset(&mpp->dst[i].raised, 0, sizeof(IRQ_queue_t));
1297
        mpp->dst[i].raised.next = -1;
1298
        memset(&mpp->dst[i].servicing, 0, sizeof(IRQ_queue_t));
1299
        mpp->dst[i].servicing.next = -1;
1300
    }
1301
    /* Initialise timers */
1302
    for (i = 0; i < MAX_TMR; i++) {
1303
        mpp->timers[i].ticc = 0x00000000;
1304
        mpp->timers[i].tibc = 0x80000000;
1305
    }
1306
    /* Go out of RESET state */
1307
    mpp->glbc = 0x00000000;
1308
}
1309

    
1310
static void mpic_timer_write (void *opaque, target_phys_addr_t addr, uint32_t val)
1311
{
1312
    openpic_t *mpp = opaque;
1313
    int idx, cpu;
1314

    
1315
    DPRINTF("%s: addr " TARGET_FMT_plx " <= %08x\n", __func__, addr, val);
1316
    if (addr & 0xF)
1317
        return;
1318
    addr &= 0xFFFF;
1319
    cpu = addr >> 12;
1320
    idx = (addr >> 6) & 0x3;
1321
    switch (addr & 0x30) {
1322
    case 0x00: /* gtccr */
1323
        break;
1324
    case 0x10: /* gtbcr */
1325
        if ((mpp->timers[idx].ticc & 0x80000000) != 0 &&
1326
            (val & 0x80000000) == 0 &&
1327
            (mpp->timers[idx].tibc & 0x80000000) != 0)
1328
            mpp->timers[idx].ticc &= ~0x80000000;
1329
        mpp->timers[idx].tibc = val;
1330
        break;
1331
    case 0x20: /* GTIVPR */
1332
        write_IRQreg_ipvp(mpp, MPIC_TMR_IRQ + idx, val);
1333
        break;
1334
    case 0x30: /* GTIDR & TFRR */
1335
        if ((addr & 0xF0) == 0xF0)
1336
            mpp->dst[cpu].tfrr = val;
1337
        else
1338
            write_IRQreg_ide(mpp, MPIC_TMR_IRQ + idx, val);
1339
        break;
1340
    }
1341
}
1342

    
1343
static uint32_t mpic_timer_read (void *opaque, target_phys_addr_t addr)
1344
{
1345
    openpic_t *mpp = opaque;
1346
    uint32_t retval;
1347
    int idx, cpu;
1348

    
1349
    DPRINTF("%s: addr " TARGET_FMT_plx "\n", __func__, addr);
1350
    retval = 0xFFFFFFFF;
1351
    if (addr & 0xF)
1352
        return retval;
1353
    addr &= 0xFFFF;
1354
    cpu = addr >> 12;
1355
    idx = (addr >> 6) & 0x3;
1356
    switch (addr & 0x30) {
1357
    case 0x00: /* gtccr */
1358
        retval = mpp->timers[idx].ticc;
1359
        break;
1360
    case 0x10: /* gtbcr */
1361
        retval = mpp->timers[idx].tibc;
1362
        break;
1363
    case 0x20: /* TIPV */
1364
        retval = read_IRQreg_ipvp(mpp, MPIC_TMR_IRQ + idx);
1365
        break;
1366
    case 0x30: /* TIDR */
1367
        if ((addr &0xF0) == 0XF0)
1368
            retval = mpp->dst[cpu].tfrr;
1369
        else
1370
            retval = read_IRQreg_ide(mpp, MPIC_TMR_IRQ + idx);
1371
        break;
1372
    }
1373
    DPRINTF("%s: => %08x\n", __func__, retval);
1374

    
1375
    return retval;
1376
}
1377

    
1378
static void mpic_src_ext_write (void *opaque, target_phys_addr_t addr,
1379
                                uint32_t val)
1380
{
1381
    openpic_t *mpp = opaque;
1382
    int idx = MPIC_EXT_IRQ;
1383

    
1384
    DPRINTF("%s: addr " TARGET_FMT_plx " <= %08x\n", __func__, addr, val);
1385
    if (addr & 0xF)
1386
        return;
1387

    
1388
    addr -= MPIC_EXT_REG_START & (OPENPIC_PAGE_SIZE - 1);
1389
    if (addr < MPIC_EXT_REG_SIZE) {
1390
        idx += (addr & 0xFFF0) >> 5;
1391
        if (addr & 0x10) {
1392
            /* EXDE / IFEDE / IEEDE */
1393
            write_IRQreg_ide(mpp, idx, val);
1394
        } else {
1395
            /* EXVP / IFEVP / IEEVP */
1396
            write_IRQreg_ipvp(mpp, idx, val);
1397
        }
1398
    }
1399
}
1400

    
1401
static uint32_t mpic_src_ext_read (void *opaque, target_phys_addr_t addr)
1402
{
1403
    openpic_t *mpp = opaque;
1404
    uint32_t retval;
1405
    int idx = MPIC_EXT_IRQ;
1406

    
1407
    DPRINTF("%s: addr " TARGET_FMT_plx "\n", __func__, addr);
1408
    retval = 0xFFFFFFFF;
1409
    if (addr & 0xF)
1410
        return retval;
1411

    
1412
    addr -= MPIC_EXT_REG_START & (OPENPIC_PAGE_SIZE - 1);
1413
    if (addr < MPIC_EXT_REG_SIZE) {
1414
        idx += (addr & 0xFFF0) >> 5;
1415
        if (addr & 0x10) {
1416
            /* EXDE / IFEDE / IEEDE */
1417
            retval = read_IRQreg_ide(mpp, idx);
1418
        } else {
1419
            /* EXVP / IFEVP / IEEVP */
1420
            retval = read_IRQreg_ipvp(mpp, idx);
1421
        }
1422
        DPRINTF("%s: => %08x\n", __func__, retval);
1423
    }
1424

    
1425
    return retval;
1426
}
1427

    
1428
static void mpic_src_int_write (void *opaque, target_phys_addr_t addr,
1429
                                uint32_t val)
1430
{
1431
    openpic_t *mpp = opaque;
1432
    int idx = MPIC_INT_IRQ;
1433

    
1434
    DPRINTF("%s: addr " TARGET_FMT_plx " <= %08x\n", __func__, addr, val);
1435
    if (addr & 0xF)
1436
        return;
1437

    
1438
    addr -= MPIC_INT_REG_START & (OPENPIC_PAGE_SIZE - 1);
1439
    if (addr < MPIC_INT_REG_SIZE) {
1440
        idx += (addr & 0xFFF0) >> 5;
1441
        if (addr & 0x10) {
1442
            /* EXDE / IFEDE / IEEDE */
1443
            write_IRQreg_ide(mpp, idx, val);
1444
        } else {
1445
            /* EXVP / IFEVP / IEEVP */
1446
            write_IRQreg_ipvp(mpp, idx, val);
1447
        }
1448
    }
1449
}
1450

    
1451
static uint32_t mpic_src_int_read (void *opaque, target_phys_addr_t addr)
1452
{
1453
    openpic_t *mpp = opaque;
1454
    uint32_t retval;
1455
    int idx = MPIC_INT_IRQ;
1456

    
1457
    DPRINTF("%s: addr " TARGET_FMT_plx "\n", __func__, addr);
1458
    retval = 0xFFFFFFFF;
1459
    if (addr & 0xF)
1460
        return retval;
1461

    
1462
    addr -= MPIC_INT_REG_START & (OPENPIC_PAGE_SIZE - 1);
1463
    if (addr < MPIC_INT_REG_SIZE) {
1464
        idx += (addr & 0xFFF0) >> 5;
1465
        if (addr & 0x10) {
1466
            /* EXDE / IFEDE / IEEDE */
1467
            retval = read_IRQreg_ide(mpp, idx);
1468
        } else {
1469
            /* EXVP / IFEVP / IEEVP */
1470
            retval = read_IRQreg_ipvp(mpp, idx);
1471
        }
1472
        DPRINTF("%s: => %08x\n", __func__, retval);
1473
    }
1474

    
1475
    return retval;
1476
}
1477

    
1478
static void mpic_src_msg_write (void *opaque, target_phys_addr_t addr,
1479
                                uint32_t val)
1480
{
1481
    openpic_t *mpp = opaque;
1482
    int idx = MPIC_MSG_IRQ;
1483

    
1484
    DPRINTF("%s: addr " TARGET_FMT_plx " <= %08x\n", __func__, addr, val);
1485
    if (addr & 0xF)
1486
        return;
1487

    
1488
    addr -= MPIC_MSG_REG_START & (OPENPIC_PAGE_SIZE - 1);
1489
    if (addr < MPIC_MSG_REG_SIZE) {
1490
        idx += (addr & 0xFFF0) >> 5;
1491
        if (addr & 0x10) {
1492
            /* EXDE / IFEDE / IEEDE */
1493
            write_IRQreg_ide(mpp, idx, val);
1494
        } else {
1495
            /* EXVP / IFEVP / IEEVP */
1496
            write_IRQreg_ipvp(mpp, idx, val);
1497
        }
1498
    }
1499
}
1500

    
1501
static uint32_t mpic_src_msg_read (void *opaque, target_phys_addr_t addr)
1502
{
1503
    openpic_t *mpp = opaque;
1504
    uint32_t retval;
1505
    int idx = MPIC_MSG_IRQ;
1506

    
1507
    DPRINTF("%s: addr " TARGET_FMT_plx "\n", __func__, addr);
1508
    retval = 0xFFFFFFFF;
1509
    if (addr & 0xF)
1510
        return retval;
1511

    
1512
    addr -= MPIC_MSG_REG_START & (OPENPIC_PAGE_SIZE - 1);
1513
    if (addr < MPIC_MSG_REG_SIZE) {
1514
        idx += (addr & 0xFFF0) >> 5;
1515
        if (addr & 0x10) {
1516
            /* EXDE / IFEDE / IEEDE */
1517
            retval = read_IRQreg_ide(mpp, idx);
1518
        } else {
1519
            /* EXVP / IFEVP / IEEVP */
1520
            retval = read_IRQreg_ipvp(mpp, idx);
1521
        }
1522
        DPRINTF("%s: => %08x\n", __func__, retval);
1523
    }
1524

    
1525
    return retval;
1526
}
1527

    
1528
static void mpic_src_msi_write (void *opaque, target_phys_addr_t addr,
1529
                                uint32_t val)
1530
{
1531
    openpic_t *mpp = opaque;
1532
    int idx = MPIC_MSI_IRQ;
1533

    
1534
    DPRINTF("%s: addr " TARGET_FMT_plx " <= %08x\n", __func__, addr, val);
1535
    if (addr & 0xF)
1536
        return;
1537

    
1538
    addr -= MPIC_MSI_REG_START & (OPENPIC_PAGE_SIZE - 1);
1539
    if (addr < MPIC_MSI_REG_SIZE) {
1540
        idx += (addr & 0xFFF0) >> 5;
1541
        if (addr & 0x10) {
1542
            /* EXDE / IFEDE / IEEDE */
1543
            write_IRQreg_ide(mpp, idx, val);
1544
        } else {
1545
            /* EXVP / IFEVP / IEEVP */
1546
            write_IRQreg_ipvp(mpp, idx, val);
1547
        }
1548
    }
1549
}
1550
static uint32_t mpic_src_msi_read (void *opaque, target_phys_addr_t addr)
1551
{
1552
    openpic_t *mpp = opaque;
1553
    uint32_t retval;
1554
    int idx = MPIC_MSI_IRQ;
1555

    
1556
    DPRINTF("%s: addr " TARGET_FMT_plx "\n", __func__, addr);
1557
    retval = 0xFFFFFFFF;
1558
    if (addr & 0xF)
1559
        return retval;
1560

    
1561
    addr -= MPIC_MSI_REG_START & (OPENPIC_PAGE_SIZE - 1);
1562
    if (addr < MPIC_MSI_REG_SIZE) {
1563
        idx += (addr & 0xFFF0) >> 5;
1564
        if (addr & 0x10) {
1565
            /* EXDE / IFEDE / IEEDE */
1566
            retval = read_IRQreg_ide(mpp, idx);
1567
        } else {
1568
            /* EXVP / IFEVP / IEEVP */
1569
            retval = read_IRQreg_ipvp(mpp, idx);
1570
        }
1571
        DPRINTF("%s: => %08x\n", __func__, retval);
1572
    }
1573

    
1574
    return retval;
1575
}
1576

    
1577
static const MemoryRegionOps mpic_glb_ops = {
1578
    .old_mmio = {
1579
        .write = { openpic_buggy_write,
1580
                   openpic_buggy_write,
1581
                   openpic_gbl_write,
1582
        },
1583
        .read  = { openpic_buggy_read,
1584
                   openpic_buggy_read,
1585
                   openpic_gbl_read,
1586
        },
1587
    },
1588
    .endianness = DEVICE_BIG_ENDIAN,
1589
};
1590

    
1591
static const MemoryRegionOps mpic_tmr_ops = {
1592
    .old_mmio = {
1593
        .write = { openpic_buggy_write,
1594
                   openpic_buggy_write,
1595
                   mpic_timer_write,
1596
        },
1597
        .read  = { openpic_buggy_read,
1598
                   openpic_buggy_read,
1599
                   mpic_timer_read,
1600
        },
1601
    },
1602
    .endianness = DEVICE_BIG_ENDIAN,
1603
};
1604

    
1605
static const MemoryRegionOps mpic_cpu_ops = {
1606
    .old_mmio = {
1607
        .write = { openpic_buggy_write,
1608
                   openpic_buggy_write,
1609
                   openpic_cpu_write,
1610
        },
1611
        .read  = { openpic_buggy_read,
1612
                   openpic_buggy_read,
1613
                   openpic_cpu_read,
1614
        },
1615
    },
1616
    .endianness = DEVICE_BIG_ENDIAN,
1617
};
1618

    
1619
static const MemoryRegionOps mpic_ext_ops = {
1620
    .old_mmio = {
1621
        .write = { openpic_buggy_write,
1622
                   openpic_buggy_write,
1623
                   mpic_src_ext_write,
1624
        },
1625
        .read  = { openpic_buggy_read,
1626
                   openpic_buggy_read,
1627
                   mpic_src_ext_read,
1628
        },
1629
    },
1630
    .endianness = DEVICE_BIG_ENDIAN,
1631
};
1632

    
1633
static const MemoryRegionOps mpic_int_ops = {
1634
    .old_mmio = {
1635
        .write = { openpic_buggy_write,
1636
                   openpic_buggy_write,
1637
                   mpic_src_int_write,
1638
        },
1639
        .read  = { openpic_buggy_read,
1640
                   openpic_buggy_read,
1641
                   mpic_src_int_read,
1642
        },
1643
    },
1644
    .endianness = DEVICE_BIG_ENDIAN,
1645
};
1646

    
1647
static const MemoryRegionOps mpic_msg_ops = {
1648
    .old_mmio = {
1649
        .write = { openpic_buggy_write,
1650
                   openpic_buggy_write,
1651
                   mpic_src_msg_write,
1652
        },
1653
        .read  = { openpic_buggy_read,
1654
                   openpic_buggy_read,
1655
                   mpic_src_msg_read,
1656
        },
1657
    },
1658
    .endianness = DEVICE_BIG_ENDIAN,
1659
};
1660

    
1661
static const MemoryRegionOps mpic_msi_ops = {
1662
    .old_mmio = {
1663
        .write = { openpic_buggy_write,
1664
                   openpic_buggy_write,
1665
                   mpic_src_msi_write,
1666
        },
1667
        .read  = { openpic_buggy_read,
1668
                   openpic_buggy_read,
1669
                   mpic_src_msi_read,
1670
        },
1671
    },
1672
    .endianness = DEVICE_BIG_ENDIAN,
1673
};
1674

    
1675
qemu_irq *mpic_init (MemoryRegion *address_space, target_phys_addr_t base,
1676
                     int nb_cpus, qemu_irq **irqs, qemu_irq irq_out)
1677
{
1678
    openpic_t    *mpp;
1679
    int           i;
1680
    struct {
1681
        const char             *name;
1682
        MemoryRegionOps const  *ops;
1683
        target_phys_addr_t      start_addr;
1684
        ram_addr_t              size;
1685
    } const list[] = {
1686
        {"glb", &mpic_glb_ops, MPIC_GLB_REG_START, MPIC_GLB_REG_SIZE},
1687
        {"tmr", &mpic_tmr_ops, MPIC_TMR_REG_START, MPIC_TMR_REG_SIZE},
1688
        {"ext", &mpic_ext_ops, MPIC_EXT_REG_START, MPIC_EXT_REG_SIZE},
1689
        {"int", &mpic_int_ops, MPIC_INT_REG_START, MPIC_INT_REG_SIZE},
1690
        {"msg", &mpic_msg_ops, MPIC_MSG_REG_START, MPIC_MSG_REG_SIZE},
1691
        {"msi", &mpic_msi_ops, MPIC_MSI_REG_START, MPIC_MSI_REG_SIZE},
1692
        {"cpu", &mpic_cpu_ops, MPIC_CPU_REG_START, MPIC_CPU_REG_SIZE},
1693
    };
1694

    
1695
    mpp = g_malloc0(sizeof(openpic_t));
1696

    
1697
    memory_region_init(&mpp->mem, "mpic", 0x40000);
1698
    memory_region_add_subregion(address_space, base, &mpp->mem);
1699

    
1700
    for (i = 0; i < sizeof(list)/sizeof(list[0]); i++) {
1701

    
1702
        memory_region_init_io(&mpp->sub_io_mem[i], list[i].ops, mpp,
1703
                              list[i].name, list[i].size);
1704

    
1705
        memory_region_add_subregion(&mpp->mem, list[i].start_addr,
1706
                                    &mpp->sub_io_mem[i]);
1707
    }
1708

    
1709
    mpp->nb_cpus = nb_cpus;
1710
    mpp->max_irq = MPIC_MAX_IRQ;
1711
    mpp->irq_ipi0 = MPIC_IPI_IRQ;
1712
    mpp->irq_tim0 = MPIC_TMR_IRQ;
1713

    
1714
    for (i = 0; i < nb_cpus; i++)
1715
        mpp->dst[i].irqs = irqs[i];
1716
    mpp->irq_out = irq_out;
1717

    
1718
    mpp->irq_raise = mpic_irq_raise;
1719
    mpp->reset = mpic_reset;
1720

    
1721
    register_savevm(NULL, "mpic", 0, 2, openpic_save, openpic_load, mpp);
1722
    qemu_register_reset(mpic_reset, mpp);
1723

    
1724
    return qemu_allocate_irqs(openpic_set_irq, mpp, mpp->max_irq);
1725
}