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