packing update
[qemu] / hw / openpic.c
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     } const 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 }