sync with tizen_2.2
[sdk/emulator/qemu.git] / hw / openpic.c
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 /*
134  * Block Revision Register1 (BRR1): QEMU does not fully emulate
135  * any version on MPIC. So to start with, set the IP version to 0.
136  *
137  * NOTE: This is Freescale MPIC specific register. Keep it here till
138  * this code is refactored for different variants of OPENPIC and MPIC.
139  */
140 #define FSL_BRR1_IPID (0x0040 << 16) /* 16 bit IP-block ID */
141 #define FSL_BRR1_IPMJ (0x00 << 8) /* 8 bit IP major number */
142 #define FSL_BRR1_IPMN 0x00 /* 8 bit IP minor number */
143
144 enum mpic_ide_bits {
145     IDR_EP     = 31,
146     IDR_CI0     = 30,
147     IDR_CI1     = 29,
148     IDR_P1     = 1,
149     IDR_P0     = 0,
150 };
151
152 #else
153 #error "Please select which OpenPic implementation is to be emulated"
154 #endif
155
156 #define OPENPIC_PAGE_SIZE 4096
157
158 #define BF_WIDTH(_bits_) \
159 (((_bits_) + (sizeof(uint32_t) * 8) - 1) / (sizeof(uint32_t) * 8))
160
161 static inline void set_bit (uint32_t *field, int bit)
162 {
163     field[bit >> 5] |= 1 << (bit & 0x1F);
164 }
165
166 static inline void reset_bit (uint32_t *field, int bit)
167 {
168     field[bit >> 5] &= ~(1 << (bit & 0x1F));
169 }
170
171 static inline int test_bit (uint32_t *field, int bit)
172 {
173     return (field[bit >> 5] & 1 << (bit & 0x1F)) != 0;
174 }
175
176 static int get_current_cpu(void)
177 {
178   return cpu_single_env->cpu_index;
179 }
180
181 static uint32_t openpic_cpu_read_internal(void *opaque, target_phys_addr_t addr,
182                                           int idx);
183 static void openpic_cpu_write_internal(void *opaque, target_phys_addr_t addr,
184                                        uint32_t val, int idx);
185
186 enum {
187     IRQ_EXTERNAL = 0x01,
188     IRQ_INTERNAL = 0x02,
189     IRQ_TIMER    = 0x04,
190     IRQ_SPECIAL  = 0x08,
191 };
192
193 typedef struct IRQ_queue_t {
194     uint32_t queue[BF_WIDTH(MAX_IRQ)];
195     int next;
196     int priority;
197 } IRQ_queue_t;
198
199 typedef struct IRQ_src_t {
200     uint32_t ipvp;  /* IRQ vector/priority register */
201     uint32_t ide;   /* IRQ destination register */
202     int type;
203     int last_cpu;
204     int pending;    /* TRUE if IRQ is pending */
205 } IRQ_src_t;
206
207 enum IPVP_bits {
208     IPVP_MASK     = 31,
209     IPVP_ACTIVITY = 30,
210     IPVP_MODE     = 29,
211     IPVP_POLARITY = 23,
212     IPVP_SENSE    = 22,
213 };
214 #define IPVP_PRIORITY_MASK     (0x1F << 16)
215 #define IPVP_PRIORITY(_ipvpr_) ((int)(((_ipvpr_) & IPVP_PRIORITY_MASK) >> 16))
216 #define IPVP_VECTOR_MASK       ((1 << VECTOR_BITS) - 1)
217 #define IPVP_VECTOR(_ipvpr_)   ((_ipvpr_) & IPVP_VECTOR_MASK)
218
219 typedef struct IRQ_dst_t {
220     uint32_t tfrr;
221     uint32_t pctp; /* CPU current task priority */
222     uint32_t pcsr; /* CPU sensitivity register */
223     IRQ_queue_t raised;
224     IRQ_queue_t servicing;
225     qemu_irq *irqs;
226 } IRQ_dst_t;
227
228 typedef struct openpic_t {
229     PCIDevice pci_dev;
230     MemoryRegion mem;
231
232     /* Sub-regions */
233     MemoryRegion sub_io_mem[7];
234
235     /* Global registers */
236     uint32_t frep; /* Feature reporting register */
237     uint32_t glbc; /* Global configuration register  */
238     uint32_t micr; /* MPIC interrupt configuration register */
239     uint32_t veni; /* Vendor identification register */
240     uint32_t pint; /* Processor initialization register */
241     uint32_t spve; /* Spurious vector register */
242     uint32_t tifr; /* Timer frequency reporting register */
243     /* Source registers */
244     IRQ_src_t src[MAX_IRQ];
245     /* Local registers per output pin */
246     IRQ_dst_t dst[MAX_CPU];
247     int nb_cpus;
248     /* Timer registers */
249     struct {
250         uint32_t ticc;  /* Global timer current count register */
251         uint32_t tibc;  /* Global timer base count register */
252     } timers[MAX_TMR];
253 #if MAX_DBL > 0
254     /* Doorbell registers */
255     uint32_t dar;        /* Doorbell activate register */
256     struct {
257         uint32_t dmr;    /* Doorbell messaging register */
258     } doorbells[MAX_DBL];
259 #endif
260 #if MAX_MBX > 0
261     /* Mailbox registers */
262     struct {
263         uint32_t mbr;    /* Mailbox register */
264     } mailboxes[MAX_MAILBOXES];
265 #endif
266     /* IRQ out is used when in bypass mode (not implemented) */
267     qemu_irq irq_out;
268     int max_irq;
269     int irq_ipi0;
270     int irq_tim0;
271     void (*reset) (void *);
272     void (*irq_raise) (struct openpic_t *, int, IRQ_src_t *);
273 } openpic_t;
274
275 static inline void IRQ_setbit (IRQ_queue_t *q, int n_IRQ)
276 {
277     set_bit(q->queue, n_IRQ);
278 }
279
280 static inline void IRQ_resetbit (IRQ_queue_t *q, int n_IRQ)
281 {
282     reset_bit(q->queue, n_IRQ);
283 }
284
285 static inline int IRQ_testbit (IRQ_queue_t *q, int n_IRQ)
286 {
287     return test_bit(q->queue, n_IRQ);
288 }
289
290 static void IRQ_check (openpic_t *opp, IRQ_queue_t *q)
291 {
292     int next, i;
293     int priority;
294
295     next = -1;
296     priority = -1;
297     for (i = 0; i < opp->max_irq; i++) {
298         if (IRQ_testbit(q, i)) {
299             DPRINTF("IRQ_check: irq %d set ipvp_pr=%d pr=%d\n",
300                     i, IPVP_PRIORITY(opp->src[i].ipvp), priority);
301             if (IPVP_PRIORITY(opp->src[i].ipvp) > priority) {
302                 next = i;
303                 priority = IPVP_PRIORITY(opp->src[i].ipvp);
304             }
305         }
306     }
307     q->next = next;
308     q->priority = priority;
309 }
310
311 static int IRQ_get_next (openpic_t *opp, IRQ_queue_t *q)
312 {
313     if (q->next == -1) {
314         /* XXX: optimize */
315         IRQ_check(opp, q);
316     }
317
318     return q->next;
319 }
320
321 static void IRQ_local_pipe (openpic_t *opp, int n_CPU, int n_IRQ)
322 {
323     IRQ_dst_t *dst;
324     IRQ_src_t *src;
325     int priority;
326
327     dst = &opp->dst[n_CPU];
328     src = &opp->src[n_IRQ];
329     priority = IPVP_PRIORITY(src->ipvp);
330     if (priority <= dst->pctp) {
331         /* Too low priority */
332         DPRINTF("%s: IRQ %d has too low priority on CPU %d\n",
333                 __func__, n_IRQ, n_CPU);
334         return;
335     }
336     if (IRQ_testbit(&dst->raised, n_IRQ)) {
337         /* Interrupt miss */
338         DPRINTF("%s: IRQ %d was missed on CPU %d\n",
339                 __func__, n_IRQ, n_CPU);
340         return;
341     }
342     set_bit(&src->ipvp, IPVP_ACTIVITY);
343     IRQ_setbit(&dst->raised, n_IRQ);
344     if (priority < dst->raised.priority) {
345         /* An higher priority IRQ is already raised */
346         DPRINTF("%s: IRQ %d is hidden by raised IRQ %d on CPU %d\n",
347                 __func__, n_IRQ, dst->raised.next, n_CPU);
348         return;
349     }
350     IRQ_get_next(opp, &dst->raised);
351     if (IRQ_get_next(opp, &dst->servicing) != -1 &&
352         priority <= dst->servicing.priority) {
353         DPRINTF("%s: IRQ %d is hidden by servicing IRQ %d on CPU %d\n",
354                 __func__, n_IRQ, dst->servicing.next, n_CPU);
355         /* Already servicing a higher priority IRQ */
356         return;
357     }
358     DPRINTF("Raise OpenPIC INT output cpu %d irq %d\n", n_CPU, n_IRQ);
359     opp->irq_raise(opp, n_CPU, src);
360 }
361
362 /* update pic state because registers for n_IRQ have changed value */
363 static void openpic_update_irq(openpic_t *opp, int n_IRQ)
364 {
365     IRQ_src_t *src;
366     int i;
367
368     src = &opp->src[n_IRQ];
369
370     if (!src->pending) {
371         /* no irq pending */
372         DPRINTF("%s: IRQ %d is not pending\n", __func__, n_IRQ);
373         return;
374     }
375     if (test_bit(&src->ipvp, IPVP_MASK)) {
376         /* Interrupt source is disabled */
377         DPRINTF("%s: IRQ %d is disabled\n", __func__, n_IRQ);
378         return;
379     }
380     if (IPVP_PRIORITY(src->ipvp) == 0) {
381         /* Priority set to zero */
382         DPRINTF("%s: IRQ %d has 0 priority\n", __func__, n_IRQ);
383         return;
384     }
385     if (test_bit(&src->ipvp, IPVP_ACTIVITY)) {
386         /* IRQ already active */
387         DPRINTF("%s: IRQ %d is already active\n", __func__, n_IRQ);
388         return;
389     }
390     if (src->ide == 0x00000000) {
391         /* No target */
392         DPRINTF("%s: IRQ %d has no target\n", __func__, n_IRQ);
393         return;
394     }
395
396     if (src->ide == (1 << src->last_cpu)) {
397         /* Only one CPU is allowed to receive this IRQ */
398         IRQ_local_pipe(opp, src->last_cpu, n_IRQ);
399     } else if (!test_bit(&src->ipvp, IPVP_MODE)) {
400         /* Directed delivery mode */
401         for (i = 0; i < opp->nb_cpus; i++) {
402             if (test_bit(&src->ide, i))
403                 IRQ_local_pipe(opp, i, n_IRQ);
404         }
405     } else {
406         /* Distributed delivery mode */
407         for (i = src->last_cpu + 1; i != src->last_cpu; i++) {
408             if (i == opp->nb_cpus)
409                 i = 0;
410             if (test_bit(&src->ide, i)) {
411                 IRQ_local_pipe(opp, i, n_IRQ);
412                 src->last_cpu = i;
413                 break;
414             }
415         }
416     }
417 }
418
419 static void openpic_set_irq(void *opaque, int n_IRQ, int level)
420 {
421     openpic_t *opp = opaque;
422     IRQ_src_t *src;
423
424     src = &opp->src[n_IRQ];
425     DPRINTF("openpic: set irq %d = %d ipvp=%08x\n",
426             n_IRQ, level, src->ipvp);
427     if (test_bit(&src->ipvp, IPVP_SENSE)) {
428         /* level-sensitive irq */
429         src->pending = level;
430         if (!level)
431             reset_bit(&src->ipvp, IPVP_ACTIVITY);
432     } else {
433         /* edge-sensitive irq */
434         if (level)
435             src->pending = 1;
436     }
437     openpic_update_irq(opp, n_IRQ);
438 }
439
440 static void openpic_reset (void *opaque)
441 {
442     openpic_t *opp = (openpic_t *)opaque;
443     int i;
444
445     opp->glbc = 0x80000000;
446     /* Initialise controller registers */
447     opp->frep = ((OPENPIC_EXT_IRQ - 1) << 16) | ((MAX_CPU - 1) << 8) | VID;
448     opp->veni = VENI;
449     opp->pint = 0x00000000;
450     opp->spve = 0x000000FF;
451     opp->tifr = 0x003F7A00;
452     /* ? */
453     opp->micr = 0x00000000;
454     /* Initialise IRQ sources */
455     for (i = 0; i < opp->max_irq; i++) {
456         opp->src[i].ipvp = 0xA0000000;
457         opp->src[i].ide  = 0x00000000;
458     }
459     /* Initialise IRQ destinations */
460     for (i = 0; i < MAX_CPU; i++) {
461         opp->dst[i].pctp      = 0x0000000F;
462         opp->dst[i].pcsr      = 0x00000000;
463         memset(&opp->dst[i].raised, 0, sizeof(IRQ_queue_t));
464         opp->dst[i].raised.next = -1;
465         memset(&opp->dst[i].servicing, 0, sizeof(IRQ_queue_t));
466         opp->dst[i].servicing.next = -1;
467     }
468     /* Initialise timers */
469     for (i = 0; i < MAX_TMR; i++) {
470         opp->timers[i].ticc = 0x00000000;
471         opp->timers[i].tibc = 0x80000000;
472     }
473     /* Initialise doorbells */
474 #if MAX_DBL > 0
475     opp->dar = 0x00000000;
476     for (i = 0; i < MAX_DBL; i++) {
477         opp->doorbells[i].dmr  = 0x00000000;
478     }
479 #endif
480     /* Initialise mailboxes */
481 #if MAX_MBX > 0
482     for (i = 0; i < MAX_MBX; i++) { /* ? */
483         opp->mailboxes[i].mbr   = 0x00000000;
484     }
485 #endif
486     /* Go out of RESET state */
487     opp->glbc = 0x00000000;
488 }
489
490 static inline uint32_t read_IRQreg_ide(openpic_t *opp, int n_IRQ)
491 {
492     return opp->src[n_IRQ].ide;
493 }
494
495 static inline uint32_t read_IRQreg_ipvp(openpic_t *opp, int n_IRQ)
496 {
497     return opp->src[n_IRQ].ipvp;
498 }
499
500 static inline void write_IRQreg_ide(openpic_t *opp, int n_IRQ, uint32_t val)
501 {
502     uint32_t tmp;
503
504     tmp = val & 0xC0000000;
505     tmp |= val & ((1ULL << 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 }
509
510 static inline void write_IRQreg_ipvp(openpic_t *opp, int n_IRQ, uint32_t val)
511 {
512     /* NOTE: not fully accurate for special IRQs, but simple and sufficient */
513     /* ACTIVITY bit is read-only */
514     opp->src[n_IRQ].ipvp = (opp->src[n_IRQ].ipvp & 0x40000000)
515                          | (val & 0x800F00FF);
516     openpic_update_irq(opp, n_IRQ);
517     DPRINTF("Set IPVP %d to 0x%08x -> 0x%08x\n", n_IRQ, val,
518             opp->src[n_IRQ].ipvp);
519 }
520
521 #if 0 // Code provision for Intel model
522 #if MAX_DBL > 0
523 static uint32_t read_doorbell_register (openpic_t *opp,
524                                         int n_dbl, uint32_t offset)
525 {
526     uint32_t retval;
527
528     switch (offset) {
529     case DBL_IPVP_OFFSET:
530         retval = read_IRQreg_ipvp(opp, IRQ_DBL0 + n_dbl);
531         break;
532     case DBL_IDE_OFFSET:
533         retval = read_IRQreg_ide(opp, IRQ_DBL0 + n_dbl);
534         break;
535     case DBL_DMR_OFFSET:
536         retval = opp->doorbells[n_dbl].dmr;
537         break;
538     }
539
540     return retval;
541 }
542
543 static void write_doorbell_register (penpic_t *opp, int n_dbl,
544                                      uint32_t offset, uint32_t value)
545 {
546     switch (offset) {
547     case DBL_IVPR_OFFSET:
548         write_IRQreg_ipvp(opp, IRQ_DBL0 + n_dbl, value);
549         break;
550     case DBL_IDE_OFFSET:
551         write_IRQreg_ide(opp, IRQ_DBL0 + n_dbl, value);
552         break;
553     case DBL_DMR_OFFSET:
554         opp->doorbells[n_dbl].dmr = value;
555         break;
556     }
557 }
558 #endif
559
560 #if MAX_MBX > 0
561 static uint32_t read_mailbox_register (openpic_t *opp,
562                                        int n_mbx, uint32_t offset)
563 {
564     uint32_t retval;
565
566     switch (offset) {
567     case MBX_MBR_OFFSET:
568         retval = opp->mailboxes[n_mbx].mbr;
569         break;
570     case MBX_IVPR_OFFSET:
571         retval = read_IRQreg_ipvp(opp, IRQ_MBX0 + n_mbx);
572         break;
573     case MBX_DMR_OFFSET:
574         retval = read_IRQreg_ide(opp, IRQ_MBX0 + n_mbx);
575         break;
576     }
577
578     return retval;
579 }
580
581 static void write_mailbox_register (openpic_t *opp, int n_mbx,
582                                     uint32_t address, uint32_t value)
583 {
584     switch (offset) {
585     case MBX_MBR_OFFSET:
586         opp->mailboxes[n_mbx].mbr = value;
587         break;
588     case MBX_IVPR_OFFSET:
589         write_IRQreg_ipvp(opp, IRQ_MBX0 + n_mbx, value);
590         break;
591     case MBX_DMR_OFFSET:
592         write_IRQreg_ide(opp, IRQ_MBX0 + n_mbx, value);
593         break;
594     }
595 }
596 #endif
597 #endif /* 0 : Code provision for Intel model */
598
599 static void openpic_gbl_write (void *opaque, target_phys_addr_t addr, uint32_t val)
600 {
601     openpic_t *opp = opaque;
602     IRQ_dst_t *dst;
603     int idx;
604
605     DPRINTF("%s: addr " TARGET_FMT_plx " <= %08x\n", __func__, addr, val);
606     if (addr & 0xF)
607         return;
608     switch (addr) {
609     case 0x00: /* Block Revision Register1 (BRR1) is Readonly */
610         break;
611     case 0x40:
612     case 0x50:
613     case 0x60:
614     case 0x70:
615     case 0x80:
616     case 0x90:
617     case 0xA0:
618     case 0xB0:
619         openpic_cpu_write_internal(opp, addr, val, get_current_cpu());
620         break;
621     case 0x1000: /* FREP */
622         break;
623     case 0x1020: /* GLBC */
624         if (val & 0x80000000 && opp->reset)
625             opp->reset(opp);
626         opp->glbc = val & ~0x80000000;
627         break;
628     case 0x1080: /* VENI */
629         break;
630     case 0x1090: /* PINT */
631         for (idx = 0; idx < opp->nb_cpus; idx++) {
632             if ((val & (1 << idx)) && !(opp->pint & (1 << idx))) {
633                 DPRINTF("Raise OpenPIC RESET output for CPU %d\n", idx);
634                 dst = &opp->dst[idx];
635                 qemu_irq_raise(dst->irqs[OPENPIC_OUTPUT_RESET]);
636             } else if (!(val & (1 << idx)) && (opp->pint & (1 << idx))) {
637                 DPRINTF("Lower OpenPIC RESET output for CPU %d\n", idx);
638                 dst = &opp->dst[idx];
639                 qemu_irq_lower(dst->irqs[OPENPIC_OUTPUT_RESET]);
640             }
641         }
642         opp->pint = val;
643         break;
644     case 0x10A0: /* IPI_IPVP */
645     case 0x10B0:
646     case 0x10C0:
647     case 0x10D0:
648         {
649             int idx;
650             idx = (addr - 0x10A0) >> 4;
651             write_IRQreg_ipvp(opp, opp->irq_ipi0 + idx, val);
652         }
653         break;
654     case 0x10E0: /* SPVE */
655         opp->spve = val & 0x000000FF;
656         break;
657     case 0x10F0: /* TIFR */
658         opp->tifr = val;
659         break;
660     default:
661         break;
662     }
663 }
664
665 static uint32_t openpic_gbl_read (void *opaque, target_phys_addr_t addr)
666 {
667     openpic_t *opp = opaque;
668     uint32_t retval;
669
670     DPRINTF("%s: addr " TARGET_FMT_plx "\n", __func__, addr);
671     retval = 0xFFFFFFFF;
672     if (addr & 0xF)
673         return retval;
674     switch (addr) {
675     case 0x1000: /* FREP */
676         retval = opp->frep;
677         break;
678     case 0x1020: /* GLBC */
679         retval = opp->glbc;
680         break;
681     case 0x1080: /* VENI */
682         retval = opp->veni;
683         break;
684     case 0x1090: /* PINT */
685         retval = 0x00000000;
686         break;
687     case 0x00: /* Block Revision Register1 (BRR1) */
688     case 0x40:
689     case 0x50:
690     case 0x60:
691     case 0x70:
692     case 0x80:
693     case 0x90:
694     case 0xA0:
695     case 0xB0:
696         retval = openpic_cpu_read_internal(opp, addr, get_current_cpu());
697         break;
698     case 0x10A0: /* IPI_IPVP */
699     case 0x10B0:
700     case 0x10C0:
701     case 0x10D0:
702         {
703             int idx;
704             idx = (addr - 0x10A0) >> 4;
705             retval = read_IRQreg_ipvp(opp, opp->irq_ipi0 + idx);
706         }
707         break;
708     case 0x10E0: /* SPVE */
709         retval = opp->spve;
710         break;
711     case 0x10F0: /* TIFR */
712         retval = opp->tifr;
713         break;
714     default:
715         break;
716     }
717     DPRINTF("%s: => %08x\n", __func__, retval);
718
719     return retval;
720 }
721
722 static void openpic_timer_write (void *opaque, uint32_t addr, uint32_t val)
723 {
724     openpic_t *opp = opaque;
725     int idx;
726
727     DPRINTF("%s: addr %08x <= %08x\n", __func__, addr, val);
728     if (addr & 0xF)
729         return;
730     addr -= 0x10;
731     addr &= 0xFFFF;
732     idx = (addr & 0xFFF0) >> 6;
733     addr = addr & 0x30;
734     switch (addr) {
735     case 0x00: /* TICC */
736         break;
737     case 0x10: /* TIBC */
738         if ((opp->timers[idx].ticc & 0x80000000) != 0 &&
739             (val & 0x80000000) == 0 &&
740             (opp->timers[idx].tibc & 0x80000000) != 0)
741             opp->timers[idx].ticc &= ~0x80000000;
742         opp->timers[idx].tibc = val;
743         break;
744     case 0x20: /* TIVP */
745         write_IRQreg_ipvp(opp, opp->irq_tim0 + idx, val);
746         break;
747     case 0x30: /* TIDE */
748         write_IRQreg_ide(opp, opp->irq_tim0 + idx, val);
749         break;
750     }
751 }
752
753 static uint32_t openpic_timer_read (void *opaque, uint32_t addr)
754 {
755     openpic_t *opp = opaque;
756     uint32_t retval;
757     int idx;
758
759     DPRINTF("%s: addr %08x\n", __func__, addr);
760     retval = 0xFFFFFFFF;
761     if (addr & 0xF)
762         return retval;
763     addr -= 0x10;
764     addr &= 0xFFFF;
765     idx = (addr & 0xFFF0) >> 6;
766     addr = addr & 0x30;
767     switch (addr) {
768     case 0x00: /* TICC */
769         retval = opp->timers[idx].ticc;
770         break;
771     case 0x10: /* TIBC */
772         retval = opp->timers[idx].tibc;
773         break;
774     case 0x20: /* TIPV */
775         retval = read_IRQreg_ipvp(opp, opp->irq_tim0 + idx);
776         break;
777     case 0x30: /* TIDE */
778         retval = read_IRQreg_ide(opp, opp->irq_tim0 + idx);
779         break;
780     }
781     DPRINTF("%s: => %08x\n", __func__, retval);
782
783     return retval;
784 }
785
786 static void openpic_src_write (void *opaque, uint32_t addr, uint32_t val)
787 {
788     openpic_t *opp = opaque;
789     int idx;
790
791     DPRINTF("%s: addr %08x <= %08x\n", __func__, addr, val);
792     if (addr & 0xF)
793         return;
794     addr = addr & 0xFFF0;
795     idx = addr >> 5;
796     if (addr & 0x10) {
797         /* EXDE / IFEDE / IEEDE */
798         write_IRQreg_ide(opp, idx, val);
799     } else {
800         /* EXVP / IFEVP / IEEVP */
801         write_IRQreg_ipvp(opp, idx, val);
802     }
803 }
804
805 static uint32_t openpic_src_read (void *opaque, uint32_t addr)
806 {
807     openpic_t *opp = opaque;
808     uint32_t retval;
809     int idx;
810
811     DPRINTF("%s: addr %08x\n", __func__, addr);
812     retval = 0xFFFFFFFF;
813     if (addr & 0xF)
814         return retval;
815     addr = addr & 0xFFF0;
816     idx = addr >> 5;
817     if (addr & 0x10) {
818         /* EXDE / IFEDE / IEEDE */
819         retval = read_IRQreg_ide(opp, idx);
820     } else {
821         /* EXVP / IFEVP / IEEVP */
822         retval = read_IRQreg_ipvp(opp, idx);
823     }
824     DPRINTF("%s: => %08x\n", __func__, retval);
825
826     return retval;
827 }
828
829 static void openpic_cpu_write_internal(void *opaque, target_phys_addr_t addr,
830                                        uint32_t val, int idx)
831 {
832     openpic_t *opp = opaque;
833     IRQ_src_t *src;
834     IRQ_dst_t *dst;
835     int s_IRQ, n_IRQ;
836
837     DPRINTF("%s: cpu %d addr " TARGET_FMT_plx " <= %08x\n", __func__, idx,
838             addr, val);
839     if (addr & 0xF)
840         return;
841     dst = &opp->dst[idx];
842     addr &= 0xFF0;
843     switch (addr) {
844 #if MAX_IPI > 0
845     case 0x40: /* IPIDR */
846     case 0x50:
847     case 0x60:
848     case 0x70:
849         idx = (addr - 0x40) >> 4;
850         /* we use IDE as mask which CPUs to deliver the IPI to still. */
851         write_IRQreg_ide(opp, opp->irq_ipi0 + idx,
852                          opp->src[opp->irq_ipi0 + idx].ide | val);
853         openpic_set_irq(opp, opp->irq_ipi0 + idx, 1);
854         openpic_set_irq(opp, opp->irq_ipi0 + idx, 0);
855         break;
856 #endif
857     case 0x80: /* PCTP */
858         dst->pctp = val & 0x0000000F;
859         break;
860     case 0x90: /* WHOAMI */
861         /* Read-only register */
862         break;
863     case 0xA0: /* PIAC */
864         /* Read-only register */
865         break;
866     case 0xB0: /* PEOI */
867         DPRINTF("PEOI\n");
868         s_IRQ = IRQ_get_next(opp, &dst->servicing);
869         IRQ_resetbit(&dst->servicing, s_IRQ);
870         dst->servicing.next = -1;
871         /* Set up next servicing IRQ */
872         s_IRQ = IRQ_get_next(opp, &dst->servicing);
873         /* Check queued interrupts. */
874         n_IRQ = IRQ_get_next(opp, &dst->raised);
875         src = &opp->src[n_IRQ];
876         if (n_IRQ != -1 &&
877             (s_IRQ == -1 ||
878              IPVP_PRIORITY(src->ipvp) > dst->servicing.priority)) {
879             DPRINTF("Raise OpenPIC INT output cpu %d irq %d\n",
880                     idx, n_IRQ);
881             opp->irq_raise(opp, idx, src);
882         }
883         break;
884     default:
885         break;
886     }
887 }
888
889 static void openpic_cpu_write(void *opaque, target_phys_addr_t addr, uint32_t val)
890 {
891     openpic_cpu_write_internal(opaque, addr, val, (addr & 0x1f000) >> 12);
892 }
893
894 static uint32_t openpic_cpu_read_internal(void *opaque, target_phys_addr_t addr,
895                                           int idx)
896 {
897     openpic_t *opp = opaque;
898     IRQ_src_t *src;
899     IRQ_dst_t *dst;
900     uint32_t retval;
901     int n_IRQ;
902
903     DPRINTF("%s: cpu %d addr " TARGET_FMT_plx "\n", __func__, idx, addr);
904     retval = 0xFFFFFFFF;
905     if (addr & 0xF)
906         return retval;
907     dst = &opp->dst[idx];
908     addr &= 0xFF0;
909     switch (addr) {
910     case 0x00: /* Block Revision Register1 (BRR1) */
911         retval = FSL_BRR1_IPID | FSL_BRR1_IPMJ | FSL_BRR1_IPMN;
912         break;
913     case 0x80: /* PCTP */
914         retval = dst->pctp;
915         break;
916     case 0x90: /* WHOAMI */
917         retval = idx;
918         break;
919     case 0xA0: /* PIAC */
920         DPRINTF("Lower OpenPIC INT output\n");
921         qemu_irq_lower(dst->irqs[OPENPIC_OUTPUT_INT]);
922         n_IRQ = IRQ_get_next(opp, &dst->raised);
923         DPRINTF("PIAC: irq=%d\n", n_IRQ);
924         if (n_IRQ == -1) {
925             /* No more interrupt pending */
926             retval = IPVP_VECTOR(opp->spve);
927         } else {
928             src = &opp->src[n_IRQ];
929             if (!test_bit(&src->ipvp, IPVP_ACTIVITY) ||
930                 !(IPVP_PRIORITY(src->ipvp) > dst->pctp)) {
931                 /* - Spurious level-sensitive IRQ
932                  * - Priorities has been changed
933                  *   and the pending IRQ isn't allowed anymore
934                  */
935                 reset_bit(&src->ipvp, IPVP_ACTIVITY);
936                 retval = IPVP_VECTOR(opp->spve);
937             } else {
938                 /* IRQ enter servicing state */
939                 IRQ_setbit(&dst->servicing, n_IRQ);
940                 retval = IPVP_VECTOR(src->ipvp);
941             }
942             IRQ_resetbit(&dst->raised, n_IRQ);
943             dst->raised.next = -1;
944             if (!test_bit(&src->ipvp, IPVP_SENSE)) {
945                 /* edge-sensitive IRQ */
946                 reset_bit(&src->ipvp, IPVP_ACTIVITY);
947                 src->pending = 0;
948             }
949
950             if ((n_IRQ >= opp->irq_ipi0) &&  (n_IRQ < (opp->irq_ipi0 + MAX_IPI))) {
951                 src->ide &= ~(1 << idx);
952                 if (src->ide && !test_bit(&src->ipvp, IPVP_SENSE)) {
953                     /* trigger on CPUs that didn't know about it yet */
954                     openpic_set_irq(opp, n_IRQ, 1);
955                     openpic_set_irq(opp, n_IRQ, 0);
956                     /* if all CPUs knew about it, set active bit again */
957                     set_bit(&src->ipvp, IPVP_ACTIVITY);
958                 }
959             }
960         }
961         break;
962     case 0xB0: /* PEOI */
963         retval = 0;
964         break;
965     default:
966         break;
967     }
968     DPRINTF("%s: => %08x\n", __func__, retval);
969
970     return retval;
971 }
972
973 static uint32_t openpic_cpu_read(void *opaque, target_phys_addr_t addr)
974 {
975     return openpic_cpu_read_internal(opaque, addr, (addr & 0x1f000) >> 12);
976 }
977
978 static void openpic_buggy_write (void *opaque,
979                                  target_phys_addr_t addr, uint32_t val)
980 {
981     printf("Invalid OPENPIC write access !\n");
982 }
983
984 static uint32_t openpic_buggy_read (void *opaque, target_phys_addr_t addr)
985 {
986     printf("Invalid OPENPIC read access !\n");
987
988     return -1;
989 }
990
991 static void openpic_writel (void *opaque,
992                             target_phys_addr_t addr, uint32_t val)
993 {
994     openpic_t *opp = opaque;
995
996     addr &= 0x3FFFF;
997     DPRINTF("%s: offset %08x val: %08x\n", __func__, (int)addr, val);
998     if (addr < 0x1100) {
999         /* Global registers */
1000         openpic_gbl_write(opp, addr, val);
1001     } else if (addr < 0x10000) {
1002         /* Timers registers */
1003         openpic_timer_write(opp, addr, val);
1004     } else if (addr < 0x20000) {
1005         /* Source registers */
1006         openpic_src_write(opp, addr, val);
1007     } else {
1008         /* CPU registers */
1009         openpic_cpu_write(opp, addr, val);
1010     }
1011 }
1012
1013 static uint32_t openpic_readl (void *opaque,target_phys_addr_t addr)
1014 {
1015     openpic_t *opp = opaque;
1016     uint32_t retval;
1017
1018     addr &= 0x3FFFF;
1019     DPRINTF("%s: offset %08x\n", __func__, (int)addr);
1020     if (addr < 0x1100) {
1021         /* Global registers */
1022         retval = openpic_gbl_read(opp, addr);
1023     } else if (addr < 0x10000) {
1024         /* Timers registers */
1025         retval = openpic_timer_read(opp, addr);
1026     } else if (addr < 0x20000) {
1027         /* Source registers */
1028         retval = openpic_src_read(opp, addr);
1029     } else {
1030         /* CPU registers */
1031         retval = openpic_cpu_read(opp, addr);
1032     }
1033
1034     return retval;
1035 }
1036
1037 static uint64_t openpic_read(void *opaque, target_phys_addr_t addr,
1038                              unsigned size)
1039 {
1040     openpic_t *opp = opaque;
1041
1042     switch (size) {
1043     case 4: return openpic_readl(opp, addr);
1044     default: return openpic_buggy_read(opp, addr);
1045     }
1046 }
1047
1048 static void openpic_write(void *opaque, target_phys_addr_t addr,
1049                           uint64_t data, unsigned size)
1050 {
1051     openpic_t *opp = opaque;
1052
1053     switch (size) {
1054     case 4: return openpic_writel(opp, addr, data);
1055     default: return openpic_buggy_write(opp, addr, data);
1056     }
1057 }
1058
1059 static const MemoryRegionOps openpic_ops = {
1060     .read = openpic_read,
1061     .write = openpic_write,
1062     .endianness = DEVICE_LITTLE_ENDIAN,
1063 };
1064
1065 static void openpic_save_IRQ_queue(QEMUFile* f, IRQ_queue_t *q)
1066 {
1067     unsigned int i;
1068
1069     for (i = 0; i < BF_WIDTH(MAX_IRQ); i++)
1070         qemu_put_be32s(f, &q->queue[i]);
1071
1072     qemu_put_sbe32s(f, &q->next);
1073     qemu_put_sbe32s(f, &q->priority);
1074 }
1075
1076 static void openpic_save(QEMUFile* f, void *opaque)
1077 {
1078     openpic_t *opp = (openpic_t *)opaque;
1079     unsigned int i;
1080
1081     qemu_put_be32s(f, &opp->frep);
1082     qemu_put_be32s(f, &opp->glbc);
1083     qemu_put_be32s(f, &opp->micr);
1084     qemu_put_be32s(f, &opp->veni);
1085     qemu_put_be32s(f, &opp->pint);
1086     qemu_put_be32s(f, &opp->spve);
1087     qemu_put_be32s(f, &opp->tifr);
1088
1089     for (i = 0; i < opp->max_irq; i++) {
1090         qemu_put_be32s(f, &opp->src[i].ipvp);
1091         qemu_put_be32s(f, &opp->src[i].ide);
1092         qemu_put_sbe32s(f, &opp->src[i].type);
1093         qemu_put_sbe32s(f, &opp->src[i].last_cpu);
1094         qemu_put_sbe32s(f, &opp->src[i].pending);
1095     }
1096
1097     qemu_put_sbe32s(f, &opp->nb_cpus);
1098
1099     for (i = 0; i < opp->nb_cpus; i++) {
1100         qemu_put_be32s(f, &opp->dst[i].tfrr);
1101         qemu_put_be32s(f, &opp->dst[i].pctp);
1102         qemu_put_be32s(f, &opp->dst[i].pcsr);
1103         openpic_save_IRQ_queue(f, &opp->dst[i].raised);
1104         openpic_save_IRQ_queue(f, &opp->dst[i].servicing);
1105     }
1106
1107     for (i = 0; i < MAX_TMR; i++) {
1108         qemu_put_be32s(f, &opp->timers[i].ticc);
1109         qemu_put_be32s(f, &opp->timers[i].tibc);
1110     }
1111
1112 #if MAX_DBL > 0
1113     qemu_put_be32s(f, &opp->dar);
1114
1115     for (i = 0; i < MAX_DBL; i++) {
1116         qemu_put_be32s(f, &opp->doorbells[i].dmr);
1117     }
1118 #endif
1119
1120 #if MAX_MBX > 0
1121     for (i = 0; i < MAX_MAILBOXES; i++) {
1122         qemu_put_be32s(f, &opp->mailboxes[i].mbr);
1123     }
1124 #endif
1125
1126     pci_device_save(&opp->pci_dev, f);
1127 }
1128
1129 static void openpic_load_IRQ_queue(QEMUFile* f, IRQ_queue_t *q)
1130 {
1131     unsigned int i;
1132
1133     for (i = 0; i < BF_WIDTH(MAX_IRQ); i++)
1134         qemu_get_be32s(f, &q->queue[i]);
1135
1136     qemu_get_sbe32s(f, &q->next);
1137     qemu_get_sbe32s(f, &q->priority);
1138 }
1139
1140 static int openpic_load(QEMUFile* f, void *opaque, int version_id)
1141 {
1142     openpic_t *opp = (openpic_t *)opaque;
1143     unsigned int i;
1144
1145     if (version_id != 1)
1146         return -EINVAL;
1147
1148     qemu_get_be32s(f, &opp->frep);
1149     qemu_get_be32s(f, &opp->glbc);
1150     qemu_get_be32s(f, &opp->micr);
1151     qemu_get_be32s(f, &opp->veni);
1152     qemu_get_be32s(f, &opp->pint);
1153     qemu_get_be32s(f, &opp->spve);
1154     qemu_get_be32s(f, &opp->tifr);
1155
1156     for (i = 0; i < opp->max_irq; i++) {
1157         qemu_get_be32s(f, &opp->src[i].ipvp);
1158         qemu_get_be32s(f, &opp->src[i].ide);
1159         qemu_get_sbe32s(f, &opp->src[i].type);
1160         qemu_get_sbe32s(f, &opp->src[i].last_cpu);
1161         qemu_get_sbe32s(f, &opp->src[i].pending);
1162     }
1163
1164     qemu_get_sbe32s(f, &opp->nb_cpus);
1165
1166     for (i = 0; i < opp->nb_cpus; i++) {
1167         qemu_get_be32s(f, &opp->dst[i].tfrr);
1168         qemu_get_be32s(f, &opp->dst[i].pctp);
1169         qemu_get_be32s(f, &opp->dst[i].pcsr);
1170         openpic_load_IRQ_queue(f, &opp->dst[i].raised);
1171         openpic_load_IRQ_queue(f, &opp->dst[i].servicing);
1172     }
1173
1174     for (i = 0; i < MAX_TMR; i++) {
1175         qemu_get_be32s(f, &opp->timers[i].ticc);
1176         qemu_get_be32s(f, &opp->timers[i].tibc);
1177     }
1178
1179 #if MAX_DBL > 0
1180     qemu_get_be32s(f, &opp->dar);
1181
1182     for (i = 0; i < MAX_DBL; i++) {
1183         qemu_get_be32s(f, &opp->doorbells[i].dmr);
1184     }
1185 #endif
1186
1187 #if MAX_MBX > 0
1188     for (i = 0; i < MAX_MAILBOXES; i++) {
1189         qemu_get_be32s(f, &opp->mailboxes[i].mbr);
1190     }
1191 #endif
1192
1193     return pci_device_load(&opp->pci_dev, f);
1194 }
1195
1196 static void openpic_irq_raise(openpic_t *opp, int n_CPU, IRQ_src_t *src)
1197 {
1198     qemu_irq_raise(opp->dst[n_CPU].irqs[OPENPIC_OUTPUT_INT]);
1199 }
1200
1201 qemu_irq *openpic_init (MemoryRegion **pmem, int nb_cpus,
1202                         qemu_irq **irqs, qemu_irq irq_out)
1203 {
1204     openpic_t *opp;
1205     int i, m;
1206
1207     /* XXX: for now, only one CPU is supported */
1208     if (nb_cpus != 1)
1209         return NULL;
1210     opp = g_malloc0(sizeof(openpic_t));
1211     memory_region_init_io(&opp->mem, &openpic_ops, opp, "openpic", 0x40000);
1212
1213     //    isu_base &= 0xFFFC0000;
1214     opp->nb_cpus = nb_cpus;
1215     opp->max_irq = OPENPIC_MAX_IRQ;
1216     opp->irq_ipi0 = OPENPIC_IRQ_IPI0;
1217     opp->irq_tim0 = OPENPIC_IRQ_TIM0;
1218     /* Set IRQ types */
1219     for (i = 0; i < OPENPIC_EXT_IRQ; i++) {
1220         opp->src[i].type = IRQ_EXTERNAL;
1221     }
1222     for (; i < OPENPIC_IRQ_TIM0; i++) {
1223         opp->src[i].type = IRQ_SPECIAL;
1224     }
1225 #if MAX_IPI > 0
1226     m = OPENPIC_IRQ_IPI0;
1227 #else
1228     m = OPENPIC_IRQ_DBL0;
1229 #endif
1230     for (; i < m; i++) {
1231         opp->src[i].type = IRQ_TIMER;
1232     }
1233     for (; i < OPENPIC_MAX_IRQ; i++) {
1234         opp->src[i].type = IRQ_INTERNAL;
1235     }
1236     for (i = 0; i < nb_cpus; i++)
1237         opp->dst[i].irqs = irqs[i];
1238     opp->irq_out = irq_out;
1239
1240     register_savevm(&opp->pci_dev.qdev, "openpic", 0, 2,
1241                     openpic_save, openpic_load, opp);
1242     qemu_register_reset(openpic_reset, opp);
1243
1244     opp->irq_raise = openpic_irq_raise;
1245     opp->reset = openpic_reset;
1246
1247     if (pmem)
1248         *pmem = &opp->mem;
1249
1250     return qemu_allocate_irqs(openpic_set_irq, opp, opp->max_irq);
1251 }
1252
1253 static void mpic_irq_raise(openpic_t *mpp, int n_CPU, IRQ_src_t *src)
1254 {
1255     int n_ci = IDR_CI0 - n_CPU;
1256
1257     if(test_bit(&src->ide, n_ci)) {
1258         qemu_irq_raise(mpp->dst[n_CPU].irqs[OPENPIC_OUTPUT_CINT]);
1259     }
1260     else {
1261         qemu_irq_raise(mpp->dst[n_CPU].irqs[OPENPIC_OUTPUT_INT]);
1262     }
1263 }
1264
1265 static void mpic_reset (void *opaque)
1266 {
1267     openpic_t *mpp = (openpic_t *)opaque;
1268     int i;
1269
1270     mpp->glbc = 0x80000000;
1271     /* Initialise controller registers */
1272     mpp->frep = 0x004f0002 | ((mpp->nb_cpus - 1) << 8);
1273     mpp->veni = VENI;
1274     mpp->pint = 0x00000000;
1275     mpp->spve = 0x0000FFFF;
1276     /* Initialise IRQ sources */
1277     for (i = 0; i < mpp->max_irq; i++) {
1278         mpp->src[i].ipvp = 0x80800000;
1279         mpp->src[i].ide  = 0x00000001;
1280     }
1281     /* Set IDE for IPIs to 0 so we don't get spurious interrupts */
1282     for (i = mpp->irq_ipi0; i < (mpp->irq_ipi0 + MAX_IPI); i++) {
1283         mpp->src[i].ide = 0;
1284     }
1285     /* Initialise IRQ destinations */
1286     for (i = 0; i < MAX_CPU; i++) {
1287         mpp->dst[i].pctp      = 0x0000000F;
1288         mpp->dst[i].tfrr      = 0x00000000;
1289         memset(&mpp->dst[i].raised, 0, sizeof(IRQ_queue_t));
1290         mpp->dst[i].raised.next = -1;
1291         memset(&mpp->dst[i].servicing, 0, sizeof(IRQ_queue_t));
1292         mpp->dst[i].servicing.next = -1;
1293     }
1294     /* Initialise timers */
1295     for (i = 0; i < MAX_TMR; i++) {
1296         mpp->timers[i].ticc = 0x00000000;
1297         mpp->timers[i].tibc = 0x80000000;
1298     }
1299     /* Go out of RESET state */
1300     mpp->glbc = 0x00000000;
1301 }
1302
1303 static void mpic_timer_write (void *opaque, target_phys_addr_t addr, uint32_t val)
1304 {
1305     openpic_t *mpp = opaque;
1306     int idx, cpu;
1307
1308     DPRINTF("%s: addr " TARGET_FMT_plx " <= %08x\n", __func__, addr, val);
1309     if (addr & 0xF)
1310         return;
1311     addr &= 0xFFFF;
1312     cpu = addr >> 12;
1313     idx = (addr >> 6) & 0x3;
1314     switch (addr & 0x30) {
1315     case 0x00: /* gtccr */
1316         break;
1317     case 0x10: /* gtbcr */
1318         if ((mpp->timers[idx].ticc & 0x80000000) != 0 &&
1319             (val & 0x80000000) == 0 &&
1320             (mpp->timers[idx].tibc & 0x80000000) != 0)
1321             mpp->timers[idx].ticc &= ~0x80000000;
1322         mpp->timers[idx].tibc = val;
1323         break;
1324     case 0x20: /* GTIVPR */
1325         write_IRQreg_ipvp(mpp, MPIC_TMR_IRQ + idx, val);
1326         break;
1327     case 0x30: /* GTIDR & TFRR */
1328         if ((addr & 0xF0) == 0xF0)
1329             mpp->dst[cpu].tfrr = val;
1330         else
1331             write_IRQreg_ide(mpp, MPIC_TMR_IRQ + idx, val);
1332         break;
1333     }
1334 }
1335
1336 static uint32_t mpic_timer_read (void *opaque, target_phys_addr_t addr)
1337 {
1338     openpic_t *mpp = opaque;
1339     uint32_t retval;
1340     int idx, cpu;
1341
1342     DPRINTF("%s: addr " TARGET_FMT_plx "\n", __func__, addr);
1343     retval = 0xFFFFFFFF;
1344     if (addr & 0xF)
1345         return retval;
1346     addr &= 0xFFFF;
1347     cpu = addr >> 12;
1348     idx = (addr >> 6) & 0x3;
1349     switch (addr & 0x30) {
1350     case 0x00: /* gtccr */
1351         retval = mpp->timers[idx].ticc;
1352         break;
1353     case 0x10: /* gtbcr */
1354         retval = mpp->timers[idx].tibc;
1355         break;
1356     case 0x20: /* TIPV */
1357         retval = read_IRQreg_ipvp(mpp, MPIC_TMR_IRQ + idx);
1358         break;
1359     case 0x30: /* TIDR */
1360         if ((addr &0xF0) == 0XF0)
1361             retval = mpp->dst[cpu].tfrr;
1362         else
1363             retval = read_IRQreg_ide(mpp, MPIC_TMR_IRQ + idx);
1364         break;
1365     }
1366     DPRINTF("%s: => %08x\n", __func__, retval);
1367
1368     return retval;
1369 }
1370
1371 static void mpic_src_ext_write (void *opaque, target_phys_addr_t addr,
1372                                 uint32_t val)
1373 {
1374     openpic_t *mpp = opaque;
1375     int idx = MPIC_EXT_IRQ;
1376
1377     DPRINTF("%s: addr " TARGET_FMT_plx " <= %08x\n", __func__, addr, val);
1378     if (addr & 0xF)
1379         return;
1380
1381     if (addr < MPIC_EXT_REG_SIZE) {
1382         idx += (addr & 0xFFF0) >> 5;
1383         if (addr & 0x10) {
1384             /* EXDE / IFEDE / IEEDE */
1385             write_IRQreg_ide(mpp, idx, val);
1386         } else {
1387             /* EXVP / IFEVP / IEEVP */
1388             write_IRQreg_ipvp(mpp, idx, val);
1389         }
1390     }
1391 }
1392
1393 static uint32_t mpic_src_ext_read (void *opaque, target_phys_addr_t addr)
1394 {
1395     openpic_t *mpp = opaque;
1396     uint32_t retval;
1397     int idx = MPIC_EXT_IRQ;
1398
1399     DPRINTF("%s: addr " TARGET_FMT_plx "\n", __func__, addr);
1400     retval = 0xFFFFFFFF;
1401     if (addr & 0xF)
1402         return retval;
1403
1404     if (addr < MPIC_EXT_REG_SIZE) {
1405         idx += (addr & 0xFFF0) >> 5;
1406         if (addr & 0x10) {
1407             /* EXDE / IFEDE / IEEDE */
1408             retval = read_IRQreg_ide(mpp, idx);
1409         } else {
1410             /* EXVP / IFEVP / IEEVP */
1411             retval = read_IRQreg_ipvp(mpp, idx);
1412         }
1413         DPRINTF("%s: => %08x\n", __func__, retval);
1414     }
1415
1416     return retval;
1417 }
1418
1419 static void mpic_src_int_write (void *opaque, target_phys_addr_t addr,
1420                                 uint32_t val)
1421 {
1422     openpic_t *mpp = opaque;
1423     int idx = MPIC_INT_IRQ;
1424
1425     DPRINTF("%s: addr " TARGET_FMT_plx " <= %08x\n", __func__, addr, val);
1426     if (addr & 0xF)
1427         return;
1428
1429     if (addr < MPIC_INT_REG_SIZE) {
1430         idx += (addr & 0xFFF0) >> 5;
1431         if (addr & 0x10) {
1432             /* EXDE / IFEDE / IEEDE */
1433             write_IRQreg_ide(mpp, idx, val);
1434         } else {
1435             /* EXVP / IFEVP / IEEVP */
1436             write_IRQreg_ipvp(mpp, idx, val);
1437         }
1438     }
1439 }
1440
1441 static uint32_t mpic_src_int_read (void *opaque, target_phys_addr_t addr)
1442 {
1443     openpic_t *mpp = opaque;
1444     uint32_t retval;
1445     int idx = MPIC_INT_IRQ;
1446
1447     DPRINTF("%s: addr " TARGET_FMT_plx "\n", __func__, addr);
1448     retval = 0xFFFFFFFF;
1449     if (addr & 0xF)
1450         return retval;
1451
1452     if (addr < MPIC_INT_REG_SIZE) {
1453         idx += (addr & 0xFFF0) >> 5;
1454         if (addr & 0x10) {
1455             /* EXDE / IFEDE / IEEDE */
1456             retval = read_IRQreg_ide(mpp, idx);
1457         } else {
1458             /* EXVP / IFEVP / IEEVP */
1459             retval = read_IRQreg_ipvp(mpp, idx);
1460         }
1461         DPRINTF("%s: => %08x\n", __func__, retval);
1462     }
1463
1464     return retval;
1465 }
1466
1467 static void mpic_src_msg_write (void *opaque, target_phys_addr_t addr,
1468                                 uint32_t val)
1469 {
1470     openpic_t *mpp = opaque;
1471     int idx = MPIC_MSG_IRQ;
1472
1473     DPRINTF("%s: addr " TARGET_FMT_plx " <= %08x\n", __func__, addr, val);
1474     if (addr & 0xF)
1475         return;
1476
1477     if (addr < MPIC_MSG_REG_SIZE) {
1478         idx += (addr & 0xFFF0) >> 5;
1479         if (addr & 0x10) {
1480             /* EXDE / IFEDE / IEEDE */
1481             write_IRQreg_ide(mpp, idx, val);
1482         } else {
1483             /* EXVP / IFEVP / IEEVP */
1484             write_IRQreg_ipvp(mpp, idx, val);
1485         }
1486     }
1487 }
1488
1489 static uint32_t mpic_src_msg_read (void *opaque, target_phys_addr_t addr)
1490 {
1491     openpic_t *mpp = opaque;
1492     uint32_t retval;
1493     int idx = MPIC_MSG_IRQ;
1494
1495     DPRINTF("%s: addr " TARGET_FMT_plx "\n", __func__, addr);
1496     retval = 0xFFFFFFFF;
1497     if (addr & 0xF)
1498         return retval;
1499
1500     if (addr < MPIC_MSG_REG_SIZE) {
1501         idx += (addr & 0xFFF0) >> 5;
1502         if (addr & 0x10) {
1503             /* EXDE / IFEDE / IEEDE */
1504             retval = read_IRQreg_ide(mpp, idx);
1505         } else {
1506             /* EXVP / IFEVP / IEEVP */
1507             retval = read_IRQreg_ipvp(mpp, idx);
1508         }
1509         DPRINTF("%s: => %08x\n", __func__, retval);
1510     }
1511
1512     return retval;
1513 }
1514
1515 static void mpic_src_msi_write (void *opaque, target_phys_addr_t addr,
1516                                 uint32_t val)
1517 {
1518     openpic_t *mpp = opaque;
1519     int idx = MPIC_MSI_IRQ;
1520
1521     DPRINTF("%s: addr " TARGET_FMT_plx " <= %08x\n", __func__, addr, val);
1522     if (addr & 0xF)
1523         return;
1524
1525     if (addr < MPIC_MSI_REG_SIZE) {
1526         idx += (addr & 0xFFF0) >> 5;
1527         if (addr & 0x10) {
1528             /* EXDE / IFEDE / IEEDE */
1529             write_IRQreg_ide(mpp, idx, val);
1530         } else {
1531             /* EXVP / IFEVP / IEEVP */
1532             write_IRQreg_ipvp(mpp, idx, val);
1533         }
1534     }
1535 }
1536 static uint32_t mpic_src_msi_read (void *opaque, target_phys_addr_t addr)
1537 {
1538     openpic_t *mpp = opaque;
1539     uint32_t retval;
1540     int idx = MPIC_MSI_IRQ;
1541
1542     DPRINTF("%s: addr " TARGET_FMT_plx "\n", __func__, addr);
1543     retval = 0xFFFFFFFF;
1544     if (addr & 0xF)
1545         return retval;
1546
1547     if (addr < MPIC_MSI_REG_SIZE) {
1548         idx += (addr & 0xFFF0) >> 5;
1549         if (addr & 0x10) {
1550             /* EXDE / IFEDE / IEEDE */
1551             retval = read_IRQreg_ide(mpp, idx);
1552         } else {
1553             /* EXVP / IFEVP / IEEVP */
1554             retval = read_IRQreg_ipvp(mpp, idx);
1555         }
1556         DPRINTF("%s: => %08x\n", __func__, retval);
1557     }
1558
1559     return retval;
1560 }
1561
1562 static const MemoryRegionOps mpic_glb_ops = {
1563     .old_mmio = {
1564         .write = { openpic_buggy_write,
1565                    openpic_buggy_write,
1566                    openpic_gbl_write,
1567         },
1568         .read  = { openpic_buggy_read,
1569                    openpic_buggy_read,
1570                    openpic_gbl_read,
1571         },
1572     },
1573     .endianness = DEVICE_BIG_ENDIAN,
1574 };
1575
1576 static const MemoryRegionOps mpic_tmr_ops = {
1577     .old_mmio = {
1578         .write = { openpic_buggy_write,
1579                    openpic_buggy_write,
1580                    mpic_timer_write,
1581         },
1582         .read  = { openpic_buggy_read,
1583                    openpic_buggy_read,
1584                    mpic_timer_read,
1585         },
1586     },
1587     .endianness = DEVICE_BIG_ENDIAN,
1588 };
1589
1590 static const MemoryRegionOps mpic_cpu_ops = {
1591     .old_mmio = {
1592         .write = { openpic_buggy_write,
1593                    openpic_buggy_write,
1594                    openpic_cpu_write,
1595         },
1596         .read  = { openpic_buggy_read,
1597                    openpic_buggy_read,
1598                    openpic_cpu_read,
1599         },
1600     },
1601     .endianness = DEVICE_BIG_ENDIAN,
1602 };
1603
1604 static const MemoryRegionOps mpic_ext_ops = {
1605     .old_mmio = {
1606         .write = { openpic_buggy_write,
1607                    openpic_buggy_write,
1608                    mpic_src_ext_write,
1609         },
1610         .read  = { openpic_buggy_read,
1611                    openpic_buggy_read,
1612                    mpic_src_ext_read,
1613         },
1614     },
1615     .endianness = DEVICE_BIG_ENDIAN,
1616 };
1617
1618 static const MemoryRegionOps mpic_int_ops = {
1619     .old_mmio = {
1620         .write = { openpic_buggy_write,
1621                    openpic_buggy_write,
1622                    mpic_src_int_write,
1623         },
1624         .read  = { openpic_buggy_read,
1625                    openpic_buggy_read,
1626                    mpic_src_int_read,
1627         },
1628     },
1629     .endianness = DEVICE_BIG_ENDIAN,
1630 };
1631
1632 static const MemoryRegionOps mpic_msg_ops = {
1633     .old_mmio = {
1634         .write = { openpic_buggy_write,
1635                    openpic_buggy_write,
1636                    mpic_src_msg_write,
1637         },
1638         .read  = { openpic_buggy_read,
1639                    openpic_buggy_read,
1640                    mpic_src_msg_read,
1641         },
1642     },
1643     .endianness = DEVICE_BIG_ENDIAN,
1644 };
1645
1646 static const MemoryRegionOps mpic_msi_ops = {
1647     .old_mmio = {
1648         .write = { openpic_buggy_write,
1649                    openpic_buggy_write,
1650                    mpic_src_msi_write,
1651         },
1652         .read  = { openpic_buggy_read,
1653                    openpic_buggy_read,
1654                    mpic_src_msi_read,
1655         },
1656     },
1657     .endianness = DEVICE_BIG_ENDIAN,
1658 };
1659
1660 qemu_irq *mpic_init (MemoryRegion *address_space, target_phys_addr_t base,
1661                      int nb_cpus, qemu_irq **irqs, qemu_irq irq_out)
1662 {
1663     openpic_t    *mpp;
1664     int           i;
1665     struct {
1666         const char             *name;
1667         MemoryRegionOps const  *ops;
1668         target_phys_addr_t      start_addr;
1669         ram_addr_t              size;
1670     } const list[] = {
1671         {"glb", &mpic_glb_ops, MPIC_GLB_REG_START, MPIC_GLB_REG_SIZE},
1672         {"tmr", &mpic_tmr_ops, MPIC_TMR_REG_START, MPIC_TMR_REG_SIZE},
1673         {"ext", &mpic_ext_ops, MPIC_EXT_REG_START, MPIC_EXT_REG_SIZE},
1674         {"int", &mpic_int_ops, MPIC_INT_REG_START, MPIC_INT_REG_SIZE},
1675         {"msg", &mpic_msg_ops, MPIC_MSG_REG_START, MPIC_MSG_REG_SIZE},
1676         {"msi", &mpic_msi_ops, MPIC_MSI_REG_START, MPIC_MSI_REG_SIZE},
1677         {"cpu", &mpic_cpu_ops, MPIC_CPU_REG_START, MPIC_CPU_REG_SIZE},
1678     };
1679
1680     mpp = g_malloc0(sizeof(openpic_t));
1681
1682     memory_region_init(&mpp->mem, "mpic", 0x40000);
1683     memory_region_add_subregion(address_space, base, &mpp->mem);
1684
1685     for (i = 0; i < sizeof(list)/sizeof(list[0]); i++) {
1686
1687         memory_region_init_io(&mpp->sub_io_mem[i], list[i].ops, mpp,
1688                               list[i].name, list[i].size);
1689
1690         memory_region_add_subregion(&mpp->mem, list[i].start_addr,
1691                                     &mpp->sub_io_mem[i]);
1692     }
1693
1694     mpp->nb_cpus = nb_cpus;
1695     mpp->max_irq = MPIC_MAX_IRQ;
1696     mpp->irq_ipi0 = MPIC_IPI_IRQ;
1697     mpp->irq_tim0 = MPIC_TMR_IRQ;
1698
1699     for (i = 0; i < nb_cpus; i++)
1700         mpp->dst[i].irqs = irqs[i];
1701     mpp->irq_out = irq_out;
1702
1703     mpp->irq_raise = mpic_irq_raise;
1704     mpp->reset = mpic_reset;
1705
1706     register_savevm(NULL, "mpic", 0, 2, openpic_save, openpic_load, mpp);
1707     qemu_register_reset(mpic_reset, mpp);
1708
1709     return qemu_allocate_irqs(openpic_set_irq, mpp, mpp->max_irq);
1710 }