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