Statistics
| Branch: | Revision:

root / hw / openpic.c @ b7169916

History | View | Annotate | Download (46 kB)

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

    
40
//#define DEBUG_OPENPIC
41

    
42
#ifdef DEBUG_OPENPIC
43
#define DPRINTF(fmt, args...) do { printf(fmt , ##args); } while (0)
44
#else
45
#define DPRINTF(fmt, args...) do { } while (0)
46
#endif
47
#define ERROR(fmr, args...) do { printf("ERROR: " fmr , ##args); } while (0)
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     0
61

    
62
#define VID (0x00000000)
63

    
64
#elif defined(USE_MPCxxx)
65

    
66
#define MAX_CPU     2
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
132

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

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

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

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

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

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

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

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

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

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

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

    
205
typedef struct openpic_t {
206
    PCIDevice pci_dev;
207
    int mem_index;
208
    /* Global registers */
209
    uint32_t frep; /* Feature reporting register */
210
    uint32_t glbc; /* Global configuration register  */
211
    uint32_t micr; /* MPIC interrupt configuration register */
212
    uint32_t veni; /* Vendor identification register */
213
    uint32_t pint; /* Processor initialization register */
214
    uint32_t spve; /* Spurious vector register */
215
    uint32_t tifr; /* Timer frequency reporting register */
216
    /* Source registers */
217
    IRQ_src_t src[MAX_IRQ];
218
    /* Local registers per output pin */
219
    IRQ_dst_t dst[MAX_CPU];
220
    int nb_cpus;
221
    /* Timer registers */
222
    struct {
223
        uint32_t ticc;  /* Global timer current count register */
224
        uint32_t tibc;  /* Global timer base count register */
225
    } timers[MAX_TMR];
226
#if MAX_DBL > 0
227
    /* Doorbell registers */
228
    uint32_t dar;        /* Doorbell activate register */
229
    struct {
230
        uint32_t dmr;    /* Doorbell messaging register */
231
    } doorbells[MAX_DBL];
232
#endif
233
#if MAX_MBX > 0
234
    /* Mailbox registers */
235
    struct {
236
        uint32_t mbr;    /* Mailbox register */
237
    } mailboxes[MAX_MAILBOXES];
238
#endif
239
    /* IRQ out is used when in bypass mode (not implemented) */
240
    qemu_irq irq_out;
241
    int max_irq;
242
    int irq_ipi0;
243
    int irq_tim0;
244
    int need_swap;
245
    void (*reset) (void *);
246
    void (*irq_raise) (struct openpic_t *, int, IRQ_src_t *);
247
} openpic_t;
248

    
249
static inline uint32_t openpic_swap32(openpic_t *opp, uint32_t val)
250
{
251
    if (opp->need_swap)
252
        return bswap32(val);
253

    
254
    return val;
255
}
256

    
257
static inline void IRQ_setbit (IRQ_queue_t *q, int n_IRQ)
258
{
259
    set_bit(q->queue, n_IRQ);
260
}
261

    
262
static inline void IRQ_resetbit (IRQ_queue_t *q, int n_IRQ)
263
{
264
    reset_bit(q->queue, n_IRQ);
265
}
266

    
267
static inline int IRQ_testbit (IRQ_queue_t *q, int n_IRQ)
268
{
269
    return test_bit(q->queue, n_IRQ);
270
}
271

    
272
static void IRQ_check (openpic_t *opp, IRQ_queue_t *q)
273
{
274
    int next, i;
275
    int priority;
276

    
277
    next = -1;
278
    priority = -1;
279
    for (i = 0; i < opp->max_irq; i++) {
280
        if (IRQ_testbit(q, i)) {
281
            DPRINTF("IRQ_check: irq %d set ipvp_pr=%d pr=%d\n",
282
                    i, IPVP_PRIORITY(opp->src[i].ipvp), priority);
283
            if (IPVP_PRIORITY(opp->src[i].ipvp) > priority) {
284
                next = i;
285
                priority = IPVP_PRIORITY(opp->src[i].ipvp);
286
            }
287
        }
288
    }
289
    q->next = next;
290
    q->priority = priority;
291
}
292

    
293
static int IRQ_get_next (openpic_t *opp, IRQ_queue_t *q)
294
{
295
    if (q->next == -1) {
296
        /* XXX: optimize */
297
        IRQ_check(opp, q);
298
    }
299

    
300
    return q->next;
301
}
302

    
303
static void IRQ_local_pipe (openpic_t *opp, int n_CPU, int n_IRQ)
304
{
305
    IRQ_dst_t *dst;
306
    IRQ_src_t *src;
307
    int priority;
308

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

    
344
/* update pic state because registers for n_IRQ have changed value */
345
static void openpic_update_irq(openpic_t *opp, int n_IRQ)
346
{
347
    IRQ_src_t *src;
348
    int i;
349

    
350
    src = &opp->src[n_IRQ];
351

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

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

    
401
static void openpic_set_irq(void *opaque, int n_IRQ, int level)
402
{
403
    openpic_t *opp = opaque;
404
    IRQ_src_t *src;
405

    
406
    src = &opp->src[n_IRQ];
407
    DPRINTF("openpic: set irq %d = %d ipvp=%08x\n",
408
            n_IRQ, level, src->ipvp);
409
    if (test_bit(&src->ipvp, IPVP_SENSE)) {
410
        /* level-sensitive irq */
411
        src->pending = level;
412
        if (!level)
413
            reset_bit(&src->ipvp, IPVP_ACTIVITY);
414
    } else {
415
        /* edge-sensitive irq */
416
        if (level)
417
            src->pending = 1;
418
    }
419
    openpic_update_irq(opp, n_IRQ);
420
}
421

    
422
static void openpic_reset (void *opaque)
423
{
424
    openpic_t *opp = (openpic_t *)opaque;
425
    int i;
426

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

    
470
static inline uint32_t read_IRQreg (openpic_t *opp, int n_IRQ, uint32_t reg)
471
{
472
    uint32_t retval;
473

    
474
    switch (reg) {
475
    case IRQ_IPVP:
476
        retval = opp->src[n_IRQ].ipvp;
477
        break;
478
    case IRQ_IDE:
479
        retval = opp->src[n_IRQ].ide;
480
        break;
481
    }
482

    
483
    return retval;
484
}
485

    
486
static inline void write_IRQreg (openpic_t *opp, int n_IRQ,
487
                                 uint32_t reg, uint32_t val)
488
{
489
    uint32_t tmp;
490

    
491
    switch (reg) {
492
    case IRQ_IPVP:
493
        /* NOTE: not fully accurate for special IRQs, but simple and
494
           sufficient */
495
        /* ACTIVITY bit is read-only */
496
        opp->src[n_IRQ].ipvp =
497
            (opp->src[n_IRQ].ipvp & 0x40000000) |
498
            (val & 0x800F00FF);
499
        openpic_update_irq(opp, n_IRQ);
500
        DPRINTF("Set IPVP %d to 0x%08x -> 0x%08x\n",
501
                n_IRQ, val, opp->src[n_IRQ].ipvp);
502
        break;
503
    case IRQ_IDE:
504
        tmp = val & 0xC0000000;
505
        tmp |= val & ((1 << MAX_CPU) - 1);
506
        opp->src[n_IRQ].ide = tmp;
507
        DPRINTF("Set IDE %d to 0x%08x\n", n_IRQ, opp->src[n_IRQ].ide);
508
        break;
509
    }
510
}
511

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

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

531
    return retval;
532
}
533

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

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

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

    
569
    return retval;
570
}
571

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

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

    
596
    DPRINTF("%s: addr %08x <= %08x\n", __func__, addr, val);
597
    if (addr & 0xF)
598
        return;
599
#if defined TARGET_WORDS_BIGENDIAN
600
    val = openpic_swap32(opp, val);
601
#endif
602
    addr &= 0xFF;
603
    switch (addr) {
604
    case 0x00: /* FREP */
605
        break;
606
    case 0x20: /* GLBC */
607
        if (val & 0x80000000 && opp->reset)
608
            opp->reset(opp);
609
        opp->glbc = val & ~0x80000000;
610
        break;
611
    case 0x80: /* VENI */
612
        break;
613
    case 0x90: /* PINT */
614
        for (idx = 0; idx < opp->nb_cpus; idx++) {
615
            if ((val & (1 << idx)) && !(opp->pint & (1 << idx))) {
616
                DPRINTF("Raise OpenPIC RESET output for CPU %d\n", idx);
617
                dst = &opp->dst[idx];
618
                qemu_irq_raise(dst->irqs[OPENPIC_OUTPUT_RESET]);
619
            } else if (!(val & (1 << idx)) && (opp->pint & (1 << idx))) {
620
                DPRINTF("Lower OpenPIC RESET output for CPU %d\n", idx);
621
                dst = &opp->dst[idx];
622
                qemu_irq_lower(dst->irqs[OPENPIC_OUTPUT_RESET]);
623
            }
624
        }
625
        opp->pint = val;
626
        break;
627
#if MAX_IPI > 0
628
    case 0xA0: /* IPI_IPVP */
629
    case 0xB0:
630
    case 0xC0:
631
    case 0xD0:
632
        {
633
            int idx;
634
            idx = (addr - 0xA0) >> 4;
635
            write_IRQreg(opp, opp->irq_ipi0 + idx, IRQ_IPVP, val);
636
        }
637
        break;
638
#endif
639
    case 0xE0: /* SPVE */
640
        opp->spve = val & 0x000000FF;
641
        break;
642
    case 0xF0: /* TIFR */
643
        opp->tifr = val;
644
        break;
645
    default:
646
        break;
647
    }
648
}
649

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

    
655
    DPRINTF("%s: addr %08x\n", __func__, addr);
656
    retval = 0xFFFFFFFF;
657
    if (addr & 0xF)
658
        return retval;
659
    addr &= 0xFF;
660
    switch (addr) {
661
    case 0x00: /* FREP */
662
        retval = opp->frep;
663
        break;
664
    case 0x20: /* GLBC */
665
        retval = opp->glbc;
666
        break;
667
    case 0x80: /* VENI */
668
        retval = opp->veni;
669
        break;
670
    case 0x90: /* PINT */
671
        retval = 0x00000000;
672
        break;
673
#if MAX_IPI > 0
674
    case 0xA0: /* IPI_IPVP */
675
    case 0xB0:
676
    case 0xC0:
677
    case 0xD0:
678
        {
679
            int idx;
680
            idx = (addr - 0xA0) >> 4;
681
            retval = read_IRQreg(opp, opp->irq_ipi0 + idx, IRQ_IPVP);
682
        }
683
        break;
684
#endif
685
    case 0xE0: /* SPVE */
686
        retval = opp->spve;
687
        break;
688
    case 0xF0: /* TIFR */
689
        retval = opp->tifr;
690
        break;
691
    default:
692
        break;
693
    }
694
    DPRINTF("%s: => %08x\n", __func__, retval);
695
#if defined TARGET_WORDS_BIGENDIAN
696
    retval = openpic_swap32(opp, retval);
697
#endif
698

    
699
    return retval;
700
}
701

    
702
static void openpic_timer_write (void *opaque, uint32_t addr, uint32_t val)
703
{
704
    openpic_t *opp = opaque;
705
    int idx;
706

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

    
736
static uint32_t openpic_timer_read (void *opaque, uint32_t addr)
737
{
738
    openpic_t *opp = opaque;
739
    uint32_t retval;
740
    int idx;
741

    
742
    DPRINTF("%s: addr %08x\n", __func__, addr);
743
    retval = 0xFFFFFFFF;
744
    if (addr & 0xF)
745
        return retval;
746
    addr -= 0x1100;
747
    addr &= 0xFFFF;
748
    idx = (addr & 0xFFF0) >> 6;
749
    addr = addr & 0x30;
750
    switch (addr) {
751
    case 0x00: /* TICC */
752
        retval = opp->timers[idx].ticc;
753
        break;
754
    case 0x10: /* TIBC */
755
        retval = opp->timers[idx].tibc;
756
        break;
757
    case 0x20: /* TIPV */
758
        retval = read_IRQreg(opp, opp->irq_tim0 + idx, IRQ_IPVP);
759
        break;
760
    case 0x30: /* TIDE */
761
        retval = read_IRQreg(opp, opp->irq_tim0 + idx, IRQ_IDE);
762
        break;
763
    }
764
    DPRINTF("%s: => %08x\n", __func__, retval);
765
#if defined TARGET_WORDS_BIGENDIAN
766
    retval = openpic_swap32(opp, retval);
767
#endif
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
#if defined TARGET_WORDS_BIGENDIAN
781
    val = openpic_swap32(opp, val);
782
#endif
783
    addr = addr & 0xFFF0;
784
    idx = addr >> 5;
785
    if (addr & 0x10) {
786
        /* EXDE / IFEDE / IEEDE */
787
        write_IRQreg(opp, idx, IRQ_IDE, val);
788
    } else {
789
        /* EXVP / IFEVP / IEEVP */
790
        write_IRQreg(opp, idx, IRQ_IPVP, val);
791
    }
792
}
793

    
794
static uint32_t openpic_src_read (void *opaque, uint32_t addr)
795
{
796
    openpic_t *opp = opaque;
797
    uint32_t retval;
798
    int idx;
799

    
800
    DPRINTF("%s: addr %08x\n", __func__, addr);
801
    retval = 0xFFFFFFFF;
802
    if (addr & 0xF)
803
        return retval;
804
    addr = addr & 0xFFF0;
805
    idx = addr >> 5;
806
    if (addr & 0x10) {
807
        /* EXDE / IFEDE / IEEDE */
808
        retval = read_IRQreg(opp, idx, IRQ_IDE);
809
    } else {
810
        /* EXVP / IFEVP / IEEVP */
811
        retval = read_IRQreg(opp, idx, IRQ_IPVP);
812
    }
813
    DPRINTF("%s: => %08x\n", __func__, retval);
814
#if defined TARGET_WORDS_BIGENDIAN
815
    retval = openpic_swap32(opp, retval);
816
#endif
817

    
818
    return retval;
819
}
820

    
821
static void openpic_cpu_write (void *opaque, target_phys_addr_t addr, uint32_t val)
822
{
823
    openpic_t *opp = opaque;
824
    IRQ_src_t *src;
825
    IRQ_dst_t *dst;
826
    int idx, s_IRQ, n_IRQ;
827

    
828
    DPRINTF("%s: addr %08x <= %08x\n", __func__, addr, val);
829
    if (addr & 0xF)
830
        return;
831
#if defined TARGET_WORDS_BIGENDIAN
832
    val = openpic_swap32(opp, val);
833
#endif
834
    addr &= 0x1FFF0;
835
    idx = addr / 0x1000;
836
    dst = &opp->dst[idx];
837
    addr &= 0xFF0;
838
    switch (addr) {
839
#if MAX_IPI > 0
840
    case 0x40: /* PIPD */
841
    case 0x50:
842
    case 0x60:
843
    case 0x70:
844
        idx = (addr - 0x40) >> 4;
845
        write_IRQreg(opp, opp->irq_ipi0 + idx, IRQ_IDE, val);
846
        openpic_set_irq(opp, opp->irq_ipi0 + idx, 1);
847
        openpic_set_irq(opp, opp->irq_ipi0 + idx, 0);
848
        break;
849
#endif
850
    case 0x80: /* PCTP */
851
        dst->pctp = val & 0x0000000F;
852
        break;
853
    case 0x90: /* WHOAMI */
854
        /* Read-only register */
855
        break;
856
    case 0xA0: /* PIAC */
857
        /* Read-only register */
858
        break;
859
    case 0xB0: /* PEOI */
860
        DPRINTF("PEOI\n");
861
        s_IRQ = IRQ_get_next(opp, &dst->servicing);
862
        IRQ_resetbit(&dst->servicing, s_IRQ);
863
        dst->servicing.next = -1;
864
        /* Set up next servicing IRQ */
865
        s_IRQ = IRQ_get_next(opp, &dst->servicing);
866
        /* Check queued interrupts. */
867
        n_IRQ = IRQ_get_next(opp, &dst->raised);
868
        src = &opp->src[n_IRQ];
869
        if (n_IRQ != -1 &&
870
            (s_IRQ == -1 ||
871
             IPVP_PRIORITY(src->ipvp) > dst->servicing.priority)) {
872
            DPRINTF("Raise OpenPIC INT output cpu %d irq %d\n",
873
                    idx, n_IRQ);
874
            opp->irq_raise(opp, idx, src);
875
        }
876
        break;
877
    default:
878
        break;
879
    }
880
}
881

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

    
890
    DPRINTF("%s: addr %08x\n", __func__, addr);
891
    retval = 0xFFFFFFFF;
892
    if (addr & 0xF)
893
        return retval;
894
    addr &= 0x1FFF0;
895
    idx = addr / 0x1000;
896
    dst = &opp->dst[idx];
897
    addr &= 0xFF0;
898
    switch (addr) {
899
    case 0x80: /* PCTP */
900
        retval = dst->pctp;
901
        break;
902
    case 0x90: /* WHOAMI */
903
        retval = idx;
904
        break;
905
    case 0xA0: /* PIAC */
906
        DPRINTF("Lower OpenPIC INT output\n");
907
        qemu_irq_lower(dst->irqs[OPENPIC_OUTPUT_INT]);
908
        n_IRQ = IRQ_get_next(opp, &dst->raised);
909
        DPRINTF("PIAC: irq=%d\n", n_IRQ);
910
        if (n_IRQ == -1) {
911
            /* No more interrupt pending */
912
            retval = IPVP_VECTOR(opp->spve);
913
        } else {
914
            src = &opp->src[n_IRQ];
915
            if (!test_bit(&src->ipvp, IPVP_ACTIVITY) ||
916
                !(IPVP_PRIORITY(src->ipvp) > dst->pctp)) {
917
                /* - Spurious level-sensitive IRQ
918
                 * - Priorities has been changed
919
                 *   and the pending IRQ isn't allowed anymore
920
                 */
921
                reset_bit(&src->ipvp, IPVP_ACTIVITY);
922
                retval = IPVP_VECTOR(opp->spve);
923
            } else {
924
                /* IRQ enter servicing state */
925
                IRQ_setbit(&dst->servicing, n_IRQ);
926
                retval = IPVP_VECTOR(src->ipvp);
927
            }
928
            IRQ_resetbit(&dst->raised, n_IRQ);
929
            dst->raised.next = -1;
930
            if (!test_bit(&src->ipvp, IPVP_SENSE)) {
931
                /* edge-sensitive IRQ */
932
                reset_bit(&src->ipvp, IPVP_ACTIVITY);
933
                src->pending = 0;
934
            }
935
        }
936
        break;
937
    case 0xB0: /* PEOI */
938
        retval = 0;
939
        break;
940
#if MAX_IPI > 0
941
    case 0x40: /* IDE */
942
    case 0x50:
943
        idx = (addr - 0x40) >> 4;
944
        retval = read_IRQreg(opp, opp->irq_ipi0 + idx, IRQ_IDE);
945
        break;
946
#endif
947
    default:
948
        break;
949
    }
950
    DPRINTF("%s: => %08x\n", __func__, retval);
951
#if defined TARGET_WORDS_BIGENDIAN
952
    retval = openpic_swap32(opp, retval);
953
#endif
954

    
955
    return retval;
956
}
957

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

    
964
static uint32_t openpic_buggy_read (void *opaque, target_phys_addr_t addr)
965
{
966
    printf("Invalid OPENPIC read access !\n");
967

    
968
    return -1;
969
}
970

    
971
static void openpic_writel (void *opaque,
972
                            target_phys_addr_t addr, uint32_t val)
973
{
974
    openpic_t *opp = opaque;
975

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

    
993
static uint32_t openpic_readl (void *opaque,target_phys_addr_t addr)
994
{
995
    openpic_t *opp = opaque;
996
    uint32_t retval;
997

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

    
1014
    return retval;
1015
}
1016

    
1017
static CPUWriteMemoryFunc *openpic_write[] = {
1018
    &openpic_buggy_write,
1019
    &openpic_buggy_write,
1020
    &openpic_writel,
1021
};
1022

    
1023
static CPUReadMemoryFunc *openpic_read[] = {
1024
    &openpic_buggy_read,
1025
    &openpic_buggy_read,
1026
    &openpic_readl,
1027
};
1028

    
1029
static void openpic_map(PCIDevice *pci_dev, int region_num,
1030
                        uint32_t addr, uint32_t size, int type)
1031
{
1032
    openpic_t *opp;
1033

    
1034
    DPRINTF("Map OpenPIC\n");
1035
    opp = (openpic_t *)pci_dev;
1036
    /* Global registers */
1037
    DPRINTF("Register OPENPIC gbl   %08x => %08x\n",
1038
            addr + 0x1000, addr + 0x1000 + 0x100);
1039
    /* Timer registers */
1040
    DPRINTF("Register OPENPIC timer %08x => %08x\n",
1041
            addr + 0x1100, addr + 0x1100 + 0x40 * MAX_TMR);
1042
    /* Interrupt source registers */
1043
    DPRINTF("Register OPENPIC src   %08x => %08x\n",
1044
            addr + 0x10000, addr + 0x10000 + 0x20 * (OPENPIC_EXT_IRQ + 2));
1045
    /* Per CPU registers */
1046
    DPRINTF("Register OPENPIC dst   %08x => %08x\n",
1047
            addr + 0x20000, addr + 0x20000 + 0x1000 * MAX_CPU);
1048
    cpu_register_physical_memory(addr, 0x40000, opp->mem_index);
1049
#if 0 // Don't implement ISU for now
1050
    opp_io_memory = cpu_register_io_memory(0, openpic_src_read,
1051
                                           openpic_src_write);
1052
    cpu_register_physical_memory(isu_base, 0x20 * (EXT_IRQ + 2),
1053
                                 opp_io_memory);
1054
#endif
1055
}
1056

    
1057
static void openpic_save_IRQ_queue(QEMUFile* f, IRQ_queue_t *q)
1058
{
1059
    unsigned int i;
1060

    
1061
    for (i = 0; i < BF_WIDTH(MAX_IRQ); i++)
1062
        qemu_put_be32s(f, &q->queue[i]);
1063

    
1064
    qemu_put_sbe32s(f, &q->next);
1065
    qemu_put_sbe32s(f, &q->priority);
1066
}
1067

    
1068
static void openpic_save(QEMUFile* f, void *opaque)
1069
{
1070
    openpic_t *opp = (openpic_t *)opaque;
1071
    unsigned int i;
1072

    
1073
    qemu_put_be32s(f, &opp->frep);
1074
    qemu_put_be32s(f, &opp->glbc);
1075
    qemu_put_be32s(f, &opp->micr);
1076
    qemu_put_be32s(f, &opp->veni);
1077
    qemu_put_be32s(f, &opp->pint);
1078
    qemu_put_be32s(f, &opp->spve);
1079
    qemu_put_be32s(f, &opp->tifr);
1080

    
1081
    for (i = 0; i < opp->max_irq; i++) {
1082
        qemu_put_be32s(f, &opp->src[i].ipvp);
1083
        qemu_put_be32s(f, &opp->src[i].ide);
1084
        qemu_put_sbe32s(f, &opp->src[i].type);
1085
        qemu_put_sbe32s(f, &opp->src[i].last_cpu);
1086
        qemu_put_sbe32s(f, &opp->src[i].pending);
1087
    }
1088

    
1089
    qemu_put_sbe32s(f, &opp->nb_cpus);
1090

    
1091
    for (i = 0; i < opp->nb_cpus; i++) {
1092
        qemu_put_be32s(f, &opp->dst[i].tfrr);
1093
        qemu_put_be32s(f, &opp->dst[i].pctp);
1094
        qemu_put_be32s(f, &opp->dst[i].pcsr);
1095
        openpic_save_IRQ_queue(f, &opp->dst[i].raised);
1096
        openpic_save_IRQ_queue(f, &opp->dst[i].servicing);
1097
    }
1098

    
1099
    for (i = 0; i < MAX_TMR; i++) {
1100
        qemu_put_be32s(f, &opp->timers[i].ticc);
1101
        qemu_put_be32s(f, &opp->timers[i].tibc);
1102
    }
1103

    
1104
#if MAX_DBL > 0
1105
    qemu_put_be32s(f, &opp->dar);
1106

    
1107
    for (i = 0; i < MAX_DBL; i++) {
1108
        qemu_put_be32s(f, &opp->doorbells[i].dmr);
1109
    }
1110
#endif
1111

    
1112
#if MAX_MBX > 0
1113
    for (i = 0; i < MAX_MAILBOXES; i++) {
1114
        qemu_put_be32s(f, &opp->mailboxes[i].mbr);
1115
    }
1116
#endif
1117

    
1118
    pci_device_save(&opp->pci_dev, f);
1119
}
1120

    
1121
static void openpic_load_IRQ_queue(QEMUFile* f, IRQ_queue_t *q)
1122
{
1123
    unsigned int i;
1124

    
1125
    for (i = 0; i < BF_WIDTH(MAX_IRQ); i++)
1126
        qemu_get_be32s(f, &q->queue[i]);
1127

    
1128
    qemu_get_sbe32s(f, &q->next);
1129
    qemu_get_sbe32s(f, &q->priority);
1130
}
1131

    
1132
static int openpic_load(QEMUFile* f, void *opaque, int version_id)
1133
{
1134
    openpic_t *opp = (openpic_t *)opaque;
1135
    unsigned int i;
1136

    
1137
    if (version_id != 1)
1138
        return -EINVAL;
1139

    
1140
    qemu_get_be32s(f, &opp->frep);
1141
    qemu_get_be32s(f, &opp->glbc);
1142
    qemu_get_be32s(f, &opp->micr);
1143
    qemu_get_be32s(f, &opp->veni);
1144
    qemu_get_be32s(f, &opp->pint);
1145
    qemu_get_be32s(f, &opp->spve);
1146
    qemu_get_be32s(f, &opp->tifr);
1147

    
1148
    for (i = 0; i < opp->max_irq; i++) {
1149
        qemu_get_be32s(f, &opp->src[i].ipvp);
1150
        qemu_get_be32s(f, &opp->src[i].ide);
1151
        qemu_get_sbe32s(f, &opp->src[i].type);
1152
        qemu_get_sbe32s(f, &opp->src[i].last_cpu);
1153
        qemu_get_sbe32s(f, &opp->src[i].pending);
1154
    }
1155

    
1156
    qemu_get_sbe32s(f, &opp->nb_cpus);
1157

    
1158
    for (i = 0; i < opp->nb_cpus; i++) {
1159
        qemu_get_be32s(f, &opp->dst[i].tfrr);
1160
        qemu_get_be32s(f, &opp->dst[i].pctp);
1161
        qemu_get_be32s(f, &opp->dst[i].pcsr);
1162
        openpic_load_IRQ_queue(f, &opp->dst[i].raised);
1163
        openpic_load_IRQ_queue(f, &opp->dst[i].servicing);
1164
    }
1165

    
1166
    for (i = 0; i < MAX_TMR; i++) {
1167
        qemu_get_be32s(f, &opp->timers[i].ticc);
1168
        qemu_get_be32s(f, &opp->timers[i].tibc);
1169
    }
1170

    
1171
#if MAX_DBL > 0
1172
    qemu_get_be32s(f, &opp->dar);
1173

    
1174
    for (i = 0; i < MAX_DBL; i++) {
1175
        qemu_get_be32s(f, &opp->doorbells[i].dmr);
1176
    }
1177
#endif
1178

    
1179
#if MAX_MBX > 0
1180
    for (i = 0; i < MAX_MAILBOXES; i++) {
1181
        qemu_get_be32s(f, &opp->mailboxes[i].mbr);
1182
    }
1183
#endif
1184

    
1185
    return pci_device_load(&opp->pci_dev, f);
1186
}
1187

    
1188
static void openpic_irq_raise(openpic_t *opp, int n_CPU, IRQ_src_t *src)
1189
{
1190
    qemu_irq_raise(opp->dst[n_CPU].irqs[OPENPIC_OUTPUT_INT]);
1191
}
1192

    
1193
qemu_irq *openpic_init (PCIBus *bus, int *pmem_index, int nb_cpus,
1194
                        qemu_irq **irqs, qemu_irq irq_out)
1195
{
1196
    openpic_t *opp;
1197
    uint8_t *pci_conf;
1198
    int i, m;
1199

    
1200
    /* XXX: for now, only one CPU is supported */
1201
    if (nb_cpus != 1)
1202
        return NULL;
1203
    if (bus) {
1204
        opp = (openpic_t *)pci_register_device(bus, "OpenPIC", sizeof(openpic_t),
1205
                                               -1, NULL, NULL);
1206
        if (opp == NULL)
1207
            return NULL;
1208
        pci_conf = opp->pci_dev.config;
1209
        pci_config_set_vendor_id(pci_conf, PCI_VENDOR_ID_IBM);
1210
        pci_config_set_device_id(pci_conf, PCI_DEVICE_ID_IBM_OPENPIC2);
1211
        pci_config_set_class(pci_conf, PCI_CLASS_SYSTEM_OTHER); // FIXME?
1212
        pci_conf[0x0e] = 0x00; // header_type
1213
        pci_conf[0x3d] = 0x00; // no interrupt pin
1214

    
1215
        /* Register I/O spaces */
1216
        pci_register_io_region((PCIDevice *)opp, 0, 0x40000,
1217
                               PCI_ADDRESS_SPACE_MEM, &openpic_map);
1218
    } else {
1219
        opp = qemu_mallocz(sizeof(openpic_t));
1220
    }
1221
    opp->mem_index = cpu_register_io_memory(0, openpic_read,
1222
                                            openpic_write, opp);
1223

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

    
1252
    register_savevm("openpic", 0, 2, openpic_save, openpic_load, opp);
1253
    qemu_register_reset(openpic_reset, opp);
1254

    
1255
    opp->irq_raise = openpic_irq_raise;
1256
    opp->reset = openpic_reset;
1257

    
1258
    opp->reset(opp);
1259
    if (pmem_index)
1260
        *pmem_index = opp->mem_index;
1261

    
1262
    return qemu_allocate_irqs(openpic_set_irq, opp, opp->max_irq);
1263
}
1264

    
1265
static void mpic_irq_raise(openpic_t *mpp, int n_CPU, IRQ_src_t *src)
1266
{
1267
    int n_ci = IDR_CI0 - n_CPU;
1268
    DPRINTF("%s: cpu:%d irq:%d (testbit idr:%x ci:%d)\n", __func__,
1269
                    n_CPU, n_IRQ, mpp->src[n_IRQ].ide, n_ci);
1270
    if(test_bit(&src->ide, n_ci)) {
1271
        qemu_irq_raise(mpp->dst[n_CPU].irqs[OPENPIC_OUTPUT_CINT]);
1272
    }
1273
    else {
1274
        qemu_irq_raise(mpp->dst[n_CPU].irqs[OPENPIC_OUTPUT_INT]);
1275
    }
1276
}
1277

    
1278
static void mpic_reset (void *opaque)
1279
{
1280
    openpic_t *mpp = (openpic_t *)opaque;
1281
    int i;
1282

    
1283
    mpp->glbc = 0x80000000;
1284
    /* Initialise controller registers */
1285
    mpp->frep = 0x004f0002;
1286
    mpp->veni = VENI;
1287
    mpp->pint = 0x00000000;
1288
    mpp->spve = 0x0000FFFF;
1289
    /* Initialise IRQ sources */
1290
    for (i = 0; i < mpp->max_irq; i++) {
1291
        mpp->src[i].ipvp = 0x80800000;
1292
        mpp->src[i].ide  = 0x00000001;
1293
    }
1294
    /* Initialise IRQ destinations */
1295
    for (i = 0; i < MAX_CPU; i++) {
1296
        mpp->dst[i].pctp      = 0x0000000F;
1297
        mpp->dst[i].tfrr      = 0x00000000;
1298
        memset(&mpp->dst[i].raised, 0, sizeof(IRQ_queue_t));
1299
        mpp->dst[i].raised.next = -1;
1300
        memset(&mpp->dst[i].servicing, 0, sizeof(IRQ_queue_t));
1301
        mpp->dst[i].servicing.next = -1;
1302
    }
1303
    /* Initialise timers */
1304
    for (i = 0; i < MAX_TMR; i++) {
1305
        mpp->timers[i].ticc = 0x00000000;
1306
        mpp->timers[i].tibc = 0x80000000;
1307
    }
1308
    /* Go out of RESET state */
1309
    mpp->glbc = 0x00000000;
1310
}
1311

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

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

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

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

    
1377
    return retval;
1378
}
1379

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

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

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

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

    
1409
    DPRINTF("%s: addr %08x\n", __func__, addr);
1410
    retval = 0xFFFFFFFF;
1411
    if (addr & 0xF)
1412
        return retval;
1413

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

    
1427
    return retval;
1428
}
1429

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

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

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

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

    
1459
    DPRINTF("%s: addr %08x\n", __func__, addr);
1460
    retval = 0xFFFFFFFF;
1461
    if (addr & 0xF)
1462
        return retval;
1463

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

    
1477
    return retval;
1478
}
1479

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

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

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

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

    
1509
    DPRINTF("%s: addr %08x\n", __func__, addr);
1510
    retval = 0xFFFFFFFF;
1511
    if (addr & 0xF)
1512
        return retval;
1513

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

    
1527
    return retval;
1528
}
1529

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

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

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

    
1558
    DPRINTF("%s: addr %08x\n", __func__, addr);
1559
    retval = 0xFFFFFFFF;
1560
    if (addr & 0xF)
1561
        return retval;
1562

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

    
1576
    return retval;
1577
}
1578

    
1579
static CPUWriteMemoryFunc *mpic_glb_write[] = {
1580
    &openpic_buggy_write,
1581
    &openpic_buggy_write,
1582
    &openpic_gbl_write,
1583
};
1584

    
1585
static CPUReadMemoryFunc *mpic_glb_read[] = {
1586
    &openpic_buggy_read,
1587
    &openpic_buggy_read,
1588
    &openpic_gbl_read,
1589
};
1590

    
1591
static CPUWriteMemoryFunc *mpic_tmr_write[] = {
1592
    &openpic_buggy_write,
1593
    &openpic_buggy_write,
1594
    &mpic_timer_write,
1595
};
1596

    
1597
static CPUReadMemoryFunc *mpic_tmr_read[] = {
1598
    &openpic_buggy_read,
1599
    &openpic_buggy_read,
1600
    &mpic_timer_read,
1601
};
1602

    
1603
static CPUWriteMemoryFunc *mpic_cpu_write[] = {
1604
    &openpic_buggy_write,
1605
    &openpic_buggy_write,
1606
    &openpic_cpu_write,
1607
};
1608

    
1609
static CPUReadMemoryFunc *mpic_cpu_read[] = {
1610
    &openpic_buggy_read,
1611
    &openpic_buggy_read,
1612
    &openpic_cpu_read,
1613
};
1614

    
1615
static CPUWriteMemoryFunc *mpic_ext_write[] = {
1616
    &openpic_buggy_write,
1617
    &openpic_buggy_write,
1618
    &mpic_src_ext_write,
1619
};
1620

    
1621
static CPUReadMemoryFunc *mpic_ext_read[] = {
1622
    &openpic_buggy_read,
1623
    &openpic_buggy_read,
1624
    &mpic_src_ext_read,
1625
};
1626

    
1627
static CPUWriteMemoryFunc *mpic_int_write[] = {
1628
    &openpic_buggy_write,
1629
    &openpic_buggy_write,
1630
    &mpic_src_int_write,
1631
};
1632

    
1633
static CPUReadMemoryFunc *mpic_int_read[] = {
1634
    &openpic_buggy_read,
1635
    &openpic_buggy_read,
1636
    &mpic_src_int_read,
1637
};
1638

    
1639
static CPUWriteMemoryFunc *mpic_msg_write[] = {
1640
    &openpic_buggy_write,
1641
    &openpic_buggy_write,
1642
    &mpic_src_msg_write,
1643
};
1644

    
1645
static CPUReadMemoryFunc *mpic_msg_read[] = {
1646
    &openpic_buggy_read,
1647
    &openpic_buggy_read,
1648
    &mpic_src_msg_read,
1649
};
1650
static CPUWriteMemoryFunc *mpic_msi_write[] = {
1651
    &openpic_buggy_write,
1652
    &openpic_buggy_write,
1653
    &mpic_src_msi_write,
1654
};
1655

    
1656
static CPUReadMemoryFunc *mpic_msi_read[] = {
1657
    &openpic_buggy_read,
1658
    &openpic_buggy_read,
1659
    &mpic_src_msi_read,
1660
};
1661

    
1662
qemu_irq *mpic_init (target_phys_addr_t base, int nb_cpus,
1663
                        qemu_irq **irqs, qemu_irq irq_out)
1664
{
1665
    openpic_t *mpp;
1666
    int i;
1667
    struct {
1668
        CPUReadMemoryFunc **read;
1669
        CPUWriteMemoryFunc **write;
1670
        target_phys_addr_t start_addr;
1671
        ram_addr_t size;
1672
    } list[] = {
1673
        {mpic_glb_read, mpic_glb_write, MPIC_GLB_REG_START, MPIC_GLB_REG_SIZE},
1674
        {mpic_tmr_read, mpic_tmr_write, MPIC_TMR_REG_START, MPIC_TMR_REG_SIZE},
1675
        {mpic_ext_read, mpic_ext_write, MPIC_EXT_REG_START, MPIC_EXT_REG_SIZE},
1676
        {mpic_int_read, mpic_int_write, MPIC_INT_REG_START, MPIC_INT_REG_SIZE},
1677
        {mpic_msg_read, mpic_msg_write, MPIC_MSG_REG_START, MPIC_MSG_REG_SIZE},
1678
        {mpic_msi_read, mpic_msi_write, MPIC_MSI_REG_START, MPIC_MSI_REG_SIZE},
1679
        {mpic_cpu_read, mpic_cpu_write, MPIC_CPU_REG_START, MPIC_CPU_REG_SIZE},
1680
    };
1681

    
1682
    /* XXX: for now, only one CPU is supported */
1683
    if (nb_cpus != 1)
1684
        return NULL;
1685

    
1686
    mpp = qemu_mallocz(sizeof(openpic_t));
1687

    
1688
    for (i = 0; i < sizeof(list)/sizeof(list[0]); i++) {
1689
        int mem_index;
1690

    
1691
        mem_index = cpu_register_io_memory(0, list[i].read, list[i].write, mpp);
1692
        if (mem_index < 0) {
1693
            goto free;
1694
        }
1695
        cpu_register_physical_memory(base + list[i].start_addr,
1696
                                     list[i].size, mem_index);
1697
    }
1698

    
1699
    mpp->nb_cpus = nb_cpus;
1700
    mpp->max_irq = MPIC_MAX_IRQ;
1701
    mpp->irq_ipi0 = MPIC_IPI_IRQ;
1702
    mpp->irq_tim0 = MPIC_TMR_IRQ;
1703

    
1704
    for (i = 0; i < nb_cpus; i++)
1705
        mpp->dst[i].irqs = irqs[i];
1706
    mpp->irq_out = irq_out;
1707
    mpp->need_swap = 0;    /* MPIC has the same endian as target */
1708

    
1709
    mpp->irq_raise = mpic_irq_raise;
1710
    mpp->reset = mpic_reset;
1711

    
1712
    register_savevm("mpic", 0, 2, openpic_save, openpic_load, mpp);
1713
    qemu_register_reset(mpic_reset, mpp);
1714
    mpp->reset(mpp);
1715

    
1716
    return qemu_allocate_irqs(openpic_set_irq, mpp, mpp->max_irq);
1717

    
1718
free:
1719
    qemu_free(mpp);
1720
    return NULL;
1721
}