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